中断按键驱动
上升沿中断的按键驱动
如下图,需要设置4个按键的EINT0, EINT2, EINT11, EINT19的模式为双边沿,且设置按键引脚为中断引脚
这里我们只需要使用request_irq函数就行了, 在request_irq函数里会初始chip->set_type(设置引脚和中断模式
1.改进中断按键驱动程序
使用等待队列,让read函数没有中断时,进入休眠状态,降低CPU.
使用dev_id来获取不同按键的状态,是上升沿还是下降沿触发?
2.接下来要用到以下几个函数:
s3c2410_gpio_getpin(unsigned int pin); //获取引脚高低电平
pin: 引脚名称,例如:S3C2410_GPA0,定义在<asm/arch/regs-gpio.h>
队列3个函数(声明队列,唤醒队列,等待队列):
static DECLARE_WAIT_QUEUE_HEAD(qname);
声明一个新的等待队列类型的中断
qname:就是中断名字,被用来后面的唤醒中断和等待中断
wake_up_interruptible(*qname);
唤醒一个中断,会将这个中断重新添加到runqueue队列(将中断置为TASK_RUNNING状态)
qname:指向声明的等待队列类型中断名字
wait_event_interruptible(qname, condition);
等待事件中断函数,用来将中断放回等待队列,
前提是condition要为0,然后将这个中断从runqueue队列中删除(将中断置为TASK_INTERRUPTIBLE状态),然后会在函数里一直for(; ;)判断condition为真才退出
注意:此时的中断属于僵尸进程(既不在等待队列,也不在运行队列),当需要这个进程时,需要使用wake_up_interruptible(*qname)来唤醒中断
qname: (wait queue):为声明的等待队列的中断名字
condition:状态,等于0时就是中断进入休眠, 1:退出休眠
3.驱动程序步骤
(1)定义引脚描述结构体数组,每个结构体都保存按键引脚和初始状态,然后在中断服务函数中通过s3c2410_gpio_getpin()来获取按键是松开还是按下(因为中断是双边沿触发),并保存在key_val里(它会在.read函数发送给用户层)
(2)声明等待队列类型的中断button_wait:
static DECLARE_WAIT_QUEUE_HEAD(button_ wait); //声明等待队列类型的中断
(3)定义全局变量even _press,用于中断事件标志:
static volatile int even _press = 0;
(4)在.read函数里,将even _press置0放入等待事件中断函数中,判断even _press为真,才发送数据:
(5)在中断服务函数里,发生中断时, 就将even _press置1,并唤醒中断button_wait(.read函数里就会发送数据给用户层):