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秒后系统将重启 */