Precision measurement of high precision timer driven by Linux

preface

  • Today, let's evaluate the high-precision timer of linux kernel. By the way, the Tektronix oscilloscope and DS100 Mini digital oscilloscope are used for cross test.
  • Because the project needs to use an accurate time cycle, it is necessary to evaluate its feasibility and verify whether the on-time atomic oscilloscope can support the embedded development process.

Linux high precision timer description

  • In fact, with the evolution of technology, the traditional low resolution timer has been unable to meet the development needs. Moreover, with the continuous development of hardware, the accuracy of hardware timer is getting higher and higher, which also creates favorable conditions for high-precision timer.
  • Most of the time complexity of low resolution timing can achieve O(1). When carry occurs, the unpredictable O(N) timer cascade migration time affects the accuracy of the timer.
  • It can be said that the timer with low division rate is more suitable in the application scenario of timeout. For the purpose of timeout and expecting to obtain the correct results before the timeout, the timer with low resolution is not suitable.
  • In order to meet the evolution of technology and the accuracy requirements of timers, the Linux kernel redesigned a set of software architecture for high-precision timers, which can provide us with nanosecond timer accuracy to meet our development needs. How to measure the accuracy before you know....

Writing Linux High Precision Timer Driver

  • In order to verify the resolution of the high-precision timer, we write a simple kernel driver (function: reverse IO within the set cycle, and then measure the accuracy through the oscilloscope).
  • Use steps of high-precision timer:
  1. Initialization timer working mode: hrtimer_ init(&kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  2. Callback function for setting timer: kthread_timer.function = hrtimer_cb_func;
  3. Start timer: hrtimer_ start(&kthread_timer, ktime_set(HRTIMER_TEST_CYCLE), HRTIMER_ MODE_ REL);
  4. In the timer callback function, add the timing expiration time: hrtimer_ forward(timer, timer->base->get_time(), ktime_ set(HRTIMER_TEST_CYCLE));
  • Code implementation of kernel driver module:
#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 %d\n", 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");

copy
  • The main functions of the driver module: in the timer callback function, periodically reverse GPIO, and then check its timer accuracy. The macro definition (HRTIMER_TEST_CYCLE) is a timed cycle.

Evaluation of Linux high precision timer

  1. Periodic 1ms evaluation:
  • Modify macro definition: HRTIMER_TEST_CYCL setting cycle is 1ms Amend as follows
#define HRTIMER_TEST_CYCLE   0, (1000000 / 2)
copy
  • Measured by Tektronix oscilloscope:
  • Measured by DS100 Mini digital oscilloscope:
  • Conclusion: the data of Tektronix oscilloscope and DS100 Mini digital oscilloscope are consistent and the waveform is stable. The calculated frequency and period are consistent with the software settings
  1. Cycle 100us evaluation:
  • Modify macro definition: HRTIMER_TEST_CYCL setting cycle is 100us Amend as follows
#define HRTIMER_TEST_CYCLE   0, (100000 / 2)
copy
  • Measured by Tektronix oscilloscope:
  • Measured by DS100 Mini digital oscilloscope:
  • Conclusion: the data of Tektronix oscilloscope and DS100 Mini digital oscilloscope are consistent and the waveform is stable. The calculated frequency and period are consistent with the software settings
  1. Periodic 10us evaluation:
  • Modify macro definition: HRTIMER_TEST_CYCL setting cycle is 10us Amend as follows
#define HRTIMER_TEST_CYCLE   0, (10000 / 2)
copy
  • Measured by Tektronix oscilloscope:
  • Measured by DS100 Mini digital oscilloscope:
  • Conclusion: the data of Tektronix oscilloscope and DS100 Mini digital oscilloscope can not be measured accurately, and the waveform is not clear.
  1. Periodic 1us evaluation:
  • Modify macro definition: HRTIMER_TEST_CYCL set the cycle to 1us Amend as follows:
#define HRTIMER_TEST_CYCLE   0, (1000 / 2)
copy
  • Measured by Tektronix oscilloscope:
  • Measured by DS100 Mini digital oscilloscope:
  • Conclusion: the data of Tektronix oscilloscope and DS100 Mini digital oscilloscope can not be measured accurately, and the waveform is not clear.

summary

  • Summary of high precision timer
  1. The high-precision timer provided by Linux can meet most of our needs. It should be noted that the timer callback function cannot do too many tasks and needs to be executed quickly, otherwise its periodicity cannot be guaranteed. (the author believes that the high-precision timer can be treated as an external interrupt)
  2. Through this evaluation, the high-precision timer provided by Linux can meet the needs of my project, and it is recommended to use tens of nanoseconds. If a few nanoseconds is not suitable.
  • Oscilloscope summary
  1. From the evaluation data, DS100 Mini digital oscilloscope can replace the general desktop oscilloscope.
  2. DS100 Mini digital oscilloscope can be used in most scenarios and can meet the needs of the project

Posted by AchillesForce on Tue, 10 May 2022 18:11:16 +0300