Linux驱动--定时器timer小记

时间:2021-12-12 02:37:35

 内核中定时器是一个基础的功能,很多的驱动程序都会用到定时器进行定时或延时,当然比较短的延时也可以使用ndelay和udelay这样的函数,但是这些函数都是以浪费机器周期来获得延时的,所以还是应该避免使用。下面介绍一下定时器的内容:


#include<linux/timer.h>  //头文件

//主要的结构体文件

struct timer_list {

  struct list_head list;
  unsigned long expires;   //定时时间
  unsigned long data;        //作为参数被传入定时器处理函数
  void (*function)(unsigned long);  //定时器处理函数

};

用到的函数:

       void init_timer(struct timer_list * timer); //初始化定时器 

       void add_timer(struct timer_list * timer);//添加定时器到链表

       int mod_timer(struct timer_list *timer, unsigned long expires);//修改定时器的expires

       int del_timer(struct timer_list * timer); //从链表中删除定时器

基本操作步骤:

1、定义一个定时器timer

struct timer_list timer;

2、初始化该定时器

init_timer(&timer);

3、给定时器成员变量赋值(主要设定定时时间、处理函数和传递参数)

timer.expires = jiffies + 延时;

timer.function = timer_handle;  //timer_handle需要自己定义的处理函数

timer.data = 0;  //传递给timer_handle的参数

4、添加该定时器到定时列表

add_timer(&timer);

5、定义并实现timer_handle函数

static void timer_handle( unsigned long arg)

{

    ... ...

    //如果不希望定时器只工作一次,需要重新定义定时expires并添加到定时器列表

    timer.expires = jiffies + 延时;

    add_timer(&timer);

   //或者使用mod_timer也可以实现循环定时

   //mod_timer(&timer, jiffies + 延时);

}

6、在release函数中删除定时器

del_timer(&timer);


       这样定时就设置好了,一旦你添加定时器到定时链表中,定时器就开始工作了,所以还是建议把定时器的初始化工作(步骤2-4)放在open函数中去实现,只有用到的时候才会开启定时器工作,这样就不会造成CPU资源的浪费了。

       定时器实现的原理还是通过CPU内部的定时器模块来实现的,软件只是对硬件寄存器进行配置,最终实现还是通过硬件完成的。一个硬件定时器的初始化需要设置定时器的初始值,注册中断向量寄存器,设置优先级,然后打开中断(定时中断、外设中断等)。定时器会按照机器周期来增加,当增加到的值和设定的定时器初值相等或者定时器溢出时,定时器会触发定时中断,然后CPU会找到中断向量寄存器中注册的中断函数进行中断的处理。CPU的机器周期是通过外部的振荡电路获取的,然后通过内部的锁相环电路(PLL)来调整到合适的频率提供给每个模块使用。