Multicore idle test with firmware relocated to radio core TCM

The test benchmarks the idle behavior of an application that runs on multiple cores. It demonstrates a radio loader pattern where the radio core firmware is loaded from MRAM into Tightly Coupled Memory (TCM) at runtime.

Requirements

The test supports the following development kit:

Hardware platforms

PCA

Board name

Board target

nRF54H20 DK

PCA10175

nrf54h20dk

nrf54h20dk/nrf54h20/cpuapp

Overview

This test demonstrates how to build a multicore idle application with Sysbuild using a two-stage boot process for the radio core:

  • Radio Loader - A small bootloader that runs on the radio core, copies firmware from MRAM to TCM, and jumps to it.

  • Remote Firmware - The actual application that runs from TCM after being loaded.

The test automatically relocates the remote firmware binary to the correct MRAM address during build time, ensuring it can be loaded by the radio loader.

Architecture

The system uses the memory layout compatible with the MCUboot bootloader. By default, the system uses the MCUboot in the direct-xip mode in the merged slot configuration (no file suffix used). To configure the system to use the MCUboot in the direct-xip mode in the split slot configuration, build the test with the split_slot file suffix.

Memory map configuration

The memory maps are defined in the common directory and are shared between all images to ensure consistency.

The following changes are included in the project overlay files:

  1. Entire Radio TCM RAM region is used for the remote firmware (common/memory_map_ram_cpurad.dtsi).

  2. A small part of Global RAM is used for the radio loader for the firmware relocation time (common/memory_map.dtsi).

  3. The MRAM is partitioned for the MCUboot, application, and radio core images (common/memory_map.dtsi).

Enabling the Radio Loader

The radio loader is automatically added to the build when you enable it in sysbuild configuration.

Set the SB_CONFIG_NRF_RADIO_LOADER Kconfig option to y in the sysbuild.conf file. This single configuration option automatically adds the radio_loader application located in the nrf/samples/nrf54h20/radio_loader folder and builds it for the CPURAD core. No manual ExternalZephyrProject_Add() is needed in sysbuild.

You must provide the DTS overlay file for the radio loader that includes the following DTS node labels:

  • cpurad_slot0_partition - The primary slot of the radio loader code.

  • cpurad_slot1_partition - The secondary slot of the radio loader code.

  • cpurad_slot2_partition - The primary slot of the remote firmware code to be relocated to TCM.

  • cpurad_slot3_partition - The secondary slot of the remote firmware code to be relocated to TCM.

  • cpurad_ram0 - The radio core TCM RAM region to be used for the remote firmware.

Automatic firmware relocation

The remote firmware is linked against the target memory partition (TCM) and must be relocated to match the MRAM partition address where it will be initially stored. This is automatically done by the CONFIG_BUILD_OUTPUT_ADJUST_LMA Kconfig option when the devicetree chosen nodes are configured correctly.

How it works

Firmware relocation is handled automatically by Zephyr’s build system using the CONFIG_BUILD_OUTPUT_ADJUST_LMA Kconfig option, which is configured in the nrf/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad file for all nRF54H20 CPURAD projects.

The configuration automatically detects if the CONFIG_XIP is enabled in the remote firmware project. When this option is enabled, the remote firmware runs directly from the zephyr,code-partition location and no relocation is needed. When this option is disabled, the remote firmware will run from the zephyr,sram location but the image is first stored in the MRAM in the zephyr,code-partition location. The build system calculates the LMA adjustment to relocate the firmware from TCM to MRAM.

Zephyr automatically calculates the Load Memory Address (LMA) adjustment based on the chosen nodes:

LMA_adjustment = zephyr,code-partition address - zephyr,sram address

The build system adjusts the hex file so that the code is loaded from MRAM (0xe000000 address space), but runs from TCM (0x23000000 address space).

Configuration of remote radio firmware

To use the radio loader pattern, you must configure the remote radio firmware in the following way:

  • Disable the CONFIG_XIP option in the remote firmware project.

  • Assign the TCM RAM region to the remote firmware code using the zephyr,sram chosen node.

  • Assign the MRAM partition to the remote firmware code using the zephyr,code-partition chosen node.

Building and running

This test can be found under samples/nrf54h20/idle_relocated_tcm in the nRF Connect SDK folder structure.

See Programming an application for information about how to build and program the tests.

Testing

After programming the test to your development kit, complete the following steps to test it:

  1. Connect to the kit with a terminal emulator (for example, the Serial Terminal app). See Testing and optimization for the required settings and steps.

  2. Reset the kit.

  3. Observe the console output for both cores:

    • For the application core, the output should be as follows:

    *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 ***
    *** Using nRF Connect SDK v3.1.99-329079d0237c ***
    *** Using Zephyr OS v4.2.99-56fbb4f3c7bb ***
    I: Starting Direct-XIP bootloader
    I: Primary slot: version=0.0.0+0
    I: Image 0 Secondary slot: Image not found
    I: Image 0 loaded from the primary slot
    I: Bootloader chainload address offset: 0x40000
    I: Image version: v0.0.0
    I: Jumping to the image slot
    *** Booting nRF Connect SDK v3.1.99-329079d0237c ***
    *** Using Zephyr OS v4.2.99-56fbb4f3c7bb ***
    [00:00:00.336,735] <inf> idle: Multicore idle test on [email protected]/nrf54h20/cpuapp
    [00:00:00.336,742] <inf> idle: build time: Dec  2 2025 08:52:18
    [00:00:00.336,745] <inf> idle: Multicore idle test iteration 0
    [00:00:02.336,834] <inf> idle: Multicore idle test iteration 1
    ...
    
    • For the radio core, the output should be as follows:

    *** Booting nRF Connect SDK v3.1.99-329079d0237c ***
    *** Using Zephyr OS v4.2.99-56fbb4f3c7bb ***
    [00:00:00.512,002] <inf> idle: Multicore idle test on [email protected]/nrf54h20/cpurad
    [00:00:00.512,004] <inf> idle: Original code partition start address: 0xe094000
    [00:00:00.512,006] <inf> idle: Running from the SRAM, start address: 0x23000000, size: 0x30000
    [00:00:00.512,007] <inf> idle: Current PC (program counter) address: 0x23000a90
    [00:00:00.512,009] <inf> idle: build time: Dec  2 2025 08:52:24
    [00:00:00.512,012] <inf> idle: Multicore idle test iteration 0
    [00:00:02.512,072] <inf> idle: Multicore idle test iteration 1
    ...
    

    The radio loader first loads the firmware from MRAM to TCM and then jumps to the loaded firmware. This process is transparent and happens during the early boot stage.

  4. Verify the DFU process:

    1. Build the firmware for the secondary app slot, increase the version number in the prj.conf file (uncomment the line):

      CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.1+0"
      
    2. Build the firmware:

      west build -p -b nrf54h20dk/nrf54h20/cpuapp
      
    3. Program the firmware to the secondary application slot:

      nrfutil device program --firmware build/zephyr_secondary_app.merged.hex  --options chip_erase_mode=ERASE_NONE
      
    4. Reset the development kit.

      nrfutil device reset
      
    5. Observe the following changes in the console output:

      • The application core boots from the secondary application slot.

      • The radio core boots from the secondary radio slot.

      • The build time changes.