Linux驱动之按键中断

该按键驱动原理虽简单,但是在处理中却运用到了Linux驱动中中断的一些关键技术,比如“顶半部”和“底半部”使用,等待队列的设置。

这里“顶半部”即中断处理函数运行时间很短,基本就做了两件事:1、关中断;2、调用定时器。具体代码如下:

<span style="font-size:13px;">static irqreturn_t key_eint_handler(int irq, void *dev_id)   {       int cnt,key_index;       key_index = 0;       //下面的for循环确定是那个按键产生了中断,并把按键编码存储在key_index中        for(cnt=0; cnt<KEY_NUM; cnt++)       {           if(g_key_info[cnt].irq_no == irq)           {               key_index = g_key_info[cnt].key_no;               break;           }       }   //    printk(KERN_NOTICE "Eint %d\n",key_index);               disable_irq(g_key_info[key_index].irq_no); //disable irq  关对应中断              g_key_dev->keystatus[key_index] = KEYSTATUS_X; //set key in unsure state    状态设置成不确定型              g_key_timer[key_index].expires = jiffies + KEY_DELAY_20MS; //set timer value    timer_list函数设置           add_timer(&g_key_timer[key_index]); //start timer  激活定时器  20ms后执行g_key_timer 函数           return IRQ_HANDLED;      //中断服务程序返回值    }</span>  

Linux驱动之按键中断

Linux驱动之按键中断

这里“底半部”通过设置内核定时器实现,“顶半部”调用定时器后便马上退出了,而定时器等待定时时间到达时调用设定的函数完成中断处理函数应该完成的事,即去抖动情况,确定按键被按下后,保存该按键序号,并唤醒被睡眠的进程,读取按键序号值。具体代码:

static void keyEvent(int key_index)   {       g_key_dev->buf[g_key_dev->head] = key_index;       g_key_dev->head = INC_BUF_POINTOR(g_key_dev->head,MAX_KEY_BUF);       wake_up_interruptible(&g_key_dev->wq);   }      static void key_timer_handler(unsigned long data)   //data是key_eint_handler中传来的key_index值    {       int key_index = data;       //printk("B:get key %d\n",s3c2410_gpio_getpin(g_tkey_info[key_index].gpio_port));           if (ISKEY_DOWN(key_index))      //按键被按下        {          printk(KERN_NOTICE "B\n");              if(g_key_dev->keystatus[key_index] == KEYSTATUS_X)   //情况一、按键状态不明确            {               g_key_dev->keystatus[key_index] = KEYSTATUS_DOWN; //change key state  // 按键设置为低                   g_key_timer[key_index].expires = jiffies + KEY_DELAY_100MS; //re_initial timer   //设定延时时间                                  keyEvent(key_index);     //保存按键序号,并唤醒等待队列中的读进程                   add_timer(&g_key_timer[key_index]); //restart timer   //激活定时器               }           else //wait for user release the key    //情况二、按键按下 进入等待释放程序               {               g_key_timer[key_index].expires = jiffies + KEY_DELAY_100MS;    //设定延时时间                add_timer(&g_key_timer[key_index]);    //激活定时间,时间到后,再次进入g_key_timer函数 ,检测按键状态            }       }       else //user have released the key              {           g_key_dev->keystatus[key_index] = KEYSTATUS_UP;           //del_timer(&g_key_timer[key_index]);               enable_irq(g_key_info[key_index].irq_no);       }   }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzjdf.html