每篇诗句分享: 赌书消得泼茶香,当时只道是寻常。
好了,进入正题了。在platform驱动中,我们用到了定时器函数timer,当时遇到也有点懵逼。不过郭工讲听了以后的,自己查阅相关资料,所以决定写下这篇博客。这就是这篇文章的典故了。
首先来两个概念,接好了。
- 系统定时器:系统定时器能以固定频率产生中断,称之为定时器中断,对应中断处理程序负责更新系统时间,也负责执行需要周期行运行的任务。
- 动态定时器:用来推迟执行程序的工具,内核可以动态创建或销毁动态定时器。我们在platform中遇到的就是这种啦。
说完了定时器分类,再说说几个具体概念:
系统定时器频率(节拍率):也就是HZ,可以理解为每秒中断的次数。在系统启动时按照HZ值对硬件进行设置,是通过静态预处理定义的,体系结构不一样,HZ的值也不同,定义在asm/param.h中。
jiffies的变量:(定义在linux/jiffies)记录了自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后每次时钟中断处理程序都会增加该变量的值。因为一秒内时钟中断的次数等于HZ,所以jiffies一秒内增加的值也就为HZ.系统运行时间以秒为单位计算,就等于jiffes/HZ.它作为在计算机表示的变量,就总存在大小,当这个变量增加到超出它的表示上限时,就要回绕到0.这个回绕看起来很简单,但实际上还是给我们编程造成了很大的麻烦,比如边界条件判断时。幸好,内核提供了四个宏来帮助比较节拍计数,这些宏定义在linux/jiffies.h可以很好的处理节拍回绕的情况。
上半场好像这双方踢球踢得像睡着了一样,下半场精彩的部分来了。那么我们就根据上半场的情况来点货真价实的实例,就拿platform遇到的timer来讲吧!
啥也不多说,具体timer函数是怎么实现的,自个百度去。
/* Initial the LED blink timer */
init_timer(&(led_device.blink_timer)); //初始化定时器
led_device.blink_timer.function = led_timer_handler; //超时后执行该函数
led_device.blink_timer.data = (unsigned long)pdata; //给定时器传参数
led_device.blink_timer.expires = jiffies + TIMER_TIMEOUT; //超时时间
add_timer(&(led_device.blink_timer)); //激活定时器
要使用定时器,这几个步骤是必不可少的。led_timer_handler这个函数是定时器超时以后就去执行这个函数。jiffies在上面具体介绍过了,大概意思可以理解为CPU上电后,内个内核每跑1HZ=100,这家伙就加100。
重要的来了,来看看具体使用。
mod_timer(&(led_device.blink_timer), jiffies + TIMER_TIMEOUT); //TIMER_TIMEOUT我们定义的是40 而HZ定义的值为100
然后就简单了:
HZ=100 -----> t'=1s/100=10 ms (10ms产生一次中断)
HZ=100 也可以理解为 jiffies一秒会增加100.
所以:TIMER_TIMEOUT换算成秒的话等于 40*10ms=400ms.
所以该定时器函数就好理解了。在延时400ms后,就接下来去执行
led_timer_handler函数。在按键驱动中可以用定时器去抖。