This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Debugging nRF5340 Net CPU Causes Stack Overflow on Reset

When compiling the net CPU with debugging configs such as CONFIG_DEBUG or CONFIG_DEBUG_OPTIMIZATIONS enabled and the resulting hex is flashed to the nRF5340; If then an Ozone debugging session is started and the system reset, a stack overflow hard fault is generated due to the CONTROL register not being reset and the PSP stack is used when it is not initialized.

Currently the PSP is initialized in the reset.S file starting at Line 134, however prior to this, the reset section calls z_platform_init which in turn calls SystemInit to perform Nordic SoC specific initializations.

When debugging configs are enabled, extra assembly is added to functions by the compiler, including z_platform_init shown below.

Without debugging configs enabled, the compiler inline optimizes all the branch calls into a single inline asm block and therefore no push or pop instructions are utilized throughout the entire execution of reset up to the PSP being initialized.

To test the state of the PSP, MSP, and CONTROL registers, I added the assembly below just after SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) entry point.

    mrs r3, PSP
    mrs r4, MSP
    mrs r5, CONTROL

With debugging enabled on the App CPU, when a reset and halt is sent through ozone, I inspected the results and PSP register is set to 0 while the MSP register is set to a 0x21XXXXXX memory address. The control register was set to 0 which means the current instructions utilize the MSP and no fault occurs when a push is executed during z_platform_init entry.

However, with debugging enabled on the Net CPU when a reset and halt is sent, both the PSP and MSP is already set to a 0x21XXXXXX address and the control register is set to 0x2 which means the current instructions will use the PSP and not the MSP.  When the push instruction is executed during z_platform_init a stack overflow hardfault is generated.

Currently the solution that I have found is to move the initialization of the PSP to the top of the reset entry before all other executions. after PSP is initialized and CONTROL is set to 0x2 push execution  runs as expected with no hard faults.

Any thoughts on why this might be happening. Should the CONTROL register not be reset to 0 and PSP be set to 0 on the net CPU just as it is on the app CPU?

  • Hi,

    Thank you for reporting this. I have reported this internally. I will keep you posted about our findings.

  • Hi,

    The Network core is a regular Cortex-M33 and any warm/cold reset should be initializing the CONTROL register. If the debugger does not do it on the NET core, then this might be a problem.

    One thing that you can do is to set the CONFIG_INIT_ARCH_HW_AT_BOOT Kconfig option for the network core. This option will set the CONTROL register before anything else, in reset.S:

     
    #if defined(CONFIG_INIT_ARCH_HW_AT_BOOT)
        / Reset CONTROL register /
        movs.n r0, #0
        msr CONTROL, r0
        isb
    #if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM)
        / Clear SPLIM registers /
        movs.n r0, #0
        msr MSPLIM, r0
        msr PSPLIM, r0
    #endif / CONFIG_CPU_CORTEX_M_HAS_SPLIM /
     
    This will ensure that the MSP is used at Network core boot, and not the PSP.

    Let me know if this workaround works for you or not.

  • Setting CONFIG_INIT_ARCH_HW_AT_BOOT does indeed fix the problem with no other changes to the base reset.S.

    The only time I observe this issue is when debugging so you mentioning that the debugger should perform a reset but not doing it makes sense. Cold boots with no debugger attached do not observe any hardfaults.

    The debugger I am using is a JTrace attached externally to P18 (debug in) on the devboard however I can confirm that it the issue was also present when using the built in JLink.

Related