Watchdog使用参考


REVISION HISTORY

Revision No.

Description

Date
1.0
  • Initial release
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下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命令参数说明

  1. 查看可用的watchdog:

    wdt list - list watchdog devices
    
    示例:
    SigmaStar # wdt list
    watchdog (sstar_wdt)
    SigmaStar #
    

    注意:示例里回显的"watchdog"才是设备name,sstar_wdt不是设备name

  2. 获取/设置当前watchdog设备:

    wdt dev [<name>] - get/set current watchdog device
    
    参数名称 描述
    name 不带参数时为获取当前操作的 watchdog 设备名称
  3. 启动watchdog:

    wdt start <timeout ms> [flags] - start watchdog timer
    
    参数名称 描述
    timeout ms 指定 watchdog 的超时时间,单位为毫秒
    flags 传递给 watchdog 驱动的 flags 信息,当前驱动未使用该参数
  4. 停止watchdog:

    wdt stop - stop watchdog timer
    
  5. 复位 watchdog 计时:

    wdt reset - reset watchdog timer
    
  6. 立刻触发 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控制命令:

    1. WDIOC_GETSUPPORT:获取看门狗支持哪些功能

    2. WDIOC_SETOPTIONS:用于开启或关闭看门狗

    3. WDIOC_KEEPALIVE:喂狗操作

    4. WDIOC_SETTIMEOUT:设置看门狗超时时间

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

 7.立即开始

加入Comake开发者社区

 主页地址: CoMake开发者社区

SDK下载: CoMake开发者社区

文档中心: CoMake开发者社区

马上购买 : 首页-Comake开发者社区商店

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐