一、看门狗定时器功能
1、产生复位信号:当系统受到由于噪声或者干扰而造成系统死机,看门狗产生一个复位信号。
2、普通定时器:16bits定时器,产生周期性的中断信号
二、看门狗系统框图
设置计数值以每隔10S就会产生一个复位信号:
第一分频值:PCLK/256 ---> 255+1 ---->781250
第二次分频值:128 ----> 781250/128 -->6103
计数值:6103 * 10 ---> 61030 不能大于 65536(0-65535) 16bits
三、看门狗定时器相关的寄存器
1、WTCON(控制寄存器)
2、WTDAT(数据寄存器)
3、WTCNT(计数寄存器)
4、WTCLRINT(清中断寄存器)
四、编程
#define WDT_START _IO('W',0)
#define WDT_KEEPALIVE _IO('W',1)
#define WDT_STOP _IO('W',2)
static struct resource *gec6818_wdt_res = NULL;
static void __iomem *wdt_va_base = NULL;
static void __iomem *wdt_va_con = NULL;//WDTCON 0XC0019000
static void __iomem *wdt_va_dat = NULL; //WDTDAT 0XC0019004
static void __iomem *wdt_va_cnt = NULL; //WDTCNT 0XC0019008
static void __iomem *wdt_va_clrint = NULL; //WTCLRINT 0XC001900C
static struct clk *wdt_clock;
static unsigned long wdt_freq;
long gec6818_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{
printk("gec6818_wdt_ioctl\n");
switch(cmd){
case WDT_START:
printk("WDT_START\n");
*(unsigned int*)wdt_va_con = (255<<8) | (3<<3) | (1<<2) | (1<<0); //[15:8] [4:3] [2] [0]
*(unsigned int*)wdt_va_con |= (1<<5); //开启看门狗功能
break;
case WDT_KEEPALIVE:
*(unsigned int*)wdt_va_cnt = 0XEE66;
break;
case WDT_STOP:
*(unsigned int*)wdt_va_cnt = 0;
break;
default:
return -ENOIOCTLCMD;/* No ioctl command */
break;
}
return 0;
}
//[2]
static struct file_operations gec6818_wdt_ops = {
.owner = THIS_MODULE,
.open = gec6818_wdt_open,
.unlocked_ioctl = gec6818_wdt_ioctl,
.release = gec6818_wdt_release,//当应用程序调用close时,执行驱动程序中的接口函数
};
//[1] 定义混杂设备
static struct miscdevice wdt_misc = {
.name = "wdt_drv", //设备文件的名字
.fops = &gec6818_wdt_ops,
.minor = MISC_DYNAMIC_MINOR, //设置次设备号,MISC_DYNAMIC_MINOR --- 表示由系统动态分配一个次设备号
};
static int __init gec6818wdt_init(void) //执行insmod执行一次
{
int ret;
// char temp;
printk("gec6818wdt_init\n");
//[3] 注册混杂设备
ret = misc_register(&wdt_misc);
if(ret < 0)
{
printk("misc_register error\n");
ret = -EBUSY;
goto misc_register_error;
}
//申请物理内存区
gec6818_wdt_res = request_mem_region(0XC0019000,0x1000,"WDTC_MEM");
if(gec6818_wdt_res == NULL)
{
printk("request_mem_region error\n");
ret = -EBUSY;
goto request_mem_region_error;
}
//动态映射
wdt_va_base = ioremap(0XC0019000,0x1000);
if(wdt_va_base == NULL)
{
printk("ioremap error\n");
ret = -EFAULT;
goto ioremap_error;
}
wdt_va_con = wdt_va_base + 0x00;
wdt_va_dat = wdt_va_base + 0x04;
wdt_va_cnt = wdt_va_base + 0x08;
wdt_va_clrint = wdt_va_base + 0x0C;
/***************给程序设置时钟源*********************/
wdt_clock = clk_get(NULL, "pclk");
if (IS_ERR(wdt_clock)) {
ret = PTR_ERR(wdt_clock);
goto err_map;
}
clk_enable(wdt_clock);
wdt_freq = clk_get_rate(wdt_clock);
printk("wdt_freq = %luHz\n",wdt_freq);
nxp_soc_peri_reset_set(RESET_ID_WDT);
nxp_soc_peri_reset_set(RESET_ID_WDT_POR);
/**********************************************/
//给对应寄存器进行初始化
*(unsigned int*)wdt_va_con = 0; //默认看门狗关闭
*(unsigned int*)wdt_va_dat = 0XEE66;//61030 --->
*(unsigned int*)wdt_va_cnt = 0XEE66;
*(unsigned int*)wdt_va_clrint = 0;
return 0;
err_map:
ioremap_error:
release_mem_region(0XC0019000,0x1000);
gec6818_wdt_res = NULL;
request_mem_region_error:
misc_deregister(&wdt_misc);
misc_register_error:
return ret;
}
觉得有帮助的话,打赏一下呗。。