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

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

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;  
}  

定时器超时函数

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

open()函数

  1. <span style="color:#555555;">static int button_open(struct inode *inode, struct file *file)  
  2. {   
  3.     struct button_device *pdev ;  
  4.     struct s3c_button_platform_data *pdata;  
  5.     int i, result;  
  6.   
  7.     pdev = container_of(inode->i_cdev,struct button_device, cdev);  //获得cdev所在结构体首地址  
  8.     pdata = pdev->data;  
  9.     file->private_data = pdev;  
  10.   
  11.    </span><span style="color:#ff0000;"/* Malloc for all the buttons remove dithering timer */</span><span style="color:#555555;">  
  12.     pdev->timers = (struct timer_list *) kmalloc(pdata->nbuttons*sizeof(struct timer_list), GFP_KERNEL);  
  13.     if(NULL == pdev->timers)  
  14.     {  
  15.         printk("Alloc %s driver for timers failure.\n", DEV_NAME);  
  16.         return -ENOMEM;  
  17.     }  
  18.     memset(pdev->timers, 0, pdata->nbuttons*sizeof(struct timer_list));  
  19.   
  20.     </span><span style="color:#ff0000;">/* Malloc for all the buttons status buffer */</span><span style="color:#555555;">  
  21.     pdev->status = (unsigned char *)kmalloc(pdata->nbuttons*sizeof(unsigned char), GFP_KERNEL);  
  22.     if(NULL == pdev->status)  
  23.     {  
  24.         printk("Alloc %s driver for status failure.\n", DEV_NAME);  
  25.         result = -ENOMEM;   
  26.         goto  ERROR;  
  27.     }  
  28.     memset(pdev->status, 0, pdata->nbuttons*sizeof(unsigned char));  //初始化所有按键状态  
  29.   
  30.     init_waitqueue_head(&(pdev->waitq));  </span><span style="color:#ff0000;">//初始化等待队列</span><span style="color:#555555;">  
  31.   
  32.     for(i=0; i<pdata->nbuttons; i++)   
  33.     {  
  34.         </span><span style="color:#ff0000;">/* Initialize all the buttons status to UP  */</span><span style="color:#555555;">  
  35.         pdev->status[i] = BUTTON_UP;   
  36.   
  37.         </span><span style="color:#ff0000;">/* Initialize all the buttons' remove dithering timer */</span><span style="color:#555555;">  
  38.         setup_timer(&(pdev->timers[i]), button_timer_handler, i);  
  39.   
  40.         </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;">  
  41.         s3c2410_gpio_cfgpin(pdata->buttons[i].gpio, pdata->buttons[i].setting);  
  42.         irq_set_irq_type(pdata->buttons[i].nIRQ, IRQ_TYPE_EDGE_FALLING);  
  43.   
  44.        </span><span style="color:#ff0000;"/* Request for button GPIO pin interrupt  */</span><span style="color:#555555;">  
  45.         result = request_irq(pdata->buttons[i].nIRQ, s3c_button_intterupt, IRQF_DISABLED, DEV_NAME, (void *)i);  
  46.         if( result )  
  47.         {  
  48.             result = -EBUSY;  
  49.             goto ERROR1;  
  50.         }  
  51.     }  
  52.   
  53.     return 0;  
  54.   
  55. ERROR1:  
  56.      kfree((unsigned char *)pdev->status);  
  57.      while(--i)   
  58.      {   
  59.          disable_irq(pdata->buttons[i].nIRQ);   
  60.          free_irq(pdata->buttons[i].nIRQ, (void *)i);   
  61.      }  
  62.   
  63. ERROR:  
  64.      kfree(pdev->timers);  
  65.   
  66.      return result;  
  67. }  
  68. </span>  

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

read()函数

  1. static int button_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)  
  2. {   
  3.     struct button_device *pdev = file->private_data;  
  4.     struct s3c_button_platform_data *pdata;  
  5.     int   i, ret;  
  6.     unsigned int status = 0;  
  7.   
  8.     pdata = pdev->data;  
  9.   
  10.     dbg_print("ev_press: %d\n", pdev->ev_press);  
  11.     if(!pdev->ev_press)  
  12.     {  
  13.          if(file->f_flags & O_NONBLOCK)   //O_NONBLOCK表示非阻塞  
  14.          {  
  15.              dbg_print("read() without block mode.\n");  
  16.              return -EAGAIN;  
  17.          }  
  18.          else  
  19.          {  
  20.              /* Read() will be blocked here */              
  21.              dbg_print("read() blocked here now.\n");      
  22.              wait_event_interruptible(pdev->waitq, pdev->ev_press);  //将进程挂起  
  23.          }  
  24.     }  
  25.   
  26.     pdev->ev_press = 0;  
  27.   
  28.     <pre name="code" class="cpp">for(i=0; i<pdata->nbuttons; i++)  
  29.     {  
  30.         dbg_print("button[%d] status=%d\n", i, pdev->status[i]);  
  31.         status |= (pdev->status[i]<<i);   
  32.     }</pre><br>  
  33. ret = copy_to_user(buf, (void *)&status, min(sizeof(status), count)); //内核向用户传输数据 return ret ? -EFAULT : min(sizeof(status), count);}  
  34. <pre></pre>  
  35. <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>  
  36. <p><strong style="font-size:18px">       </strong><span style="font-size:14px">read()函数主要是用来读取按键,发生阻塞后等待中断返回唤醒。唤醒后继续执行下面函数:</span></p>  
  37. <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++)  
  38.     {  
  39.         dbg_print("button[%d] status=%d\n", i, pdev->status[i]);  
  40.         status |= (pdev->status[i]<<i);   
  41.     }</pre>      并把内核数据传给用户空间,最后返回一个ret的值,ret储存了所有按键对应的status,每个按键对应一个值,所以应用定义按键时,需和此处的对应。分别对应1<<1,1<<2,1<<3,1<<4。<p></p>  
  42. <p></p>  
  43. <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">  
  44. <span style="font-weight:bold; font-size:18px">五、poll()函数:</span></p>  
  45. <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">  
  46. <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/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8" 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/%E6%96%87%E4%BB%B6%E6%8C%87%E9%92%88" 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  
  47.  <poll.h>中。和epoll,select类似可用来查询某个或多个文件描述符的读取或写入是否被阻塞。如果驱动程序将poll的方法定义为NULL,则设备被认为可读也可写,并且不会阻塞。</span></span></p>  
  48. <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">  
  49. <span style="font-size:14px"></span></p>  
  50. <pre name="code" class="cpp">static unsigned int button_poll(struct file *file, poll_table * wait)  
  51. {   
  52.     struct button_device *pdev = file->private_data;  
  53.     unsigned int mask = 0;  
  54.   
  55.     poll_wait(file, &(pdev->waitq), wait);    
  56.     if(pdev->ev_press)  
  57.     {  
  58.         mask |= POLLIN | POLLRDNORM; /* The data aviable */   <span style="color:#ff0000;">//表示可读可写</span>  
  59.     }  
  60.   
  61.     return mask;  
  62. }</pre><br>  
  63. <p>    相关测试程序以及select具体用法请参考第二篇:</p>  
  64. <p><a target="_blank" href="http://blog.csdn.net/qicheng777/article/details/70229456">http://blog.csdn.net/qicheng777/article/details/70229456</a><br>  
  65. </p>  
  66. <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">  
  67. <span style="font-size:14px">    </span></p>  
  68. <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:'microsoft yahei'; line-height:35px">  
  69. <span style="font-size:18px"><strong><br>  
  70. </strong><br>  
  71. </span></p>  
  72. <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">  
  73. <br>  
  74. </p>  
  75.      



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值