在各種嵌入式設備soc中基本都提供了看門狗,在很長一段時間裡我對看門狗的理解就是“關掉它,不然它會找麻煩”。但是當某種需求存在的時候,它又是必不可少的,比如你的產品是一個類似路由器的服務設備,可能在陽台的某刻角落一丟就是好幾年,雖然孤獨聽起來讓人傷感,可是如果在孤獨中死去,那就會給客戶帶來更大的煩惱。所以我們應該去了解它
講解中使用的環境主要基於linux系統,設備是arm s3c6410
- #include <linux/io.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/clk.h>
- staticint wdt_probe(struct platform_device * dev);
- staticint wdt_remove(struct platform_device * dev);
- struct wdt_driver
- {
- struct platform_driver pdrv;
- unsigned long phys_regs;
- unsigned long phys_regs_len;
- struct timer_list timer;
- int irq;
- void * regs;
- };
- staticstruct wdt_driver wdtdrv =
- {
- .pdrv =
- {
- .probe = wdt_probe,
- .remove = wdt_remove,
- .driver =
- {
- .name = "s3c2410-wdt",
- .owner = THIS_MODULE,
- },
- },
- };
- irqreturn_t wdt_irq(int irq,void * data)
- {
- struct wdt_driver * wdtdrv = data;
- iowrite32(1,wdtdrv->regs+0xc);
- printk("wdt_irq\n");
- return IRQ_HANDLED;
- }
- void wdt_timeout(unsigned long data)
- {//喂狗
- struct wdt_driver * wdtdrv = (void *)data;
- //printk("wdt_timeout\n");
- iowrite32(3764,wdtdrv->regs+8);
- mod_timer(&wdtdrv->timer,jiffies+HZ/2);
- }
- //pclk 66500000
- staticint wdt_init(struct wdt_driver * wdtdrv)
- {
- iowrite32(3764,wdtdrv->regs+4);
- iowrite32(3764,wdtdrv->regs+8);
- //狗中斷
- //iowrite32(0x80<<8|0x1<<5|0x1<<2|0x3<<3,wdtdrv->regs);
- //狗reset
- iowrite32(0x80<<8|0x1<<5|0x3<<3|1,wdtdrv->regs);
- printk("WTCON=%x\n",ioread32(wdtdrv->regs));
- printk("WTDAT=%x\n",ioread32(wdtdrv->regs+4));
- printk("WTCNT=%x\n",ioread32(wdtdrv->regs+8));
- //啟動喂狗定時器
- setup_timer(&wdtdrv->timer, wdt_timeout,(unsigned long)wdtdrv);
- mod_timer(&wdtdrv->timer,jiffies+HZ/2);
- //狗超時中斷
- // if(!request_irq(wdtdrv->irq,wdt_irq,IRQF_TRIGGER_FALLING,"wdt",wdtdrv))
- // goto err_timer;
- return 0;
- }
- staticint wdt_destroy(struct wdt_driver * wdtdrv)
- {
- //狗timer停止運行
- iowrite32(0x80<<8|0<<5|0x3<<3|1,wdtdrv->regs);
- //啟動喂狗定時器
- del_timer(&wdtdrv->timer);
- //狗超時中斷
- //free_irq(wdtdrv->irq,(unsigned long)wdtdrv);
- return 0;
- }
- staticint wdt_probe(struct platform_device * dev)
- {
- struct wdt_driver * wdtdrv;
- struct resource * res;
- printk("wdt_probe:%s\n",dev->name);
- wdtdrv = container_of(container_of(dev->dev.driver,struct platform_driver,driver),struct wdt_driver,pdrv);
- //獲取控制器寄存器地址
- res = platform_get_resource(dev,IORESOURCE_MEM,0);
- if(!res)
- goto err_out;
- wdtdrv->phys_regs = res->start;
- wdtdrv->phys_regs_len = res->end-res->start;
- wdtdrv->regs = ioremap(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
- if(!wdtdrv->regs)
- goto err_out;
- if(!request_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len,dev_name(&dev->dev)))
- goto err_ioremap;
- //獲取中斷
- wdtdrv->irq = platform_get_irq(dev,0);
- if(wdtdrv->irq<0)
- goto err_request_mem;
- printk("irq=%d\n",wdtdrv->irq);
- wdt_init(wdtdrv);
- return 0;
- err_request_mem:
- release_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
- err_ioremap:
- iounmap(wdtdrv->regs);
- err_out:
- return -1;
- }
- staticint wdt_remove(struct platform_device * dev)
- {
- struct wdt_driver * wdtdrv;
- printk("wdt_remove:%s\n",dev->name);
- wdtdrv = container_of(container_of(dev->dev.driver,struct platform_driver,driver),struct wdt_driver,pdrv);
- wdt_destroy(wdtdrv);
- release_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
- iounmap(wdtdrv->regs);
- return 0;
- }
- staticint modinit(void)
- {
- printk("mod init\n");
- platform_driver_register(&wdtdrv.pdrv);
- return 0;
- }
- staticvoid modexit(void)
- {
- platform_driver_unregister(&wdtdrv.pdrv);
- printk("mod exit\n");
- }
- module_init(modinit);
- module_exit(modexit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("dragon101788");
首先對模塊進行初始化
module_init(modinit);
module_exit(modexit);
從平台中通過文件名"s3c2410-wdt"找出設備,回調wdt_probe
當然你的確定arch/arm/mach-s3c64xx/mach-s3c6410的static struct platform_device *smdk6410_devices[] __initdata中找到&s3c_device_wdt,,如果沒有,看看arch/arm/plat-samsung/中有沒有dev-wdt.c文件搞到裡面的platform_device對象,添加到__initdata中。