十四、【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;

}

  

  

 

posted @ 2021-12-26 16:09  轻轻的吻  阅读(455)  评论(0编辑  收藏  举报