Watchdog Reset After DFU Despite Feed

Our product is experiencing an issue where a watchdog reset occurs after DFU, even though we are feeding the watchdog in the application.

However, this issue does not occur during a normal boot or normal reset, so it is not a major operational problem, but we would like to understand the cause, which is why we are reaching out.

Below are the relevant parts of our product's watchdog configuration. We confirmed that commenting out section 2 prevents the watchdog reset after DFU.

1.Watchdog settings in the bootloader on every boot

#define BOOTLOADER_WATCHDOG_TIMEOUT		(20 * 32768)	// 20-second

static void init_watchdog()
{
	NRF_WDT->CONFIG = (WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos);
	NRF_WDT->CRV = BOOTLOADER_WATCHDOG_TIMEOUT;
	NRF_WDT-> RR [0] = 0x6E524635UL;
	NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos;
	NRF_WDT->TASKS_START = 1; 
}

2.Watchdog feed settings during DFU operation in the bootloader

void nrf_bootloader_wdt_init(void)
{
    static bool initialized = false;
    
    if (initialized)
    {
        return;
    }

    if (nrf_wdt_started())
    {
        uint32_t wdt_ticks = nrf_wdt_reload_value_get();

        NRF_LOG_INFO("WDT enabled CRV:%d ticks", wdt_ticks);

        //wdt_ticks must be reduced to feed the watchdog before the timeout.
        uint32_t reduced_timeout_ticks = MAX((int32_t)wdt_ticks - MAX_FLASH_OP_TIME_TICKS,
                                             NRF_BOOTLOADER_MIN_TIMEOUT_TICKS);

        /* initial watchdog feed */
        wdt_feed();

        NRF_LOG_INFO("Starting a timer (%d ticks) for feeding watchdog.", reduced_timeout_ticks);
        nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler);

        NVIC_EnableIRQ(WDT_IRQn);
    }
    else
    {
        NRF_LOG_INFO("WDT is not enabled");
    }

    initialized = true;
}

3.Watchdog settings during application operation on every boot

	//Configure WDT.
	nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    NRF_LOG_INFO("WatchdogInit reload_value: %d",config.reload_value);
	err_code = nrf_drv_wdt_init(&config, Cradle_wdt_event_handler);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_wdt_channel_alloc(&m_cradle_channel_id);
	APP_ERROR_CHECK(err_code);

every 1sec Kick 

nrf_drv_wdt_feed(); 

The ideal solution for us is to modify only the application to prevent the watchdog reset after DFU.

Any assistance you can provide would be greatly appreciated.

  •  I understand that since the watchdog reload time is already set to 20 seconds in the bootloader, even if it is set again in the application, it remains at 20 seconds instead of 2 seconds.

    The watchdog must be configured before it is started. After it is started,
    the watchdog’s configuration registers, which comprise registers CRV, RREN,
    and CONFIG, will be blocked for further configuration.

     After the operation of step 1(1.Watchdog settings in the bootloader on every boot ), it is true that the watchdog reset was not triggered even without the operation of step 2(2.Watchdog feed settings during DFU operation in the bootloader).

    Can I understand this as meaning that the watchdog is not triggered by just the operation of step 1(1.Watchdog settings in the bootloader on every boot )?"

    Does the watchdog start functioning only after the first feed is given?

  • Hi,

    Do your hardware have the optional 32.768 kHz crystal oscillator? If not, and it use LFRC, there is a bug in the bootloader that manifest itself when using the wtachdog. This is that when the watchdog is active, the LFRC is not reset by a soft reset. However, after reset the clock is only provided to the WDT before explicitly started. However, the status register LFCLKSTAT will indicate that the clock is running even though it is not distributed to the RTC etc. Therefore this implementation in timer_init() nrf_bootloader_dfu_timers.c is incorrect:

            if (!nrf_clock_lf_is_running())
            {
                nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
            }

    and should be simplified so that nrf_clock_task_trigger() is always called:

                nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);

    Without it, the WDT wil lcount down, but not the RTC, so the timer handling wathcdog feedign will not run.

    bilas77 said:

    Can I understand this as meaning that the watchdog is not triggered by just the operation of step 1(1.Watchdog settings in the bootloader on every boot )?"

    Does the watchdog start functioning only after the first feed is given?

    The watchdog starts immediately after triggering the start task (which you do by NRF_WDT->TASKS_START = 1;),. After that, it cannot be re-configured or stopped (though it will be stopped after a watchdog reset or power on reset, but not after a soft reset).

  • Thank you for your answer.

    First of all, our device does not have a 32.768 kHz crystal oscillator, and as you mentioned, it seems that the watchdog feeding timer wasn't working during the bootloader operation. Thank you for pointing that out.

    However, this is a separate issue from our main problem.

    The issue with our device is that the watchdog reset does not occur in the bootloader but happens during the first application execution after a DFU.

    1. Normal Boot (No Watchdog Reset Occurs)

      • The bootloader sets a 20-second watchdog (reload) timer (1. Watchdog settings in the bootloader on every boot).
      • Then, it jumps to the application.
      • In the application, a 2-second watchdog (reload) is set (3. Watchdog settings during application operation on every boot).
      • A software timer (FreeRTOS) feeds the watchdog every second.
      • The watchdog reset does not occur, and the device works normally.
    2. DFU Operation (Watchdog Reset Occurs)

      • DFU reset.
      • The bootloader sets a 20-second watchdog (reload) timer (1. Watchdog settings in the bootloader on every boot).
      • image_copy.
      • In the nrf_bootloader_wdt_init() function, the wdt_feed(); function feeds the watchdog once.
      • nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler) is called.
      • The DFU completes before the watchdog reset occurs.
      • The device moves to the application.
      • In the application, a 2-second watchdog (reload) is set.(3. Watchdog settings during application operation on every boot).
      • A software timer (FreeRTOS) feeds the watchdog every second.
      • After several tens of seconds, the watchdog reset occurs.
    3. DFU Operation (No Watchdog Reset Occurs)

      • DFU reset.
      • The bootloader sets a 20-second watchdog (reload) timer (1. Watchdog settings in the bootloader on every boot).
      • image_copy.
      • In the nrf_bootloader_wdt_init() function, the wdt_feed(); function feeds the watchdog once.
      • nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler) is skipped by commenting out the function.
      • The DFU completes before the watchdog reset occurs.
      • The device moves to the application.
      • In the application, a 2-second watchdog (reload) is set (3. Watchdog settings during application operation on every boot).
      • A software timer (FreeRTOS) feeds the watchdog every second.
      • The device works without the watchdog reset.

    If we compare only step 2 and step 3, it seems that the nrf_bootloader_wdt_feed_timer_start function has something key in it. I’ll analyze other aspects further.

  • Hi,

    It seems the bootloader does not properly clean up after itself before jumping to the application, and it use RTC1 for nrf_bootloader_wdt_feed_timer_start(), which is the same used for FreeRTOS (or app_timer when not using FreeRTOS). The solution should be to reset the RTC1 registers either in the bootloader before starting the application or in the beginning of you rapplication, before initializing FreeRTOS. See this post. Also, the same bug as I described in my initial post also exist in the clock driver, which should be fixed. See this post.

Related