fl2440开发板的platform按键驱动的一些函数

xiaoxiao2021-02-28  102

首先按键驱动的中断部分代码

static irqreturn_t s3c_button_intterupt(int irq,void *de_id) { int i; int found = 0; //通过found的值来判断是否产生了中断 struct s3c_button_platform_data *pdata = button_device.data; for(i=0; i<pdata->nbuttons; i++) { if(irq == pdata->buttons[i].nIRQ) { found = 1; break; } } if(!found) /* An ERROR interrupt */ return IRQ_NONE; /* Only when button is up then we will handle this event */ if(BUTTON_UP == button_device.status[i]) { button_device.status[i] = BUTTON_UNCERTAIN; mod_timer(&(button_device.timers[i]), jiffies+TIMER_DELAY_DOWN); // mod_timer()用于去抖动。因为按键按下时可能产生抖动 } return IRQ_HANDLED; }

定时器超时函数

<span style="color:#555555;">static void button_timer_handler(unsigned long data)   {       struct s3c_button_platform_data *pdata = button_device.data;       int num =(int)data;       int status = s3c2410_gpio_getpin( pdata->buttons[num].gpio );          if(LOWLEVEL == status)       {           if(BUTTON_UNCERTAIN == button_device.status[num])   /* Come from interrupt */           {               //dbg_print("Key pressed!\n");               button_device.status[num] = BUTTON_DOWN;                  printk("%s pressed.\n", pdata->buttons[num].name);                  /* Wake up the wait queue for read()/poll() */               button_device.ev_press = 1;     </span><span style="color:#ff0000;">//值为1表示事件发生</span><span style="color:#555555;">               wake_up_interruptible(&(button_device.waitq)); </span><span style="color:#ff0000;">//唤醒等待的操作,往下继续执行</span><span style="color:#555555;">           }              /* Cancel the dithering  */           mod_timer(&(button_device.timers[num]), jiffies+TIMER_DELAY_UP);        }       else       {           //dbg_print("Key Released!\n");           button_device.status[num] = BUTTON_UP;        //   enable_irq(pdata->buttons[num].nIRQ);       }          return ;   }</span>   中断发生时,定时器去抖产生超时。超时期间执行本段函数。函数主要 用于检测按键是否有效 ,如果有效,则唤醒等待的队列。此处调用mod_timer()函数延时用于等待按键为电平为止,以便进入if语句唤醒队列。

open()函数

<span style="color:#555555;">static int button_open(struct inode *inode, struct file *file)   {        struct button_device *pdev ;       struct s3c_button_platform_data *pdata;       int i, result;          pdev = container_of(inode->i_cdev,struct button_device, cdev);  //获得cdev所在结构体首地址       pdata = pdev->data;       file->private_data = pdev;         </span><span style="color:#ff0000;"/* Malloc for all the buttons remove dithering timer */</span><span style="color:#555555;">       pdev->timers = (struct timer_list *) kmalloc(pdata->nbuttons*sizeof(struct timer_list), GFP_KERNEL);       if(NULL == pdev->timers)       {           printk("Alloc %s driver for timers failure.\n", DEV_NAME);           return -ENOMEM;       }       memset(pdev->timers, 0, pdata->nbuttons*sizeof(struct timer_list));          </span><span style="color:#ff0000;">/* Malloc for all the buttons status buffer */</span><span style="color:#555555;">       pdev->status = (unsigned char *)kmalloc(pdata->nbuttons*sizeof(unsigned char), GFP_KERNEL);       if(NULL == pdev->status)       {           printk("Alloc %s driver for status failure.\n", DEV_NAME);           result = -ENOMEM;            goto  ERROR;       }       memset(pdev->status, 0, pdata->nbuttons*sizeof(unsigned char));  //初始化所有按键状态          init_waitqueue_head(&(pdev->waitq));  </span><span style="color:#ff0000;">//初始化等待队列</span><span style="color:#555555;">          for(i=0; i<pdata->nbuttons; i++)        {           </span><span style="color:#ff0000;">/* Initialize all the buttons status to UP  */</span><span style="color:#555555;">           pdev->status[i] = BUTTON_UP;               </span><span style="color:#ff0000;">/* Initialize all the buttons' remove dithering timer */</span><span style="color:#555555;">           setup_timer(&(pdev->timers[i]), button_timer_handler, i);              </span><span style="color:#ff0000;">/* Set all the buttons GPIO to </span><span style="color:#cc33cc;">EDGE_FALLING </span><span style="color:#ff0000;">interrupt mode */</span><span style="color:#555555;">           s3c2410_gpio_cfgpin(pdata->buttons[i].gpio, pdata->buttons[i].setting);           irq_set_irq_type(pdata->buttons[i].nIRQ, IRQ_TYPE_EDGE_FALLING);             </span><span style="color:#ff0000;"/* Request for button GPIO pin interrupt  */</span><span style="color:#555555;">           result = request_irq(pdata->buttons[i].nIRQ, s3c_button_intterupt, IRQF_DISABLED, DEV_NAME, (void *)i);           if( result )           {               result = -EBUSY;               goto ERROR1;           }       }          return 0;      ERROR1:        kfree((unsigned char *)pdev->status);        while(--i)         {             disable_irq(pdata->buttons[i].nIRQ);             free_irq(pdata->buttons[i].nIRQ, (void *)i);         }      ERROR:        kfree(pdev->timers);           return result;   }   </span>  

open()函数理解起来其实很简单。无非就是做一些内存的分配,以及初始化工作。不过这里多引入了关于中断的注册,以及将中断设置为下降沿触发(EDGE_FALLING)。

read()函数

static int button_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)   {        struct button_device *pdev = file->private_data;       struct s3c_button_platform_data *pdata;       int   i, ret;       unsigned int status = 0;          pdata = pdev->data;          dbg_print("ev_press: %d\n", pdev->ev_press);       if(!pdev->ev_press)       {            if(file->f_flags & O_NONBLOCK)   //O_NONBLOCK表示非阻塞            {                dbg_print("read() without block mode.\n");                return -EAGAIN;            }            else            {                /* Read() will be blocked here */                            dbg_print("read() blocked here now.\n");                    wait_event_interruptible(pdev->waitq, pdev->ev_press);  //将进程挂起            }       }          pdev->ev_press = 0;          <pre name="code" class="cpp">for(i=0; i<pdata->nbuttons; i++)       {           dbg_print("button[%d] status=%d\n", i, pdev->status[i]);           status |= (pdev->status[i]<<i);        }</pre><br>   ret = copy_to_user(buf, (void *)&status, min(sizeof(status), count)); //内核向用户传输数据 return ret ? -EFAULT : min(sizeof(status), count);}   <pre></pre>   <p><span style="font-size:18px"><strong>      </strong></span><span style="font-size:14px"> 值得一提的是,如果文件以阻塞的方式打开的话,read()函数如果未读取到数据(按键状态)则会<strong><span style="color:#ff0000">发生阻塞</span></strong>,如果不引入中断概念,则cpu将永远阻塞在此处。此处,read函数调用wait_event_interruptible()将进程挂起,等待中断函数处理完成后唤醒,所以接下来介绍一个<span style="color:#ff0000">函数poll() </span>用于将一些操作丢进等待队列,待中断唤醒后方可继续执行。</span></p>   <p><strong style="font-size:18px">       </strong><span style="font-size:14px">read()函数主要是用来读取按键,发生阻塞后等待中断返回唤醒。唤醒后继续执行下面函数:</span></p>   <p><span style="font-size:14px"></span></p><pre name="code" class="cpp" style="color: rgb(85, 85, 85); font-size: 18px; font-weight: bold;">for(i=0; i<pdata->nbuttons; i++)       {           dbg_print("button[%d] status=%d\n", i, pdev->status[i]);           status |= (pdev->status[i]<<i);        }</pre>      并把内核数据传给用户空间,最后返回一个ret的值,ret储存了所有按键对应的status,每个按键对应一个值,所以应用定义按键时,需和此处的对应。分别对应1<<1,1<<2,1<<3,1<<4。<p></p>   <p></p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">   <span style="font-weight:bold; font-size:18px">五、poll()函数:</span></p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">   <span style="font-size:18px">       </span><span style="font-size:14px">应用程序调用select()函数时会调用此函数用于监听函数。将设备信息丢入等待队列,便于唤醒后继续执行。<span style="color:rgb(51,51,51); font-family:arial,宋体,sans-serif; font-size:14px; text-indent:28px">此函数在</span><a target="_blank" href="http://baike.baidu.com/item/系统调用" style="color:rgb(19,110,194); text-decoration:none; font-family:arial,宋体,sans-serif; font-size:14px; text-indent:28px">系统调用</a><span style="color:rgb(51,51,51); font-family:arial,宋体,sans-serif; font-size:14px; text-indent:28px">select内部被使用,作用是把当前的</span><a target="_blank" href="http://baike.baidu.com/item/文件指针" style="color:rgb(19,110,194); text-decoration:none; font-family:arial,宋体,sans-serif; font-size:14px; text-indent:28px">文件指针</a><span style="color:rgb(51,51,51); font-family:arial,宋体,sans-serif; font-size:14px; text-indent:28px"><strong>挂到设备内部定义的等待</strong>,定义在</span><span style="color:rgb(54,46,43); font-family:Arial; font-size:18px">#include    <poll.h>中。和epoll,select类似可用来查询某个或多个文件描述符的读取或写入是否被阻塞。如果驱动程序将poll的方法定义为NULL,则设备被认为可读也可写,并且不会阻塞。</span></span></p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">   <span style="font-size:14px"></span></p>   <pre name="code" class="cpp">static unsigned int button_poll(struct file *file, poll_table * wait)   {        struct button_device *pdev = file->private_data;       unsigned int mask = 0;          poll_wait(file, &(pdev->waitq), wait);         if(pdev->ev_press)       {           mask |= POLLIN | POLLRDNORM; /* The data aviable */   <span style="color:#ff0000;">//表示可读可写</span>       }          return mask;   }</pre><br>   <p>    相关测试程序以及select具体用法请参考第二篇:</p>   <p><a target="_blank" href="http://blog.csdn.net/qicheng777/article/details/70229456">http://blog.csdn.net/qicheng777/article/details/70229456</a><br>   </p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">   <span style="font-size:14px">    </span></p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">   <span style="font-size:18px"><strong><br>   </strong><br>   </span></p>   <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(85,85,85); font-family:'microsoft yahei'; font-size:15px; line-height:35px">   <br>   </p>        

转载请注明原文地址: https://www.6miu.com/read-85466.html

最新回复(0)