Linux下的hrtimer高精度定时器【转】

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

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

[cpp] view plain copy

  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误差)。

[plain] view plain copy

    1. [email protected]:~/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
时间: 2024-10-06 18:28:20

Linux下的hrtimer高精度定时器【转】的相关文章

linux下jiffies定时器和hrtimer高精度定时器【转】

本文转载自:http://blog.csdn.net/dosculler/article/details/7932315 一.jiffies定时器,HZ=100,精度只能达到10ms. 注:采用jiffies+msecs_to_jiffies(xx ms);可做到ms级,不过精度不够 #include <Linux/jiffies.h>//DO-->jiffies调用头文件#include <linux/timer.h>  //DO-->timer_list结构体 st

使用linux内核hrtimer高精度定时器实现GPIO口模拟PWM,【原创】

关键词:Android  linux hrtimer 蜂鸣器  等待队列 信号量 字符设备 平台信息:内核:linux3.4.39 系统:android/android5.1平台:S5P4418  作者:庄泽彬(欢迎转载,请注明作者) 邮箱:[email protected] 程序描述:本文控制的设备是无源蜂鸣器,由于无源蜂鸣器是需要产生一定的频率的PWM才能够控制蜂鸣器,不像有源蜂鸣器,只需要提供高低电平就可以控制蜂鸣器.linux内核普通的定时器,由于具有一定的局限性,不能达到纳秒级别的定时

关于linux hrtimer高精度定时器的使用注意事项

关于linux hrtimer高精度定时器的使用注意事项 需要注意:由于hrtimer本身没有interval周期的概念,如果要实现hrtimer的周期调用,方法1) 超时函数,调用hrtimer_start(, tim,HRTIMER_MODE_REL);即把timer根据此tim超时时间插入到timer_base的队列中, 并返回HRTIMER_NORESTART方法2) 超时函数,调用hrtimer_forward()或者hrtimer_forward_now(), 把hrtimer的_s

高精度定时器实现 z

1背景Permalink .NET Framework 提供了四种定时器,然而其精度都不高(一般情况下 15ms 左右),难以满足一些场景下的需求. 在进行媒体播放.绘制动画.性能分析以及和硬件交互时,可能需要 10ms 以下精度的定时器.这里不讨论这种需求是否合理,它是确实存在的问题,也有相当多的地方在讨论,说明这是一个切实的需求.然而,实现它并不是一件轻松的事情. 这里并不涉及内核驱动层面的定时器,只分析在 .NET 托管环境下应用层面的高精度定时器实现. Windows 不是实时操作系统,

Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现

上一篇文章,我介绍了传统的低分辨率定时器的实现原理.而随着内核的不断演进,大牛们已经对这种低分辨率定时器的精度不再满足,而且,硬件也在不断地发展,系统中的定时器硬件的精度也越来越高,这也给高分辨率定时器的出现创造了条件.内核从2.6.16开始加入了高精度定时器架构.在实现方式上,内核的高分辨率定时器的实现代码几乎没有借用低分辨率定时器的数据结构和代码,内核文档给出的解释主要有以下几点: 低分辨率定时器的代码和jiffies的关系太过紧密,并且默认按32位进行设计,并且它的代码已经经过长时间的优化

Linux下的定时器:alarm()与setitimer()

Linux下的定时器有两种,以下分别介绍: 1.alarm 如果不要求很精确的话,用alarm()和signal()就够了 unsigned int alarm(unsigned int seconds) 函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程.如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回. 返回值: 返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0. alarm()执行后,进程将继续执行,在后期(al

linux 下高精度时间

今天在公司代码中看到了使用select函数的超时功能作定时器的用法,便整理了如下几个Linux下的微秒级别的定时器.在我的Ubutu10.10 双核环境中,编译通过. [cpp] view plain copy /* * @FileName: test_sleep.c * @Author: wzj * @Brief: * * * @History: * * @Date: 2012年02月07日星期二22:20:00 * */ #include<stdio.h> #include<stdl

Linux下的微秒级别的定时器

/* * @FileName: test_sleep.c * @Author: wzj * @Brief: * * * @History: * * @Date: 2012年02月07日星期二22:20:00 * */ #include<stdio.h> #include<stdlib.h> #include<time.h> #include<sys/time.h> #include<errno.h> #include<string.h>

Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()

我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些API基于低分辨率定时器或高精度定时器来实现,本章的内容就是讨论这些方便.好用的API是如何利用定时器系统来完成所需的功能的. /**************************************************************************************