十四、【watchdog】看门狗
6818看门狗定时器框图
由上图可知PCLK经过8bit分频器分频然后再经过最高1/128的分频就是看门狗定时器的时钟频率,8bit最大分频系数为255,t_watchdog=200M/(255+1)/128=6103HZ.所以最小频率为6103HZ.
如果我们想要实现10s不喂狗就产生复位信号的功能,那WTCNT(计数器)的值设定为10*6103=61030 ,十六进制为0xEE66.当在10s内不喂狗,当WTCNT减到0(即10s后)产生复位信号,系统复位。
1、代码编写
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <cfg_type.h>
#include <linux/ioctl.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <mach/platform.h>
#include <mach/devices.h>
#include <mach/soc.h>
#include <linux/clk.h>
//提供三个命令字,启动、停止、喂狗
#define WDT_START _IO('W', 0)
#define WDT_STOP _IO('W', 1)
#define WDT_FEED _IO('W', 2)
//IO内存的静态映射
#define WTREG(x) ((x) + IO_ADDRESS(PHY_BASEADDR_WDT))
#define WTCON WTREG(0x00)
#define WTDAT WTREG(0x04)
#define WTCNT WTREG(0x08)
#define WTCLRINT WTREG(0x0C)
static long wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case WDT_START:
writel(( readl(WTCON)|(1<<5)|(1<<2)|(1<<0) ),WTCON);
break;
case WDT_STOP:
writel(( readl(WTCON)&(~((1<<5)|(1<<2)|(1<<0))) ),WTCON);
break;
case WDT_FEED:
writel(0xEE66,WTCNT);
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
//定义文件操作集合结构体
static struct file_operations wdt_misc_fops =
{
//.open = wdt_open,//操作集合中没有提供.open和.release
//.release = wdt_close,//使用系统默认的,其它操作函数没有默认
.unlocked_ioctl = wdt_ioctl,
};
static struct miscdevice wdt_misc= //定义杂项字符设备
{
.minor = MISC_DYNAMIC_MINOR,//让内核动态分配次设备号
.name = "wdt_misc",//设备名,也是设备文件名
.fops = &wdt_misc_fops,
};
//入口函数
static int __init wdt_init (void)
{
int ret;
printk("<1>""wdt_init\n");
//注册杂项设备
ret = misc_register(&wdt_misc);
if(ret < 0)
{
printk(KERN_ALERT"misc_register fail\n");
goto misc_register_err;
}
printk("<1>""misc_register OK\n");
//复位WDT
nxp_soc_peri_reset_set(RESET_ID_WDT);
nxp_soc_peri_reset_set(RESET_ID_WDT_POR);
//通过虚拟地址设置寄存器
writel( 0, WTCON);//
writel( ( readl(WTCON)|(3<<3) ), WTCON);//再分频参数 11b = 128
writel( ( (readl(WTCON) & (~(0xff<<8))) | (255<<8) ), WTCON);//预分频参数255
writel( 0xEE66, WTDAT);//10S对应的计数值
writel( 0xEE66, WTCNT);//10S对应的计数值
writel( 0, WTCLRINT);
printk("<1>""wdt_init OK\n");
return 0;
misc_register_err:
return ret;
}
//出口函数
static void __exit wdt_exit(void)
{
printk(KERN_ALERT"wdt_exit\n");
//注销杂项设备
misc_deregister(&wdt_misc);
}
module_init(wdt_init);
module_exit(wdt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XLG");
MODULE_DESCRIPTION("first chardev drv");
main.c
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <sys/ioctl.h> #define WDT_START _IO('W', 0) #define WDT_STOP _IO('W', 1) #define WDT_FEED _IO('W', 2) int main(void) { int digtal = 0; int ret,i; int fd = open("/dev/wdt_misc",O_RDWR); if(fd < 0) { perror("open failed"); return -1; } ret = ioctl(fd,WDT_START); if(ret < 0) { perror("ioctl failed"); return ret; } i = 0; while(1) { sleep(8); printf("%d seconds\n",++i*8); ioctl(fd,WDT_FEED); //喂狗 } ioctl(fd,WDT_STOP); close(fd); return 0; }