需要板子一起学习的可以这里购买(含资料):点击跳转
一、看门狗定时器功能
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;
}
觉得有帮助的话,打赏一下呗。。