2019-3-12系统滴答定时器中断使用
其实就是使用系统的滴答定时器产生一个中断。
- 初始化timer
- 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 :保存当前的基地址
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(0, "sixth_drv", &sencod_drv_fops);
sixthdrv_class = class_create(THIS_MODULE, "sixth_drv");
sixthdrv_class_dev = class_device_create(sixthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */
gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;
gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
gpgdat = gpgcon + 1;
return 0;
}
按键中断处理函数:
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)
{
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 = 1; /* 表示中断发生了 */
wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
kill_fasync (&button_async, SIGIO, POLL_IN);
}