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

Bootloader WDT not Firing

Hi,

I am still investigating this but, I think it is best that we discuss it on this forum. 

I am using SDK 16.0.0, nRF52840, secure_bootloader_usb on a custom board. The problem appears to be the following:

My application is using the WDT to provide a means of system reset within 10 seconds if WDT is not refreshed. 

I am entering DFU by causing a writing to GPREGRET 0xB1 and causing a softreset with the purpose of downloading firmware via USB. 

At this point the bootloader takes control and should be able to identify that the WDT was running in the application and hence keep feeding it. 

Indeed, the bootloader checks for the enabled WDT and normally should enable RTC2 as a WDT refresh timer. 

What we are finding is that (at least in the release version of the bootloader) this is not happening. 

For some reason, the RTC2 interrupts are for Channel 2 (and Channel 1) compare are not enabled and the task of is also not enabled. The result is that the MCU is reset from the running WDT. 

Now comes the good part:

Trying to identify why this is happening we were setting breakpoints to various locations and checking what the firmware was doing. We found that in the file nrf_bootloader_dfu_timers and in the code shown below, a break point right at if(!m_timer_initialized) would do the trick.

/**@brief Function for initializing the timer if it is not already initialized.
 */
static void timer_init(void)
{
    static bool m_timer_initialized;

    if (!m_timer_initialized)
    {
        if (!nrf_clock_lf_is_running())
        {
            //nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal_Full_Swing);      //Added VG 20200213
            //nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
            //while(nrf_clock_lf_is_running() == false){}                 //Added VG 20200213 Wait till LFCLK Initializes

            lfclk_config();

        }
                        
        nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_TICK);
        nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_0);
        nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_1);
        NRFX_IRQ_PRIORITY_SET(RTC_IRQn, 5);
        NRFX_IRQ_ENABLE(RTC_IRQn);
        nrf_rtc_prescaler_set(RTC_STRUCT, RTC_PRESCALER);
        nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_CLEAR);
        nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_START);
        nrf_rtc_int_enable(RTC_STRUCT, RTC_INTENSET_OVRFLW_Msk);

        m_timer_initialized = true;
    }
}

When a break point is placed there, then after continuing code execution, the RTC2 timer starts normally and the interrupt CC2 is enabled. As a concsequence the WDT running is reset by RTC2 feed action. Breakpoints after this location in the code DO NOT have any effect. The RTC2 is not initialized correctly and does not feed the WDT. 

We cannot, at the moment, explain this behavior. Best guess is that it has do to with the way the code is written because the same routines are used to initialize the inactivity timer used by the bootloader. 

We will keep investigating but any help is greatly appreciated. 

Thanks.

  • I ran into possibly the same issue in SDK 17.1.0. The problem for me seems to be that nrf_clock_lf_is_running() returns true if the WDT is running, but the LF clock somehow might not be running well enough for the RTC to run. What worked for me is to start the LF clock even if it says it is running (see lines I commented in nrf_bootloader_dfu_timers.c):

    /**@brief Function for initializing the timer if it is not already initialized.
     */
    static void timer_init(void)
    {
        static bool m_timer_initialized;
    
        if (!m_timer_initialized)
        {
    //        if (!nrf_clock_lf_is_running())    * With the WDT running, the LF is running, but somehow not consistently well enough for the RTC, so really start it regardless.
    //        {
                nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
    //        }
            nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_TICK);
            nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_0);
            nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_1);
            NRFX_IRQ_PRIORITY_SET(RTC_IRQn, 5);
            NRFX_IRQ_ENABLE(RTC_IRQn);
            nrf_rtc_prescaler_set(RTC_STRUCT, RTC_PRESCALER);
            nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_CLEAR);
            nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_START);
            nrf_rtc_int_enable(RTC_STRUCT, RTC_INTENSET_OVRFLW_Msk);
    
            m_timer_initialized = true;
        }
    }


Related