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

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

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

  1. rtbeat(inttimeout)
  2. {
  3. unsignedintfreq=clk_get_rate(wdt_clock);
  4. unsignedintcount;
  5. unsignedintdivisor=1;
  6. unsignedlongwtcon;
  7. if(timeout<1)
  8. return-EINVAL;
  9. freq/=128;
  10. count=timeout*freq;
  11. /*ifthecountisbiggerthanthewatchdogregister,
  12. thenworkoutwhatweneedtodo(andif)wecan
  13. actuallymakethisvalue
  14. */
  15. //如果计时的时间过大,则适当加大预分频值
  16. if(count>=0x10000)
  17. {
  18. for(divisor=1;divisor<=0x100;divisor++)
  19. {
  20. if((count/divisor)<0x10000)
  21. break;
  22. }
  23. //若预分频最大仍不能满足计时周期,则报错
  24. if((count/divisor)>=0x10000)
  25. {
  26. dev_err(wdt_dev,"timeout%dtoobig\n",timeout);
  27. return-EINVAL;
  28. }
  29. }
  30. tmr_margin=timeout;
  31. count/=divisor;
  32. wdt_count=count;
  33. /*updatethepre-scaler*/
  34. wtcon=readl(wdt_base+S3C2410_WTCON);
  35. wtcon&=~S3C2410_WTCON_PRESCALE_MASK;
  36. wtcon|=S3C2410_WTCON_PRESCALE(divisor-1);
  37. writel(count,wdt_base+S3C2410_WTDAT);//是指WTDAT寄存器
  38. writel(wtcon,wdt_base+S3C2410_WTCON);//设置预分频值
  39. return0;
  40. }
  41. /*
  42. */dev/watchdoghandling
  43. */
  44. staticints3c2410wdt_open(structinode*inode,structfile*file)
  45. {
  46. if(test_and_set_bit(0,&open_lock))//测试并设置open_lock第0位为1
  47. return-EBUSY;
  48. if(nowayout)
  49. __module_get(THIS_MODULE);
  50. allow_close=CLOSE_STATE_NOT;
  51. /*startthetimer*/
  52. s3c2410wdt_start();//启动watchdog
  53. returnnonseekable_open(inode,file);
  54. }
  55. staticints3c2410wdt_release(structinode*inode,structfile*file)
  56. {
  57. /*
  58. *Shutoffthetimer.
  59. *Lockitinifitsamoduleandwesetnowayout
  60. */
  61. if(allow_close==CLOSE_STATE_ALLOW)
  62. s3c2410wdt_stop();
  63. else
  64. {
  65. dev_err(wdt_dev,"Unexpectedclose,notstoppingwatchdog\n");
  66. s3c2410wdt_keepalive();
  67. }
  68. allow_close=CLOSE_STATE_NOT;
  69. clear_bit(0,&open_lock);//清楚open_lock第0位
  70. return0;
  71. }
  72. staticssize_ts3c2410wdt_write(structfile*file,constchar__user*data,
  73. size_tlen,loff_t*ppos)
  74. {
  75. /*
  76. *Refreshthetimer.
  77. */
  78. if(len)
  79. {
  80. if(!nowayout)
  81. {
  82. size_ti;
  83. /*Incaseitwassetlongago*/
  84. allow_close=CLOSE_STATE_NOT;
  85. for(i=0;i!=len;i++)
  86. {
  87. charc;
  88. if(get_user(c,data+i))//从用户空间copy数据
  89. return-EFAULT;
  90. if(c==V)//当输入V时,关闭watchdog
  91. allow_close=CLOSE_STATE_ALLOW;
  92. }
  93. }
  94. //注意:这里要手动喂狗一次?!
  95. s3c2410wdt_keepalive();//由于将allow_close设置成CLOSE_STATE_ALLOW后,当release时无法再次喂狗
  96. }
  97. returnlen;
  98. }
  99. #defineOPTIONSWDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE
  100. staticconststructwatchdog_infos3c2410_wdt_ident=
  101. {
  102. .options=OPTIONS,
  103. .firmware_version=0,
  104. .identity="S3C2410Watchdog",
  105. };
  106. //IO控制接口函数
  107. staticlongs3c2410wdt_ioctl(structfile*file,unsignedintcmd,
  108. unsignedlongarg)
  109. {
  110. void__user*argp=(void__user*)arg;
  111. int__user*p=argp;
  112. intnew_margin;
  113. switch(cmd){
  114. caseWDIOC_GETSUPPORT:
  115. returncopy_to_user(argp,&s3c2410_wdt_ident,
  116. sizeof(s3c2410_wdt_ident))?-EFAULT:0;
  117. caseWDIOC_GETSTATUS:
  118. caseWDIOC_GETBOOTSTATUS:
  119. returnput_user(0,p);
  120. caseWDIOC_KEEPALIVE:
  121. s3c2410wdt_keepalive();
  122. return0;
  123. caseWDIOC_SETTIMEOUT:
  124. if(get_user(new_margin,p))
  125. return-EFAULT;
  126. if(s3c2410wdt_set_heartbeat(new_margin))
  127. return-EINVAL;
  128. s3c2410wdt_keepalive();
  129. returnput_user(tmr_margin,p);
  130. caseWDIOC_GETTIMEOUT:
  131. returnput_user(tmr_margin,p);
  132. default:
  133. return-ENOTTY;
  134. }
  135. }
  136. /*kernelinterface*/
  137. //文件操作结构体
  138. staticconststructfile_operationss3c2410wdt_fops=
  139. {
  140. .owner=THIS_MODULE,
  141. .llseek=no_llseek,//屏蔽seek操作
  142. .write=s3c2410wdt_write,//写方法
  143. .unlocked_ioctl=s3c2410wdt_ioctl,//控制方法
  144. .open=s3c2410wdt_open,//代开设备方法
  145. .release=s3c2410wdt_release,//关闭设备方法
  146. };
  147. staticstructmiscdevices3c2410wdt_miscdev=
  148. {
  149. .minor=WATCHDOG_MINOR,
  150. .name="watchdog",
  151. .fops=&s3c2410wdt_fops,
  152. };
  153. /*interrupthandlercode*/
  154. staticirqreturn_ts3c2410wdt_irq(intirqno,void*param)
  155. {
  156. //dev_info(wdt_dev,"watchdogtimerexpired(irq)\n");
  157. s3c2410_gpio_setpin(S3C2410_GPB10,(count++)%2);
  158. s3c2410wdt_keepalive();
  159. returnIRQ_HANDLED;
  160. }
  161. /*deviceinterface*/
  162. //注册设备时执行
  163. staticints3c2410wdt_probe(structplatform_device*pdev)
  164. {
  165. structresource*res;
  166. structdevice*dev;
  167. unsignedintwtcon;
  168. intstarted=0;
  169. intret;
  170. intsize;
  171. dev=&pdev->dev;
  172. wdt_dev=&pdev->dev;
  173. /*getthememoryregionforthewatchdogtimer*/

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

网站地图

Top