Skip to content

WATCHDOG设备

WATCHDOG简介

硬件看门狗(watchdog timer)是一个定时器,其定时输出连接到电路的复位端。在产品化的嵌入式系统中,为了使系统在异常情况下能自动复位,一般都需要引入看门狗。当看门狗启动后,计数器开始自动计数,在计数器溢出前如果没有被复位,计数器溢出就会对 CPU 产生一个复位信号使系统重启(俗称 “被狗咬”)。系统正常运行时,需要在看门狗允许的时间间隔内对看门狗计数器清零(俗称“喂狗“),不让复位信号产生。如果系统不出问题,程序能够按时“喂狗”。一旦程序发生跑飞、死锁等情况,没有“喂狗”,系统“被咬”导致复位。

驱动支持

访问WATCHDOG设备前,需要保证相关驱动配置已选中。

Windows环境:利用RT-Thread官方env工具直接在代码根目录下执行menuconfig进入配置。

Linux环境:在代码根目录下执行scons --menuconfig进入配置。

WATCHDOG驱动所在路径如下:

RT-Thread Components -> Device Drivers -> Using Watch Dog device drivers

访问WATCHDOG设备

访问WATCHDOG设备,库中提供了以下接口:

函数 描述
rt_device_find() 根据WATCHDOG名称查找设备获取设备句柄
rt_device_control() 控制WATCHDOG设备

查找WATCHDOG设备

查找WATCHDOG设备,函数原型如下所示:

rt_device_t rt_device_find(const char* name);
  • 参数

    [IN]name:WATCHDOG设备名称,目前注册到的系统中的WATCHDOG设备名称为"wdt"。

  • 返回值

    RT_NULL:失败,设备不存在。

    非RT_NULL:成功,该返回值是操作WATCHDOG设备的句柄,在后续的接口中作为函数入参。

控制WATCHDOG设备

控制指定WATCHDOG设备,函数原型如下所示:

rt_err_t rt_device_control(rt_device_t dev, int cmd, void* arg);
  • 参数

    [IN]dev:WATCHDOG设备句柄,查找设备函数的返回值

    [IN]cmd:命令控制字,在这里主要支持以下宏定义

    // 宏定义所在文件相对路径:
    // rt-thread/components/drivers/include/drivers/watchdog.h
    #define RT_DEVICE_CTRL_WDT_GET_TIMEOUT    (1) /* 获取溢出时间 */
    #define RT_DEVICE_CTRL_WDT_SET_TIMEOUT    (2) /* 设置溢出时间 */
    #define RT_DEVICE_CTRL_WDT_KEEPALIVE      (4) /* 喂狗 */
    #define RT_DEVICE_CTRL_WDT_START          (5) /* 启动看门狗 */
    #define RT_DEVICE_CTRL_WDT_STOP           (6) /* 停止看门狗 */
    

    [INOUT]arg:输入/输出值,类型为(rt_uint32_t *)。

  • 返回值

    0,正常

    其他:错误,RT-Thread定义的错误类型。

WATCHDOG使用示例

使用示例需要配置menuconfig,使能例程与外设,步骤如下:

  1. 使能例程
Application Example Config -> Enable Watchdog Example
  1. 使能外设驱动
Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable WDT

以下提供WATCHDOG测试实例,测试步骤如下:

  1. 根据WATCHDOG设备名称,获取WATCHDOG设备句柄。
  2. 设置WATCHDOG输出。
#include <rtthread.h>
#ifdef APP_EXAMPLE_WATCHDOG

#ifndef RT_USING_WDT
#error "Please enable rt-thread wdt device driver"
#endif

#ifndef BSP_USING_WDT
#error "Please enable on-chip peripheral wdt config"
#endif

#include <rtdevice.h>
#include "uc_watchdog_app.h"

#define WDT_DEVICE_NAME "wdt"

#define WACHDOG_KEEP_TIMEOUT 5

static rt_device_t wdg_dev = NULL;

static void idle_watchdog_hook(void)
{
    rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
}

static int watchdog_app_disable(void)
{
    rt_err_t ret = RT_EOK;

    ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_STOP, RT_NULL);
    if (ret != RT_EOK)
    {
        rt_kprintf("start %s failed!\n", WDT_DEVICE_NAME);
        return -RT_ERROR;
    }

    return ret;
}

static int watchdog_app_enable(void)
{
    rt_err_t ret = RT_EOK;

    ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL);
    if (ret != RT_EOK)
    {
        rt_kprintf("start %s failed!\n", WDT_DEVICE_NAME);
        return -RT_ERROR;
    }

    return ret;
}

static void watchdog_app_close(void)
{
    watchdog_app_disable();
    rt_thread_idle_delhook(idle_watchdog_hook);
}

int watchdog_app_sample(void)
{
    rt_err_t ret = RT_EOK;
    rt_uint32_t timeout = WACHDOG_KEEP_TIMEOUT;

    rt_kprintf("watchdog_app_sample\n");

    wdg_dev = rt_device_find(WDT_DEVICE_NAME);
    if (!wdg_dev)
    {
        rt_kprintf("find %s failed!\n", WDT_DEVICE_NAME);
        return -RT_ERROR;
    }

    ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
    if (ret != RT_EOK)
    {
        rt_kprintf("set %s timeout failed!\n", WDT_DEVICE_NAME);
        return -RT_ERROR;
    }

    rt_thread_idle_sethook(idle_watchdog_hook);

    watchdog_app_enable();
    rt_kprintf("enable %s success!\n", WDT_DEVICE_NAME);

    rt_kprintf("current tick is %d\n", rt_tick_get());
    rt_kprintf("delay wdt for %d seconds, the iddle thread will feed the dog twice\n", (WACHDOG_KEEP_TIMEOUT * 2));
    rt_kprintf("current tick is %d, wait for %d seconds\n", rt_tick_get(), (WACHDOG_KEEP_TIMEOUT * 2));
    rt_thread_delay((WACHDOG_KEEP_TIMEOUT * 2) * 1000);
    rt_kprintf("current tick is %d\n", rt_tick_get());
    rt_kprintf("The chip is dead, please wait for the watchdog to restart the chip...\n");
    rt_kprintf("The watchdog will restart the chip in %d seconds...\n", WACHDOG_KEEP_TIMEOUT);
    while (1)
    {
        ;
    }

    return RT_EOK;
}

#endif
Back to top