(1)中断服务程序(ISR);
在按键没有被按下的时候,线程处在阻塞状态,等待着资源的到来,而当按键被按下的时候,首先产生一个中断,这个时候中断服务子程序会保存按键的值,并且唤醒阻塞的线程。
中断阻塞函数:
wait_event_interruptible(button_waitq, ev_press);
当env_press == 0时,中断程序在阻塞睡眠状态:
当env_press == 1时,中断程序被唤醒。
唤醒函数:
wake_up_interruptible(&button_waitq)
extern unsigned int ev_press;
(2)注册中断(中断号,中断服务程序)
int request_irq( unsigned int irq,irq_handler_t handler, unsigned long flags, constchar *name, void *dev);
handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它
flags说明:设置了flag之后就知道ISR什么时候被调用了。
#define IRQF_TRIGGER_NONE 0x00000000
#define IRQF_TRIGGER_RISING 0x00000001 /* 上升沿触发 */
#define IRQF_TRIGGER_FALLING 0x00000002 /* 下降沿触发 */
#define IRQF_TRIGGER_HIGH 0x00000004 /* 高电平触发 */
#define IRQF_TRIGGER_LOW 0x00000008 /* 低电平触发 */
#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
#define IRQF_TRIGGER_PROBE 0x00000010
int open(struct inode* inode,struct file* file)
{
int ret = request_irq(IRQ_INT0,ISR,FLAG1,"up",(void*)0x01);
ret = request_irq(IRQ_INT1,ISR,FLAG1,"down",(void*)0x02);
return ret;
}
中断服务子程序:irq_handler_t handler如下
unsigned int press_key = 0;
extern int get_gpio_value(unsigned int kid,unsigned int* gpioValue)
void ISR(int irq,void* value)
{
unsigned int key_value =0;
unsigned int key_id = (unsigned int)*value;//那个按键
get_gpio_value(key_id, &key_value);
//最高位
if(key_value)
{
press_key = key_id | 0x80;
}
else
{
press_key = key_id ;
}
ev_Press = 1;
wake_up_interruptible(&button_waitq);//有动作产生,唤醒
}
int release(struct inode* inode,struct file* file)
{
free_irq(IRQ_INT0,(void*)0x01);
free_irq(IRQ_INT1,(void*)0x02);
return 0;
}
int read(struct file* file,char __user* buf,size_t count,loff_t* f_pos)
{
wait_event_interruptible(button_waitq, ev_press);
ret = copy_to_user(buf,&press_value,1);
en_press = 0;
return 0;
}
ev_press == 1时,表示有动作产生,即是我们从中断服务程序中可以看到key_action = 1 ;
ev_press == 0会阻塞,即是press_value没有发生改变
当没有按键时,没有电平相关触发事件产生,所以中断没有被触发。而当按键被按下时,中断处理函数ISR就被调用。