暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Linux内核高精度定时器

嵌入式软件开发交流 2021-01-06
1476

点击上方 蓝字 关注我们!




前言




    之前有写过一篇《Linux内核定时器》,今天来看看高精度定时器,它可以为我们提供纳秒级的定时精度,以满足对精确时间有迫切需求的内核驱动。



高精度定时器编程




Linux版本:4.20


Linux内核中,使用hrtimer来描述一个高精度定时器。

struct hrtimer {
  struct timerqueue_node node;
ktime_t _softexpires; //定时器到期时间
enum hrtimer_restart (*function)(struct hrtimer *); //回调函数
struct hrtimer_clock_base *base;
u8 state;
  u8 is_rel;
  u8 is_soft;
};


(1)初始化高精度定时器

void hrtimer_init(struct hrtimer *timer, 
clockid_t which_clock,
enum hrtimer_mode mode);

which_clock:

  • CLOCK_REALTIME: 系统实时时间

  • CLOCK_MONOTONIC: 从系统启动这一刻起开始计时

  • CLOCK_BOOTTIME:  与 CLOCK_MONOTONIC 完全一致,但把系统暂停的时间也算在内

mode:

  • HRTIMER_MODE_REL:相对时间

  • HRTIMER_MODE_ABS:绝对时间


(2)启动高精度定时器

int hrtimer_start(struct hrtimer *timer, ktime_t time,
const enum hrtimer_mode mode);

根据time和mode参数的值计算hrtimer的超时时间。


(3)取消高精度定时器

int hrtimer_cancel(struct hrtimer *timer);


(4)设置超时回调

timer.function = hr_callback;

初始化时需要对struct hrtimer中的超时回调函数进行赋值。定时器一旦到期,function字段指定的回调函数会被调用,该函数的返回值为一个枚举值,它决定了该hrtimer是否需要被重新激活。

enum hrtimer_restart {
HRTIMER_NORESTART, /* Timer is not restarted */
HRTIMER_RESTART, /* Timer must be restarted */
};



例子




#include <linux/input.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/of_gpio.h>
#include <linux/io.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/i2c.h>
#include <linux/i2c/mms114.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>

unsigned int timer_count=0;
struct hrtimer hrtimer_test_timer;
ktime_t m_kt;
int value=2000;

static enum hrtimer_restart hrtimer_test_timer_poll(struct hrtimer *timer)
{

printk("================timer_count=%d ==============\n",timer_count++);
//把hrtimer的到期时间推进一个tick周期
hrtimer_forward(timer, timer->base->get_time(), m_kt);
  //重启高精度定时器
return HRTIMER_RESTART;
}

ssize_t hrtimer_test_write(struct file *f, const char __user *buf, size_t t, loff_t *len){
int i;
int ret = -1;

printk("hrtimer Debug buf:%x size:%d\n",*buf,t);

if(*buf == '0'){

printk("hrtimer_start\n");
m_kt=ktime_set(value / 1000, (value % 1000) * 1000000);
    //启动高精度定时器
hrtimer_start(&hrtimer_test_timer,m_kt, HRTIMER_MODE_REL);

}
else if(*buf == '1'){
printk("hrtimer_cancel\n");
//取消定时器
hrtimer_cancel(&hrtimer_test_timer);
}

return t;
}
static const struct file_operations hrtimer_test_fops =
{
.owner = THIS_MODULE,
.write = hrtimer_test_write,
};

struct miscdevice hrtimer_test_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "hrtimer_test",
.fops = &hrtimer_test_fops,
};


static int __init hrtimer_test_init(void)
{
int ret;
  //注册混杂设备
ret = misc_register(&hrtimer_test_dev);
//初始化高精度定时器
hrtimer_init(&hrtimer_test_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  //设置回调函数
hrtimer_test_timer.function = hrtimer_test_timer_poll;
  return 0;
}

static void __exit hrtimer_test_exit(void)
{
misc_deregister(&hrtimer_test_dev);
}


module_init(hrtimer_test_init);
module_exit(hrtimer_test_exit);
MODULE_AUTHOR("hrtimer<hrtimer@hrtimer.cc>");
MODULE_LICENSE("GPL");

上面驱动通过应用层打开设备节点,然后写入‘0’ 来启动高精度定时器,写入‘1’ 来关闭高精度定时器。









精彩推荐




年终汇总
带你入门Autotools
Linux内核定时器



长按识别图中二维码关注



点个在看你最好看

文章转载自嵌入式软件开发交流,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论