linux驱动学习(十二)之看门狗

一、看门狗定时器功能

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;	
}

觉得有帮助的话,打赏一下呗。。

           

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值