高校网站建设滞后,注册网站要多久,室内装饰设计网站,wordpress调用站点标题目录看门狗应用编程介绍打开设备获取设备支持哪些功能#xff1a;WDIOC_GETSUPPORT获取/设置超时时间#xff1a;WDIOC_GETTIMEOUT、WDIOC_SETTIMEOUT开启/关闭看门狗#xff1a;WDIOC_SETOPTIONS喂狗#xff1a;WDIOC_KEEPALIVE看门狗应用编程实战在产品化的嵌入式系统中WDIOC_GETSUPPORT获取/设置超时时间WDIOC_GETTIMEOUT、WDIOC_SETTIMEOUT开启/关闭看门狗WDIOC_SETOPTIONS喂狗WDIOC_KEEPALIVE看门狗应用编程实战在产品化的嵌入式系统中为了使系统在异常情况下能自动复位一般都需要引入看门狗。看门狗其实就是一个可以在一定时间内被复位的计数器。当看门狗启动后计数器开始自动计数经过一定时间如果没有被复位计数器溢出就会对CPU 产生一个复位信号使系统重启俗称“被狗咬”。系统正常运行时需要在看门狗允许的时间间隔内对看门狗计数器清零俗称“喂狗”不让复位信号产生。如果系统不出问题程序保证按时“喂狗”一旦程序跑飞没有“喂狗”系统“被咬”复位。看门狗应用编程介绍 
前面已经说到看门狗其实就是一个可以在一定时间内被复位/重置的计数器一般叫做看门狗计时器或看门狗定时器如果在规定时间内没有复位看门狗计时器计数器溢出则会对CPU 产生一个复位信号使系统重启当然有些看门狗也可以只产生中断信号而不会使系统复位。 I.MX6UL/I.MX6ULL SoC 集成了两个看门狗定时器WDOGWDOG1 和WDOG2WDOG2 用于安全目的而WDOG1 则是一个普通的看门狗支持产生中断信号以及复位CPU。 Linux 系统中所注册的看门狗外设都会在/dev/目录下生成对应的设备节点设备文件设备节点名称通常为watchdogXX 表示一个数字编号0、1、2、3 等譬如/dev/watchdog0、/dev/watchdog1 等通过这些设备节点可以控制看门狗外设。  这个watchdog0 其实就是I.MX6U 的WDOG1 所对应的设备节点从图中可知除了/dev/watchdog0 之外还有一个watchdog 设备节点这个设备节点的名称没有后面的数字编号这个又是什么意思呢因为系统中可能注册了多个看门狗设备/dev/watchdog 设备节点则代表系统默认的看门狗设备通常这指的就是watchdog0所以上图中/dev/watchdog 其实就等于/dev/watchdog0也就意味着它俩代表的是同一个硬件外设。 应用层控制看门狗其实非常简单通过ioctl()函数即可做到接下来笔者向大家进行介绍。 首先在我们的应用程序中需要包含头文件linux/watchdog.h头文件该头文件中定义了一些ioctl 指令宏每一个不同的指令宏表示向设备请求不同的操作如下所示 
#define WDIOC_GETSUPPORT 		_IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
#define WDIOC_GETSTATUS 		_IOR(WATCHDOG_IOCTL_BASE, 1, int)
#define WDIOC_GETBOOTSTATUS 	_IOR(WATCHDOG_IOCTL_BASE, 2, int)
#define WDIOC_GETTEMP 			_IOR(WATCHDOG_IOCTL_BASE, 3, int)
#define WDIOC_SETOPTIONS 		_IOR(WATCHDOG_IOCTL_BASE, 4, int)
#define WDIOC_KEEPALIVE 		_IOR(WATCHDOG_IOCTL_BASE, 5, int)
#define WDIOC_SETTIMEOUT 		_IOWR(WATCHDOG_IOCTL_BASE, 6, int)
#define WDIOC_GETTIMEOUT 		_IOR(WATCHDOG_IOCTL_BASE, 7, int)
#define WDIOC_SETPRETIMEOUT 	_IOWR(WATCHDOG_IOCTL_BASE, 8, int)
#define WDIOC_GETPRETIMEOUT 	_IOR(WATCHDOG_IOCTL_BASE, 9, int)
#define WDIOC_GETTIMELEFT 		_IOR(WATCHDOG_IOCTL_BASE, 10, int)比较常用指令包括WDIOC_GETSUPPORT 、WDIOC_SETOPTIONS 、WDIOC_KEEPALIVE 、 WDIOC_SETTIMEOUT、WDIOC_GETTIMEOUT说明如下  
打开设备 
首先在调用ioctl()函数之前需要先打开看门狗设备得到文件描述符如下所示 
int fd;fd  open(/dev/watchdog, O_RDWR);
if (0  fd)fprintf(stderr, open error: %s: %s\n, /dev/watchdog, strerror(errno));获取设备支持哪些功能WDIOC_GETSUPPORT 
使用WDIOC_GETSUPPORT 指令获取看门狗设备支持哪些功能使用方式如下 ioctl(int fd, WDIOC_GETSUPPORT, struct watchdog_info *info); 使用WDIOC_GETSUPPORT 指令可以获取设备的信息调用ioctl()需要传入一个struct watchdog_info *指针ioctl()会将获取到的数据写入到info 指针所指向的对象中。struct watchdog_info 结构体描述了看门狗设备的信息我们来看看struct watchdog_info 结构体的定义 
struct watchdog_info {__u32 options; /* Options the card/driver supports */__u32 firmware_version; /* Firmware version of the card */__u8 identity[32]; /* Identity of the board */
};options 字段记录了设备支持哪些功能或选项 firmware_version 字段记录了设备的固件版本号 identity 字段则是一个描述性的字符串。 我们重点关注的是options 字段该字段描述了设备支持哪些功能、选项该字段的值如下可以是以下任意一个值或多个值的位或关系 
#define WDIOF_OVERHEAT 0x0001 /* Reset due to CPU overheat */
#define WDIOF_FANFAULT 0x0002 /* Fan failed */
#define WDIOF_EXTERN1 0x0004 /* External relay 1 */
#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */
#define WDIOF_ALARMONLY 0x0400 /* Watchdog triggers a management or other external alarm not a reboot */
#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */一般常见的值包括WDIOF_SETTIMEOUT、WDIOF_KEEPALIVEPINGWDIOF_SETTIMEOUT 表示设备支持设置超时时间WDIOF_KEEPALIVEPING 表示设备支持“喂狗”操作也就是重置看门狗计时器。 使用示例如下 
struct watchdog_info info;if (0  ioctl(fd, WDIOC_GETSUPPORT, info)) {fprintf(stderr, ioctl error: WDIOC_GETSUPPORT: %s\n, strerror(errno));return -1;
}printf(identity: %s\n, info.identity);
printf(version: %u\n, firmware_version);if (0  (WDIOF_KEEPALIVEPING  info.options))printf(设备不支持喂狗操作\n);
if (0  (WDIOF_SETTIMEOUT  info.options))printf(设备不支持设置超时时间\n);获取/设置超时时间WDIOC_GETTIMEOUT、WDIOC_SETTIMEOUT 
使用WDIOC_GETTIMEOUT 指令可获取设备当前设置的超时时间使用方式如下 
ioctl(int fd, WDIOC_GETTIMEOUT, int *timeout);使用WDIOC_SETTIMEOUT 指令可设置看门狗的超时时间使用方式如下 
ioctl(int fd, WDIOC_SETTIMEOUT, int *timeout);超时时间是以秒为单位设置超时时间时不可超过其最大值、否则ioctl()调用将会失败使用示例如下所示 
int timeout;/* 获取超时时间*/
if (0  ioctl(fd, WDIOC_GETTIMEOUT, timeout)) {fprintf(stderr, ioctl error: WDIOC_GETTIMEOUT: %s\n, strerror(errno));return -1;
}printf(current timeout: %ds\n, timeout);/* 设置超时时间*/
timeout  10; //10 秒钟
if (0  ioctl(fd, WDIOC_SETTIMEOUT, timeout)) {fprintf(stderr, ioctl error: WDIOC_SETTIMEOUT: %s\n, strerror(errno));return -1;
}开启/关闭看门狗WDIOC_SETOPTIONS 
设置好超时时间之后接着便可以开启看门狗计时了使用WDIOC_SETOPTIONS 指令可以开启看门狗计时或停止看门狗计时使用方式如下 
ioctl(int fd, WDIOC_SETOPTIONS, int *option);option 指针指向一个int 类型变量该变量可取值如下 
#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */
#define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */WDIOS_DISABLECARD 表示停止看门狗计时WDIOS_ENABLECARD 则表示开启看门狗计时。 使用示例如下所示 
int option  WDIOS_ENABLECARD; //开启
//int option  WDIOS_DISABLECARD; //停止if (0  ioctl(fd, WDIOC_SETOPTIONS, option)) {fprintf(stderr, ioctl error: WDIOC_SETOPTIONS: %s\n, strerror(errno));return -1;
}需要注意的是当调用open()打开看门狗设备的时候即使程序中没有开启看门狗计时器当close()关闭设备时看门狗会自动启动所以当打开设备之后需要使用WDIOC_SETOPTIONS 指令停止看门狗计时等所有设置完成之后再开启看门狗计时器。 
喂狗WDIOC_KEEPALIVE 
看门狗计时器启动之后我们需要在超时之前去“喂狗”否则计时器溢出超时将会导致系统复位或产生一个中断信号通过WDIOC_KEEPALIVE 指令喂狗使用方式如下 ioctl(int fd, WDIOC_KEEPALIVE, NULL); 使用示例如下 
if (0  ioctl(fd, WDIOC_KEEPALIVE, NULL)) {fprintf(stderr, ioctl error: WDIOC_KEEPALIVE: %s\n, strerror(errno));
}看门狗应用编程实战 
通过上小节介绍之后我们已经知道了如何编写应用程序去控制看门狗外设了本小节我们来编写一个简单地看门狗应用程序示例代码如下所示 本例程源码对应的路径为开发板光盘-11、Linux C 应用编程例程源码-27_watchdog-watchdog_test.c。 
/***************************************************************Copyright © ALIENTEK Co., Ltd. 1998-2021. All rights reserved.文件名 : watchdog_test.c作者 : 邓涛版本 : V1.0描述 : 看门狗应用程序示例代码其他 : 无论坛 : www.openedv.com日志 : 初版 V1.0 2021/7/14 邓涛创建***************************************************************/#include stdio.h
#include stdlib.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include sys/ioctl.h
#include errno.h
#include string.h
#include linux/watchdog.h#define  WDOG_DEV   /dev/watchdogint main(int argc, char *argv[])
{struct watchdog_info info;int timeout;int time;int fd;int op;if (2 ! argc) {fprintf(stderr, usage: %s timeout\n, argv[0]);exit(EXIT_FAILURE);}/* 打开看门狗 */fd  open(WDOG_DEV, O_RDWR);if (0  fd) {fprintf(stderr, open error: %s: %s\n, WDOG_DEV, strerror(errno));exit(EXIT_FAILURE);}/* 打开之后看门狗计时器会开启、先停止它 */op  WDIOS_DISABLECARD;if (0  ioctl(fd, WDIOC_SETOPTIONS, op)) {fprintf(stderr, ioctl error: WDIOC_SETOPTIONS: %s\n, strerror(errno));close(fd);exit(EXIT_FAILURE);}timeout  atoi(argv[1]);if (1  timeout)timeout  1;/* 设置超时时间 */printf(timeout: %ds\n, timeout);if (0  ioctl(fd, WDIOC_SETTIMEOUT, timeout)) {fprintf(stderr, ioctl error: WDIOC_SETTIMEOUT: %s\n, strerror(errno));close(fd);exit(EXIT_FAILURE);}/* 开启看门狗计时器 */op  WDIOS_ENABLECARD;if (0  ioctl(fd, WDIOC_SETOPTIONS, op)) {fprintf(stderr, ioctl error: WDIOC_SETOPTIONS: %s\n, strerror(errno));close(fd);exit(EXIT_FAILURE);}/* 喂狗 */time  (timeout * 1000 - 100) * 1000;//喂狗时间设置us微秒、在超时时间到来前100ms喂狗for ( ; ; ) {usleep(time);ioctl(fd, WDIOC_KEEPALIVE, NULL);}
}示例代码很简单首先打开看门狗设备接着使用WDIOC_SETOPTIONS 指令op  WDIOS_DISABLECARD先停止看门狗计时器接着通过atoi 获取到用户传入的超时时间所以执行该测试程序的时候需要传入一个参数作为看门狗超时时间。 接着使用WDIOC_SETTIMEOUT 指令设置超时时间再使用WDIOC_SETOPTIONS 指令op  WDIOS_ENABLECARD开启看门狗计时器看门狗开始工作。接着我们需要在超时时间到来之前去喂狗喂狗之后计时器重置重新计时不断地喂狗重置计时器、不让其超时、如果一旦超时系统将会复位重启。 编译示例代码  将编译得到的可执行文件拷贝到开发板Linux 系统/home/root 目录下执行测试程序譬如启动看门狗设置超时时间为2 秒钟如下  执行程序之后开门狗计时器就已经启动了程序中会不断的喂狗重置计时器以保证程序不会重启。 现在我们按Ctrl  C 结束程序结束程序意味着已经停止喂狗了、然后看门狗计时器并没有停止这样将会导致计时器溢出、发生复位重启  当按CtrlC 终止进程后内核打印出“watchdog watchdog0: watchdog did not stop!”信息表示看门狗计时器还正在计时、未停止。