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

WDT triggered too early

Hi everyone,

I'm using nrf52840 custom board (pca10056)

SDK version: 15.3

OS: Fedora

I work on a custom board and try to use WDT like so in the WTD project example:

int main(void)
{
    uint32_t err_code = NRF_SUCCESS;

    //BSP configuration for button support: button pushing will feed the dog.
    err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);

    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

    // err_code = bsp_init(BSP_INIT_BUTTONS, bsp_event_callback);
    // APP_ERROR_CHECK(err_code);

    //Configure all LEDs on board.
    // bsp_board_init(BSP_INIT_LEDS);
    nrf_gpio_cfg_output(RLED);
    nrf_gpio_cfg_output(GLED);
    nrf_gpio_cfg_output(BLED);
    nrf_gpio_pin_set(RLED);
    nrf_gpio_pin_set(GLED);
    nrf_gpio_pin_set(BLED);

    //Configure WDT.
    nrf_drv_wdt_config_t config  = NRF_DRV_WDT_DEAFULT_CONFIG;
    config.behaviour = NRF_WDT_BEHAVIOUR_RUN_HALT;
    config.reload_value = 360000;
    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();

    //Indicate program start on LEDs.
    // for (uint32_t i = 0; i < LEDS_NUMBER; i++)
    // {   nrf_delay_ms(200);
    //     bsp_board_led_on(i);
    // }
    //  err_code = bsp_buttons_enable();
    //  APP_ERROR_CHECK(err_code);

    nrf_delay_ms(2000);

    led_on(GLED);

    while (1) {
        // __SEV();
        // __WFE();
        // __WFE();
    }
}

When I set the reload value to 10 000ms my WDT is triggered every 10s but when I try 360 000ms (6min) it's triggered approximately at 1min and 30s only...

What am I doing wrong?

Parents
  • Hello, 

    You're not doing anything wrong. The SDK15.3 watchdog init function is here:

    nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
                             nrfx_wdt_event_handler_t  wdt_event_handler)
    {
        NRFX_ASSERT(p_config);
        nrfx_err_t err_code;
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_ASSERT(wdt_event_handler != NULL);
        m_wdt_event_handler = wdt_event_handler;
    #else
        NRFX_ASSERT(wdt_event_handler == NULL);
        (void)wdt_event_handler;
    #endif
        if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
        {
            m_state = NRFX_DRV_STATE_INITIALIZED;
        }
        else
        {
            err_code = NRFX_ERROR_INVALID_STATE;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
    
        nrf_wdt_behaviour_set(p_config->behaviour);
    
        nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000);
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
        NRFX_IRQ_ENABLE(WDT_IRQn);
    #endif
    
        err_code = NRFX_SUCCESS;
        NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }

    the nrfx_wdt_config_t->reload_value is uint32_t.

    When you set the reload to 360 000, it gets multiplied by 32768 which is 11 796 480 000 and the uint32_t overflows. 

    As a fix convert the reload_value to uint64_t before multiplication:

      if((((uint64_t) p_config->reload_value * 32768) / 1000) >
          UINT32_MAX)  // Check for overflow
      {
        return NRF_ERROR_INVALID_PARAM;
      }
      nrf_wdt_reload_value_set(((uint64_t) p_config->reload_value * 32768) / 1000);

Reply
  • Hello, 

    You're not doing anything wrong. The SDK15.3 watchdog init function is here:

    nrfx_err_t nrfx_wdt_init(nrfx_wdt_config_t const * p_config,
                             nrfx_wdt_event_handler_t  wdt_event_handler)
    {
        NRFX_ASSERT(p_config);
        nrfx_err_t err_code;
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_ASSERT(wdt_event_handler != NULL);
        m_wdt_event_handler = wdt_event_handler;
    #else
        NRFX_ASSERT(wdt_event_handler == NULL);
        (void)wdt_event_handler;
    #endif
        if (m_state == NRFX_DRV_STATE_UNINITIALIZED)
        {
            m_state = NRFX_DRV_STATE_INITIALIZED;
        }
        else
        {
            err_code = NRFX_ERROR_INVALID_STATE;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
    
        nrf_wdt_behaviour_set(p_config->behaviour);
    
        nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000);
    
    #if !NRFX_CHECK(NRFX_WDT_CONFIG_NO_IRQ)
        NRFX_IRQ_PRIORITY_SET(WDT_IRQn, p_config->interrupt_priority);
        NRFX_IRQ_ENABLE(WDT_IRQn);
    #endif
    
        err_code = NRFX_SUCCESS;
        NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }

    the nrfx_wdt_config_t->reload_value is uint32_t.

    When you set the reload to 360 000, it gets multiplied by 32768 which is 11 796 480 000 and the uint32_t overflows. 

    As a fix convert the reload_value to uint64_t before multiplication:

      if((((uint64_t) p_config->reload_value * 32768) / 1000) >
          UINT32_MAX)  // Check for overflow
      {
        return NRF_ERROR_INVALID_PARAM;
      }
      nrf_wdt_reload_value_set(((uint64_t) p_config->reload_value * 32768) / 1000);

Children
No Data
Related