ARM-Linux驱动--Watch Dog Timer(看门狗)驱动分析
时间:11-20
来源:互联网
点击:
硬件平台:FL2440
内核版本:2.6.28
主机平台:Ubuntu 11,04
内核版本:2.6.39
1、看门狗驱动的原理
下图是看门狗驱动的原理图
可以看出,PCLK是系统时钟,经过8位的预分频,然后再被分频(16、32、64、128)然后产生计数脉冲,进行计数,当计数器WTCNT加到0或减到0,然后产生中断,或引起系统复位。所以要隔一段时间,重置WTCNT的值,防止WTCNT减到0,称之“喂狗”。
2、驱动分析
下面是自己的驱动分析,如有理解错误,请指正
注,为了尽量是驱动容易理解,这个驱动暂时将有关电源管理的功能删除了,等理解透彻再完善
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
interrupt.h> - #include
- #include
- #include
- #include
- #include
- #undefS3C_VA_WATCHDOG
- #defineS3C_VA_WATCHDOG(0)
- #include
- #definePFX"s3c2410-wdt:"
- #defineCONFIG_S3C2410_WATCHDOG_ATBOOT(0)
- #defineCONFIG_S3C2410_WATCHDOG_DEFAULT_TIME(15)
- staticintnowayout=WATCHDOG_NOWAYOUT;
- staticinttmr_margin=CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
- staticinttmr_atboot=CONFIG_S3C2410_WATCHDOG_ATBOOT;
- staticintsoft_noboot=1;//设置默认为执行中断
- staticintdebug;
- staticintcount;//用于计数,控制LED灯的亮灭
- module_param(tmr_margin,int,0);
- module_param(tmr_atboot,int,0);
- module_param(nowayout,int,0);
- module_param(soft_noboot,int,0);
- module_param(debug,int,0);
- MODULE_PARM_DESC(tmr_margin,"Watchdogtmr_margininseconds.default="
- __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME)")");
- MODULE_PARM_DESC(tmr_atboot,
- "Watchdogisstartedatboottimeifsetto1,default="
- __MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
- MODULE_PARM_DESC(nowayout,"Watchdogcannotbestoppedoncestarted(default="
- __MODULE_STRING(WATCHDOG_NOWAYOUT)")");
- MODULE_PARM_DESC(soft_noboot,"Watchdogaction,setto1toignorereboots,0to\
- reboot(defaultdependsonONLY_TESTING)");
- MODULE_PARM_DESC(debug,"Watchdogdebug,setto>1fordebug,(default0)");
- typedefenumclose_state
- {
- CLOSE_STATE_NOT,
- CLOSE_STATE_ALLOW=0x4021
- }close_state_t;
- staticunsignedlongopen_lock;
- staticstructdevice*wdt_dev;/*platformdeviceattachedto*/
- staticstructresource*wdt_mem;//用来保存IO端口占用的内存资源
- staticstructresource*wdt_irq;//保存wdt中断号
- staticstructclk*wdt_clock;//保存从平台获取的watchdog时钟
- staticvoid__iomem*wdt_base;//经过ioremap后的内存基地址
- staticunsignedintwdt_count;//保存向WTCNT写的计数值
- staticclose_state_tallow_close;
- staticDEFINE_SPINLOCK(wdt_lock);//定义一个自旋锁,用于资源的互斥访问
- /*watchdogcontrolroutines*/
- #defineDBG(msg...)do{\
- if(debug)\
- printk(KERN_INFOmsg);\
- }while(0)
- /*functions*/
- //喂狗函数,实际上是将wdt_count写入WTCNT寄存器
- staticvoids3c2410wdt_keepalive(void)
- {
- spin_lock(&wdt_lock);//给资源上锁
- writel(wdt_count,wdt_base+S3C2410_WTCNT);//写WTCNT寄存器
- spin_unlock(&wdt_lock);//解锁资源,下同
- }
- staticvoid__s3c2410wdt_stop(void)
- {
- unsignedlongwtcon;
- wtcon=readl(wdt_base+S3C2410_WTCON);
- wtcon&=~(S3C2410_WTCON_ENABLE|S3C2410_WTCON_RSTEN);
- writel(wtcon,wdt_base+S3C2410_WTCON);//设备看门狗使能无效、复位功能无效
- }
- //停止watchdog计时
- staticvoids3c2410wdt_stop(void)
- {
- spin_lock(&wdt_lock);
- __s3c2410wdt_stop();
- spin_unlock(&wdt_lock);
- }
- //启动watchdog计时
- staticvoids3c2410wdt_start(void)
- {
- unsignedlongwtcon;
- spin_lock(&wdt_lock);
- __s3c2410wdt_stop();
- wtcon=readl(wdt_base+S3C2410_WTCON);
- wtcon|=S3C2410_WTCON_ENABLE|S3C2410_WTCON_div128;//看门狗定时器使能、时钟除数因子128
- if(soft_noboot)//使用参数soft_noboot来选择看门狗到时是重启还是执行中断函数
- {
- wtcon|=S3C2410_WTCON_INTEN;//中断使能
- wtcon&=~S3C2410_WTCON_RSTEN;//复位功能无效
- }
- else
- {
- wtcon&=~S3C2410_WTCON_INTEN;//中断不使能
- wtcon|=S3C2410_WTCON_RSTEN;//复位功能有效
- }
- writel(wdt_count,wdt_base+S3C2410_WTDAT);//将wdt_count写入WTDAT
- writel(wdt_count,wdt_base+S3C2410_WTCNT);//将wdt_count写入WTCNT
- writel(wtcon,wdt_base+S3C2410_WTCON);//设置WTCON
- spin_unlock(&wdt_lock);
- }
- //设置WatchDog周期timeout
- staticints3c2410wdt_set_hea
ARMLinux驱动看门 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)