微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > linux驱动之内核定时器驱动设计

linux驱动之内核定时器驱动设计

时间:12-01 来源:互联网 点击:

}

}

timer->expires = expires;

internal_add_timer(base, timer);

out_unlock:

spin_unlock_irqrestore(&base->lock, flags);

return ret;

}

static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)

{

unsigned long expires = timer->expires;

unsigned long idx = expires - base->timer_jiffies;

struct list_head *vec;

if (idx < TVR_SIZE) {

int i = expires & TVR_MASK;

vec = base->tv1.vec + i;

} else if (idx < 1 < (TVR_BITS + TVN_BITS)) {

int i = (expires >> TVR_BITS) & TVN_MASK;

vec = base->tv2.vec + i;

} else if (idx < 1 < (TVR_BITS + 2 * TVN_BITS)) {

int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;

vec = base->tv3.vec + i;

} else if (idx < 1 < (TVR_BITS + 3 * TVN_BITS)) {

int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;

vec = base->tv4.vec + i;

} else if ((signed long) idx < 0) {

/*

* Can happen if you add a timer with expires == jiffies,

* or you set a timer to go off in the past

*/

vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);

} else {

int i;

/* If the timeout is larger than 0xffffffff on 64-bit

* architectures then we use the maximum timeout:

*/

if (idx > 0xffffffffUL) {

idx = 0xffffffffUL;

expires = idx + base->timer_jiffies;

}

i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;

vec = base->tv5.vec + i;

}

/*

* Timers are FIFO:

*/

/*添加到链表的最后,这说明mod_timer实现了重新注册一个定时器的操作*/

list_add_tail(&timer->entry, vec);

}

从上面的分析可以看出,mod_timer的实现过程比较复杂,但是基本上说明了mod_timer函数重新注册定时器的操作过程。

一般而言定时器的基本操作主要是上面的几个函数。

我的基于内核定时器的驱动函数如下,参考了宋宝华的Linux设备驱动开发详解(第二版)。

驱动程序:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*采用宏定义设置设备的主设备号*/

#define SECOND_MAJOR 0

/*静态的分别保存静态主设备号的变量*/

static int second_major = SECOND_MAJOR;

/*设备结构体,通常在设备中包含需要的设备,比如字符、块等类型*/

struct second_dev{

/*添加设备类型,

我认为可以采用一个联合体,

包含块设备或者字符设备,类似inode的实现方法,

这样可以提高结构体的通用性

*/

struct cdev cdev;

/*原子变量,用来统计*/

atomic_t counter;

/*添加内核定时器结构体变量*/

struct timer_list s_timer;

/*用于动态创建设备文件的设备类*/

struct class *myclass;

};

/*结构体指针或者采用全局变量直接定义结构都可以*/

struct second_dev *second_devp;

/*如果定时时间到了,定时器的处理函数*/

static void second_timer_handler(unsigned long arg)

{

/*

修改定时器中的到期时间,增加时间为1s,

需要注意的是mod_timer函数是重新注册定时器到内核

而不管定时器是否被运行过

*/

mod_timer(&second_devp->s_timer,jiffies + HZ);

/*原子变量的增加*/

atomic_inc(&second_devp->counter);

/*输出jiffies值*/

printk(KERN_NOTICE "Current jiffies is %d",jiffies);

}

/*open函数实现*/

static int second_open(struct inode *inode,struct file *filp)

{

/*初始化定义的内核定时器*/

init_timer(&second_devp->s_timer);

/*指定内核定时器的处理函数是上面定义好的函数*/

second_devp->s_timer.function = second_timer_handler;

/*指定定时间隔是1s*/

second_devp->s_timer.expires = jiffies + HZ;

/*将定时器添加到内核*/

add_timer(&second_devp->s_timer);

/*同时设备相关的统计值为0*/

atomic_set(&second_devp->counter,0);

return 0;

}

/*release函数的实现*/

static int second_release(struct inode *inode,struct file *filp)

{

/*如果没有到时间

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top