Skip to content

Commit 5e71661

Browse files
committed
samples: boards: nordic: add sample for secondary boot
Add a sample that demonstrates how a secondary boot image could be built. Signed-off-by: Sebastian Bøe <[email protected]>
1 parent ec1ffaf commit 5e71661

File tree

10 files changed

+254
-0
lines changed

10 files changed

+254
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.13.1)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
11+
project(secondary_boot_primary)
12+
13+
target_sources(app PRIVATE
14+
src/main.c
15+
)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
.. zephyr:code-sample:: secondary_boot_corruption
2+
:name: Secondary Boot Corruption Sample
3+
:relevant-to: nrf54h20dk
4+
5+
Demonstrate secondary image boot after primary image corruption
6+
7+
Overview
8+
********
9+
10+
This sample demonstrates the secondary boot functionality on nRF54H20DK when the
11+
primary image is corrupted. The sample consists of two applications that work
12+
together to show how the system can recover from primary image corruption by
13+
booting a secondary image.
14+
15+
The sample uses UICR (User Information Configuration Registers) to configure
16+
secondary boot and protected memory regions, then intentionally corrupts the
17+
primary image to trigger a reboot to the secondary image.
18+
19+
Architecture
20+
************
21+
22+
The sample consists of three components:
23+
24+
* **Primary Image**: Runs initially on the application core (cpuapp), prints a
25+
hello world message, corrupts protected memory, and reboots the system.
26+
27+
* **Secondary Image**: Runs on the same application core (cpuapp) after the
28+
primary image corruption triggers a reboot. Prints its own hello world message
29+
and continues running with periodic heartbeat messages.
30+
31+
* **UICR Image**: Generates UICR configuration that enables secondary boot and
32+
protected memory regions.
33+
34+
Requirements
35+
************
36+
37+
* nRF54H20DK board
38+
* Zephyr SDK 0.17.0 or later
39+
40+
Building and Running
41+
********************
42+
43+
This sample uses :ref:`sysbuild` to build multiple images. The ``--sysbuild``
44+
flag is required.
45+
46+
Build the sample:
47+
48+
.. zephyr-app-commands::
49+
:zephyr-app: samples/boards/nordic/nrf_ironside/secondary_boot_corruption
50+
:board: nrf54h20dk/nrf54h20/cpuapp
51+
:west-args: --sysbuild
52+
:goals: build
53+
54+
Flash the sample:
55+
56+
.. zephyr-app-commands::
57+
:zephyr-app: samples/boards/nordic/nrf_ironside/secondary_boot_corruption
58+
:board: nrf54h20dk/nrf54h20/cpuapp
59+
:west-args: --sysbuild
60+
:goals: flash
61+
62+
Sample Output
63+
*************
64+
65+
When the sample runs successfully, you should see output similar to the following:
66+
67+
.. code-block:: console
68+
69+
*** Booting Zephyr OS build v4.2.99 ***
70+
=== Hello World from Primary Image ===
71+
Rebooting
72+
*** Booting Zephyr OS build v4.2.99 ***
73+
=== Hello World from Secondary Image ===
74+
Secondary image heartbeat
75+
Secondary image heartbeat
76+
...
77+
78+
How It Works
79+
************
80+
81+
1. The primary image starts and prints a hello world message.
82+
83+
2. The primary image intentionally corrupts protected memory regions by writing
84+
specific values to memory addresses. This is only possible because the MPU
85+
(Memory Protection Unit) is disabled in the configuration.
86+
87+
3. The primary image triggers a system reset.
88+
89+
4. During the next boot, the system detects the corruption and boots the
90+
secondary image instead of the primary image.
91+
92+
5. The secondary image starts and prints its own hello world message, then
93+
continues running with periodic heartbeat messages.
94+
95+
Configuration
96+
*************
97+
98+
The sample uses the following key configurations:
99+
100+
* ``CONFIG_ARM_MPU=n``: Disables the MPU to allow memory corruption
101+
* ``CONFIG_GEN_UICR_SECONDARY=y``: Enables secondary boot in UICR
102+
* ``CONFIG_GEN_UICR_PROTECTEDMEM=y``: Enables protected memory in UICR
103+
* ``CONFIG_FLASH_LOAD_OFFSET=0x1b0000``: Places secondary image at correct address
104+
105+
Memory Layout
106+
*************
107+
108+
* **Primary Image**: Located at ``0xe030000`` (default slot0_partition)
109+
* **Secondary Image**: Located at ``0xe1b0000`` (secondary_partition)
110+
* **UICR Configuration**: Generated and placed at ``0xfff8000``
111+
112+
Dependencies
113+
************
114+
115+
This sample uses the following Zephyr subsystems:
116+
117+
* :ref:`sysbuild` for multi-image builds
118+
* UICR generation system for configuration
119+
* Device tree for memory layout configuration
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# Disable the MPU to allow the sample to corrupt itself
8+
CONFIG_ARM_MPU=n
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sample:
2+
name: Secondary Boot Corruption Sample
3+
description: |
4+
Demonstrates secondary image boot after primary image corruption on nRF54H20DK.
5+
The primary image corrupts protected memory and reboots, triggering the system
6+
to boot the secondary image instead.
7+
8+
common:
9+
sysbuild: true
10+
harness: console
11+
harness_config:
12+
type: multi_line
13+
regex:
14+
- "=== Hello World from Primary Image ==="
15+
- "=== Hello World from Secondary Image ==="
16+
17+
tests:
18+
sample.boards.nordic.nrf_ironside.secondary_boot_corruption:
19+
tags:
20+
- sysbuild
21+
- nrf_ironside
22+
platform_allow:
23+
- nrf54h20dk/nrf54h20/cpuapp
24+
integration_platforms:
25+
- nrf54h20dk/nrf54h20/cpuapp
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
cmake_minimum_required(VERSION 3.13.1)
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(secondary_boot_secondary)
7+
8+
# Create marker file to identify this as secondary firmware
9+
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/is_secondary_firmware.txt "")
10+
11+
target_sources(app PRIVATE src/main.c)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
# NB: Must match secondary_partition in DT
8+
# Secondary partition is at 0x1b0000
9+
CONFIG_FLASH_LOAD_OFFSET=0x1b0000
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/printk.h>
9+
10+
int main(void)
11+
{
12+
printk("=== Hello World from Secondary Image ===\n");
13+
14+
while (1) {
15+
k_msleep(3000);
16+
printk("Secondary image heartbeat\n");
17+
}
18+
19+
return 0;
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/printk.h>
9+
#include <zephyr/sys/reboot.h>
10+
#include <string.h>
11+
12+
int main(void)
13+
{
14+
printk("=== Hello World from Primary Image ===\n");
15+
16+
/* Corrupt the protected memory (This is only possible because we
17+
* have disabled CONFIG_ARM_MPU).
18+
*/
19+
*((volatile uint32_t *)0xe030000) = 0x5EB0;
20+
*((volatile uint32_t *)0xe030004) = 0x5EB0;
21+
*((volatile uint32_t *)0xe030008) = 0x5EB0;
22+
*((volatile uint32_t *)0xe030010) = 0x5EB0;
23+
24+
printk("Rebooting\n");
25+
26+
sys_reboot(SYS_REBOOT_COLD);
27+
28+
return 0;
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
ExternalZephyrProject_Add(
5+
APPLICATION secondary
6+
SOURCE_DIR ${APP_DIR}/secondary
7+
BOARD nrf54h20dk/nrf54h20/cpuapp
8+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
# Configuration overlay for uicr image
5+
# Enable UICR.SECONDARY.ENABLE
6+
CONFIG_GEN_UICR_SECONDARY=y
7+
8+
# Enable UICR protected memory
9+
CONFIG_GEN_UICR_PROTECTEDMEM=y
10+
CONFIG_GEN_UICR_PROTECTEDMEM_SIZE_BYTES=4096

0 commit comments

Comments
 (0)