ARMmbed / mbed-os

Arm Mbed OS is a platform operating system designed for the internet of things
https://mbed.com
Other
4.68k stars 2.99k forks source link

NCS36510 hard fault when entering deep sleep #5065

Closed c1728p9 closed 3 years ago

c1728p9 commented 7 years ago

In certain configurations the NCS36510 crashes with a hard fault when entering deep sleep mode with interrupts disabled. When single stepping through the same code with a debugger a crash does not occur. Additionally adding breakpoints after the WFI instruction makes the crash go away, but may not be a robust solution.

Example program which can reproduce the crash (needs to be build with IAR - mbed compile -t IAR -m NCS36510 --profile debug) :

#include "mbed.h"

DigitalOut led1(LED1);
LowPowerTicker ticker;

void blink()
{
    led1 = !led1;
}

#define ENABLE          (uint8_t)0x01
#define DISABLE         (uint8_t)0x00
#define MAC_LUT_SIZE    (uint8_t)96

void test_sleep()
{
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    PMUREG->CONTROL.BITS.ENCOMA = DISABLE;

    /** Enter into deep sleep mode */
    __ISB();
    __WFI();
    // Uncomment the below two lines to fix the hardfault
    //__NOP();
    //__NOP();

    /** Wait for the external 32MHz to be power-ed up & running
     * Re-power down the 32MHz internal osc
     */
    while (!CLOCKREG->CSR.BITS.XTAL32M);
    PMUREG->CONTROL.BITS.INT32M = 1;
}

void test_func()
{
    test_sleep();
}

int main() {
    ticker.attach_us(blink, 500 * 1000);

    printf("Running test\r\n");
    core_util_critical_section_enter();
    test_func();
    core_util_critical_section_exit();
    printf("Test completed\r\n");
}

Hex and elf files build at mbed-os revision e12f116ec1ef0851195f4b0a085497e2811f8a28 with above program can be found here: ncs32510_files.zip

IAR version used to build: IAR Embedded Workbench for ARM - 7.80.4.12495 IAR Embedded Workbench shared components - 7.5.6.4719

0xc0170 commented 7 years ago

cc @jacobjohnson-ON @danclement [Mirrored to Jira]

danclement commented 7 years ago

Why would it matter if GCC or IAR is used? It seems this bug would be consistent between both toolchains.

In deep sleep the FLASH memory should be powered down. I wonder if that's why adding the NOPs works because it give the memory time to wake up before it tries to run code. Same for single stepping in the debugger.

We can look into this, maybe we need to add a routine to monitor the flash power up and status. [Mirrored to Jira]

0xc0170 commented 7 years ago

@danclement Let us know if any update, it would be good to have a fix for this. we have seen this bug with IAR in our CI recently. [Mirrored to Jira]

danclement commented 7 years ago

Hi @0xc0170, I had to spend several days fighting with toolchains and computer issues so I haven't looked into this yet. I plan to soon.

@maclobdell, If you could send at least one more CI test shield to us, preferably 2, that would help also.

Thanks, Dan [Mirrored to Jira]

danclement commented 7 years ago

@0xc0170 , I think I was right about the FLASH not being ready before program execution continued. That's why it worked with the NOPs and the single stepping. I added the following to the code and it works using IAR (in the CLI), where it didn't work before I added it.

void test_sleep()
{
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    PMUREG->CONTROL.BITS.ENCOMA = DISABLE;

    /** Enter into deep sleep mode */
    __ISB();
    __WFI();

    // After waking from interrupt, wait for flash banks to be powered up and ready
    // TODO: Later need to make sure this still works well for a dual stack or dual FLASH application
    while ((FLASHREG->STATUS.BITS.FLASH_A_BUSY == 1));

    // Uncomment the below two lines to fix the hardfault
    //__NOP();
    //__NOP();

    /** Wait for the external 32MHz to be power-ed up & running
     * Re-power down the 32MHz internal osc
     */
    while (!CLOCKREG->CSR.BITS.XTAL32M);
    PMUREG->CONTROL.BITS.INT32M = 1;
}

@jacobjohnson-ON , @maclobdell [Mirrored to Jira]

0xc0170 commented 7 years ago

@danclement Can you please send a fix? [Mirrored to Jira]

c1728p9 commented 7 years ago

@danclement thanks for looking into this. I'm a little confused, if the flash isn't ready then how are instructions after the WFI executed? Does this same code fix the crash if it is moved until after the 32MHz clock powerup? [Mirrored to Jira]

0xc0170 commented 7 years ago

@danclement thanks for looking into this. I'm a little confused, if the flash isn't ready then how are instructions after the WFI executed? Does this same code fix the crash if it is moved until after the 32MHz clock powerup?

@danclement Can you please send a fix?

Any update? [Mirrored to Jira]

danclement commented 7 years ago

@c1728p9, if I put this fix after the 32MHz power up it still works fine.

When I can, I will update the real file and run the tests and do the pull request. [Mirrored to Jira]

danclement commented 7 years ago

See PR #5396 [Mirrored to Jira]

ciarmcom commented 4 years ago

Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers. Internal Jira reference: https://jira.arm.com/browse/IOTOSM-2140

ciarmcom commented 3 years ago

We closed this issue because it has been inactive for quite some time and we believe it to be low priority. If you think that the priority should be higher, then please reopen with your justification for increasing the priority.