zynq看门狗
一、背景和用途
-
项目程序在运行过程中出现了内核崩溃的问题,在本质问题没解决情况下,又想推进项目的进行,可以考虑使用看门狗可以立即恢复
-
在解决问题后,可以使用看门狗规避整个系统程序长时间运行后可能跑飞的情况
二、zynq7000的看门狗配置
查看文档描述
- 文档ug585-Zynq-7000-TRM-2018.pdf,可以看到看门狗和复位的描述
- 由于zynq私有看门狗属于PS端,所以在vivado环境中不需要对pl进行配置
配置
内核配置
- 打开menuconfig,选择Device Drivers ---> [] Watchdog Timer Support ---> <> Xilinx Watchdog timer
设备树配置
- 编辑系统设备树zynq-7000.dtsi,找到watchdog,添加reset-on-timeout
watchdog0: watchdog@f8005000 {
clocks = <&clkc 45>;
compatible = "cdns,wdt-r1p2";
interrupt-parent = <&intc>;
interrupts = <0 9 1>;
reg = <0xf8005000 0x1000>;
timeout-sec = <10>;
reset-on-timeout; //加上这一行
};
三、应用程序测试
- 说明:程序编译运行,ctrl+c停止程序运行3s后系统重启
#include <stdio.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include <linux/types.h>
#define WATCHDOG_IOCTL_BASE 'W'
#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)
int errnon = -1;
#define HI_APPCOMM_MAX_PATH_LEN (64)
#define HAL_FD_INITIALIZATION_VAL (-1)
#define HAL_WATCHDOG_DEV "/dev/watchdog"
static int s_s32HALWATCHDOGfd = HAL_FD_INITIALIZATION_VAL;
int WATCHDOG_Init(int s32Time_s)
{
int s32Ret = 1;
if (s32Time_s < 2 || s32Time_s > 1000)
{
printf("Interval time should not be less then two and bigger then 100. %d\n", s32Time_s);
return -1;
}
s_s32HALWATCHDOGfd = open(HAL_WATCHDOG_DEV, O_RDWR);
if (s_s32HALWATCHDOGfd < 0)
{
printf("open [%s] failed\n",HAL_WATCHDOG_DEV);
return -1;
}
s32Ret = ioctl(s_s32HALWATCHDOGfd, WDIOC_SETTIMEOUT, &s32Time_s);
if(-1 == s32Ret)
{
printf("WDIOC_SETTIMEOUT: failed, errnon(%d)\n", errnon);
return -1;
}
printf("WDIOC_SETTIMEOUT: timeout=%ds\n", s32Time_s);
s32Ret = ioctl(s_s32HALWATCHDOGfd, WDIOC_KEEPALIVE);/**feed dog */
if(-1 == s32Ret)
{
printf("WDIOC_KEEPALIVE: failed, errnon(%d)\n", errnon);
return -1;
}
return 1;
}
int HAL_WATCHDOG_Feed(void)
{
int s32Ret = 1;
s32Ret = ioctl(s_s32HALWATCHDOGfd, WDIOC_KEEPALIVE);/**feed dog */
if(-1 == s32Ret)
{
printf("WDIOC_KEEPALIVE: failed, errnon(%d)\n", errnon);
return -1;
}
return 1;
}
int HAL_WATCHDOG_Deinit(void)
{
int s32Ret;
s32Ret = close(s_s32HALWATCHDOGfd);
if (0 > s32Ret)
{
printf("wdrfd[%d] close,fail,errnon(%d)\n",s_s32HALWATCHDOGfd,errnon);
return -1;
}
return 1;
}
int main()
{
WATCHDOG_Init(3);
while(1)
{
sleep(1);
HAL_WATCHDOG_Feed();
}
return 1;
}