nRF54L15 custom board: sysbuild merged.hex omits the application, and flashing both images separately gives a silent board
Environment
- nRF Connect SDK v2.9.2 (Zephyr 3.7.99)
- Board target:
nrf54l15dk/nrf54l15/cpuapp - Custom PCB using nRF54L15, powered by an nPM1300 PMIC
- Toolchain b620d30767, Windows,
westcommand line - Debug output over RTT (UART pins are in use as GPIO on this board)
What works
The application without MCUboot runs correctly. BLE advertises, I2C peripherals respond, RTT output is reliable. RTT has been verified working with several other programs on this board.
MCUboot flashed on its own also runs correctly. This is the key data point — the bootloader is not dead on this hardware:
west flash --erase --hex-file build/mcuboot/zephyr/zephyr.hex
*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.2-4ab7b98fc76f ***
I: Starting bootloader
I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Boot source: none
W: Failed reading image headers; Image=0
E: Unable to find bootable image
Which is correct with no application present.
Problem 1: merged.hex contains only MCUboot
After a successful west build with SB_CONFIG_BOOTLOADER_MCUBOOT=y, the generated build/merged.hex contains only the bootloader. It ends at address 0x2B64 with no extended-address record and no data anywhere near 0x16000, where the application slot begins.
Last lines of merged.hex:
:102B5000892DE9FDA245E15B15D9D30C5C9B1B5483
:042B6000281B0D051C
:00000001FF
Flashing this and booting gives the same Unable to find bootable image, which is consistent: nothing was written to the primary slot.
The application's own signed hex is generated and looks correct. build/<app>/zephyr/zephyr.signed.hex begins:
:020000040001F9
:106000003DB8F396000000000008000094C20200B2
Base 0x10000 plus offset 0x6000 = 0x16000, and the first word is the MCUboot image magic 0x96F3B83D. So the image is built, signed and linked for the right address — it is simply absent from merged.hex.
Problem 2: flashing both images separately produces a silent board
west flash --erase --hex-file build/mcuboot/zephyr/zephyr.hex
west flash --hex-file build/<app>/zephyr/zephyr.signed.hex
Both report Verifying image and success. After this:
- No BLE advertising
- No RTT output from either image — including MCUboot, which logged correctly moments earlier when it was alone on the chip
To rule out RTT picking the wrong control block, the application's RTT was disabled (CONFIG_USE_SEGGER_RTT=n, CONFIG_RTT_CONSOLE=n, CONFIG_CONSOLE=n) so only MCUboot's block exists. Still silent. Tried auto-detect, a fixed address of 0x20000000, and search ranges covering the whole RAM region.
Problem 3: the unmodified smp_svr sample behaves the same
west build -b nrf54l15dk/nrf54l15/cpuapp \
zephyr/samples/subsys/mgmt/mcumgr/smp_svr -d build_smp --sysbuild
west flash -d build_smp --erase
Builds cleanly with defaults — RSA-2048, MCUboot at 72.69% of 48 KB, no pm_static.yml. After flashing: no BLE, no RTT, nothing.
Partition layout
build/partitions.yml matches the pm_static.yml in the project root:
mcuboot: 0x0 - 0x16000 (0x16000)
mcuboot_pad: 0x16000 - 0x16800 (0x800)
app: 0x16800 - 0xbd000 (0xa6800)
mcuboot_primary: 0x16000 - 0xbd000 (0xa7000)
mcuboot_secondary: 0xbd000 - 0x164000 (0xa7000)
EMPTY_0: 0x164000 - 0x165000 (0x1000)
MCUboot builds at 53.99% of its 88 KB partition.
Already tried, no change
- ED25519 signing (
SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519=y) as well as the RSA-2048 default - MCUboot partition at the default 0xC000 (99.12% full) and at 0x16000 (54%)
- With and without
pm_static.yml CONFIG_PICOLIBC=yin the MCUboot image- LF clock variations in
sysbuild/mcuboot.conf:CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y+XTAL=n- the above plus
RC_CALIBRATION=n RC=y+500PPM=y+RC_CALIBRATION=y+CALIBRATION_LF_ALWAYS_ON=y
nrfutil device recoverbefore flashing- MCUboot RTT logging enabled (
CONFIG_LOG=y,CONFIG_MCUBOOT_LOG_LEVEL_INF=y)
Board details that may matter
- 32.768 kHz crystal fitted at AX1, 32 MHz at AX2
- Powered by an nPM1300 PMIC over I2C at 0x6B
app.overlaycontains&uicr { nfct-pins-as-gpios; }because two GPIOs used as buttons are on the NFC pins. MCUboot's build has no such overlay.
Questions
- Why does
merged.hexcontain only MCUboot and not the application, when the signed application hex is generated correctly? - Why does MCUboot stop producing RTT output as soon as an application is present in the primary slot, having logged correctly when alone?
- Could the
&uicrnode in the application's overlay affect MCUboot, given that UICR is device-wide and MCUboot boots first?
Attached
partitions.ymlpm_static.ymlsysbuild.confsysbuild/mcuboot.confprj.confapp.overlay
# Static partition layout, derived from this project's own generated layout # with MCUboot enlarged from 0xc000 (48 KB) to 0x16000 (88 KB). At 48 KB # MCUboot reached 99% full. # # Once a board ships with this layout it is fixed: an update image must match # the partition map already on the device. mcuboot: address: 0x0 end_address: 0x16000 size: 0x16000 region: flash_primary mcuboot_pad: address: 0x16000 end_address: 0x16800 size: 0x800 region: flash_primary app: address: 0x16800 end_address: 0xbd000 size: 0xa6800 region: flash_primary mcuboot_primary: address: 0x16000 end_address: 0xbd000 size: 0xa7000 region: flash_primary span: [mcuboot_pad, app] mcuboot_primary_app: address: 0x16800 end_address: 0xbd000 size: 0xa6800 region: flash_primary span: [app] mcuboot_secondary: address: 0xbd000 end_address: 0x164000 size: 0xa7000 region: flash_primary EMPTY_0: address: 0x164000 end_address: 0x165000 size: 0x1000 region: flash_primary
EMPTY_0: address: 0x164000 end_address: 0x165000 region: flash_primary size: 0x1000 app: address: 0x16800 end_address: 0xbd000 region: flash_primary size: 0xa6800 mcuboot: address: 0x0 end_address: 0x16000 region: flash_primary size: 0x16000 mcuboot_pad: address: 0x16000 end_address: 0x16800 region: flash_primary size: 0x800 mcuboot_primary: address: 0x16000 end_address: 0xbd000 region: flash_primary size: 0xa7000 span: - mcuboot_pad - app mcuboot_primary_app: address: 0x16800 end_address: 0xbd000 region: flash_primary size: 0xa6800 span: - app mcuboot_secondary: address: 0xbd000 end_address: 0x164000 region: flash_primary size: 0xa7000 otp: address: 0xffd500 end_address: 0xffd9fc region: otp size: 0x4fc sram_primary: address: 0x20000000 end_address: 0x2002f000 region: sram_primary size: 0x2f000