RT-Thread设备框架使用指南之——WATCHDOG 设备

WATCHDOG 简介

硬件看门狗(watchdog timer)是一个定时器,其定时输出连接到电路的复位端。在产品化的嵌入式系统中,为了使系统在异常情况下能自动复位,一般都需要引入看门狗。

当看门狗启动后,计数器开始自动计数,在计数器溢出前如果没有被复位,计数器溢出就会对 CPU 产生一个复位信号使系统重启(俗称 “被狗咬”)。系统正常运行时,需要在看门狗允许的时间间隔内对看门狗计数器清零(俗称“喂狗“),不让复位信号产生。如果系统不出问题,程序能够按时“喂狗”。一旦程序跑飞,没有“喂狗”,系统“被咬” 复位。

访问看门狗设备

应用程序通过 RT-Thread 提供的 I/O 设备管理接口来访问看门狗硬件,相关接口如下所示:

函数原型 功能简介
rt_device_find() 根据看门狗设备设备名称查找设备获取设备句柄
rt_device_init() 初始化看门狗设备
rt_device_control() 控制看门狗设备
rt_device_close() 关闭看门狗设备

查找看门狗

应用程序根据看门狗设备名称获取设备句柄,进而可以操作看门狗设备,查找设备函数如下所示:

1rt_device_t rt_device_find(const char* name);
参数 描述
name 看门狗设备名称
返回 ——
设备句柄 查找到对应设备将返回相应的设备句柄
RT_NULL 没有找到相应的设备对象

使用示例如下所示:

1#define IWDG_DEVICE_NAME    "iwg"    /* 看门狗设备名称 */
2
3static rt_device_t wdg_dev;         /* 看门狗设备句柄 */
4/* 根据设备名称查找看门狗设备,获取设备句柄 */
5wdg_dev = rt_device_find(IWDG_DEVICE_NAME);

初始化看门狗

使用看门狗设备前需要先初始化,通过如下函数初始化看门狗设备:

1rt_err_t rt_device_init(rt_device_t dev);
参数 描述
dev 看门狗设备句柄
返回 ——
RT_EOK 设备初始化成功
-RT_ENOSYS 初始化失败,看门狗设备驱动初始化函数为空
其他错误码 设备打开失败

使用示例如下所示:

1#define IWDG_DEVICE_NAME    "iwg"    /* 看门狗设备名称 */
2
3static rt_device_t wdg_dev;    /* 看门狗设备句柄 */
4/* 根据设备名称查找看门狗设备,获取设备句柄 */
5wdg_dev = rt_device_find(IWDG_DEVICE_NAME);
6
7/* 初始化设备 */
8rt_device_init(wdg_dev);

控制看门狗

通过命令控制字,应用程序可以对看门狗设备进行配置,通过如下函数完成:

1rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
参数 描述
dev 看门狗设备句柄
cmd 命令控制字
arg 控制的参数
返回 ——
RT_EOK 函数执行成功
-RT_ENOSYS 执行失败,dev 为空
其他错误码 执行失败

命令控制字可取如下宏定义值:

1#define RT_DEVICE_CTRL_WDT_GET_TIMEOUT    (1) /* 获取溢出时间 */
2#define RT_DEVICE_CTRL_WDT_SET_TIMEOUT    (2) /* 设置溢出时间 */
3#define RT_DEVICE_CTRL_WDT_GET_TIMELEFT   (3) /* 获取剩余时间 */
4#define RT_DEVICE_CTRL_WDT_KEEPALIVE      (4) /* 喂狗 */
5#define RT_DEVICE_CTRL_WDT_START          (5) /* 启动看门狗 */
6#define RT_DEVICE_CTRL_WDT_STOP           (6) /* 停止看门狗 */

设置看门狗溢出时间使用示例如下所示:

 1#define IWDG_DEVICE_NAME    "iwg"    /* 看门狗设备名称 */
 2
 3rt_uint32_t timeout = 1000;    /* 溢出时间 */
 4static rt_device_t wdg_dev;    /* 看门狗设备句柄 */
 5/* 根据设备名称查找看门狗设备,获取设备句柄 */
 6wdg_dev = rt_device_find(IWDG_DEVICE_NAME);
 7/* 初始化设备 */
 8rt_device_init(wdg_dev);
 9
10/* 设置看门狗溢出时间 */
11rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, (void *)timeout);
12/* 设置空闲线程回调函数 */
13rt_thread_idle_sethook(idle_hook);

在空闲线程钩子函数里喂狗使用示例如下所示:

1static void idle_hook(void)
2{
3    /* 在空闲线程的回调函数里喂狗 */
4    rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
5}

关闭看门狗

当应用程序完成看门狗操作后,可以关闭看门狗设备,通过如下函数完成:

1rt_err_t rt_device_close(rt_device_t dev);
参数 描述
dev 看门狗设备句柄
返回 ——
RT_EOK 关闭设备成功
-RT_ERROR 设备已经完全关闭,不能重复关闭设备
其他错误码 关闭设备失败

关闭设备接口和打开设备接口需配对使用,打开一次设备对应要关闭一次设备,这样设备才会被完全关闭,否则设备仍处于未关闭状态。

看门狗设备使用示例

看门狗设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:

  1. 首先根据设备名称 “iwg” 查找设备获取设备句柄。

  2. 初始化设备后设置看门狗溢出时间。

  3. 设置空闲线程回调函数。

  4. 当系统执行空闲线程时就会运行此回调函数,并喂狗。

 1/*
 2 * 程序清单:这是一个独立看门狗设备使用例程
 3 * 例程导出了 iwdg_sample 命令到控制终端
 4 * 命令调用格式:iwdg_sample iwg
 5 * 命令解释:命令第二个参数是要使用的看门狗设备名称,为空则使用例程默认的看门狗设备。
 6 * 程序功能:程序通过设备名称查找看门狗设备,然后初始化设备并设置看门狗设备溢出时间。
 7 *           然后设置空闲线程回调函数,在回调函数里会喂狗。
 8*/
 9
10#include 
11#include 
12
13#define IWDG_DEVICE_NAME    "iwg"    /* 看门狗设备名称 */
14
15static rt_device_t wdg_dev;         /* 看门狗设备句柄 */
16
17static void idle_hook(void)
18{
19    /* 在空闲线程的回调函数里喂狗 */
20    rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
21    rt_kprintf("feed the dog!\n ");
22}
23
24static int iwdg_sample(int argc, char *argv[])
25{
26    rt_err_t ret = RT_EOK;
27    rt_uint32_t timeout = 1000;    /* 溢出时间 */
28    char device_name[RT_NAME_MAX];
29
30    /* 判断命令行参数是否给定了设备名称 */
31    if (argc == 2)
32    {
33        rt_strncpy(device_name, argv[1], RT_NAME_MAX);
34    }
35    else
36    {
37        rt_strncpy(device_name, IWDG_DEVICE_NAME, RT_NAME_MAX);
38    }
39    /* 根据设备名称查找看门狗设备,获取设备句柄 */
40    wdg_dev = rt_device_find(device_name);
41    if (!wdg_dev)
42    {
43        rt_kprintf("find %s failed!\n", device_name);
44        return RT_ERROR;
45    }
46    /* 初始化设备 */
47    ret = rt_device_init(wdg_dev);
48    if (ret != RT_EOK)
49    {
50        rt_kprintf("initialize %s failed!\n", device_name);
51        return RT_ERROR;
52    }
53    /* 设置看门狗溢出时间 */
54    ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
55    if (ret != RT_EOK)
56    {
57        rt_kprintf("set %s timeout failed!\n", device_name);
58        return RT_ERROR;
59    }
60    /* 设置空闲线程回调函数 */
61    rt_thread_idle_sethook(idle_hook);
62
63    return ret;
64}
65/* 导出到 msh 命令列表中 */
66MSH_CMD_EXPORT(iwdg_sample, iwdg sample);

你可能感兴趣的:(RT-THREAD)