转自:http://blog.csdn.net/waverider2012/article/details/38305785

hrtimer高精度定时器的interval由ktime_set(const long secs, const unsigned long nsecs)决定,可做到ns级。此处的例子为5ms interval:

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/hrtimer.h>
  4. #include <linux/ktime.h>
  5. MODULE_LICENSE("GPL");
  6. static struct hrtimer hr_timer;
  7. static struct work_struct wq_hrtimer;
  8. static ktime_t ktime;
  9. static unsigned int interval=5000; /* unit: us */
  10. struct timespec uptimeLast;
  11. static unsigned int count=0;
  12. #define COUNT_INTERVAL 4000
  13. unsigned long long diff_tv(struct timespec start, struct timespec end) {
  14. return (end.tv_sec-start.tv_sec)*1000000000+(end.tv_nsec-start.tv_nsec);
  15. }
  16. enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer )
  17. {
  18. schedule_work(&wq_hrtimer);
  19. return HRTIMER_NORESTART;
  20. }
  21. static void wq_func_hrtimer(struct work_struct *work)
  22. {
  23. struct timespec uptime;
  24. hr_timer.function = my_hrtimer_callback;
  25. ktime = ktime_set( interval/1000000, (interval%1000000)*1000 );
  26. hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL );
  27. /* print time every COUNT_INTERVAL*interval second*/
  28. if(count%COUNT_INTERVAL==0)
  29. {
  30. do_posix_clock_monotonic_gettime(&uptime);
  31. printk(KERN_INFO"hrtimer:%9lu sec, %9lu ns, interval_delay=%lu ns\n",
  32. (unsigned long) uptime.tv_sec, uptime.tv_nsec,
  33. (unsigned long)(diff_tv(uptimeLast, uptime)-interval*1000*COUNT_INTERVAL) \
  34. /COUNT_INTERVAL);
  35. uptimeLast=uptime;
  36. }
  37. count++;
  38. }
  39. static int __init module_hrtimer_init( void )
  40. {
  41. struct timespec uptime;
  42. printk(KERN_INFO"HR Timer module installing\n");
  43. hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
  44. ktime = ktime_set( interval/1000000, (interval%1000000)*1000 );
  45. hr_timer.function = my_hrtimer_callback;
  46. hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );
  47. do_posix_clock_monotonic_gettime(&uptime);
  48. uptimeLast = uptime;
  49. printk(KERN_INFO"hrtimer:%9lu sec, %9lu ns\n", (unsigned long) uptime.tv_sec,
  50. uptime.tv_nsec );
  51. INIT_WORK(&wq_hrtimer, wq_func_hrtimer);
  52. return 0;
  53. }
  54. static void __exit module_hrtimer_exit( void )
  55. {
  56. int ret;
  57. ret = hrtimer_cancel( &hr_timer );
  58. if (ret)
  59. printk("The timer was still in use...\n");
  60. printk("HR Timer module uninstalling\n");
  61. return;
  62. }
  63. module_init(module_hrtimer_init);
  64. module_exit(module_hrtimer_exit);

如果在my_hrtimer_callback()里面直接返回HRTIMER_RESTART会导致立即重新进入my_hrtimer_callback()。这时shell对输入没有任何响应。

所以为了解决这个问题,创建了一个work queue,由my_hrtimer_callback() enqueue这个工作队列。在work queue的处理函数里面重启hrtimer。

但是这样带来的负面影响是进入hrtimer_callback和wq_func被调用之间有Linux系统调度引入的延迟,导致interval出现误差。经过实测,在ZC706缺省配置下,这个延迟大约是17.5us (hrtimer interval为5ms,每20秒计算一次interval误差)。

    1. root@zynq:~/nfs/hrtimer# insmod hrtimer.ko
    2. HR Timer module installing
    3. hrtimer:    2900 sec, 993366078 ns
    4. hrtimer:    2900 sec, 998395278 ns, interval_delay=369966 ns
    5. hrtimer:    2921 sec,  69525447 ns, interval_delay=17782 ns
    6. hrtimer:    2941 sec, 139764655 ns, interval_delay=17559 ns
    7. hrtimer:    2961 sec, 210029519 ns, interval_delay=17566 ns
    8. hrtimer:    2981 sec, 280465631 ns, interval_delay=17609 ns
    9. hrtimer:    3001 sec, 350677038 ns, interval_delay=17552 ns
    10. hrtimer:    3021 sec, 420625114 ns, interval_delay=17487 ns
    11. hrtimer:    3041 sec, 490744847 ns, interval_delay=17529 ns

最新文章

  1. 【需求设计1】VIP积分系统无聊YY
  2. java Timer 定时每天凌晨1点执行任务
  3. Appium移动自动化测试之安装Appium
  4. 阿里前CEO卫哲用自己10余年经历,倾诉B2B的三差、四率、两大坑
  5. [麦先生]Laravel SQL语句记录方式
  6. Windows-001-Win7系统变量设置
  7. android 系统定制的小技巧(网络收集)
  8. 【HTML】Advanced5:Accessible Forms
  9. GitHub使用说明
  10. sqlite3插入日期时间出错解决
  11. Sets 比赛时想错方向了。。。。 (大数不能处理负数啊)
  12. java----Java的栈,堆,代码,静态存储区的存储顺序和位置
  13. Oracle课程档案,第六天
  14. 学机器学习,不会数据处理怎么行?—— 二、Pandas详解
  15. visual studio 2013设置背景图片
  16. Codeforces 101487E - Enter The Dragon
  17. php file_get_contents计时读取一个文件/页面 防止读取不到内容
  18. 6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程
  19. 用 TensorFlow 实现 SVM 分类问题
  20. Linux学习笔记(第零章)

热门文章

  1. JavaScript调试中Console命令
  2. 孤荷凌寒自学python第六十八天学习并实践beautifulsoup模块1
  3. Fluentd插件使用方法
  4. 机器学习实战一:kNN手写识别系统
  5. mongodb数据库高级操作
  6. WebStorm强大的调试JavaScript功能(转载)
  7. PAT 1080 MOOC期终成绩
  8. PHP与webserver【简书看到的】
  9. PHP的报错级别并返回当前级别error_reporting()
  10. something about Parameter Estimation (参数估计)