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

RTC stops running after soft reset with WDT enabled

I'm using nRF52840, PCA10056, and finding that if WDT is enabled (but not expired), after a soft reset (NVIC_SystemReset, or a debugger reset) the RTC no longer runs.

If the watchdog expires, or there is a hard reset, then RTC works again. Probably also works after system OFF/NFC wake, but I didn't try.

It looks the same as this ticket, but had no resolution:

https://devzone.nordicsemi.com/f/nordic-q-a/14321/wdt-halts-rtc-after-nvic_systemreset

The issue is reproducible with the nRF SDK WDT example (SDK 17.0, examples/peripheral/wdt):

Replace the wdt init and for() loop in main with the following (changes highlighted):

    //Configure WDT.
    nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    config.reload_value = 10000;  // NEW
    err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
    APP_ERROR_CHECK(err_code);
    nrf_drv_wdt_enable();
    err_code = app_timer_create(&m_timer, APP_TIMER_MODE_REPEATED, timer_handler);
    APP_ERROR_CHECK(err_code);
    err_code = app_timer_start(m_timer, APP_TIMER_TICKS(200), NULL);
    APP_ERROR_CHECK(err_code);
    err_code = bsp_buttons_enable();
    APP_ERROR_CHECK(err_code);

    nrf_delay_ms(2000);
    NVIC_SystemReset();

and add the handler:

APP_TIMER_DEF(m_timer);
static void timer_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    static int count = 0;
    if (count < LEDS_NUMBER)
    {
        bsp_board_led_on(count);
        count++;
    }
}

That is, instead of a busy-wait to light the LEDs at boot, they are lit from an app_timer (using RTC).
So behavior should be:
- LEDS light up, 200msec apart
- 2 seconds later, device soft resets (LEDs off)
- Since WDT is preserved on soft reset, process should repeat about 5 times (10 seconds) before WDT expires
Instead, what happens is:
- (after a power cycle)
- LEDs light up
- 2 seconds later, LEDs turn off (from soft reset)
- LEDs stay off for ~8 seconds more, until watchdog expires, then the process starts again
 
That implies that the RTC is not running after soft-reset, but starts working again after watchdog timeout (or power cycle). With a debugger attached, the RTC counter does not show it incrementing (counter displayed in debugger never updates during HALT, but if it is running it will have a non-zero value at break, and it will change while single-stepping).
Disabling the WDT, the LEDs work as expected: turn on incrementally, off after 2 seconds, repeat.
Any ideas? Can Nordic reproduce this behavior?
  • Hello,

    Thank you for providing the code needed to reproduce this behavior, it's really helpful! It sounds like this issue may be the same as the one discussed here: https://devzone.nordicsemi.com/f/nordic-q-a/65329/bootloader-with-wdt-and-app_time which I'm still working on. I will continue to debug the problem and keep you posted.

    Best regards,

    Vidar

    Update: I think this related to the behavior Håkon describes here (link) in that you have to start the LF clock start task even if the clock has been started by the WDT first. Removing the if condition in nrf_drv_clock_init() as shown below should fix the problem.

    ret_code_t nrf_drv_clock_init(void)
    {
        ret_code_t err_code = NRF_SUCCESS;
        if (m_clock_cb.module_initialized)
        {
            err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED;
        }
        else
        {
            m_clock_cb.p_hf_head      = NULL;
            m_clock_cb.hfclk_requests = 0;
            m_clock_cb.p_lf_head      = NULL;
            m_clock_cb.lfclk_requests = 0;
            err_code = nrfx_clock_init(clock_irq_handler);
    #ifdef SOFTDEVICE_PRESENT
            if (!nrf_sdh_is_enabled())
    #endif
            {
                nrfx_clock_enable();
            }
    
    #if CALIBRATION_SUPPORT
            m_clock_cb.cal_state = CAL_STATE_IDLE;
    #endif
    
            m_clock_cb.module_initialized = true;
        }
    
    /* Mod: start LF clock regardless of WDT state */
    
    //    if (nrf_wdt_started())
    //    {
    //        m_clock_cb.lfclk_on = true;
    //    }
    //
        NRF_LOG_INFO("Function: %s, error code: %s.",
                     (uint32_t)__func__,
                     (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }
    

  • Thanks for the speedy reply!

    I can confirm that disabling those lines fixes the issue both in the example and in my application.

    To avoid modifying SDK code, I am actually using the following:

        err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
        nrfx_clock_lfclk_start();
    which also works.
     
Related