Hi Nordic Team,
I'm debugging an unexpected software reset on an nRF54L15 running nRF Connect SDK v3.4.0. BLE FOTA through MCUmgr completes successfully and the new image is marked as pending/test, but the device reboots while the application is still waiting for its own 120-second reboot timer to expire (this timeout configured by us).
This has happened repeatedly. I don't see the log from my FOTA reboot handler, my __wrap_sys_reboot() wrapper, or even the printk() statements I added directly to Zephyr's sys_reboot().
After reboot, HWINFO reports:
Reset cause: 0x00000002 Reset cause flag: software
I'm trying to identify what could trigger this reset without going through the normal Zephyr reboot path.
Setup
- SoC: nRF54L15 on a custom PCB
- Application Build: CPUAPP
- nRF Connect SDK: v3.4.0
- Boot chain: NSIB/b0 → MCUboot → application
- MCUboot update method: swap using the move algorithm
- FOTA: BLE SMP/MCUmgr
- Image manager and OS management group enabled
- MCUboot verification key provisioned using KMU
- Other application components: LoRaWAN, external flash, NFC, a GRTC-based time service, and an event-driven workflow scheduler
- FOTA App: nRF Connect Mobile App
Relevant sysbuild.conf settings:
SB_CONFIG_SECURE_BOOT_APPCORE=y
SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_SECURE_BOOT_SIGNATURE_TYPE_ED25519=y
SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519=y
SB_CONFIG_MCUBOOT_SIGNATURE_USING_KMU=y
SB_CONFIG_SECURE_BOOT_SIGNING_KEY_FILE="${APP_DIR}/keys/nsib_private_key.pem"
SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/keys/mcuboot_private_key.pem"
SB_CONFIG_MCUBOOT_GENERATE_DEFAULT_KEY_FILE=y
SB_CONFIG_SECURE_BOOT_GENERATE_DEFAULT_KMU_KEYFILE=y
SB_CONFIG_MCUBOOT_UPDATEABLE_IMAGES=1
Expected behavior
After the image upload finishes, the application starts a local 120-second timer rather than rebooting immediately:
#define FOTA_REBOOT_DELAY_S 120U
The MCUmgr OS reset event (MGMT_EVT_OP_OS_MGMT_RESET) is intercepted. The callback rejects the request with:
*rc = MGMT_ERR_EACCESSDENIED; return MGMT_CB_ERROR_RC;
The request data is consistently logged as force=0 and boot_mode=0. The intended sequence is that the upload completes, the image is marked pending/test, the MCUmgr reset is rejected, and the application waits for its own timer before calling sys_reboot(SYS_REBOOT_COLD).
What happens in practice
I've reproduced this several times. The delay from marking the image pending to the unexpected reboot varies, but it is always shorter than 120 seconds.
Case 1: The image was uploaded and marked pending at 16:20:04.510. The local reboot timer started at 16:20:04.556, and the MCUmgr reset request was intercepted at 16:20:05.665. The device started booting again at 16:21:02.566, about 58 seconds after the image became pending.
MCUboot then reported:
I: Secondary image: magic=good, swap_type=0x2 I: Image index: 0, Swap type: test I: Starting swap using move algorithm. I: Image version: v1.0.1 I: Jumping to the first image slot
Case 2: The image was marked pending at 16:30:06.090, and the reset request was intercepted at 16:30:07.280. The next boot started at 16:30:54.692, about 48 seconds after the image became pending.
Case 3: The image was marked pending at 17:15:55.246. The callback received the reset request at 17:15:56.384, logged force=0 boot_mode=0, and rejected it. The device continued running, then rebooted at 17:16:39.101, around 43 seconds after the rejected request.
After these reboots, HWINFO reported:
Reset causes supported: 0x000009b3
Reset cause: 0x00000002
Reset cause flag: software
Case 4: I enabled additional fatal-error and stack diagnostics to check for a Zephyr fatal error, assertion, or stack overflow:
CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_ASSERT=y CONFIG_STACK_SENTINEL=y CONFIG_STACK_CANARIES=y CONFIG_THREAD_NAME=y CONFIG_THREAD_MONITOR=y CONFIG_INIT_STACKS=y CONFIG_THREAD_STACK_INFO=y CONFIG_THREAD_ANALYZER=y CONFIG_THREAD_ANALYZER_AUTO=y CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=10
After rejecting the MCUmgr reset request, the application continued running and the thread analyzer kept printing statistics. For example, the main thread used 956 of 2048 bytes (46%), the MCUmgr SMP thread used 1548 of 2048 bytes (75%), and the LoRaWAN thread used 1316 of 2048 bytes (64%). There was no assertion, hard fault, MPU fault, fatal-error message, or stack-overflow indication before the reboot. The device started booting again at 17:41:23.582; HWINFO again reported reset cause 0x00000002 (software).
In all cases, the image upload succeeds, the image becomes pending/test, the MCUmgr reset request is rejected, the BLE connection disconnects normally, and the application continues running for tens of seconds before the unexpected reset. MCUboot then detects and installs the pending image.
Reboot-path instrumentation
My own FOTA reboot handler logs this immediately before rebooting:
APP_LOG_ERR("### FOTA CALLING sys_reboot(SYS_REBOOT_COLD) ###");k_msleep(100);sys_reboot(SYS_REBOOT_COLD);
That message never appears during the unexpected reset.
I also enabled linker wrapping (-Wl,--wrap=sys_reboot) and added a wrapper that logs the caller and current thread before calling __real_sys_reboot(). The wrapper's log never appears either.
Finally, I added printk() instrumentation directly inside Zephyr's sys_reboot() implementation. Those messages also never appear, although the reset still happens. This makes me suspect the reset may be triggered by a lower-level mechanism that bypasses Zephyr's sys_reboot() path.
MCUmgr reset delay
My configuration includes:
CONFIG_MCUMGR_GRP_OS_RESET_MS=250
My understanding is that this controls the delay before rebooting after an accepted MCUmgr OS reset request, allowing the response to be sent first. Since my callback returns MGMT_ERR_EACCESSDENIED and MGMT_CB_ERROR_RC, I would like to confirm whether this delay can still schedule a reset after the callback rejects the request.
Other areas checked:
I checked the LoRaWAN service and GRTC-based time service for explicit reset calls but haven't found any. The GRTC driver schedules callbacks through compare channels and does not directly call sys_reboot(). I'm still auditing the timer users and other application timeout paths.
Debugging the protected boot chain
I also tried to start a debug session in nRF Connect for VS Code while retaining the full NSIB → MCUboot → application chain. I selected “Start a session on Application Core” and “Stop in My_Application at main()”, but the extension tried to program the sysbuild image and failed with:
-- runners.nrfutil: Connecting to probe -- runners.nrfutil: Programming image Error: One or more batch tasks failed: * 1057728952: Device error: Address 0x00000000 is in a protected RRAMC region (Generic)
The device already has KMU/security information provisioned, so I have avoided running recover because I don't want to erase or reprovision the security state just to investigate this issue.
What is the recommended way to attach GDB to the Application Core/application ELF without reflashing the protected NSIB region?
Questions:
- On the nRF54L15, what mechanisms can cause RESET_SOFTWARE (Reset cause = 0x00000002) without going through Zephyr's sys_reboot()?
- Could MPSL, the SoftDevice Controller, MCUmgr/SMP, image management, MCUboot integration, NSIB/b0, secure firmware, the system event subsystem, GRTC/system timer, or the nRF54L security/protection subsystem initiate a software reset through a lower-level mechanism?
- Since neither __wrap_sys_reboot() nor the instrumented Zephyr sys_reboot() is reached, which lower-level nRF54L reset function, API, or register would you recommend instrumenting or setting a breakpoint on? Is there a hardware reset task/register below sys_arch_reboot() that could help identify the caller?
- Is there retained reset information on the nRF54L15 that can distinguish a Zephyr reboot, an NVIC/SystemReset, a secure-domain reset, a subsystem-initiated reset, or a bootloader-initiated reset when HWINFO reports the same software-reset cause?
- Does returning MGMT_ERR_EACCESSDENIED and MGMT_CB_ERROR_RC fully reject an MCUmgr OS reset request when force=0 and boot_mode=0 ?
- Is CONFIG_MCUMGR_GRP_OS_RESET_MS=250 used only after the request has been accepted, or can a delayed reset remain scheduled after the callback returns an error?
- Are there known issues in NCS v3.4.0 involving nRF54L15 + NSIB + MCUboot + BLE SMP FOTA where the image is marked TEST, the MCUmgr OS reset is rejected, but a software reset occurs later?
- What is the recommended way to debug the Application Core while preserving NSIB, MCUboot, KMU provisioning, and protected RRAM, without trying to reprogram address 0x00000000 ?
The main point is that the device keeps running after the MCUmgr reset request is rejected, but then resets roughly 43–58 seconds later. The local 120-second timer and all the sys_reboot() instrumentation remain silent, and no fatal-error or stack-overflow indication is logged. MCUboot subsequently sees the pending test image and completes the swap.
Let me know if additional information needed. I would appreciate any suggestions or solutions as soon as possible.
Best regards,
Mathiyazhagan S.
