Skip to content

Commit 9bcb019

Browse files
committed
ab_split: Enable boot preference persistance
Add additional region to keep the value of boot preference across reboots. Ref: NCSDK-35479 Signed-off-by: Tomasz Chyrowicz <[email protected]>
1 parent 49e7512 commit 9bcb019

File tree

5 files changed

+101
-103
lines changed

5 files changed

+101
-103
lines changed

samples/dfu/ab_split/README.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ The following conditions decide which slot is considered *active* and is booted
8383
#. For all other images, the same slot is selected.
8484

8585
You can set the preferred slot using the ``boot_request_set_preferred_slot`` function.
86-
Currently, this only sets the boot preference for a single reboot.
86+
If the :kconfig:option:`CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP` option is enabled, the slot preference remains persistent across reboots..
87+
Otherwise, the slot preference is cleared on reboot.
88+
To enable the persistence of a preferred slot, define a backup region for the bootloader request area by using the ``nrf,bootloader-request-backup`` chosen node in the devicetree.
8789

8890
Identifying the active slot
8991
---------------------------

samples/dfu/ab_split/prj.conf

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,9 @@ CONFIG_MCUBOOT_UTIL_LOG_LEVEL_WRN=y
4141
# Disable debug logging
4242
CONFIG_LOG_MAX_LEVEL=3
4343

44-
# Enable boot requests through retained memory.
45-
CONFIG_RETAINED_MEM=y
46-
CONFIG_RETENTION=y
44+
# Enable boot requests.
4745
CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y
4846

49-
CONFIG_RETENTION_BOOT_MODE=y
50-
CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE=y
51-
5247
# Enable DK LED/button library
5348
CONFIG_DK_LIBRARY=y
5449

@@ -102,5 +97,7 @@ CONFIG_DEVMEM_SHELL=n
10297
CONFIG_FLASH_SHELL=n
10398

10499
# Read bootloader version and security counters values from the retained RAM
100+
CONFIG_RETAINED_MEM=y
101+
CONFIG_RETENTION=y
105102
CONFIG_RETENTION_BOOTLOADER_INFO=y
106103
CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT=y

samples/dfu/ab_split/src/ab_utils.c

Lines changed: 81 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,11 @@
1414

1515
LOG_MODULE_DECLARE(ab_sample);
1616

17-
#define ACTIVE_IMAGE 0
18-
1917
#define CODE_PARTITION DT_CHOSEN(zephyr_code_partition)
2018
#define CODE_PARTITION_OFFSET FIXED_PARTITION_NODE_OFFSET(CODE_PARTITION)
2119

2220
#define SLOT_A_PARTITION cpuapp_slot0_partition
2321
#define SLOT_B_PARTITION cpuapp_slot1_partition
24-
#define CPURAD_SLOT_A_PARTITION cpurad_slot0_partition
25-
#define CPURAD_SLOT_B_PARTITION cpurad_slot1_partition
2622

2723
#define SLOT_A_OFFSET FIXED_PARTITION_OFFSET(SLOT_A_PARTITION)
2824
#define SLOT_B_OFFSET FIXED_PARTITION_OFFSET(SLOT_B_PARTITION)
@@ -31,8 +27,6 @@ LOG_MODULE_DECLARE(ab_sample);
3127

3228
#define SLOT_A_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT_A_PARTITION)
3329
#define SLOT_B_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT_B_PARTITION)
34-
#define CPURAD_SLOT_A_FLASH_AREA_ID FIXED_PARTITION_ID(CPURAD_SLOT_A_PARTITION)
35-
#define CPURAD_SLOT_B_FLASH_AREA_ID FIXED_PARTITION_ID(CPURAD_SLOT_B_PARTITION)
3630

3731
#define IS_SLOT_A \
3832
(CODE_PARTITION_OFFSET >= SLOT_A_OFFSET && \
@@ -45,12 +39,6 @@ LOG_MODULE_DECLARE(ab_sample);
4539
#define STATUS_LEDS_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1)
4640
K_THREAD_STACK_DEFINE(status_leds_thread_stack_area, STATUS_LEDS_THREAD_STACK_SIZE);
4741

48-
enum ab_boot_slot {
49-
SLOT_A = 0,
50-
SLOT_B = 1,
51-
SLOT_INVALID,
52-
};
53-
5442
/** @brief Radio firmware self test
5543
*
5644
* @details
@@ -78,44 +66,79 @@ static bool app_domain_healthy(void)
7866
return true;
7967
}
8068

81-
static enum ab_boot_slot active_boot_slot_get(void)
69+
static enum boot_slot active_boot_slot_get(void)
8270
{
83-
enum ab_boot_slot active_slot = SLOT_INVALID;
71+
enum boot_slot active_slot = BOOT_SLOT_NONE;
8472

8573
if (IS_SLOT_A) {
86-
active_slot = SLOT_A;
74+
active_slot = BOOT_SLOT_PRIMARY;
8775
} else if (IS_SLOT_B) {
88-
active_slot = SLOT_B;
76+
active_slot = BOOT_SLOT_SECONDARY;
8977
} else {
9078
LOG_ERR("Cannot determine current slot");
9179
}
9280

9381
return active_slot;
9482
}
9583

96-
static void device_healthcheck(void)
84+
static bool slot_confirmed(enum boot_slot slot)
9785
{
98-
int err;
99-
char *img_set = NULL;
86+
struct boot_swap_state state;
10087
const struct flash_area *fa;
10188
int area_id = -1;
102-
int cpurad_area_id = -1;
103-
enum ab_boot_slot active_slot = active_boot_slot_get();
104-
105-
if (active_slot == SLOT_INVALID) {
106-
return;
107-
}
89+
char *img_set = NULL;
90+
bool confirmed = false;
91+
int ret;
10892

109-
/* Confirming only in non-degraded boot states
110-
*/
111-
if (active_slot == SLOT_A) {
93+
if (slot == BOOT_SLOT_PRIMARY) {
11294
img_set = "A";
11395
area_id = SLOT_A_FLASH_AREA_ID;
114-
cpurad_area_id = CPURAD_SLOT_A_FLASH_AREA_ID;
115-
} else if (active_slot == SLOT_B) {
96+
} else if (slot == BOOT_SLOT_SECONDARY) {
11697
img_set = "B";
11798
area_id = SLOT_B_FLASH_AREA_ID;
118-
cpurad_area_id = CPURAD_SLOT_B_FLASH_AREA_ID;
99+
} else {
100+
LOG_ERR("Cannot determine slot to check for confirmation");
101+
return false;
102+
}
103+
104+
if (flash_area_open(area_id, &fa) != 0) {
105+
LOG_ERR("Cannot open flash area for slot %s", img_set);
106+
return false;
107+
}
108+
109+
ret = boot_read_swap_state(fa, &state);
110+
if (ret != 0) {
111+
LOG_ERR("Cannot read swap state for slot %s", img_set);
112+
} else if (state.image_ok == BOOT_FLAG_SET) {
113+
confirmed = true;
114+
} else {
115+
confirmed = false;
116+
}
117+
118+
flash_area_close(fa);
119+
120+
return confirmed;
121+
}
122+
123+
static void device_healthcheck(void)
124+
{
125+
int err;
126+
char *img_set = NULL;
127+
enum boot_slot active_slot = active_boot_slot_get();
128+
129+
/* Confirming only in non-degraded boot states */
130+
if (active_slot == BOOT_SLOT_PRIMARY) {
131+
img_set = "A";
132+
} else if (active_slot == BOOT_SLOT_SECONDARY) {
133+
img_set = "B";
134+
} else {
135+
LOG_ERR("Cannot determine active slot for health check");
136+
return;
137+
}
138+
139+
if (slot_confirmed(active_slot)) {
140+
LOG_INF("Slot %s already confirmed, no action needed", img_set);
141+
return;
119142
}
120143

121144
LOG_INF("Testing image set %s...", img_set);
@@ -139,54 +162,40 @@ static void device_healthcheck(void)
139162

140163
LOG_INF("Confirming...");
141164

142-
if (flash_area_open(area_id, &fa) != 0) {
143-
LOG_ERR("Cannot open flash area for application slot %s", img_set);
144-
return;
145-
}
146-
147-
err = boot_set_next(fa, true, true);
148-
149-
flash_area_close(fa);
150-
if (err == 0) {
151-
LOG_INF("Application confirmed\n");
152-
} else {
153-
LOG_ERR("Failed to confirm application, err: %d", err);
154-
}
155-
156-
if (flash_area_open(cpurad_area_id, &fa) != 0) {
157-
LOG_ERR("Cannot open flash area for radio slot %s", img_set);
158-
return;
159-
}
160-
161-
err = boot_set_next(fa, true, true);
162-
163-
flash_area_close(fa);
165+
err = boot_request_confirm_slot(CONFIG_NCS_MCUBOOT_MANIFEST_IMAGE_INDEX, active_slot);
164166
if (err == 0) {
165-
LOG_INF("Radio confirmed\n");
167+
LOG_INF("Confirmed\n");
166168
} else {
167-
LOG_ERR("Failed to confirm radio, err: %d", err);
169+
LOG_ERR("Failed to confirm, err: %d", err);
168170
}
169171
}
170172

171-
static void select_slot_for_single_boot(enum ab_boot_slot slot)
173+
static void select_slot_for_single_boot(enum boot_slot slot)
172174
{
173175
int err = 0;
174-
char active_slot = (active_boot_slot_get() == SLOT_A) ? 'A' : 'B';
175-
enum boot_slot new_slot = BOOT_SLOT_NONE;
176+
char active_slot = (active_boot_slot_get() == BOOT_SLOT_PRIMARY) ? 'A' : 'B';
176177

177-
if (slot == SLOT_A) {
178+
#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP
179+
if (slot == BOOT_SLOT_PRIMARY) {
180+
LOG_INF("Switching slots (%c -> A)", active_slot);
181+
} else if (slot == BOOT_SLOT_SECONDARY) {
182+
LOG_INF("Switching slots (%c -> B)", active_slot);
183+
} else {
184+
LOG_ERR("Cannot determine active slot, cannot toggle");
185+
return;
186+
}
187+
#else
188+
if (slot == BOOT_SLOT_PRIMARY) {
178189
LOG_INF("Temporarily switching slots (%c -> A)", active_slot);
179-
new_slot = BOOT_SLOT_PRIMARY;
180-
} else if (slot == SLOT_B) {
190+
} else if (slot == BOOT_SLOT_SECONDARY) {
181191
LOG_INF("Temporarily switching slots (%c -> B)", active_slot);
182-
new_slot = BOOT_SLOT_SECONDARY;
183192
} else {
184193
LOG_ERR("Cannot determine active slot, cannot toggle");
185194
return;
186195
}
196+
#endif
187197

188-
err = boot_request_set_preferred_slot(ACTIVE_IMAGE, new_slot);
189-
198+
err = boot_request_set_preferred_slot(CONFIG_NCS_MCUBOOT_MANIFEST_IMAGE_INDEX, slot);
190199
if (err == 0) {
191200
LOG_INF("Slot toggled, restart the device to enforce");
192201
} else {
@@ -196,11 +205,11 @@ static void select_slot_for_single_boot(enum ab_boot_slot slot)
196205

197206
static void boot_state_report(void)
198207
{
199-
enum ab_boot_slot active_slot = active_boot_slot_get();
208+
enum boot_slot active_slot = active_boot_slot_get();
200209

201-
if (active_slot == SLOT_A) {
210+
if (active_slot == BOOT_SLOT_PRIMARY) {
202211
LOG_INF("Booted from slot A");
203-
} else if (active_slot == SLOT_B) {
212+
} else if (active_slot == BOOT_SLOT_SECONDARY) {
204213
LOG_INF("Booted from slot B");
205214
} else {
206215
LOG_INF("Cannot determine active slot");
@@ -210,9 +219,9 @@ static void boot_state_report(void)
210219
static void button_handler(uint32_t button_state, uint32_t has_changed)
211220
{
212221
if ((has_changed & DK_BTN1_MSK) && (button_state & DK_BTN1_MSK)) {
213-
select_slot_for_single_boot(SLOT_A);
222+
select_slot_for_single_boot(BOOT_SLOT_PRIMARY);
214223
} else if ((has_changed & DK_BTN2_MSK) && (button_state & DK_BTN2_MSK)) {
215-
select_slot_for_single_boot(SLOT_B);
224+
select_slot_for_single_boot(BOOT_SLOT_SECONDARY);
216225
}
217226
}
218227

@@ -221,11 +230,11 @@ struct k_thread status_leds_thread_data;
221230
static void status_leds_thread_entry_point(void *p1, void *p2, void *p3)
222231
{
223232
int blinking_led = DK_LED1;
224-
enum ab_boot_slot active_slot = active_boot_slot_get();
233+
enum boot_slot active_slot = active_boot_slot_get();
225234

226-
if (active_slot == SLOT_A) {
235+
if (active_slot == BOOT_SLOT_PRIMARY) {
227236
blinking_led = DK_LED1;
228-
} else if (active_slot == SLOT_B) {
237+
} else if (active_slot == BOOT_SLOT_SECONDARY) {
229238
blinking_led = DK_LED2;
230239
} else {
231240
return;

samples/dfu/ab_split/sysbuild/mcuboot/prj.conf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# Enable boot requests through retained memory.
2-
CONFIG_RETAINED_MEM=y
3-
CONFIG_RETENTION=y
1+
# Enable boot requests.
2+
CONFIG_CRC=y
43
CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y
54

65
CONFIG_NRF_SECURITY=y
@@ -32,6 +31,8 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0
3231
CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot"
3332

3433
# Expose bootloader version and security counter through retention
34+
CONFIG_RETAINED_MEM=y
35+
CONFIG_RETENTION=y
3536
CONFIG_BOOT_SHARE_DATA=y
3637
CONFIG_BOOT_SHARE_DATA_BOOTINFO=y
3738
CONFIG_BOOT_SHARE_BACKEND_RETENTION=y

samples/dfu/ab_split/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,24 @@
77
/ {
88
chosen {
99
nrf,bootloader-request = &boot_request;
10+
nrf,bootloader-request-backup = &boot_request_backup;
1011
zephyr,bootloader-info = &boot_info0;
1112
};
1213
};
1314

14-
/ {
15-
reserved-memory {
16-
cpuapp_retained_mem: memory@e1ad000 {
17-
compatible = "zephyr,memory-region";
18-
reg = <0xe1ad000 DT_SIZE_K(4)>;
19-
zephyr,memory-region = "RetainedNvm";
20-
status = "okay";
21-
22-
retainedmem {
23-
compatible = "zephyr,retained-ram";
24-
status = "okay";
25-
#address-cells = <1>;
26-
#size-cells = <1>;
15+
&mram1x {
16+
partitions {
17+
boot_request: partition@1ad000 {
18+
reg = <0x1ad000 16>;
19+
};
2720

28-
boot_request: boot_request@0 {
29-
compatible = "zephyr,retention";
30-
status = "okay";
31-
reg = <0x0 16>;
32-
prefix = [0B 01];
33-
checksum = <4>;
34-
};
35-
};
21+
boot_request_backup: partition@1ad010 {
22+
reg = <0x1ad010 16>;
3623
};
3724
};
25+
};
3826

27+
/ {
3928
sram@22007FC0 {
4029
compatible = "zephyr,memory-region", "mmio-sram";
4130
reg = <0x22007FC0 0x40>;

0 commit comments

Comments
 (0)