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

WDT in bootloader

I have a nrf51-DK, SDK 9.0, S110, dual-bank bootloader that supports both serial and ble protocols, developed using GCC/Eclipse. My application uses the watchdog timer. I have the ability to switch to the bootloader from the app using a button press in order to do either do a DFU or a system reset. I realize the WDT is still running, so I've added a timer in the bootloader to feed the watchdog. I'm also toggling an LED in the same timer service routine, so I can verify that I'm getting there. Here's my code in the app for switching to the bootloader:

void app_reset(bool enter_dfu)
{
    m_reset_prepare();

    if (enter_dfu)
    {
        // Tell the bootloader to go into DFU mode
        err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
        APP_ERROR_CHECK(err_code);

        err_code = sd_softdevice_disable();
        APP_ERROR_CHECK(err_code);

        err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR);
        APP_ERROR_CHECK(err_code);

        //dfu_app_peer_data_set(conn_handle);

        NVIC_ClearPendingIRQ(SWI2_IRQn);
        interrupts_disable();
        bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR);
    }
    else
    {
        sd_nvic_SystemReset();
    }
}

And here's my wdt init code which is called from the app:

void wdt_init(void)
{
    uint32_t err_code = NRF_SUCCESS;

    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();
}

And here's my code in the bootloader to feed the watchdog:

#define WD_FEED_INTERVAL  APP_TIMER_TICKS(500, APP_TIMER_PRESCALER)
static void timers_start(void)
{
    uint32_t err_code;

    // Start timer.
    err_code = app_timer_start(m_wd_feed_timer_id, WD_FEED_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);
}
static void wd_feed_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    nrf_drv_wdt_feed();
    nrf_gpio_pin_toggle(BSP_LED_3);
}

If I switch to the bootloader using the "enter_dfu" path, the watchdog timer resets the system several seconds after switching over to the bootloader - the LED flashes several times, and then the unit resets. If I switch to the bootloader using the "else" path, I also get a watchdog reset in the bootloader. If I comment out starting the watchdog in the app, both paths work fine.

Is there wdt setup that needs to be done in the bootloader? I've tried various iterations of what's in wdt_init(), but have not come up with anything that works. I'm assuming the setup in the app is sufficient, but maybe not. What am I missing?

Parents
  • The WDT keeps running in DFU mode as well as you've noticed. So it needs to be reloaded in the bootloader. So it seems like the wd_feed_timeout_handler() is not being called in time, or that the interval is too short.

    Another alternative to creating an additional timer instance is to add nrf_drv_wdt_feed() function to the wait_for_events() loop in bootloader.c. Thus, WDT will be reloaded whenever an event has occurred. Just change the APP_ADV_TIMEOUT_IN_SECONDS to also get events when advertising openly (advertising will restart automaticcally on timeout events, so no actual timeout).

  • Thanks for the suggestions Vidar. My original code had a 500 ms timer to feed the watchdog. Even at 50 ms, I could see the LED flashing for several seconds which I was also toggling on the timer callback. I increased the timer frequency to 100 ms. I see the LED blinking faster now for several seconds, but then the board resets. I also added the code to feed the watchdog from wait_for_events(), but that didn't help either. Any idea why I'm unable to feed the watchdog in the bootloader?

Reply
  • Thanks for the suggestions Vidar. My original code had a 500 ms timer to feed the watchdog. Even at 50 ms, I could see the LED flashing for several seconds which I was also toggling on the timer callback. I increased the timer frequency to 100 ms. I see the LED blinking faster now for several seconds, but then the board resets. I also added the code to feed the watchdog from wait_for_events(), but that didn't help either. Any idea why I'm unable to feed the watchdog in the bootloader?

Children
No Data
Related