Watchdog使用参考
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 04/21/2023 |
1. 概述¶
watchdog(看门狗,简称 "WDT")是一种具备超时复位系统功能的硬件或软件机制,核心由定时器与复位模块组成,具体工作原理如下:
- 用户预先设定一个超时时间,在该时间周期内需通过 “喂狗” 操作重置 watchdog 的内部计数器
- 若内部计数器数值达到设定的超时时间,且未及时 “喂狗”,watchdog 将触发系统复位,使系统重新启动
本文中出现的 "WDT","看门狗","Watchdog" 表述,均指代上述超时复位系统的功能。本文介绍PCUPID 系列芯片的硬件看门狗机制。
2. 关键字说明¶
-
硬件watchdog:独立的看门狗硬件电路(包含定时和复位电路,SoC内置),软件定期向硬件寄存器写入特定值,超时后输出硬件复位信号,强制系统重启,不依赖操作系统运行,即使 CPU 死机仍能触发硬件复位
-
软件watchdog:基于内核定时器的软件逻辑模拟,用户程序定期喂狗,超时后通过内核 API 触发系统重启或告警,无需硬件支持,实现灵活,可定制超时动作,CPU死机后不能触发超时动作
-
watchdog timeout:看门狗的超时时长,如果超过这个时长不喂狗,硬件看门狗会输出硬件复位信号,软件看门狗会触发超时动作
-
watchdog pretimeout:看门狗预超时是看门狗机制中的一种提前预警机制,指在看门狗真正超时前的一个提前告警阶段。当预超时触发时,系统会收到一个预警信号(如中断),此时仍有一段缓冲时间(预超时到实际超时的间隔)供系统进行故障排查(如记录日志、保存关键数据)或尝试自我恢复(如杀死异常进程)
3. 功能描述¶
linux 内核支持基于高精度定时器的软件看门狗(softdog)和基于硬件的硬件看门狗,提供了/dev/watchdog* 设备文件与用户空间程序进行交互。应用程序可以通过/dev/watchdog* 设备进行周期性喂狗。

软件看门狗:linux自带功能,按需打开,默认关闭
硬件看门狗:soc内置,sigmastar提供驱动,linux内核提供devfs的watchdog接口,用户使用ioctl操作watchdog设备
4. 硬件连接介绍¶
PCUPID 系列芯片的硬件看门狗内置在soc里,没有引脚对外开放,无需外围硬件电路连接,由驱动程序写soc的寄存器实现对看门狗硬件电路的控制
5. Uboot用法介绍¶
5.1 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.2 uboot config配置¶
通过make menuconfig打开或关闭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启动时会默认启动看门狗,并且超时时间由CONFIG_WATCHDOG_TIMEOUT_MSECS设定。CONFIG_WATCHDOG_TIMEOUT_MSECS默认值为2000,单位ms,也就是2s
(3) 喂狗配置项 CONFIG_WATCHDOG:
[*] Device Drivers ---> [*] Watchdog Timer Support ---> [*] Enable U-Boot watchdog reset
注意:如果开启这个宏,uboot会每隔一秒喂一次狗。如果开启 CONFIG_WATCHDOG_AUTOSTART 但是不开启 CONFIG_WATCHDOG,系统在WATCHDOG_TIMEOUT_MSECS ms后将重启
(4) 打开wdt命令配置项 CONFIG_WATCHDOG:
[*] Command line interface ---> [*] Device access commands ---> [*] wdt
注意: 只有开启这个宏,uboot下才可以执行wdt命令
5.3 wdt命令参数说明¶
-
查看可用的watchdog:
wdt list - list watchdog devices 示例: SigmaStar # wdt list watchdog (sstar_wdt) SigmaStar #
注意:示例里回显的"watchdog"才是设备name,sstar_wdt不是设备name
-
获取/设置当前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
-
复位 watchdog 计时:
wdt reset - reset watchdog timer
-
立刻触发 watchdog 超时:
wdt expire [flags] - expire watchdog timer immediately
参数名称 描述 flag -f 强制触发超时; -d 延迟触发超时; -s 触发超时过程中不输出日志信息 注意:
wdt expire命令的作用为立刻触发watchdog超时,U-Boot原生的实现为将超时设置为1ms,当前硬件不支持此命令。
5.4 wdt使用示例¶
先关闭“自启动看门狗”和“自动喂狗”配置项,然后执行下列操作
wdt list → wdt list // 查看有哪些watchdog设备 wdt dev [<name>] → wdt dev 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_AUTOSTART配置项。关闭自动喂狗功能,即关闭CONFIG_WATCHDOG配置项,关闭方法见上文uboot config配置小节。如果不关闭这两个配置项,uboot系统每隔一段时间会自动ping一次watchdog,你无法用此demo测试wdt start功能。
6. Kernel用法介绍¶
6.1 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.2 kernel config配置¶
通过make menuconfig打开或关闭watchdog相关的config配置项:
Device Drivers --->
[*] SStar SoC platform drivers --->
<*> watchdog driver
6.3 使用介绍¶
6.3.1 devfs使用方法¶
Linux提供了/dev/watchdog节点供用户使用,可以用ioctl操作,需要用户程序主动打开watchdog功能。
-
头文件:include/uapi/linux/watchdog.h
-
数据结构:struct watchdog_info结构体描述了看门狗设备的信息
-
ioctl控制命令:
-
WDIOC_GETSUPPORT:获取看门狗支持哪些功能
-
WDIOC_SETOPTIONS:用于开启或关闭看门狗
-
WDIOC_KEEPALIVE:喂狗操作
-
WDIOC_SETTIMEOUT:设置看门狗超时时间
-
WDIOC_GETPRETIMEOUT:获取看门狗超时时间
-
watchdog.h头文件内容如下
#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.4 示例代码¶
6.4.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.4.2 关闭看门狗¶
参考代码如下:
int option = WDIOS_DISABLECARD; ioctl(wdt_fd, WDIOC_SETOPTIONS, &option); if (wdt_fd != -1) { close(wdt_fd); wdt_fd = -1; }
6.4.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.4.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.4.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.4.6 测试用例¶
kernel的硬件看门狗单元测试demo:<Kernel>drivers/sstar/watchdog/ut/wdt_ut.c
Example: # wdt_ut start 10 /* 启动watchdog后,系统会不断去喂狗,所以10秒后系统不会重启 */ # wdt_ut reset 10 /* 启动watchdog后,系统不会去喂狗,所以10秒后系统将重启 */