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

时间:2022-04-29 00:50:02

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

  1. 定义一个timer

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

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

  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 = -;
memset(timer->start_comm, , TASK_COMM_LEN);
endif
}
EXPORT_SYMBOL(init_timer);
liunx驱动----系统滴答时钟的使用
liunx驱动----系统滴答时钟的使用
从这个结构的内容中可以看出,必须要设置 entry:链表相关 expires:保存超时时间 function :指向当超时事件发生后进入那个处理函数 data:需要传递给这个函数的参数 *base :保存当前的基地址
  1. 在按键中断中修改 超时时间
liunx驱动----系统滴答时钟的使用

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

jiffies :当前系统滴答值 HZ:默认为100 10ms一个节拍
实现功能:当按键中断发生后等待10ms后才去处理,获取到的值。
初始化函数:
static int sixth_drv_init(void)
{ /*初始化 timer 定义的这个软件定时器*/
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);//告诉内核有这样一个定时器 major = register_chrdev(, "sixth_drv", &sencod_drv_fops); sixthdrv_class = class_create(THIS_MODULE, "sixth_drv"); sixthdrv_class_dev = class_device_create(sixthdrv_class, NULL, MKDEV(major, ), NULL, "buttons"); /* /dev/buttons */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, );
gpfdat = gpfcon + ; gpgcon = (volatile unsigned long *)ioremap(0x56000060, );
gpgdat = gpgcon + ; return ;
}

按键中断处理函数:

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/);//jiffies 是一个全局变量 系统每隔10ms就会产生一个系统时钟中断 过100个10ms进入中断
return IRQ_RETVAL(IRQ_HANDLED);
}

超时事件处理函数:

static void buttons_timer_function(unsigned long data)
{ struct pin_desc * pindesc = irq_pd;
unsigned int pinval;
if(!pinval)return ;//如果为空直接返回0
pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval)
{
/* 松开 */
key_val = 0x80 | pindesc->key_val;
}
else
{
/* 按下 */
key_val = pindesc->key_val;
} ev_press = ; /* 表示中断发生了 */
wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ kill_fasync (&button_async, SIGIO, POLL_IN);
}