Watchdog使用参考
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 04/21/2023 |
1. 概述¶
Watchdog即硬件看门狗,它提供超时复位系统的功能,其功能由定时器和复位功能组成,用户可以设定一个超时时间,并在超时时间以内对它进行“喂狗”的操作,重置其内部计数,如果其内部计算达到了设定的超时时间,就会对系统进行复位重启系统。
本文中的“WDT”、“看门狗”、“Watchdog”皆为概述中提到的本功能。
2. 关键字说明¶
-
watchdog
看门狗,是一个定时器电路,一般有一个输入,叫喂狗(kicking the dog/service the dog),一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给 WDT清零,如果超过规定的时间不喂狗(一般在程序跑飞时),WDT定时超过,就会给出一个复位信号到MCU,使MCU复位。防止MCU死机. 看门狗的作用就是防止程序发生死循环,或者说程序跑飞。
-
watchdog timeout
看门狗的超时时长,如果超过这个时长不喂狗,WDT定时超过,就会给出一个复位信号到MCU,使MCU复位。
-
watchdog pretimeout
看门狗的预超时时长。pretimeout是触发时间到系统重启时间点的长度。比如,如果你设置timeout为60, pretimeout为50,那么在50秒的时候(重启之前的 10秒)将触发机关。
3. 功能描述¶
linux 内核支持基于 hrtimer 的 softdog 和基于硬件的硬件看门狗,创建 /dev/watchdog* 设备文件与用户空间程序进行交互。用户空间的 watchdog 程序,会通过/dev/watchdog* 设备进行周期性喂狗。
4. 硬件连接介绍¶
NA
5. Uboot用法介绍¶
5.1. uboot config配置¶
Watchdog 驱动相关的 CONFIG 配置如下:
(1) CONFIG_SSTAR_WDT:
[*] SigmaStar drivers ---> [*] Sigmastar watchdog
(2) CONFIG_WATCHDOG_AUTOSTART和CONFIG_WATCHDOG_TIMEOUT_MSECS:
[*] Device Drivers ---> [*] Watchdog Timer Support ---> [*] Automatically start watchdog timer [*] Watchdog timeout in msec
-
CONFIG_WATCHDOG_AUTOSTART=Y则uboot启动的时候以WATCHDOG_TIMEOUT_MSECS为超时时间启动watchdog
-
CONFIG_WATCHDOG_TIMEOUT_MSECS默认值为2000,也就是2s
(3) CONFIG_WATCHDOG:
[*] Device Drivers ---> [*] Watchdog Timer Support ---> [*] Enable U-Boot watchdog reset
-
开启这个宏,uboot每隔一秒喂一次狗
-
如果开启了CONFIG_WATCHDOG_AUTOSTART但是不开启CONFIG_WATCHDOG,系统在WATCHDOG_TIMEOUT_MSECS ms后将重启
5.2. Dts配置¶
Watchdog 驱动相关的 DTS 配置如下:
watchdog: watchdog { compatible = "sstar,wdt"; reg = <0x1F006000 0x40>; status = "okay"; };
watchdog DTS配置说明:
属性 | 描述 | 设定值 | 备注 |
---|---|---|---|
compatible | 匹配驱动进行驱动注册 | "sstar,wdt" | 禁止修改 |
reg | watchdog寄存器信息 | 硬件设计决定 | 禁止修改 |
status | 选择是否使能watchdog驱动 | "ok" or "disable" | 可根据需要修改 |
5.3. Uboot cmd参数说明¶
-
列出可用的watchdog:
wdt list - list watchdog devices
参数名称 描述 NA NA -
获取/设置当前watchdog设备:
wdt dev [<name>] - get/set current watchdog device
参数名称 描述 name 不带参数时为获取当前操作的 watchdog 设备名称 -
启动watchdog:
wdt start <timeout ms> [flags] - start watchdog timer
参数名称 描述 timeout ms 指定 watchdog 的超时时间,单位为毫秒 flags 传递给 watchdog 驱动的 flags 信息,当前驱动未使用该参数 -
停止watchdog:
wdt stop - stop watchdog timer
参数名称 描述 NA NA -
复位 watchdog 计时:
wdt reset - reset watchdog timer
参数名称 描述 NA NA -
立刻触发 watchdog 超时:
wdt expire [flags] - expire watchdog timer immediately
参数名称 描述 flag NA wdt expire
命令的作用为立刻触发watchdog超时,U-Boot原生的实现为将超时设置为1ms,当前硬件不支持此命令。
5.4. Uboot cmd 使用实例¶
wdt list → wdt list // wdt dev [<name>] → wdt dev watchdog // 使用名字为watchdog这个watchdog wdt start <timeout ms> [flags] → wdt start 10000 //设置watchdog超时时间为10s wdt reset → wdt reset //在watchdog未超时前,复位watchdog计时 wdt stop → wdt stop // 在watchdog未超时前,停止watchdog
使用这个功能进行测试时需要先关闭CONFIG_WATCHDOG 和CONFIG_WATCHDOG_AUTOSTART,否则uboot系统每隔一段时间会自动ping一次watchdog,你无法测试wdt start功能。
6. Kernel用法介绍¶
6.1. CONFIG 配置¶
Watchdog 驱动相关的 CONFIG 配置如下:
Device Drivers ---> [*] SStar SoC platform drivers ---> <*> watchdog driver
6.2. DTS 配置¶
Watchdog 驱动相关的 DTS 配置如下:
WDT: watchdog { compatible = "sstar,wdt"; reg = <0x0 0x1F006000 0x0 0x40>; interrupts = <GIC_SPI INT_FIQ_WDT IRQ_TYPE_LEVEL_HIGH>; max-length = <40>; status = "okay"; };
watchdog DTS配置说明:
属性 | 描述 | 设定值 | 备注 |
---|---|---|---|
compatible | 匹配驱动进行驱动注册 | "sstar,wdt" | 禁止修改 |
reg | 设定寄存器bank地址 | 硬件设计决定 | 禁止修改 |
interrupts | 指定 Watchdog 使用的硬件中断号 | 硬件设计决定 | 禁止修改 |
max-length | watchdog计数宽带 | 硬件设计决定 | 禁止修改 |
status | 选择是否使能Watchdog驱动 | "ok" or "disable" | 可根据需要修改 |
6.3. Padmux配置¶
NA
6.4. 模块使用介绍¶
6.4.1. SYSFS 使用方法¶
NA
6.4.2. ioctl使用方法¶
头文件include/uapi/linux/watchdog.h,struct watchdog_info结构体是对描述了看门狗设备的信息
-
WDIOC_GETSUPPORT:获取看门狗支持哪些功能
-
WDIOC_SETOPTIONS:用于开启或关闭看门狗
-
WDIOC_KEEPALIVE:喂狗操作
-
WDIOC_SETTIMEOUT:设置看门狗超时时间
-
WDIOC_GETPRETIMEOUT:获取看门狗超时时间
#ifndef _UAPI_LINUX_WATCHDOG_H #define _UAPI_LINUX_WATCHDOG_H #include <linux/ioctl.h> #include <linux/types.h> #define WATCHDOG_IOCTL_BASE 'W' 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 */ }; #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) #define WDIOF_UNKNOWN -1 /* Unknown flag error */ #define WDIOS_UNKNOWN -1 /* Unknown status error */ #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 */ #define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ #define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */ #define WDIOS_TEMPPANIC 0x0004 /* Kernel panic on temperature trip */ #endif /* _UAPI_LINUX_WATCHDOG_H */
6.5. SampleCode¶
6.5.1. 启动看门狗¶
打开/dev/watchdog设备,watchdog将被启动。
参考代码如下:
int wdt_fd = -1; wdt_fd = open("/dev/watchdog", O_WRONLY); if (wdt_fd == -1) { // fail to open watchdog device }
6.5.2. 关闭看门狗¶
参考代码如下:
int option = WDIOS_DISABLECARD; ioctl(wdt_fd, WDIOC_SETOPTIONS, &option); if (wdt_fd != -1) { close(wdt_fd); wdt_fd = -1; }
6.5.3. 设定超时¶
通过标准的IOCTL命令WDIOC_SETTIMEOUT以秒为单位来设定超时,超时时间建议大于5s,参考代码如下:
#define WATCHDOG_IOCTL_BASE 'W' #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int) int timeout = 20; ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout);
6.5.4. 喂狗¶
通过标准的IOCTL命令WDIOC_KEEPALIVE来喂狗,喂狗的间隔应该比超时时间小,参考代码如下:
#define WATCHDOG_IOCTL_BASE 'W' #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int) ioctl(wdt_fd, WDIOC_KEEPALIVE, 0);
6.5.5. demo¶
#include <stdio.h> #include <iwatchdog.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/ioctl.h> #include <linux/watchdog.h> int main() { int fd = open("/dev/watchdog", O_WRONLY); if (fd < 0) { perror("Failed to open /dev/watchdog"); return -1; } if (ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD) < 0) { perror("Failed to enable watchdog"); close(fd); return -1; } while (1) { if (write(fd, "V", 1) != 1) { // Reset watchdog timer perror("Failed to reset watchdog timer"); break; } sleep(1); // Sleep for a while before resetting again } close(fd); return 0; }
6.5.6 测试用例¶
Linux的测试demo:<Kernel>drivers/sstar/watchdog/ut/wdt_ut.c
Example: # wdt_ut start 10 /* 启动watchdog后,系统会不断去喂狗,所以10秒后系统不会重启 */ # wdt_ut reset 10 /* 启动watchdog后,系统不会去喂狗,所以10秒后系统将重启 */
7. API参考¶
NA
8. FAQ¶
NA