Watchdog 使用

简介

看门狗(watchdog)实际是一个定时器,启动之后会开始计时。系统或者软件需
要在规定时间内与看门狗通信(俗称喂狗)重置计时,如此反复下去,以此来确
定系统和软件正常运行。

如果规定时间内没有喂狗,看门狗超时,说明系统或应用陷入循环、卡死,此时
看门狗会发出复位信号让主控复位,脱离卡死。

本章节主要介绍 ITX-3588J  开发板内部看门狗的使用。

DTS配置

ITX-3588J 的 watchdog 的 DTS 节点在
"kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s.dtsi" 文件中定义,如
下所示:

   wdt: watchdog@feaf0000 {
       compatible = "snps,dw-wdt";
       reg = <0x0 0xfeaf0000 0x0 0x100>;
       clocks = <&cru TCLK_WDT0>, <&cru PCLK_WDT0>;
       clock-names = "tclk", "pclk";
       interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>;
       status = "disabled";
   };

用户首先需在 DTS 文件中打开 wdt 节点:

   &wdt{
       status = "okay";
   };

使用

watchdog 默认是关闭的,需按上述说明在 DTS 文件中打开相关节点方能使用。

watchdog 的驱动文件为 "kernel-5.10/drivers/watchdog/dw_wdt.c"。下面介
绍两种方法来使用 watchdog:

内部看门狗的设备名称为"/dev/watchdog",用户可通过 "echo" 命令来控制该
设备

   # 写入任意内容(大写字母‘V’除外),开启看门狗,每 44 秒内需要写入一次(喂狗)
   echo A > /dev/watchdog

   # 开启看门狗,并且内核会每隔 22 秒自动喂一次狗
   echo V > /dev/watchdog

也可以通过程序来控制看门狗,通过Android.mk编译生成可执行文件,在机器启
动后,push到上面运行,demo代码如下:

   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <unistd.h>
   #include <fcntl.h>
   #include <signal.h>
   #include <sys/ioctl.h>
   #include <linux/types.h>
   #include <linux/watchdog.h>

   #define WDIOC_SETTIMEOUT        _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
   #define WDIOC_GETTIMEOUT        _IOR(WATCHDOG_IOCTL_BASE, 7, int)

   int main(void)
   {
       int timeout1 = 22;
       int timeout2;
       int fd = open("/dev/watchdog", O_WRONLY); //start watchdog
       int ret = 0;
       if (fd == -1) {
           perror("watchdog");
           exit(EXIT_FAILURE);
       }

       ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeout1); //set timeout
       if (ret < 0)
           printf("ioctl WDIOC_SETTIMEOUT failed.\n"); 

       ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout2); //get timeout
       if (ret < 0)
           printf("ioctl WDIOC_SETTIMEOUT failed.\n"); 
       printf("timeout = %d\n", timeout2);

       while (1) {
           ret = write(fd, "\0", 1); //feed the dog
           if (ret != 1) {
               ret = -1;
               break;
           }
           printf("feed the dog\n");
           sleep(10);

       }
       close(fd);
       return ret;
   }

demo说明:

1、内部看门狗在使用 open 函数打开后会立刻开始计时。

2、关于超时时间:用户可以用 ioctl 来设置超时时间和获取超时时间。当用户
没有设置超时时间时,驱动会应用默认请求的超时时间为 30 s。需要说明的是
驱动最终设置的超时时间并不一定是应用层传输的时间或者驱动一开始设置的默
认时间。驱动函数里有一个超时时间的列表,该列表中存放了 16 个超时时间(
前 9 个是 0)。驱动会在超时时间列表中找到一个合适的时间作为最终
watchdog 设置的超时时间。

以下为超时时间的详细列表:

参考文档:SDK/RKDocs(linux 为 docs)/common/watchdog

外部看门狗

很多设备上有外部硬件看门狗,通过查看设备文件可以确认是否支持外部看门狗
。如果有硬件看门狗 /dev/ 下应该会生成 wdt_XXX 的设备文件。

   ls /dev/wdt_*

通过写设备文件完成使能和喂狗。

   echo e > /dev/wdt_core
   echo 1 > /dev/wdt_core

   case '0':0.64s
   case '1':2.56s
   case '2':10.24s
   case '3':40.96s
   case 'e':enable wdt