微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--Watch Dog Timer(看门狗)驱动分析

ARM-Linux驱动--Watch Dog Timer(看门狗)驱动分析

时间:11-20 来源:互联网 点击:

  1. //获取IO端口资源,这里IORESOURCE_MEM和平台设备中资源的定义一致
  2. res=platform_get_resource(pdev,IORESOURCE_MEM,0);
  3. if(res==NULL){
  4. dev_err(dev,"nomemoryresourcespecified\n");
  5. return-ENOENT;
  6. }
  7. size=(res->end-res->start)+1;
  8. //申请内存空间
  9. wdt_mem=request_mem_region(res->start,size,pdev->name);
  10. if(wdt_mem==NULL){
  11. dev_err(dev,"failedtogetmemoryregion\n");
  12. ret=-ENOENT;
  13. gotoerr_req;
  14. }
  15. //地址映射,wdt_base为基地址
  16. wdt_base=ioremap(res->start,size);
  17. if(wdt_base==NULL){
  18. dev_err(dev,"failedtoioremap()region\n");
  19. ret=-EINVAL;
  20. gotoerr_req;
  21. }
  22. DBG("probe:mappedwdt_base=%p\n",wdt_base);
  23. //从平台设备中获取中断号
  24. wdt_irq=platform_get_resource(pdev,IORESOURCE_IRQ,0);
  25. if(wdt_irq==NULL){
  26. dev_err(dev,"noirqresourcespecified\n");
  27. ret=-ENOENT;
  28. gotoerr_map;
  29. }
  30. //注册中断,中断处理函数s3c2410wdt_irq()
  31. ret=request_irq(wdt_irq->start,s3c2410wdt_irq,0,pdev->name,pdev);
  32. if(ret!=0){
  33. dev_err(dev,"failedtoinstallirq(%d)\n",ret);
  34. gotoerr_map;
  35. }
  36. //获取系统时钟
  37. wdt_clock=clk_get(&pdev->dev,"watchdog");
  38. if(IS_ERR(wdt_clock)){
  39. dev_err(dev,"failedtofindwatchdogclocksource\n");
  40. ret=PTR_ERR(wdt_clock);
  41. gotoerr_irq;
  42. }
  43. //使能时钟
  44. clk_enable(wdt_clock);
  45. /*seeifwecanactuallysettherequestedtimermargin,andif
  46. *not,trythedefaultvalue*/
  47. if(s3c2410wdt_set_heartbeat(tmr_margin))
  48. {//这里第一次设置计时周期为tmr_margin,如果设置不成功,则重新设置为默认值
  49. started=s3c2410wdt_set_heartbeat(
  50. CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
  51. if(started==0)
  52. dev_info(dev,
  53. "tmr_marginvalueoutofrange,default%dused\n",
  54. CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
  55. else
  56. dev_info(dev,"defaulttimervalueisoutofrange,cannotstart\n");
  57. }
  58. //注册设备
  59. ret=misc_register(&s3c2410wdt_miscdev);
  60. if(ret)
  61. {
  62. dev_err(dev,"cannotregistermiscdevonminor=%d(%d)\n",
  63. WATCHDOG_MINOR,ret);
  64. gotoerr_clk;
  65. }
  66. if(tmr_atboot&&started==0)
  67. {
  68. dev_info(dev,"startingwatchdogtimer\n");
  69. s3c2410wdt_start();//启动看门狗
  70. }
  71. elseif(!tmr_atboot)
  72. {
  73. /*ifwerenotenablingthewatchdog,thenensureitis
  74. *disabledifithasbeenleftrunningfromthebootloader
  75. *orothersource*/
  76. s3c2410wdt_stop();
  77. }
  78. /*printoutastatementofreadiness*/
  79. wtcon=readl(wdt_base+S3C2410_WTCON);
  80. dev_info(dev,"watchdog%sactive,reset%sabled,irq%sabled\n",
  81. (wtcon&S3C2410_WTCON_ENABLE)?"":"in",
  82. (wtcon&S3C2410_WTCON_RSTEN)?"":"dis",
  83. (wtcon&S3C2410_WTCON_INTEN)?"":"en");
  84. //设置GPB10端口为输出端口,用于点亮LED10
  85. s3c2410_gpio_cfgpin(S3C2410_GPB10,S3C2410_GPB10_OUTP);
  86. return0;
  87. //出错跳转表,异常处理
  88. err_clk:
  89. clk_disable(wdt_clock);
  90. clk_put(wdt_clock);
  91. err_irq:
  92. free_irq(wdt_irq->start,pdev);
  93. err_map:
  94. iounmap(wdt_base);
  95. err_req:
  96. release_resource(wdt_mem);
  97. kfree(wdt_mem);
  98. returnret;
  99. }
  100. //设备移除函数,释放资源和映射
  101. staticints3c2410wdt_remove(structplatform_device*dev)
  102. {
  103. release_resource(wdt_mem);
  104. kfree(wdt_mem);
  105. wdt_mem=NULL;
  106. free_irq(wdt_irq->start,dev);
  107. wdt_irq=NULL;
  108. clk_disable(wdt_clock);
  109. clk_put(wdt_clock);
  110. wdt_clock=NULL;
  111. iounmap(wdt_base);
  112. misc_deregister(&s3c2410wdt_miscdev);
  113. return0;
  114. }
  115. //关闭看门狗
  116. staticvoids3c2410wdt_shutdown(structplatform_device*dev)
  117. {
  118. s3c2410wdt_stop();
  119. }
  120. //定义平台设备驱动
  121. staticstructplatform_drivers3c2410wdt_driver={
  122. .probe=s3c2410wdt_probe,
  123. .remove=s3c2410wdt_remove,
  124. .shutdown=s3c2410wdt_shutdown,
  125. .driver={
  126. .owner=THIS_MODULE,
  127. .name="s3c2410-wdt",//该名称参照内核源码中该资源的名称,两者必须一致
  128. },
  129. };
  130. staticcharbanner[]__initdata=
  131. KERN_INFO"S3C2410WatchdogTimer,(c)2004SimtecElectronics\n";
  132. //驱动安装时执行
  133. staticint__initwatchdog_init(void)
  134. {
  135. printk(banner);
  136. returnplatform_driver_register(&s3c2410wdt_driver);//注册设备
  137. }
  138. //驱动移除是执行
  139. staticvoid__exitwatchdog_exit(void)
  140. {
  141. platform_driver_unregister(&s3c2410wdt_driver);//移除设备
  142. }
  143. module_init(watchdog_init);
  144. module_exit(watchdog_exit);
  145. MODULE_AUTHOR("YanMing");
  146. MODULE_DESCRIPTION("S3C2410WatchdogDeviceDriver");
  147. MODULE_LICENSE("GPL");
  148. MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);


设置默认不是重启机器,而是执行中断函数,当不喂狗,计数器减到0,点亮LED,然后喂狗,重新计数。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top