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).

Reply
  • 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).

Children
Related