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打开配置(默认关闭),路径如下:

wiota APP -> open wdt, default close(_WATCHDOG_APP_)

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

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

#define WDT_DEVICE_NAME    "wdt"

static rt_device_t wdg_dev = NULL;

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

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

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

    return ret;
}

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


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

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

#endif
Back to top