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

How to do a low power sleep without interrupts?

I'm trying to do a low power sleep of 1s directly after a device reset, i.e. in Reset_Handler().

During this stage, my application does not allow any interrupts.

So my question: how to do it actually?

Current attempt is as follows:

extern "C" void Reset_Handler_Delay( void )
{
    NRF_POWER->TASKS_LOWPWR = 1;

    //
    // enable clock as Internal 32KHz oscillator
    //
    NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos);
    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_LFCLKSTART    = 1;
    while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {
    }
    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;

    NRF_RTC1->TASKS_STOP  = 1;
    NRF_RTC1->TASKS_CLEAR = 1;
    NRF_RTC1->PRESCALER   = 0;
    NRF_RTC1->INTENCLR    = 0xffffffffUL;
    NRF_RTC1->EVTENCLR    = 0xffffffffUL;
    NRF_RTC1->INTENSET    = RTC_INTENSET_COMPARE3_Msk;         // TODO CC[0] and [1] are not working
    NRF_RTC1->EVTENSET    = RTC_EVTENSET_COMPARE3_Msk;
    NRF_RTC1->EVENTS_COMPARE[3] = 0;
    NRF_RTC1->CC[3] = NRF_RTC1->COUNTER + (1000 * 32768UL) / 1000UL;
    NRF_RTC1->TASKS_START = 1;
    __SEV();
    while ( !NRF_RTC1->EVENTS_COMPARE[3]) {
        __WFE();
    }

    NRF_RTC1->TASKS_STOP = 1;
    NRF_RTC1->TASKS_CLEAR = 1;
    NRF_RTC1->INTENCLR = 0xffffffffUL;
    NRF_RTC1->EVTENCLR = 0xffffffffUL;
    NRF_CLOCK->TASKS_LFCLKSTOP = 1;
}   // Reset_Handler_Delay

Without the __WFE() is is working (with high current of course), with __WFE() included, the loop hangs.

Thanks for suggestions.

Hardy

Parents
  • Ok, I've found a way to implement a low power delay which seems to work always.

    Beforehand the problem was, that depending on the state of the Cortex EV flag, the __WFE() did not return.  Situation could be reproduced if there have been the NFC->GPIO configuration selected, which actually reprograms some values in UICR and then does a NVIC_SystemReset().  On this boot the loop hung.

    My solution is to use the watchdog timer for the low power boot delay, i.e. if RESETREAS shows 0, the watchdog is initialized to "bark" after 1s.  After init of this the program goes into an __WFE() loop and waits for the watchdog.

    On the watchdog reboot, RESETREAS shows nonzero and the program continues.

    Disadvantage is, that on application start, the DOG bit is always set in RESETREAS.  But I can actually live with that ;-)

    Hardy

    PS: note, that this only works as low power delay on startup.

    PPS: just for the record: my feeling says, that NVIC_SystemReset() does not do a complete reset.

Reply
  • Ok, I've found a way to implement a low power delay which seems to work always.

    Beforehand the problem was, that depending on the state of the Cortex EV flag, the __WFE() did not return.  Situation could be reproduced if there have been the NFC->GPIO configuration selected, which actually reprograms some values in UICR and then does a NVIC_SystemReset().  On this boot the loop hung.

    My solution is to use the watchdog timer for the low power boot delay, i.e. if RESETREAS shows 0, the watchdog is initialized to "bark" after 1s.  After init of this the program goes into an __WFE() loop and waits for the watchdog.

    On the watchdog reboot, RESETREAS shows nonzero and the program continues.

    Disadvantage is, that on application start, the DOG bit is always set in RESETREAS.  But I can actually live with that ;-)

    Hardy

    PS: note, that this only works as low power delay on startup.

    PPS: just for the record: my feeling says, that NVIC_SystemReset() does not do a complete reset.

Children
No Data
Related