|  | 
|  | 1 | +.. _ab_split_sample: | 
|  | 2 | + | 
|  | 3 | +A/B with MCUboot and separated slots | 
|  | 4 | +#################################### | 
|  | 5 | + | 
|  | 6 | +.. contents:: | 
|  | 7 | +   :local: | 
|  | 8 | +   :depth: 2 | 
|  | 9 | + | 
|  | 10 | +The A/B with MCUboot and separated slots sample demonstrates how to configure the application for updates using the A/B method using MCUboot. | 
|  | 11 | +This sample is a variant of the :ref:`A/B sample <ab_sample>`, where the application and radio images are not merged, but reside in separate MCUboot slots. | 
|  | 12 | +This split increases demand on the number of memory areas that should be individually locked from accidental writes as well as requires additional care when preparing updates, so only a compatible set of slots are booted. | 
|  | 13 | +The additional dependency check during the boot process increases the time to boot the system. | 
|  | 14 | + | 
|  | 15 | +It also includes an example to perform a device health check before confirming the image after the update. | 
|  | 16 | +You can update the sample using the Simple Management Protocol (SMP) with UART or Bluetooth® Low Energy. | 
|  | 17 | + | 
|  | 18 | +To prevent the build system from merging slots, the sysbuild :kconfig:option:`SB_CONFIG_MCUBOOT_SIGN_MERGED_BINARY` option is disabled. | 
|  | 19 | +To enable slot-based dependency management, the :kconfig:option:`CONFIG_BOOT_VERSION_CMP_USE_SLOT_NUMBER` option is enabled in the :file:`sysbuild/mcuboot/prj.conf` file. | 
|  | 20 | + | 
|  | 21 | +Requirements | 
|  | 22 | +************ | 
|  | 23 | + | 
|  | 24 | +The sample supports the following development kits: | 
|  | 25 | + | 
|  | 26 | +.. table-from-sample-yaml:: | 
|  | 27 | + | 
|  | 28 | +You need the nRF Device Manager app for update over Bluetooth Low Energy: | 
|  | 29 | + | 
|  | 30 | +* `nRF Device Manager mobile app for Android`_ | 
|  | 31 | +* `nRF Device Manager mobile app for iOS`_ | 
|  | 32 | + | 
|  | 33 | + | 
|  | 34 | +Overview | 
|  | 35 | +******** | 
|  | 36 | + | 
|  | 37 | +This sample demonstrates firmware update using the A/B method. | 
|  | 38 | +This method allows two copies of the application in the NVM memory. | 
|  | 39 | +It is possible to switch between these copies without performing a swap, which significantly reduces time of device's unavailability during the update. | 
|  | 40 | +The switch between images can be triggered by the application or, for example, by a hardware button. | 
|  | 41 | + | 
|  | 42 | +This sample implements an SMP server. | 
|  | 43 | +SMP is a basic transfer encoding used with the MCUmgr management protocol. | 
|  | 44 | +For more information about MCUmgr and SMP, see :ref:`device_mgmt`. | 
|  | 45 | + | 
|  | 46 | +The sample supports the following MCUmgr transports by default: | 
|  | 47 | + | 
|  | 48 | +* Bluetooth | 
|  | 49 | +* Serial (UART) | 
|  | 50 | + | 
|  | 51 | +A/B functionality | 
|  | 52 | +================= | 
|  | 53 | + | 
|  | 54 | +When the A/B with separated slots functionality is used, the device has two slots for each application and radio firmwares: slot A and slot B. | 
|  | 55 | +The slots are equivalent, and the device can boot from either of them. | 
|  | 56 | +By design, the slot A of the application image boots the slot A of the radio image, so there is a slot-based dependency required to correctly verify the correctness of the images. | 
|  | 57 | +In the case of MCUboot, this is achieved by using the Direct XIP feature. | 
|  | 58 | +Thus, note that the terms slot 0, primary slot, slot A and slot 1, secondary slot, slot B are used interchangeably throughout the documentation. | 
|  | 59 | +This configuration allows a background update of the non-active slot while the application runs from the active slot. | 
|  | 60 | +After the update is complete, the device can quickly switch to the updated slot on the next reboot. | 
|  | 61 | + | 
|  | 62 | +The following conditions decide which slot will be booted (active) on the next reboot: | 
|  | 63 | + | 
|  | 64 | +1. If one of the slots contains a valid image, it is marked as valid only if the same slot of the other image is also valid. | 
|  | 65 | +#. If one of the slots is not valid, the other slot is selected as active. | 
|  | 66 | +#. If both slots are valid, the slot marked as "preferred" is selected as active. | 
|  | 67 | +#. If both slots are valid and none is marked as "preferred," the slot with the higher version number is selected as active. | 
|  | 68 | +#. If none of the above conditions is met, slot A is selected as active. | 
|  | 69 | + | 
|  | 70 | +You can set the preferred slot using the ``boot_request_set_preferred_slot`` function. | 
|  | 71 | +Currently, this only sets the boot preference for a single reboot. | 
|  | 72 | + | 
|  | 73 | +Identifying the active slot | 
|  | 74 | +--------------------------- | 
|  | 75 | + | 
|  | 76 | +If the project uses the Partition Manager, the currently running slot can be identified by checking if ``CONFIG_NCS_IS_VARIANT_IMAGE`` is defined. | 
|  | 77 | +If it is defined, the application is running from slot B. | 
|  | 78 | +Otherwise, it is running from slot A. | 
|  | 79 | + | 
|  | 80 | +If the project does not use the Partition Manager (a configuration currently only supported on the nRF54H20), the currently running slot can be identified by comparing the address pointed `zephyr,code-partition` to specific node addresses defined in the device tree. | 
|  | 81 | +The following node partitions are used by default: | 
|  | 82 | + | 
|  | 83 | +* ``cpuapp_slot0_partition`` - Application core, slot A | 
|  | 84 | +* ``cpuapp_slot1_partition`` - Application core, slot B | 
|  | 85 | +* ``cpurad_slot0_partition`` - Radio core, slot A | 
|  | 86 | +* ``cpurad_slot1_partition`` - Radio core, slot B | 
|  | 87 | + | 
|  | 88 | +For example, verifying that the application is running from slot A can be done by using the following macro: | 
|  | 89 | + | 
|  | 90 | +.. code-block:: c | 
|  | 91 | +
 | 
|  | 92 | +    #define IS_RUNNING_FROM_SLOT_A \ | 
|  | 93 | +        (FIXED_PARTITION_NODE_OFFSET(DT_CHOSEN(zephyr_code_partition)) == \ | 
|  | 94 | +         FIXED_PARTITION_OFFSET(cpuapp_slot0_partition)) | 
|  | 95 | +
 | 
|  | 96 | +.. _ab_split_build_files: | 
|  | 97 | + | 
|  | 98 | +Build files | 
|  | 99 | +----------- | 
|  | 100 | + | 
|  | 101 | +This sample overrides the default build strategy, so application and radio images are built separately.  | 
|  | 102 | +In this case, the following files should be sent to the device when performing an update: | 
|  | 103 | + | 
|  | 104 | +* :file:`build/mcuboot_secondary_app/zephyr/zephyr.signed.bin` - Contains the slot B of the application image. | 
|  | 105 | +  This file should be uploaded to the secondary slot when the device is running from slot A. | 
|  | 106 | +* :file:`build/ipc_radio_secondary_app/zephyr/zephyr.signed.bin` - Contains the slot B of the radio image. | 
|  | 107 | +  This file should be uploaded to the secondary slot when the device is running from slot A. | 
|  | 108 | +* :file:`build/ab/zephyr/zephyr.signed.bin` - Contains the slot A of the application image. | 
|  | 109 | +  This file should be uploaded to the primary slot when the device is running from slot B. | 
|  | 110 | +* :file:`build/ipc_radio/zephyr/zephyr.signed.bin` - Contains the slot A of the radio image. | 
|  | 111 | +  This file should be uploaded to the primary slot when the device is running from slot B. | 
|  | 112 | + | 
|  | 113 | +User interface | 
|  | 114 | +************** | 
|  | 115 | + | 
|  | 116 | +LED 0: | 
|  | 117 | +    This LED indicates that the application is running from slot A. | 
|  | 118 | +    It is controlled as active low, meaning it will turn on once the application is booted and blinks (turns off) in short intervals. | 
|  | 119 | +    The number of short blinks is configurable using the :kconfig:option:`CONFIG_N_BLINKS` Kconfig option. | 
|  | 120 | +    It will remain off if the application is running from slot B. | 
|  | 121 | + | 
|  | 122 | +LED 1: | 
|  | 123 | +    This LED indicates that the application is running from slot B. | 
|  | 124 | +    It is controlled as active low, meaning it will turn on once the application is booted and blinks (turns off) in short intervals. | 
|  | 125 | +    The number of short blinks is configurable using the :kconfig:option:`CONFIG_N_BLINKS` Kconfig option. | 
|  | 126 | +    It will remain off if the application is running from slot A. | 
|  | 127 | + | 
|  | 128 | +Button 0: | 
|  | 129 | +    By pressing this button, the non-active slot will be selected as the preferred slot on the next reboot. | 
|  | 130 | +    This preference applies only to the next boot and is cleared after the subsequent reset. | 
|  | 131 | + | 
|  | 132 | +Configuration | 
|  | 133 | +************* | 
|  | 134 | + | 
|  | 135 | +|config| | 
|  | 136 | + | 
|  | 137 | +Configuration options | 
|  | 138 | +===================== | 
|  | 139 | + | 
|  | 140 | +Check and configure the following configuration option for the sample: | 
|  | 141 | + | 
|  | 142 | +.. _CONFIG_N_BLINKS: | 
|  | 143 | + | 
|  | 144 | +CONFIG_N_BLINKS - The number of blinks. | 
|  | 145 | +   This configuration option sets the number of times the LED corresponding to the currently active slot blinks (LED0 for slot A, LED1 for slot B). | 
|  | 146 | +   The default value of the option is set to ``1``, causing a single blink to indicate *Version 1*. | 
|  | 147 | +   You can increment this value to represent an update, such as set it to ``2`` to indicate *Version 2*. | 
|  | 148 | + | 
|  | 149 | +.. _CONFIG_EMULATE_APP_HEALTH_CHECK_FAILURE: | 
|  | 150 | + | 
|  | 151 | +CONFIG_EMULATE_APP_HEALTH_CHECK_FAILURE - Enables emulation of a broken application that fails the self-test. | 
|  | 152 | +   This configuration option emulates a broken application that does not pass the self-test. | 
|  | 153 | + | 
|  | 154 | +Additional configuration | 
|  | 155 | +======================== | 
|  | 156 | + | 
|  | 157 | +Check and configure the :kconfig:option:`CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION` library Kconfig option specific to the MCUboot library. | 
|  | 158 | +This configuration option sets the version to pass to imgtool when signing. | 
|  | 159 | +To ensure the updated build is preferred after a DFU, set this option to a higher version than the version currently running on the device. | 
|  | 160 | + | 
|  | 161 | +In addition, set the :kconfig:option:`CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS` library Kconfig option specific to the MCUboot library to specify the slot-specific image dependencies. | 
|  | 162 | +For example, to ensure that there is a valid radio image with version ``1.0.0`` or greater in the radio primary slot set: | 
|  | 163 | + | 
|  | 164 | +.. code-block:: console | 
|  | 165 | +
 | 
|  | 166 | +    CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS="--dependencies \"(0,primary,1.0.0)\"" | 
|  | 167 | +
 | 
|  | 168 | +The slot-specific dependency is automatically converted to point to the secondary slot when building the second variant of each image. | 
|  | 169 | + | 
|  | 170 | +Building and running | 
|  | 171 | +******************** | 
|  | 172 | + | 
|  | 173 | +.. |sample path| replace:: :file:`samples/dfu/ab` | 
|  | 174 | + | 
|  | 175 | +.. include:: /includes/build_and_run.txt | 
|  | 176 | + | 
|  | 177 | +Testing | 
|  | 178 | +======= | 
|  | 179 | + | 
|  | 180 | +To perform DFU using the `nRF Connect Device Manager`_ mobile app, complete the following steps: | 
|  | 181 | + | 
|  | 182 | +.. include:: /app_dev/device_guides/nrf52/fota_update.rst | 
|  | 183 | +   :start-after: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_start | 
|  | 184 | +   :end-before: fota_upgrades_over_ble_nrfcdm_common_dfu_steps_end | 
|  | 185 | + | 
|  | 186 | +Instead of using the :file:`dfu_application.zip` file, you can also send the appropriate binary file directly, as described in :ref:`ab_build_files`. | 
|  | 187 | +Make sure to select the correct file based on the currently running slot. | 
|  | 188 | + | 
|  | 189 | +Dependencies | 
|  | 190 | +************ | 
|  | 191 | + | 
|  | 192 | +This sample uses the following |NCS| library: | 
|  | 193 | + | 
|  | 194 | +* :ref:`MCUboot <mcuboot_index_ncs>` | 
0 commit comments