diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst index 8791a9261744..0e952101bd81 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst @@ -781,6 +781,11 @@ For more information on the boot sequence, see :ref:`ug_nrf54h20_architecture_bo The term "secondary slot" and "secondary image" are used in the MCUboot context. This usage is unrelated to the "secondary firmware" described in this section. +Sample +====== + +For an example of how to create a secondary image with automatic triggers, see the :ref:`secondary_boot_trigger_lockup_sample` sample. + .. _ug_nrf54h20_ironside_se_secondary_conf_trigger: Configuration and triggering diff --git a/samples/ironside_se/secondary_boot_gen_uicr/README.rst b/samples/ironside_se/secondary_boot_gen_uicr/README.rst index 3b3c657fdf3c..709de9a8b00a 100644 --- a/samples/ironside_se/secondary_boot_gen_uicr/README.rst +++ b/samples/ironside_se/secondary_boot_gen_uicr/README.rst @@ -52,7 +52,6 @@ After programming the test to your development kit, complete the following steps #. Reset the kit. #. Observe the console output for both cores: - .. code-block:: console [00:00:00.123,456] === Hello World from Primary Image === diff --git a/samples/ironside_se/secondary_boot_gen_uicr/sample.yaml b/samples/ironside_se/secondary_boot_gen_uicr/sample.yaml index 871bd4045cf8..268ad1f1d9f4 100644 --- a/samples/ironside_se/secondary_boot_gen_uicr/sample.yaml +++ b/samples/ironside_se/secondary_boot_gen_uicr/sample.yaml @@ -19,7 +19,7 @@ tests: samples.secondary_boot.nrf54h20dk: tags: - sysbuild - - ci_samples_secondary_boot + - ci_samples_sdfw platform_allow: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/CMakeLists.txt b/samples/ironside_se/secondary_boot_trigger_lockup/CMakeLists.txt new file mode 100644 index 000000000000..74065accc71e --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(secondary_boot_trigger_lockup) + +# Source files +target_sources(app PRIVATE src/main.c) diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/README.rst b/samples/ironside_se/secondary_boot_trigger_lockup/README.rst new file mode 100644 index 000000000000..de65ded76b95 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/README.rst @@ -0,0 +1,109 @@ +.. _secondary_boot_trigger_lockup_sample: + +Secondary boot with APPLICATIONLOCKUP trigger +############################################## + +.. contents:: + :local: + :depth: 2 + +This sample demonstrates an automatic secondary boot triggered by a lockup of the application core CPU on the nRF54H20 DK. +When the primary application triggers a CPU lockup, IronSide SE automatically boots the secondary image without requiring any application-level software intervention. + +Requirements +************ + +The sample supports the following development kit: + +.. table-from-sample-yaml:: + +Overview +******** + +The sample consists of two applications: + +* *Primary Image*: Runs initially on the application core (``cpuapp``), prints status messages, and deliberately triggers a CPU lockup by disabling fault exceptions and then causing a fault. +* *Secondary Image*: Automatically boots after the lockup is detected and runs continuously. + +The UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP configuration causes IronSide SE to automatically boot the secondary image when a CPU lockup is detected. + +Configuration +************* + +The sample uses the following UICR configuration in the :file:`sysbuild/uicr.conf` file: + +.. code-block:: kconfig + + CONFIG_GEN_UICR_SECONDARY=y + CONFIG_GEN_UICR_SECONDARY_TRIGGER=y + CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONLOCKUP=y + +This enables automatic secondary boot when the application core experiences a CPU lockup. + +For more information about secondary firmware configuration and other available triggers, see :ref:`ug_nrf54h20_ironside_se_secondary_firmware`. + +Building and running +******************** + +.. |sample path| replace:: :file:`samples/ironside_se/secondary_boot_trigger_lockup` + +.. include:: /includes/build_and_run_ns.txt + +To build the sample for the nRF54H20 DK, run the following command: + +.. code-block:: console + + west build -b nrf54h20dk/nrf54h20/cpuapp samples/ironside_se/secondary_boot_trigger_lockup + +To program the sample on the device, run the following command: + +.. code-block:: console + + west flash + +Testing +******* + +After programming the sample to your development kit, complete the following steps to test it: + +1. |connect_terminal| +#. Reset the kit. +#. Observe in the console output the primary image startup and lockup trigger: + + .. code-block:: console + + === Primary Image: Demonstrating APPLICATIONLOCKUP trigger === + This image will intentionally trigger a CPU lockup. + The UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP configuration will + automatically boot the secondary image. + + Triggering CPU lockup now! + Step 1: Disabling fault exceptions and then accessing invalid memory... + +#. Observe in the console output that the system automatically reboots into the secondary image: + + .. code-block:: console + + === Secondary Image: Successfully booted! === + The system automatically booted the secondary image due to + APPLICATION LOCKUP in the primary image. + + This demonstrates UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP + automatic failover capability. + + Secondary image heartbeat - system is stable + Secondary image heartbeat - system is stable + ... + +Dependencies +************ + +This sample uses the following |NCS| subsystems: + +* Sysbuild - Enables building multiple images in a single build process +* UICR generation - Configures the User Information Configuration Registers for automatic secondary boot on lockup + +In addition, it uses the following Zephyr subsystems: + +* :ref:`Kernel ` - Provides basic system functionality and threading +* :ref:`Console ` - Enables UART console output for debugging and user interaction diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/prj.conf b/samples/ironside_se/secondary_boot_trigger_lockup/prj.conf new file mode 100644 index 000000000000..1617178f6f40 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/prj.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# This file is intentionally left empty diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/sample.yaml b/samples/ironside_se/secondary_boot_trigger_lockup/sample.yaml new file mode 100644 index 000000000000..2d7d9f909251 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/sample.yaml @@ -0,0 +1,26 @@ +sample: + name: Secondary Boot APPLICATIONLOCKUP Trigger Sample + description: | + Sample demonstrating automatic secondary boot triggered by APPLICATIONLOCKUP + on nRF54H20DK. The primary image deliberately triggers a CPU lockup, and the + UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP configuration causes IronSide SE to + automatically boot the secondary image. + +common: + sysbuild: true + harness: console + harness_config: + type: multi_line + regex: + - "=== Primary Image: Demonstrating APPLICATIONLOCKUP trigger ===" + - "=== Secondary Image: Successfully booted! ===" + +tests: + samples.secondary_boot_trigger_lockup.nrf54h20dk: + tags: + - sysbuild + - ci_samples_sdfw + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/secondary/CMakeLists.txt b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/CMakeLists.txt new file mode 100644 index 000000000000..3c70a0d2e7e4 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(secondary_image) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/secondary/app.overlay b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/app.overlay new file mode 100644 index 000000000000..c8b66d51a8b3 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/app.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + zephyr,code-partition = &secondary_partition; + }; +}; diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/secondary/prj.conf b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/prj.conf new file mode 100644 index 000000000000..63e151e4a158 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/prj.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_IS_IRONSIDE_SE_SECONDARY_IMAGE=y + +# Use the devicetree chosen code-partition to determine flash load offset +CONFIG_USE_DT_CODE_PARTITION=y + +# NB: app.overlay sets zephyr,code-partition to secondary_partition diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/secondary/src/main.c b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/src/main.c new file mode 100644 index 000000000000..efc89921f179 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/secondary/src/main.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +int main(void) +{ + printk("\n=== Secondary Image: Successfully booted! ===\n"); + printk("The system automatically booted the secondary image due to\n"); + printk("APPLICATION LOCKUP in the primary image.\n"); + printk("\nThis demonstrates UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP\n"); + printk("automatic failover capability.\n"); + + /* Secondary firmware runs continuously */ + while (1) { + k_msleep(5000); + printk("Secondary image heartbeat - system is stable\n"); + } + + return 0; +} diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/src/main.c b/samples/ironside_se/secondary_boot_trigger_lockup/src/main.c new file mode 100644 index 000000000000..606a28c9651d --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/src/main.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +int main(void) +{ + printk("=== Primary Image: Demonstrating APPLICATIONLOCKUP trigger ===\n"); + printk("This image will intentionally trigger a CPU lockup.\n"); + printk("The UICR.SECONDARY.TRIGGER.APPLICATIONLOCKUP configuration will\n"); + printk("automatically boot the secondary image.\n"); + printk("\nTriggering CPU lockup now!\n"); + printk("Step 1: Disabling fault exceptions and then accessing invalid memory...\n"); + + /* Set FAULTMASK to disable all exceptions except NMI. + * Then trigger a fault - since faults are disabled, this causes lockup. + * Any fault (unaligned access, invalid memory, etc.) will trigger lockup. + */ + __asm volatile("cpsid f" ::: "memory"); + + /* Trigger fault by accessing invalid memory */ + *(volatile uint32_t *)0xFFFFFFFF = 0xDEADBEEF; + + /* This line will never be reached */ + printk("ERROR: Should have triggered lockup!\n"); + + return 0; +} diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild.cmake b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild.cmake new file mode 100644 index 000000000000..4e600e2f11e6 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +ExternalZephyrProject_Add( + APPLICATION secondary + SOURCE_DIR ${APP_DIR}/secondary + ) diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf new file mode 100644 index 000000000000..929e422b1c96 --- /dev/null +++ b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf @@ -0,0 +1,8 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +# Configuration overlay for uicr image +# Enable UICR.SECONDARY with automatic trigger on APPLICATIONLOCKUP +CONFIG_GEN_UICR_SECONDARY=y +CONFIG_GEN_UICR_SECONDARY_TRIGGER=y +CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONLOCKUP=y diff --git a/scripts/ci/tags.yaml b/scripts/ci/tags.yaml index 146c5e643f0f..7b811e3bbab3 100644 --- a/scripts/ci/tags.yaml +++ b/scripts/ci/tags.yaml @@ -1504,7 +1504,7 @@ ci_samples_sdfw: - modules/hal/nordic/nrfs/ - modules/hal/nordic/nrfx/ - modules/lib/zcbor/ - - nrf/samples/sdfw/ + - nrf/samples/ironside_se/ - nrf/subsys/nrf_rpc/ - nrf/subsys/sdfw_services/ - nrfxlib/nrf_rpc/ diff --git a/west.yml b/west.yml index 20dc2ffa1686..85222f880930 100644 --- a/west.yml +++ b/west.yml @@ -65,7 +65,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: dc45b2a09c7872f52b2ddb00c20bd02eb547a8ae + revision: 5696f6b423a54390721955d6e0e63c363e02cfff import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above