Skip to content

Commit c6d0e27

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. Added a linker script with the assert statement that prevents the executable RAM region of the application image to overflow the standard RAM region of the MCUboot image. Ref: NCSDK-35506 Signed-off-by: Kamil Piszczek <[email protected]>
1 parent 15efef3 commit c6d0e27

File tree

4 files changed

+123
-16
lines changed

4 files changed

+123
-16
lines changed

applications/nrf_desktop/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,7 @@ if(CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE)
5454
INPUT "config_channel_modules"
5555
SYMBOLS __start_config_channel_modules __stop_config_channel_modules
5656
KEEP SORT NAME)
57+
if(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD)
58+
zephyr_linker_sources(RODATA linker/config_channel_dfu_ram_load.ld)
59+
endif()
5760
endif()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* Validate that the executable RAM region does not overlap with the MCUboot RAM region. */
2+
ASSERT(__rom_region_end <= CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD_MCUBOOT_RAM_START_ADDR,
3+
"The executable RAM region overlaps with the MCUboot RAM region");

applications/nrf_desktop/src/modules/Kconfig.config_channel

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,18 @@ 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"
76+
choice DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT
77+
prompt "Adjust the DFU module to be compatible with the specific mode of MCUboot"
7878
depends on BOOTLOADER_MCUBOOT
79-
default y if MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
79+
default DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP if MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
80+
default DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD if MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
81+
default DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_UNSPECIFIED
82+
help
83+
Adjust the DFU module behavior to the MCUboot bootloader mode. The choice options are
84+
only available for the bootloader modes that require adjustments.
85+
86+
config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
87+
bool "Adjust the DFU module to be compatible with the direct-xip mode of MCUboot"
8088
help
8189
The option informs the DFU module that the MCUboot bootloader supports
8290
direct-xip mode. In this mode, the image is booted directly from the
@@ -88,6 +96,46 @@ config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
8896
the image with a higher version. The module does not mark the newly
8997
uploaded image as pending nor confirm it after a successful boot.
9098

99+
config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
100+
bool "Adjust the DFU module to be compatible with the RAM load mode of MCUboot"
101+
depends on USE_DT_CODE_PARTITION
102+
depends on $(dt_nodelabel_exists,cpuapp_sram_mcuboot_ram_region)
103+
select EXPERIMENTAL
104+
help
105+
The option informs the DFU module that the MCUboot bootloader supports
106+
RAM load mode. In this mode, the image with the higher version is copied to
107+
the RAM and booted from there.
108+
109+
The DFU module assumes that MCUboot RAM load bootloader simply copies
110+
the image with a higher version and boots it from there. The module does not
111+
mark the newly uploaded image as pending nor confirm it after a successful boot.
112+
113+
This option also requires the definition of the cpuapp_sram_mcuboot_ram_region DTS node
114+
to indicate the RAM region reserved for the MCUboot image. This information is used to
115+
validate if the executable RAM region of the application image does not overlap with
116+
the RAM region of the MCUboot image.
117+
118+
config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_UNSPECIFIED
119+
bool "Use this option when the bootloader mode does not require any adjustments"
120+
help
121+
Use this option when the bootloader mode does not require any adjustments. For example,
122+
the bootloader in the swap mode defaults to this option as it does not require any
123+
adjustments.
124+
125+
endchoice
126+
127+
if DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
128+
129+
config DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD_MCUBOOT_RAM_START_ADDR
130+
hex
131+
default $(dt_nodelabel_reg_addr_hex,cpuapp_sram_mcuboot_ram_region)
132+
help
133+
The start address of the MCUboot RAM region. The Kconfig option is used to validate
134+
if the executable RAM region of the application image (also called the ROM section)
135+
does not overlap with the RAM region of the MCUboot image.
136+
137+
endif # DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
138+
91139
config DESKTOP_CONFIG_CHANNEL_DFU_VID
92140
hex "Configuration channel Vendor ID"
93141
range 0 0XFFFF

applications/nrf_desktop/src/modules/dfu.c

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
7272
#define BOOTLOADER_NAME "MCUBOOT"
7373
#endif
7474

75+
/* Validate the MCUboot bootloader mode compatibility with this DFU module. */
76+
#if CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
77+
BUILD_ASSERT(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP);
78+
#elif CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
79+
BUILD_ASSERT(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD);
80+
#else
81+
BUILD_ASSERT(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_UNSPECIFIED);
82+
#endif
83+
7584
#if CONFIG_PARTITION_MANAGER_ENABLED
7685
#include <pm_config.h>
7786

@@ -123,18 +132,28 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
123132
#define MCUBOOT_PRIMARY_SLOT_ID DT_FIXED_PARTITION_ID(MCUBOOT_PRIMARY_NODE)
124133
#define MCUBOOT_SECONDARY_SLOT_ID DT_FIXED_PARTITION_ID(MCUBOOT_SECONDARY_NODE)
125134

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
135+
136+
#if CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
137+
/* Use the macro alias for the DFU slot ID that needs to be set in runtime
138+
* when the MCUboot is configured for the RAM load mode.
139+
*/
140+
#define DFU_SLOT_ID_INVALID (0xFF)
141+
static uint8_t dfu_slot_id = DFU_SLOT_ID_INVALID;
142+
#define DFU_SLOT_ID (dfu_slot_id)
136143
#else
137-
#error Missing partition definitions in DTS.
144+
/* Use range check to allow for placing MCUboot header in a separate
145+
* partition,so the application code partition is not an alias for the
146+
* MCUboot partition, but a subpartition of the MCUboot partition.
147+
*/
148+
#if (CODE_PARTITION_START_ADDR >= MCUBOOT_PRIMARY_START_ADDR) && \
149+
(CODE_PARTITION_START_ADDR < MCUBOOT_PRIMARY_END_ADDR)
150+
#define DFU_SLOT_ID MCUBOOT_SECONDARY_SLOT_ID
151+
#elif (CODE_PARTITION_START_ADDR >= MCUBOOT_SECONDARY_START_ADDR) && \
152+
(CODE_PARTITION_START_ADDR < MCUBOOT_SECONDARY_END_ADDR)
153+
#define DFU_SLOT_ID MCUBOOT_PRIMARY_SLOT_ID
154+
#else
155+
#error Missing partition definitions in DTS.
156+
#endif
138157
#endif
139158
#else
140159
#error Unsupported partitioning scheme.
@@ -143,6 +162,15 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_LOG_LEVEL);
143162
#error Bootloader not supported.
144163
#endif
145164

165+
/* This value denotes whether the revert feature is supported by the bootloader.
166+
* Currently, the revert feature is only supported by the MCUboot bootloader that
167+
* is not configured for the standard direct-xip or RAM load mode.
168+
*/
169+
#define DFU_REVERT_FEATURE_IS_SUPPORTED \
170+
(CONFIG_BOOTLOADER_MCUBOOT) && \
171+
!(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP) && \
172+
!(CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD)
173+
146174
static struct k_work_delayable dfu_timeout;
147175
static struct k_work_delayable reboot_request;
148176
static struct k_work_delayable background_erase;
@@ -357,7 +385,7 @@ static void complete_dfu_data_store(void)
357385

358386
if (cur_offset == img_length) {
359387
LOG_INF("DFU image written");
360-
#if CONFIG_BOOTLOADER_MCUBOOT && !CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
388+
#if DFU_REVERT_FEATURE_IS_SUPPORTED
361389
int err = boot_request_upgrade(false);
362390
if (err) {
363391
LOG_ERR("Cannot request the image upgrade (err:%d)", err);
@@ -879,6 +907,26 @@ static void fetch_config(const uint8_t opt_id, uint8_t *data, size_t *size)
879907
}
880908
}
881909

910+
#if CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
911+
static void dfu_slot_id_runtime_init(void)
912+
{
913+
uint8_t active_slot_id;
914+
915+
__ASSERT_NO_MSG(dfu_slot_id == DFU_SLOT_ID_INVALID);
916+
917+
active_slot_id = boot_fetch_active_slot();
918+
dfu_slot_id = (active_slot_id == MCUBOOT_SECONDARY_SLOT_ID) ?
919+
MCUBOOT_PRIMARY_SLOT_ID : MCUBOOT_SECONDARY_SLOT_ID;
920+
921+
__ASSERT_NO_MSG(dfu_slot_id != DFU_SLOT_ID_INVALID);
922+
__ASSERT_NO_MSG((active_slot_id == MCUBOOT_PRIMARY_SLOT_ID) ||
923+
(active_slot_id == MCUBOOT_SECONDARY_SLOT_ID));
924+
925+
LOG_INF("DFU slot configured in runtime for the %s slot",
926+
dfu_slot_id == MCUBOOT_PRIMARY_SLOT_ID ? "primary" : "secondary");
927+
}
928+
#endif
929+
882930
static bool app_event_handler(const struct app_event_header *aeh)
883931
{
884932
if (is_hid_report_event(aeh)) {
@@ -902,7 +950,12 @@ static bool app_event_handler(const struct app_event_header *aeh)
902950

903951
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
904952
int err;
905-
#if CONFIG_BOOTLOADER_MCUBOOT && !CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_DIRECT_XIP
953+
954+
#if CONFIG_DESKTOP_CONFIG_CHANNEL_DFU_MCUBOOT_RAM_LOAD
955+
dfu_slot_id_runtime_init();
956+
#endif
957+
958+
#if DFU_REVERT_FEATURE_IS_SUPPORTED
906959
err = boot_write_img_confirmed();
907960

908961
if (err) {

0 commit comments

Comments
 (0)