我是靠谱客的博主 现实自行车,这篇文章主要介绍Linux驱动开发高精度定时器的精度测量,现在分享给大家,希望可以做个参考。

前言

  • 今天我们来评测linux内核的高精度定时器。顺便利用通过Tektronix示波器 和 DS100 Mini 数字示波器进行交叉测试。

  • 因项目需要用到精准的时间周期,所以要评估它的可行性,并验证正点原子的示波器能不能支撑嵌入式开发流程。

Linux高精度定时器说明

  • 其实传统的低分辨率定时器随着技术的演进,已经无法满足开发需求。而且硬件的不断发展,硬件定时器的精度也越来越高,这也给高精度定时器创建了有利条件。

  • 低分辨率的定时大部分时间复杂度可以实现O(1),当有进位发生时,不可预测的O(N)定时器级联迁移时间,影响定时器的精度。

  • 低分率的定时器可以说在超时应用场景上更加合适,以超时为目的,期望在超时到来之前获得正确的结果的场景,应用低分辨率的定时器适合不过。

  • 为了满足技术的演进及定时器的精度要求,Linux内核为高精度定时器重新设计了一套软件架构,它可以为我们提供纳秒级的定时器精度,以满足我们开发需求。精度如何实测才知道。。。。

Linux高精度定时器驱动编写

  • 为了验证高精度定时器的分辨率,我们写一个简单的内核驱动(功能:在设定的周期内反转IO,然后通过示波器测量精度)。

  • 高精度定时器使用步骤:

  1. 初始化定时器工作模式:hrtimer_init(&kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  2. 设置定时器的回调函数:kthread_timer.function = hrtimer_cb_func;

  3. 启动定时器:hrtimer_start(&kthread_timer, ktime_set(HRTIMER_TEST_CYCLE), HRTIMER_MODE_REL);

  4. 在定时器回调函数中,增加定时到期时间:hrtimer_forward(timer, timer->base->get_time(), ktime_set(HRTIMER_TEST_CYCLE));

  • 内核驱动模块代码模块实现:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "hrtimer_test.h" #define HRTIMER_TEST_PIN 7 #define HRTIMER_TEST_CYCLE   0, (100000 / 2) #define DEVICE_NAME    "HRTIMER_TEST" #define CLASS_NAME    "HRTIMER_TEST" int major_number; struct device *device; struct class *class; static struct hrtimer kthread_timer; int value = 0; enum hrtimer_restart hrtimer_cb_func(struct hrtimer *timer) {     ChipBspGpio_ExportSet(ULTRASONIC_TEST_PIN, value);     value = !value;     hrtimer_forward(timer, timer->base->get_time(), ktime_set(HRTIMER_TEST_CYCLE));     return HRTIMER_RESTART; } void kthread_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); } static int __init hrtimer_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: Register fail!n");         return major_number;     }     printk(KERN_ALERT "Registe success, major number is %dn", major_number);     class = class_create(THIS_MODULE, CLASS_NAME);     if (IS_ERR(class)) {         unregister_chrdev(major_number, DEVICE_NAME);         return PTR_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);         return PTR_ERR(device);     }     printk(KERN_ALERT "hrtimer_test: init success!!n");     kthread_hrtimer_init();     return 0; } static void __exit hrtimer_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: exit success!!n"); } module_init(hrtimer_test_init); module_exit(hrtimer_test_exit); MODULE_AUTHOR("RieChen"); MODULE_LICENSE("GPL");
  • 该驱动模块主要功能:在定时器回调函数中,周期性反转GPIO,然后查看其定时器精度。其中宏定义(HRTIMER_TEST_CYCLE)为定时的周期。

Linux高精度定时器的评测

  1. 周期1ms评测:

  • 修改宏定义:HRTIMER_TEST_CYCL设置周期为1ms. 修改如下

复制代码
1
#define HRTIMER_TEST_CYCLE   0, (1000000 / 2)
  • 通过Tektronix示波器测量:

6275ede2bf2eb05f1ab11a18a059ee1d.png
  • 通过DS100 Mini 数字示波器测量:

824af0c6bf550800e2da9b8e6d727a88.png
  • 结论:Tektronix示波器和DS100 Mini 数字示波器数据相符,波形稳定。统计出的频率与周期跟软件设置一致

  1. 周期100us评测:

  • 修改宏定义:HRTIMER_TEST_CYCL设置周期为100us. 修改如下

复制代码
1
#define HRTIMER_TEST_CYCLE   0, (100000 / 2)
  • 通过Tektronix示波器测量:

6520eb243cae6c30aab228d0f275b6a8.png
  • 通过DS100 Mini 数字示波器测量:

b31f0207b4a73dce12b2207e41990f45.png
  • 结论:Tektronix示波器和DS100 Mini 数字示波器数据相符,波形稳定。统计出的频率与周期跟软件设置一致

  1. 周期10us评测:

  • 修改宏定义:HRTIMER_TEST_CYCL设置周期为10us. 修改如下

复制代码
1
#define HRTIMER_TEST_CYCLE   0, (10000 / 2)
  • 通过Tektronix示波器测量:

a825e4b2daaffe9b2487d3fcd390217d.png
  • 通过DS100 Mini 数字示波器测量:

b1f97d760f41e4fa52f3b24e9b985d0c.png
  • 结论:Tektronix示波器和DS100 Mini 数字示波器数据都无法精确测量,波形不清晰。

  1. 周期1us评测:

  • 修改宏定义:HRTIMER_TEST_CYCL设置周期为1us. 修改如下:

复制代码
1
#define HRTIMER_TEST_CYCLE   0, (1000 / 2)
  • 通过Tektronix示波器测量:

ca3c21e690bc8434f2dcd9813b1be579.png
  • 通过DS100 Mini 数字示波器测量:

60337d8fc1a1d84ddb2270ac228ba483.png
  • 结论:Tektronix示波器和DS100 Mini 数字示波器数据都无法精确测量,波形不清晰。

总结

  • 高精度定时器总结

  1. Linux提供的高精度定时器可以满足我们大部分需求的,要注意的的,定时器回调函数不能做太多任务,并需要快速执行,否则无法保证其周期性。(作者认为高精度定时器可以看作一个外部中断的思想进行处理)

  2. 通过此次评估,Linux提供的高精度定时器可以满足我的项目需求,而且建议几十纳秒级的需求使用比较合适,如果几纳秒的需求不适合。

  • 示波器总结

  1. 通过评估数据上看,DS100 Mini 数字示波器可以替代一般的台式示波器。

  2. DS100 Mini 数字示波器可以在大部分场景上使用,可以满足项目需求


关注微信公众号『Rice嵌入式开发技术分享』,后台回复“微信”添加作者微信,备注”入群“,便可邀请进入技术交流群。

d134a9a45e36631cbca3c5eb2af6118b.png

最后

以上就是现实自行车最近收集整理的关于Linux驱动开发高精度定时器的精度测量的全部内容,更多相关Linux驱动开发高精度定时器内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(110)

评论列表共有 0 条评论

立即
投稿
返回
顶部