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

watchdog with multiple channels fails on nrf52 using zephyr (ncs v1.2.0)

Hi,

I'm using Zephyr with nrf52 and want to setup watchdog support with multiple channels (different timer settings for separate different threads).

I can add 1 channel, but adding two, get's me a fail, error.

This should not happen on the 52, it has support for at least 8 channels I see in the wdt spec for the chip.

I get error when creating the 2nd channel.

Code looks like this:

#define PERIPH_WATCHDOG_TIMEOUT_MS (30 * 1000U)
#define NETWORK_QUEUE_WATCHDOG_TIMEOUT_MS (10 * 1000U)

int watchdog_init()
{
    int error_code = 0;

    LOG_INF("Watchdog starting");

    wdt = device_get_binding(WDT_DEV_NAME);
    if (!wdt)
    {
        LOG_ERR("Cannot get WDT device\n");
        return -ENXIO;
    }
    return error_code;
}

int watchdog_add_channel_timeout(u32_t timeout_ms)
{
    /* Reset SoC when watchdog timer expires. */
    struct wdt_timeout_cfg wdt_config;
    wdt_config.flags = WDT_FLAG_RESET_SOC;

    /* Expire watchdog after 30*1000 milliseconds. */
    wdt_config.window.min = 0U;
    wdt_config.window.max = timeout_ms; // 30 * 1000U;

    /* Set up watchdog callback. Jump into it when watchdog expired. */
    wdt_config.callback = wdt_callback;

    int wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
    if (wdt_channel_id == -ENOTSUP)
    {
        wdt_config.callback = NULL;
        wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
    }

    if (wdt_channel_id < 0)
    {
        LOG_ERR("Watchdog install error");
        return -ENXIO;
    }

    return wdt_channel_id;
}

int watchdog_start()
{
    int error_code = wdt_setup(wdt, 0);
    if (error_code < 0)
    {
        LOG_ERR("Watchdog setup error");
        return error_code;
    }

    return error_code;
}


From main I setup like this:

main()
{
...
    int error_code = watchdog_init();
    if (error_code < 0)
    {
        LOG_ERR("Failed to init watchdog");
    }

    // install periph watchdog channel
    int periph_channel_id = -1;
    periph_channel_id = watchdog_add_channel_timeout(PERIPH_WATCHDOG_TIMEOUT_MS);
    if (periph_channel_id < 0)
    {
        LOG_ERR("Failed to setup periph watchdog timer");
    }

    // install network_queue watchdog channel
    int network_queue_channel_id = -1;
    network_queue_channel_id = watchdog_add_channel_timeout(NETWORK_QUEUE_WATCHDOG_TIMEOUT_MS);
    if (network_queue_channel_id < 0)
    {
        LOG_ERR("Failed to setup network_queue watchdog timer");
    }

    // Finally start the watchdog timer
    watchdog_start();

...

}

  • I tested this with an nRF52840 DK (I don't have an nRF52832 DK available at the moment) and was able to make it work with NCS v1.2.0. I added two channels and configured the timeout to 1 second. In the sample I uploaded, the chip will reset after a second, since only one of the reload registers are fed. 

    watchdog.7z

    Best regards,

    Simon

  • Ok, I see you do set the same timeout for the different timers.
    I want different timeouts for each channel.
    We have different threads, with different challenges, thus different timeouts.

    Sure worst case would be to use the longest needed timeout for every thread, if there can only be one setting for all timers. That would be strange though.

    I might be misunderstanding the usage of channels for the watchdog. Can you explain what is the purpose of channels?

    In my brain, I'm thinking, setting the wdt timeout, and it needs to be feed before it timeouts. One timer only exists, so any thread could reload the wdt. What is a channel I do not understand in this case, since there are not multiple wdt-timers.

    Johan

  • This is unfortunately not possible, if you look in the infocenter you can see that the nRF52840 only has one watchdog, with only one CRV register and counter. This is taken into account in Zephyr and if you try to configure different timeouts for different channels, it will fail in zephyr\drivers\watchdog\wdt_nrfx.c-->wdt_nrf_install_timeout():

    	if (get_dev_data(dev)->m_allocated_channels == 0U) {
            .
            .
        // If choosing different timeouts
    	} else if (cfg->window.max != get_dev_data(dev)->m_timeout) {
    		return -EINVAL;
    	}

    Best regards,

    Simon

  • Yes sure. 
    I got it working with more channels now, due to not trying to change the timer for next channel. Thanks for the help.

Related