基于Linux构建无人值守系统(看门狗)


在各种嵌入式设备soc中基本都提供了看门狗,在很长一段时间里我对看门狗的理解就是“关掉它,不然它会找麻烦”。但是当某种需求存在的时候,它又是必不可少的,比如你的产品是一个类似路由器的服务设备,可能在阳台的某刻角落一丢就是好几年,虽然孤独听起来让人伤感,可是如果在孤独中死去,那就会给客户带来更大的烦恼。所以我们应该去了解它

讲解中使用的环境主要基于linux系统,设备是arm s3c6410

  1. #include <linux/io.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/platform_device.h>
  5. #include <linux/delay.h>
  6. #include <linux/interrupt.h>
  7. #include <linux/clk.h>
  8. staticint wdt_probe(struct platform_device * dev);
  9. staticint wdt_remove(struct platform_device * dev);
  10. struct wdt_driver
  11. {
  12. struct platform_driver pdrv;
  13. unsigned long phys_regs;
  14. unsigned long phys_regs_len;
  15. struct timer_list timer;
  16. int irq;
  17. void * regs;
  18. };
  19. staticstruct wdt_driver wdtdrv =
  20. {
  21. .pdrv =
  22. {
  23. .probe = wdt_probe,
  24. .remove = wdt_remove,
  25. .driver =
  26. {
  27. .name = "s3c2410-wdt",
  28. .owner = THIS_MODULE,
  29. },
  30. },
  31. };
  32. irqreturn_t wdt_irq(int irq,void * data)
  33. {
  34. struct wdt_driver * wdtdrv = data;
  35. iowrite32(1,wdtdrv->regs+0xc);
  36. printk("wdt_irq\n");
  37. return IRQ_HANDLED;
  38. }
  39. void wdt_timeout(unsigned long data)
  40. {//喂狗
  41. struct wdt_driver * wdtdrv = (void *)data;
  42. //printk("wdt_timeout\n");
  43. iowrite32(3764,wdtdrv->regs+8);
  44. mod_timer(&wdtdrv->timer,jiffies+HZ/2);
  45. }
  46. //pclk 66500000
  47. staticint wdt_init(struct wdt_driver * wdtdrv)
  48. {
  49. iowrite32(3764,wdtdrv->regs+4);
  50. iowrite32(3764,wdtdrv->regs+8);
  51. //狗中断
  52. //iowrite32(0x80<<8|0x1<<5|0x1<<2|0x3<<3,wdtdrv->regs);
  53. //狗reset
  54. iowrite32(0x80<<8|0x1<<5|0x3<<3|1,wdtdrv->regs);
  55. printk("WTCON=%x\n",ioread32(wdtdrv->regs));
  56. printk("WTDAT=%x\n",ioread32(wdtdrv->regs+4));
  57. printk("WTCNT=%x\n",ioread32(wdtdrv->regs+8));
  58. //启动喂狗定时器
  59. setup_timer(&wdtdrv->timer, wdt_timeout,(unsigned long)wdtdrv);
  60. mod_timer(&wdtdrv->timer,jiffies+HZ/2);
  61. //狗超时中断
  62. // if(!request_irq(wdtdrv->irq,wdt_irq,IRQF_TRIGGER_FALLING,"wdt",wdtdrv))
  63. // goto err_timer;
  64. return 0;
  65. }
  66. staticint wdt_destroy(struct wdt_driver * wdtdrv)
  67. {
  68. //狗timer停止运行
  69. iowrite32(0x80<<8|0<<5|0x3<<3|1,wdtdrv->regs);
  70. //启动喂狗定时器
  71. del_timer(&wdtdrv->timer);
  72. //狗超时中断
  73. //free_irq(wdtdrv->irq,(unsigned long)wdtdrv);
  74. return 0;
  75. }
  76. staticint wdt_probe(struct platform_device * dev)
  77. {
  78. struct wdt_driver * wdtdrv;
  79. struct resource * res;
  80. printk("wdt_probe:%s\n",dev->name);
  81. wdtdrv = container_of(container_of(dev->dev.driver,struct platform_driver,driver),struct wdt_driver,pdrv);
  82. //获取控制器寄存器地址
  83. res = platform_get_resource(dev,IORESOURCE_MEM,0);
  84. if(!res)
  85. goto err_out;
  86. wdtdrv->phys_regs = res->start;
  87. wdtdrv->phys_regs_len = res->end-res->start;
  88. wdtdrv->regs = ioremap(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
  89. if(!wdtdrv->regs)
  90. goto err_out;
  91. if(!request_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len,dev_name(&dev->dev)))
  92. goto err_ioremap;
  93. //获取中断
  94. wdtdrv->irq = platform_get_irq(dev,0);
  95. if(wdtdrv->irq<0)
  96. goto err_request_mem;
  97. printk("irq=%d\n",wdtdrv->irq);
  98. wdt_init(wdtdrv);
  99. return 0;
  100. err_request_mem:
  101. release_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
  102. err_ioremap:
  103. iounmap(wdtdrv->regs);
  104. err_out:
  105. return -1;
  106. }
  107. staticint wdt_remove(struct platform_device * dev)
  108. {
  109. struct wdt_driver * wdtdrv;
  110. printk("wdt_remove:%s\n",dev->name);
  111. wdtdrv = container_of(container_of(dev->dev.driver,struct platform_driver,driver),struct wdt_driver,pdrv);
  112. wdt_destroy(wdtdrv);
  113. release_mem_region(wdtdrv->phys_regs,wdtdrv->phys_regs_len);
  114. iounmap(wdtdrv->regs);
  115. return 0;
  116. }
  117. staticint modinit(void)
  118. {
  119. printk("mod init\n");
  120. platform_driver_register(&wdtdrv.pdrv);
  121. return 0;
  122. }
  123. staticvoid modexit(void)
  124. {
  125. platform_driver_unregister(&wdtdrv.pdrv);
  126. printk("mod exit\n");
  127. }
  128. module_init(modinit);
  129. module_exit(modexit);
  130. MODULE_LICENSE("GPL");
  131. 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中。

相关内容