Skip to content

Commit cff13a3

Browse files
committed
applications: nrf_desktop: dfu: add support for MCUboot RAM load
Added support for the RAM load mode of the MCUboot bootloader to the nRF Desktop application DFU module. Ref: NCSDK-35506 Signed-off-by: Kamil Piszczek <[email protected]>
1 parent 0d9915b commit cff13a3

File tree

3 files changed

+71
-37
lines changed

3 files changed

+71
-37
lines changed

applications/nrf_desktop/doc/dfu.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ If the MCUboot bootloader in the swap mode is selected, the DFU module does the
5757
If the MCUboot bootloader's direct-xip mode is used, the module does not mark the newly uploaded image as pending and does not confirm it after a successful boot.
5858
In that case, the DFU module assumes that the MCUboot direct-xip bootloader simply boots an image with the higher version, so there is no need to mark the image as pending and confirm it.
5959

60-
The :ref:`CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP <config_desktop_app_options>` Kconfig option is used to inform the DFU module that the device uses the MCUboot bootloader in the direct-xip mode.
60+
The :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option is used to inform the DFU module that the device uses the MCUboot bootloader in the direct-xip mode.
6161
If the option is enabled, the DFU module reports the ``MCUBOOT+XIP`` bootloader name instead of ``MCUBOOT`` to indicate that the bootloader working in the direct-xip mode is used.
62-
The option depends on enabling the MCUboot bootloader (:kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT`) and is enabled by default if the MCUboot direct-xip mode of operations is set (:kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP`).
6362
See the :ref:`nrf_desktop_bootloader` section for more information on the MCUboot bootloader configuration.
6463

6564
Device identification information

applications/nrf_desktop/src/modules/Kconfig.config_channel

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,6 @@ config DESKTOP_CONFIG_CHANNEL_DFU_SYNC_BUFFER_SIZE
7373
The host must perform progress synchronization at least
7474
every synchronization buffer bytes count.
7575

76-
config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
77-
bool "Device uses MCUboot bootloader in direct-xip mode"
78-
depends on BOOTLOADER_MCUBOOT
79-
default y if MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
80-
help
81-
The option informs the DFU module that the MCUboot bootloader supports
82-
direct-xip mode. In this mode, the image is booted directly from the
83-
secondary slot instead of moving it to the primary slot. The module by
84-
default assumes that MCUboot with direct-xip is used when direct-xip
85-
variant image is built.
86-
87-
The DFU module assumes that MCUboot direct-xip bootloader simply boots
88-
the image with a higher version. The module does not mark the newly
89-
uploaded image as pending nor confirm it after a successful boot.
90-
9176
config DESKTOP_CONFIG_CHANNEL_DFU_VID
9277
hex "Configuration channel Vendor ID"
9378
range 0 0XFFFF

applications/nrf_desktop/src/modules/dfu.c

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
5151

5252
#define SYNC_BUFFER_SIZE (CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_SYNC_BUFFER_SIZE * sizeof(uint32_t)) /* bytes */
5353

54+
/* This value denotes whether the revert feature is supported by the MCUboot bootloader.
55+
* Currently, the revert feature is only supported by the MCUboot bootloader that is not
56+
* configured for the standard direct-xip or RAM load mode.
57+
*/
58+
#define MCUBOOT_REVERT_FEATURE_IS_SUPPORTED \
59+
(IS_ENABLED(CONFIG_BOOTLOADER_MCUBOOT) && \
60+
!IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) && \
61+
!IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD))
62+
63+
/* This value denotes whether it is possible to resolve the DFU slot ID at build time.
64+
* If the build time information is available, the DFU_SLOT_ID macro should be defined
65+
* and point to the flash area where the new DFU image should be placed. Otherwise, if
66+
* dynamic information is required, the function dfu_slot_id_get() should be extended
67+
* to support the new bootloader mode. To support the dynamic resolution for the MCUboot
68+
* bootloader, the user must define the MCUBOOT_PRIMARY_SLOT_ID and MCUBOOT_SECONDARY_SLOT_ID
69+
* macros.
70+
*/
71+
#define BUILD_TIME_DFU_SLOT_ID_INFO_IS_AVAILABLE \
72+
((IS_ENABLED(CONFIG_BOOTLOADER_MCUBOOT) && \
73+
!IS_ENABLED(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)) || \
74+
IS_ENABLED(CONFIG_SECURE_BOOT))
75+
5476
#if CONFIG_SECURE_BOOT
5577
BUILD_ASSERT(IS_ENABLED(CONFIG_PARTITION_MANAGER_ENABLED),
5678
"B0 bootloader supported only with Partition Manager");
@@ -66,12 +88,18 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
6688
#endif
6789
#elif CONFIG_BOOTLOADER_MCUBOOT
6890
#include <zephyr/dfu/mcuboot.h>
69-
#if CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
91+
#if CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
7092
#define BOOTLOADER_NAME "MCUBOOT+XIP"
7193
#else
7294
#define BOOTLOADER_NAME "MCUBOOT"
7395
#endif
7496

97+
#if CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
98+
/* The RAM load requires the code partition to be defined in DTS. */
99+
BUILD_ASSERT(!IS_ENABLED(CONFIG_PARTITION_MANAGER_ENABLED) &&
100+
IS_ENABLED(CONFIG_USE_DT_CODE_PARTITION));
101+
#endif
102+
75103
#if CONFIG_PARTITION_MANAGER_ENABLED
76104
#include <pm_config.h>
77105

@@ -123,18 +151,20 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
123151
#define MCUBOOT_PRIMARY_SLOT_ID DT_FIXED_PARTITION_ID(MCUBOOT_PRIMARY_NODE)
124152
#define MCUBOOT_SECONDARY_SLOT_ID DT_FIXED_PARTITION_ID(MCUBOOT_SECONDARY_NODE)
125153

126-
/* Use range check to allow for placing MCUboot header in a separate partition,
127-
* so the application code partition is not an alias for the MCUboot partition,
128-
* but a subpartition of the MCUboot partition.
129-
*/
130-
#if (CODE_PARTITION_START_ADDR >= MCUBOOT_PRIMARY_START_ADDR) && \
131-
(CODE_PARTITION_START_ADDR < MCUBOOT_PRIMARY_END_ADDR)
132-
#define DFU_SLOT_ID MCUBOOT_SECONDARY_SLOT_ID
133-
#elif (CODE_PARTITION_START_ADDR >= MCUBOOT_SECONDARY_START_ADDR) && \
134-
(CODE_PARTITION_START_ADDR < MCUBOOT_SECONDARY_END_ADDR)
135-
#define DFU_SLOT_ID MCUBOOT_PRIMARY_SLOT_ID
136-
#else
137-
#error Missing partition definitions in DTS.
154+
#if BUILD_TIME_DFU_SLOT_ID_INFO_IS_AVAILABLE
155+
/* Use range check to allow for placing MCUboot header in a separate
156+
* partition,so the application code partition is not an alias for the
157+
* MCUboot partition, but a subpartition of the MCUboot partition.
158+
*/
159+
#if (CODE_PARTITION_START_ADDR >= MCUBOOT_PRIMARY_START_ADDR) && \
160+
(CODE_PARTITION_START_ADDR < MCUBOOT_PRIMARY_END_ADDR)
161+
#define DFU_SLOT_ID MCUBOOT_SECONDARY_SLOT_ID
162+
#elif (CODE_PARTITION_START_ADDR >= MCUBOOT_SECONDARY_START_ADDR) && \
163+
(CODE_PARTITION_START_ADDR < MCUBOOT_SECONDARY_END_ADDR)
164+
#define DFU_SLOT_ID MCUBOOT_PRIMARY_SLOT_ID
165+
#else
166+
#error Missing partition definitions in DTS.
167+
#endif
138168
#endif
139169
#else
140170
#error Unsupported partitioning scheme.
@@ -208,6 +238,25 @@ static void config_channel_dfu_lock_release(void)
208238
}
209239
}
210240

241+
static uint8_t dfu_slot_id_get(void)
242+
{
243+
#if BUILD_TIME_DFU_SLOT_ID_INFO_IS_AVAILABLE
244+
return DFU_SLOT_ID;
245+
#else
246+
uint8_t active_slot_id;
247+
248+
/* Dynamic resolution of the DFU slot ID is supported only for MCUboot. */
249+
BUILD_ASSERT(IS_ENABLED(CONFIG_BOOTLOADER_MCUBOOT));
250+
251+
active_slot_id = boot_fetch_active_slot();
252+
__ASSERT_NO_MSG((active_slot_id == MCUBOOT_PRIMARY_SLOT_ID) ||
253+
(active_slot_id == MCUBOOT_SECONDARY_SLOT_ID));
254+
255+
return (active_slot_id == MCUBOOT_SECONDARY_SLOT_ID) ?
256+
MCUBOOT_PRIMARY_SLOT_ID : MCUBOOT_SECONDARY_SLOT_ID;
257+
#endif
258+
}
259+
211260
static bool is_page_clean(const struct flash_area *fa, off_t off, size_t len)
212261
{
213262
static const size_t chunk_size = FLASH_READ_CHUNK_SIZE;
@@ -298,7 +347,7 @@ static void background_erase_handler(struct k_work *work)
298347
}
299348

300349
if (!flash_area) {
301-
err = flash_area_open(DFU_SLOT_ID, &flash_area);
350+
err = flash_area_open(dfu_slot_id_get(), &flash_area);
302351
if (err) {
303352
LOG_ERR("Cannot open flash area (%d)", err);
304353
flash_area = NULL;
@@ -357,7 +406,7 @@ static void complete_dfu_data_store(void)
357406

358407
if (cur_offset == img_length) {
359408
LOG_INF("DFU image written");
360-
#if CONFIG_BOOTLOADER_MCUBOOT && !CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
409+
#if MCUBOOT_REVERT_FEATURE_IS_SUPPORTED
361410
int err = boot_request_upgrade(false);
362411
if (err) {
363412
LOG_ERR("Cannot request the image upgrade (err:%d)", err);
@@ -564,7 +613,7 @@ static void handle_dfu_start(const uint8_t *data, const size_t size)
564613
}
565614

566615
__ASSERT_NO_MSG(flash_area == NULL);
567-
int err = flash_area_open(DFU_SLOT_ID, &flash_area);
616+
int err = flash_area_open(dfu_slot_id_get(), &flash_area);
568617

569618
if (err) {
570619
LOG_ERR("Cannot open flash area (%d)", err);
@@ -721,7 +770,7 @@ static void handle_image_info_request(uint8_t *data, size_t *size)
721770
const struct fw_info *info;
722771
uint8_t flash_area_id;
723772

724-
if (DFU_SLOT_ID == PM_S1_IMAGE_ID) {
773+
if (dfu_slot_id_get() == PM_S1_IMAGE_ID) {
725774
info = fw_info_find(PM_S0_IMAGE_ADDRESS);
726775
flash_area_id = 0;
727776
} else {
@@ -779,7 +828,7 @@ static void handle_image_info_request(uint8_t *data, size_t *size)
779828
uint8_t flash_area_id;
780829
uint8_t bank_header_area_id;
781830

782-
if (DFU_SLOT_ID == MCUBOOT_SECONDARY_SLOT_ID) {
831+
if (dfu_slot_id_get() == MCUBOOT_SECONDARY_SLOT_ID) {
783832
flash_area_id = 0;
784833
bank_header_area_id = MCUBOOT_PRIMARY_SLOT_ID;
785834
} else {
@@ -902,15 +951,16 @@ static bool app_event_handler(const struct app_event_header *aeh)
902951

903952
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
904953
int err;
905-
#if CONFIG_BOOTLOADER_MCUBOOT && !CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
954+
955+
#if MCUBOOT_REVERT_FEATURE_IS_SUPPORTED
906956
err = boot_write_img_confirmed();
907957

908958
if (err) {
909959
LOG_ERR("Cannot confirm a running image");
910960
}
911961
#endif
912962

913-
err = flash_area_open(DFU_SLOT_ID, &flash_area);
963+
err = flash_area_open(dfu_slot_id_get(), &flash_area);
914964
if (!err) {
915965
flash_write_block_size = flash_area_align(flash_area);
916966
erased_val = flash_area_erased_val(flash_area);

0 commit comments

Comments
 (0)