liunx驱动----系统滴答时钟的使用

2019-3-12 系统滴答定时器中断使用

  1. 定义一个 timer

其实就是使用系统的滴答定时器产生一个中断。

  1. 初始化 timer
  2.   init_timer 函数 实现如下
void fastcall init_timer(struct timer_list *timer)
{
timer->entry.next = NULL;
timer->base = __raw_get_cpu_var(tvec_bases);
ifdef CONFIG_TIMER_STATS
timer->start_site = NULL;
timer->start_pid = -1;
memset(timer->start_comm, 0, TASK_COMM_LEN);
endif
}
EXPORT_SYMBOL(init_timer);

 

 
从这个结构的内容中可以看出,必须要设置 entry: 链表相关 expires: 保存超时时间 function :指向当超时事件发生后进入那个处理函数 data: 需要传递给这个函数的参数 *base :保存当前的基地址
  1. 在按键中断中修改 超时时间

 

 

 

jiffies :当前系统滴答值 HZ: 默认为 100 10ms 一个节拍
 
 
 
实现功能:当按键中断发生后等待 10ms 后才去处理,获取到的值。
初始化函数:
static int sixth_drv_init(void)
{
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">初始化  timer  定义的这个软件定时器</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">  
init_timer(</span>&amp;<span style="color: rgba(0, 0, 0, 1)">buttons_timer);
buttons_timer.function </span>=<span style="color: rgba(0, 0, 0, 1)"> buttons_timer_function;
add_timer(</span>&amp;buttons_timer);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">告诉内核有这样一个定时器</span>
major = register_chrdev(0, "sixth_drv", &sencod_drv_fops);
sixthdrv_class </span>= class_create(THIS_MODULE, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sixth_drv</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

sixthdrv_class_dev </span>= class_device_create(sixthdrv_class, NULL, MKDEV(major, <span style="color: rgba(128, 0, 128, 1)">0</span>), NULL, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">buttons</span><span style="color: rgba(128, 0, 0, 1)">"</span>); <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> /dev/buttons </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

gpfcon </span>= (<span style="color: rgba(0, 0, 255, 1)">volatile</span> unsigned <span style="color: rgba(0, 0, 255, 1)">long</span> *)ioremap(<span style="color: rgba(128, 0, 128, 1)">0x56000050</span>, <span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">);
gpfdat </span>= gpfcon + <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;

gpgcon </span>= (<span style="color: rgba(0, 0, 255, 1)">volatile</span> unsigned <span style="color: rgba(0, 0, 255, 1)">long</span> *)ioremap(<span style="color: rgba(128, 0, 128, 1)">0x56000060</span>, <span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">);
gpgdat </span>= gpgcon + <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;

}

按键中断处理函数:

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
    irq_pd = (struct pin_desc *)dev_id;
    //修改定时器的超时时间  HZ = 100  jiffies 当前时钟  10ms 后进入中断处理函数
    mod_timer(&buttons_timer, jiffies+HZ/100);//jiffies  是一个全局变量  系统每隔 10ms 就会产生一个系统时钟中断 过 100 个 10ms 进入中断  
    return IRQ_RETVAL(IRQ_HANDLED);
}

超时事件处理函数:

static void buttons_timer_function(unsigned long data)
{
</span><span style="color: rgba(0, 0, 255, 1)">struct</span> pin_desc * pindesc =<span style="color: rgba(0, 0, 0, 1)"> irq_pd;
unsigned </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pinval;
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(!pinval)<span style="color: rgba(0, 0, 255, 1)">return</span> ;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果为空直接返回0</span>
pinval = s3c2410_gpio_getpin(pindesc-&gt;<span style="color: rgba(0, 0, 0, 1)">pin);

</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (pinval)
{
    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 松开 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    key_val </span>= <span style="color: rgba(128, 0, 128, 1)">0x80</span> | pindesc-&gt;<span style="color: rgba(0, 0, 0, 1)">key_val;
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 按下 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    key_val </span>= pindesc-&gt;<span style="color: rgba(0, 0, 0, 1)">key_val;
}

ev_press </span>= <span style="color: rgba(128, 0, 128, 1)">1</span>;                   <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 表示中断发生了 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
wake_up_interruptible(</span>&amp;button_waitq);    <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 唤醒休眠的进程 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

kill_fasync (</span>&amp;<span style="color: rgba(0, 0, 0, 1)">button_async, SIGIO, POLL_IN);

}