前言
- 今天我们来评测linux内核的高精度定时器。顺便利用通过Tektronix示波器 和 DS100 Mini 数字示波器进行交叉测试。
- 因项目需要用到精准的时间周期,所以要评估它的可行性,并验证正点原子的示波器能不能支撑嵌入式开发流程。
Linux高精度定时器说明
- 其实传统的低分辨率定时器随着技术的演进,已经无法满足开发需求。而且硬件的不断发展,硬件定时器的精度也越来越高,这也给高精度定时器创建了有利条件。
- 低分辨率的定时大部分时间复杂度可以实现O(1),当有进位发生时,不可预测的O(N)定时器级联迁移时间,影响定时器的精度。
- 低分率的定时器可以说在超时应用场景上更加合适,以超时为目的,期望在超时到来之前获得正确的结果的场景,应用低分辨率的定时器适合不过。
- 为了满足技术的演进及定时器的精度要求,Linux内核为高精度定时器重新设计了一套软件架构,它可以为我们提供纳秒级的定时器精度,以满足我们开发需求。精度如何实测才知道。。。。
Linux高精度定时器驱动编写
-
为了验证高精度定时器的分辨率,我们写一个简单的内核驱动(功能:在设定的周期内反转IO,然后通过示波器测量精度)。
-
高精度定时器使用步骤:
- 初始化定时器工作模式:hrtimer_init(&kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- 设置定时器的回调函数:kthread_timer.function = hrtimer_cb_func;
- 启动定时器:hrtimer_start(&kthread_timer, ktime_set(HRTIMER_TEST_CYCLE), HRTIMER_MODE_REL);
- 在定时器回调函数中,增加定时到期时间:hrtimer_forward(timer, timer->base->get_time(), ktime_set(HRTIMER_TEST_CYCLE));
- 内核驱动模块代码模块实现:
#include"hrtimer_test.h"
#defineHRTIMER_TEST_PIN7
#defineHRTIMER_TEST_CYCLE0,(100000/2)
#defineDEVICE_NAME"HRTIMER_TEST"
#defineCLASS_NAME"HRTIMER_TEST"
intmajor_number;
structdevice*device;
structclass*class;
staticstructhrtimerkthread_timer;
intvalue=0;
enumhrtimer_restarthrtimer_cb_func(structhrtimer*timer){
ChipBspGpio_ExportSet(ULTRASONIC_TEST_PIN,value);
value=!value;
hrtimer_forward(timer,timer->base->get_time(),ktime_set(HRTIMER_TEST_CYCLE));
returnHRTIMER_RESTART;
}
voidkthread_hrtimer_init(void){
hrtimer_init(&kthread_timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
kthread_timer.function=hrtimer_cb_func;
hrtimer_start(&kthread_timer,ktime_set(HRTIMER_TEST_CYCLE),HRTIMER_MODE_REL);
}
staticint__inithrtimer_test_init(void){
printk(KERN_ALERT"hrtimer_test:Init!!\n");
major_number=register_chrdev(0,DEVICE_NAME,NULL);
if(major_number< 0){
printk(KERN_ALERT"hrtimer_test:Registerfail!\n");
returnmajor_number;
}
printk(KERN_ALERT"Registesuccess,majornumberis%d\n",major_number);
class=class_create(THIS_MODULE,CLASS_NAME);
if(IS_ERR(class)){
unregister_chrdev(major_number,DEVICE_NAME);
returnPTR_ERR(class);
}
device=device_create(class,NULL,MKDEV(major_number,0),NULL,DEVICE_NAME);
if(IS_ERR(device)){
class_destroy(class);
unregister_chrdev(major_number,DEVICE_NAME);
returnPTR_ERR(device);
}
printk(KERN_ALERT"hrtimer_test:initsuccess!!\n");
kthread_hrtimer_init();
return0;
}
staticvoid__exithrtimer_test_exit(void){
hrtimer_cancel(&kthread_timer);
device_destroy(class,MKDEV(major_number,0));
class_unregister(class);
class_destroy(class);
unregister_chrdev(major_number,DEVICE_NAME);
printk(KERN_ALERT"hrtimer_test:exitsuccess!!\n");
}
module_init(hrtimer_test_init);
module_exit(hrtimer_test_exit);
MODULE_AUTHOR("RieChen");
MODULE_LICENSE("GPL");
- 该驱动模块主要功能:在定时器回调函数中,周期性反转GPIO,然后查看其定时器精度。其中宏定义(HRTIMER_TEST_CYCLE)为定时的周期。
Linux高精度定时器的评测
- 周期1ms评测:
- 修改宏定义:HRTIMER_TEST_CYCL设置周期为1ms. 修改如下
#defineHRTIMER_TEST_CYCLE0,(1000000/2)
- 通过Tektronix示波器测量:
- 通过DS100 Mini 数字示波器测量:
- 结论:Tektronix示波器和DS100 Mini 数字示波器数据相符,波形稳定。统计出的频率与周期跟软件设置一致
- 周期100us评测:
- 修改宏定义:HRTIMER_TEST_CYCL设置周期为100us. 修改如下
#defineHRTIMER_TEST_CYCLE0,(100000/2)
- 通过Tektronix示波器测量:
- 通过DS100 Mini 数字示波器测量:
- 结论:Tektronix示波器和DS100 Mini 数字示波器数据相符,波形稳定。统计出的频率与周期跟软件设置一致
- 周期10us评测:
- 修改宏定义:HRTIMER_TEST_CYCL设置周期为10us. 修改如下
#defineHRTIMER_TEST_CYCLE0,(10000/2)
- 通过Tektronix示波器测量:
- 通过DS100 Mini 数字示波器测量:
- 结论:Tektronix示波器和DS100 Mini 数字示波器数据都无法精确测量,波形不清晰。
- 周期1us评测:
- 修改宏定义:HRTIMER_TEST_CYCL设置周期为1us. 修改如下:
#defineHRTIMER_TEST_CYCLE0,(1000/2)
- 通过Tektronix示波器测量:
- 通过DS100 Mini 数字示波器测量:
- 结论:Tektronix示波器和DS100 Mini 数字示波器数据都无法精确测量,波形不清晰。
总结
- 高精度定时器总结
- Linux提供的高精度定时器可以满足我们大部分需求的,要注意的的,定时器回调函数不能做太多任务,并需要快速执行,否则无法保证其周期性。(作者认为高精度定时器可以看作一个外部中断的思想进行处理)
- 通过此次评估,Linux提供的高精度定时器可以满足我的项目需求,而且建议几十纳秒级的需求使用比较合适,如果几纳秒的需求不适合。
- 示波器总结
- 通过评估数据上看,DS100 Mini 数字示波器可以替代一般的台式示波器。
- DS100 Mini 数字示波器可以在大部分场景上使用,可以满足项目需求
审核编辑 黄昊宇
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
驱动
+关注
关注
12文章
1838浏览量
85262 -
Linux
+关注
关注
87文章
11292浏览量
209333 -
定时器
+关注
关注
23文章
3246浏览量
114721
发布评论请先 登录
相关推荐
详解高精度定时器与高级控制定时器
在高精度定时器中,可以使用外部事件来对 PWM 输出进行封锁,并可自动恢复;在高级控制定时器中,可以使用 Break 或是 Clr_input 来对 PWM 输出进行封锁, 然后也可以自动恢复,其中 Break 必须结合 AOE
Linux高精度定时器hrtimer使用示例
要使用高精度定时器hrtimer。 使用示例 单次定时 加载驱动一秒后输出“ hrtimer handler ”: # include # include # include # in
评论