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

Watchdog : NRFX_WDT_CONFIG_BEHAVIOUR => Run in SLEEP, Pause in HALT

Hello,

I'm using the watchdog and i'm feeding it in my main loop : 

// Initialize watchdog as soon as possible
err_code = watchdog_init();
APP_ERROR_CHECK(err_code);

// Enter main loop.
for (;;)
{
    if (NRF_LOG_PROCESS() == false)
    {
#ifdef NDEBUG
        // Clear exceptions and PendingIRQ from the FPU unit
        // TODO : find why the following code can trigger an exception in debug
        __set_FPSCR(__get_FPSCR()  & ~(FPU_EXCEPTION_MASK));
        (void) __get_FPSCR();
        NVIC_ClearPendingIRQ(FPU_IRQn);

        // Handle power management
        power_manage();
#endif
    }

    // Feed the watchdog once the CPU has been waken up
    watchdog_feed();
}

/**@brief   Sleep until an event is received. */
void power_manage(void)
{
//#ifdef SOFTDEVICE_PRESENT
    (void) sd_app_evt_wait();
/*#else
    __WFE();
#endif*/
}

I tried with 

#define NRFX_WDT_CONFIG_BEHAVIOUR 1

and 

#define NRFX_WDT_CONFIG_BEHAVIOUR 0

But i'm still having a watchdog that is triggered and i don't knwo why. If someone can help me to debug this. I suspecting to not feeding the watchdog at the right place. The issue only occurs when i'm building and loading a release version (my debug version under Segger Embedded is working)

Best regards,

Aurélien

  • Hi,

    The NRFX_WDT_CONFIG_BEHAVIOUR define is replaced by whatever you have set WDT_CONFIG_BEHAVIOUR, unless you have taken the effort to remove the legacy driver and apply_old_configs.h (which there is no reason to do). Therefore, you should make sure you set WDT_CONFIG_BEHAVIOUR to the configuration you want. If you want the WDT to pause when the CPU is sleeping you should use 0 or 8. I don't understand why you see a difference with debug mode or not, though. Can you show your complete code, at least the implementation of your watchdog_init() and whatchdog_feed() functions, as well as your sdk_config.h?

    Regarding feeding the watchdog at the right place or not, that depends entirely on what you want to do and how you use the watchdog. In my opinion, making the WDT pause when CPU is sleeping and just feeding it in the main loop is a bit useless, as there can be several cases where the WDT should have fired but does not with this configuration. (For instance, there is a problem with the wake-up interrupt, so the CPU sleeps forever and the WDT does not reset it. And always feeding the watchdog in the main loop means that the only thing the WDT would save you from is if the application is stuck in some state that prevents the main loop from running. Any other error would go undetected.)

  • Hi Einar,

    Thank you very much for the help.

    Here is the code of the watchdog : 

    /* Private variables ---------------------------------------------------------*/
    
    nrf_drv_wdt_channel_id m_channel_id;
    
    /* Private functions ---------------------------------------------------------*/
    
    /**
     * @brief WDT events handler.
     */
    static void wdt_event_handler(void)
    {
        //bsp_board_leds_off();
        NRF_LOG_INFO("Watchdog ISR triggered");
    
        //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
    }
    
    uint32_t watchdog_init(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    
        //Configure WDT.
        nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
        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();
    
        return err_code;
    }
    
    void watchdog_feed(void) {
        nrf_drv_wdt_channel_feed(m_channel_id);
    

    It is mainly inspired from the example in the SDK.

    Here is my sdk_config file :

     5810.sdk_config.h

    I totally agree with your analysis. Actually, i was assuming that the SDK and softdevice was working fine and i only wanted to protect my application code from blocking that's why i put the feeding function in the main loop.

    Then, i wanted to stop the watchdog in sleep mode just because of power consumption constrain i have on my device but i didn't evaluate the current consumption of the watchdog yet, and maybe it is insignificant. 

    Finally, i have understood why the issue occurs only in release. It is just because in debug i don't call : power_manage(); So the CPU never goes in sleep mode.

    Regards,

    Aurélien

  • Hi Aurélien,

    I see. Then it all makes sense:

    • WDT_CONFIG_BEHAVIOUR is 1, so the WDT runs in sleep.
    • You don't call power_manage() in debug mode, so watchdog_feed() is called frequently.
    • In release mode, you call power_manage(), which makes the CPU sleep until there is an event/interrupt. If there are no interrupts before the WDT times out there is no new call to watchdog_feed(), and the WDT resets the device as expected.

    Einar

  • I agree with what you said but even when i set WDT_CONFIG_BEHAVIOUR to 8 (watchdog stopped in sleep), it still triggers a wdt interrupt after a while.

  • My bad, i finally found out the issue. It was coming from my confusion between WDT_CONFIG_BEHAVIOUR and NRFX_WDT_CONFIG_BEHAVIOUR. 

    I'm sorry for the inconvenience, all is working fine, now i'm just setting all configuration flag that does not start with "NRFX_"

    By the way, one more question, i'm using the following behaviour : WDT_CONFIG_BEHAVIOUR = 0

    (Pause in SLEEP and HALT ) I want to stop the watchdog in sleep mode because of consumption constrain i have, but for the HALT, do you agree the only purpose is to allow the user to debug wihtout being disturbed by the watchdog ?

Related