0
点赞
收藏
分享

微信扫一扫

Linux应用开发 ——看门狗编程

Spinach菠菜 2022-05-03 阅读 77
linux

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 */

看门狗编程

编程步骤:

  1. open看门狗设备节点,打开狗看门狗会立即运行
  2. WDIOC_SETOPTIONS,关闭看门狗
  3. WDIOC_SETTIMEOUT ,设置看门狗超时时间
  4. 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
Reset-------->
--------> 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信息可以知道系统重启了

举报

相关推荐

MCU看门狗

看门狗 WDG

ARM32开发--WDGT看门狗

STM32看门狗

看门狗定时器

看门狗电路设计

0 条评论