IMX6ULL上的看门狗
ls /dev/watchdog*
/dev/watchdog /dev/watchdog0
<linux/watchdog.h> : watch的ioctl命令
#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)
#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 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 */
常用指令:
ioctl指令 | |
---|---|
WDIOC_GETSUPPORT | 获取看门狗支持哪些功能 |
WDIOC_SETOPTIONS | 用于开启或关闭看门狗 |
WDIOC_KEEPALIVE | 喂狗操作 |
WDIOC_SETTIMEOUT | 设置看门狗超时时间 |
WDIOC_GETTIMEOUT | 获取看门狗超时时间 |
WDIOC_GETSUPPORT 通过struct watchdog_info获取看够支持的功能。
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 */
};
- options,记录看够支持的功能或选项
- firmware_version,设备版本号
- identity,描述性的字符串
options字段主要是以下值的位或:
#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 */
看门狗编程
编程步骤:
- open看门狗设备节点,打开狗看门狗会立即运行
- WDIOC_SETOPTIONS,关闭看门狗
- WDIOC_SETTIMEOUT ,设置看门狗超时时间
- WDIOC_KEEPALIVE,喂狗
wdg.h :
#ifndef __WDG_H__
#define __WDG_H__
enum {
WDG_OFF = 0,
WDG_ON,
};
typedef unsigned char wdg_on_off_t;
/*
* @brief : 打开看门狗
*/
int wdg_open(const char *devname);
/*
* @brief : 开启or停止看门狗
*/
int wdg_on_off(int fd, wdg_on_off_t on_off);
/*
* @brief : 设置看门狗超时时间
* @param : timeout 超时时间,单位s(秒)
*/
int wdg_set_timeout(int fd, int timeout);
/*
* @brief : 喂狗
*/
int wdg_feed(int fd);
#endif /* __WDG_H__ */
wdg.c :
#include "wdg.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <linux/watchdog.h>
/*
* @brief : 打开看门狗
*/
int wdg_open(const char *devname)
{
return open(devname, O_RDWR);
}
/*
* @brief : 开启or停止看门狗
*/
int wdg_on_off(int fd, wdg_on_off_t on_off)
{
int op = WDIOS_ENABLECARD;
if (on_off == WDG_OFF)
op = WDIOS_DISABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &op);
}
/*
* @brief : 设置看门狗超时时间
* @param : timeout 超时时间,单位s(秒)
*/
int wdg_set_timeout(int fd, int timeout)
{
return ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
}
/*
* @brief : 喂狗
*/
int wdg_feed(int fd)
{
return ioctl(fd, WDIOC_KEEPALIVE, NULL);
}
wdg_sample:
#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <stdint.h>
#include <sys/select.h>
#include "wdg.h"
#define WDOG_DEV "/dev/watchdog0"
void sleep_ms(unsigned int ms)
{
struct timeval delay;
delay.tv_sec = 0;
delay.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &delay);
}
int main(int argc, char **argv)
{
int fd;
fd = wdg_open(WDOG_DEV);
if (fd < 0)
{
printf("Open watchdog err\r\n");
return -1;
}
wdg_on_off(fd, WDG_OFF);
wdg_set_timeout(fd, 2);
wdg_on_off(fd, WDG_ON);
int cnt = 0;
while (1)
{
printf("--------> %d\r\n", cnt);
wdg_feed(fd);
if (++cnt < 20)
{
sleep_ms(500);
}
else
{
while (1)
{
sleep_ms(5000);
}
}
}
return 0;
}
测试:
debian@npi:~/nfs_root$ sudo ./wdg_sample
--------> 0
--------> 1
--------> 2
--------> 3
--------> 4
--------> 5
--------> 6
--------> 7
--------> 8
--------> 9
--------> 10
--------> 11
--------> 12
--------> 13
--------> 14
--------> 15
--------> 16
--------> 17
--------> 18
--------> 19
U-Boot 2020.10-g4f79a1a2 (Apr 08 2021 - 09:59:52 +0800)
CPU: Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 52C
Reset cause: WDOG
Model: Freescale i.MX6 UltraLiteLite 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
看够uboot信息可以知道系统重启了