Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98122
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 384
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-06 16:52
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-06 12:33:48

poll机制的分析可以参考http://blog.csdn.net/frankyzhangc/article/details/6692210

int poll(struct pollfd *fds,nfds_t nfds, int timeout);

总的来说,Poll机制会判断fds中的文件是否可读,如果可读则会立即返回,返回的值就是可读fd的数量,如果不可读,那么就进程就会休眠timeout这么长的时间,然后再来判断是否有文件可读,如果有,返回fd的数量,如果没有,则返回0. 

1.按键中断poll机制的驱动程序代码如下,只要在原有驱动的基础上加上poll函数(红色部分)

点击(此处)折叠或打开

  1. //moudle.h 包含了大量加载模块需要的函数和符号的定义
  2. #include <linux/module.h>
  3. //kernel.h以便使用printk()等函数
  4. #include <linux/kernel.h>
  5. //fs.h包含常用的数据结构,如struct file等
  6. #include <linux/fs.h>
  7. //uaccess.h 包含copy_to_user(),copy_from_user()等函数
  8. #include <linux/uaccess.h>
  9. //io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
  10. #include <linux/io.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/pci.h>
  13. //init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
  14. #include <linux/init.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/cdev.h>
  18. #include <linux/gpio.h>
  19. #include <linux/irq.h>
  20. #include <linux/sched.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/poll.h>
  23. //irq.h中断与并发请求事件
  24. #include <asm/irq.h>
  25. //下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
  26. //#include <mach/gpio.h>
  27. #include <mach/regs-gpio.h>
  28. #include <plat/gpio-cfg.h>
  29. #include <mach/hardware.h>
  30. #include <mach/map.h>


  31. static struct class *button_poll_class;
  32. static int major;

  33. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
  34. /* 中断事件标志, 中断服务程序将它置1,button_poll_read将它清0 */
  35. static volatile int ev_press = 0;

  36. struct pin_desc {
  37.     unsigned int pin;
  38.     unsigned int button_val;
  39. };

  40. static unsigned char button_val;

  41. static struct pin_desc pins_desc[6] = {
  42.     {S3C64XX_GPN(0), 0x01},
  43.     {S3C64XX_GPN(1), 0x02},
  44.     {S3C64XX_GPN(2), 0x03},
  45.     {S3C64XX_GPN(3), 0x04},
  46.     {S3C64XX_GPN(4), 0x05},
  47.     {S3C64XX_GPN(5), 0x06},
  48. };

  49. /*中断服务函数*/
  50. /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 ...*/
  51. /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 ...*/
  52. static irqreturn_t button_poll_irq(int irq, void *dev_id)
  53. {
  54.     struct pin_desc *pindesc = (struct pin_desc *)dev_id;
  55.     unsigned char pinval;
  56.     
  57.     pinval = gpio_get_value(pindesc->pin);
  58.     
  59.     if(pinval == 1)
  60.         button_val = 0x80 | pindesc->button_val;
  61.     else
  62.         button_val = pindesc->button_val;
  63.     
  64.     ev_press = 1; /* 表示中断发生了 */
  65.     wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
  66.     
  67.     return IRQ_HANDLED;
  68. }

  69. static int button_poll_open(struct inode *inode, struct file *file)
  70. {    
  71.     int ret;
  72.     
  73.     /*request_irq注册中断
  74.      *第一个参数是中断号,也是中断处理函数button_poll的第一个参数
  75.      *第二个参数是中断处理函数
  76.      *第三个参数是中断触发方式
  77.      *第四个参数是设备名称
  78.      *第五个参数是设备ID,也是中断处理函数button_poll的第二个参数
  79.      */
  80.     ret = request_irq(IRQ_EINT(0), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k1", &pins_desc[0]);
  81.     if (ret){
  82.         printk("request IRQ_EINT(0) error!\n");
  83.         free_irq(IRQ_EINT(0), &pins_desc[0]);
  84.     }    
  85.     ret = request_irq(IRQ_EINT(1), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k2", &pins_desc[1]);
  86.     if (ret){
  87.         printk("request IRQ_EINT(1) error!\n");
  88.         free_irq(IRQ_EINT(1), &pins_desc[1]);
  89.     }
  90.         
  91.     ret = request_irq(IRQ_EINT(2), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k3", &pins_desc[2]);
  92.     if (ret){
  93.         printk("request IRQ_EINT(2) error!\n");
  94.         free_irq(IRQ_EINT(2), &pins_desc[2]);
  95.     }
  96.         
  97.     ret = request_irq(IRQ_EINT(3), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k4", &pins_desc[3]);
  98.     if (ret){
  99.         printk("request IRQ_EINT(3) error!\n");
  100.         free_irq(IRQ_EINT(3), &pins_desc[3]);
  101.     }
  102.         
  103.     ret = request_irq(IRQ_EINT(4), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k5", &pins_desc[4]);
  104.     if (ret){
  105.         printk("request IRQ_EINT(4) error!\n");
  106.         free_irq(IRQ_EINT(4), &pins_desc[4]);
  107.     }
  108.         
  109.     ret = request_irq(IRQ_EINT(5), button_poll_irq, IRQ_TYPE_EDGE_BOTH, "k6", &pins_desc[5]);
  110.     if (ret){
  111.         printk("request IRQ_EINT(5) error!\n");
  112.         free_irq(IRQ_EINT(5), &pins_desc[5]);
  113.     }
  114.     return 0;
  115. }

  116. static ssize_t button_poll_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
  117. {
  118.     if (size != 1)
  119.         return -EINVAL;
  120.         
  121.     /* 如果没有按键动作, 休眠 */
  122.     /*ev_press=0时休眠,ev_press=1时继续向下执行程序*/
  123.     wait_event_interruptible(button_waitq, ev_press);
  124.         
  125.     /* 如果有按键动作, 返回键值 */
  126.     if( copy_to_user(buf, &button_val, 1) ){
  127.         printk("error in function ‘copy_to_user’ !\n");
  128.             return -EFAULT;
  129.     }
  130.     
  131.     ev_press = 0;
  132.     return 0;
  133. }

  134. static ssize_t button_poll_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  135. {
  136.     return 0;
  137. }

  138. static int button_poll_release(struct inode *inode, struct file *file)
  139. {
  140.     free_irq(IRQ_EINT(0), &pins_desc[0]);    
  141.     free_irq(IRQ_EINT(1), &pins_desc[1]);
  142.     free_irq(IRQ_EINT(2), &pins_desc[2]);
  143.     free_irq(IRQ_EINT(3), &pins_desc[3]);
  144.     free_irq(IRQ_EINT(4), &pins_desc[4]);
  145.     free_irq(IRQ_EINT(5), &pins_desc[5]);

  146.     return 0;
  147. }

  148. static unsigned button_poll_poll(struct file *file, poll_table *wait)
  149. {
  150.     unsigned int mask = 0;
  151.     poll_wait(file, &button_waitq, wait); // 不会立即休眠

  152.     if (ev_press)
  153.         mask |= POLLIN | POLLRDNORM;

  154.     return mask;
  155. }

  156. static struct file_operations button_poll_fops = {
  157.     .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
  158.     .open = button_poll_open,
  159.     .read = button_poll_read,
  160.     .write = button_poll_write,
  161.     .release = button_poll_release,
  162.     .poll = button_poll_poll,
  163. };

  164. static int button_poll_init(void)
  165. {
  166.     major = register_chrdev(0, "button_poll_dev", &button_poll_fops);//注册,告诉内核
  167.     button_poll_class = class_create(THIS_MODULE, "button_poll_cls");
  168.     device_create(button_poll_class, NULL, MKDEV(major, 0), NULL, "button_poll");/* /dev/button_poll */
  169.     
  170.     return 0;
  171. }

  172. static void button_poll_exit(void)
  173. {
  174.     unregister_chrdev(major, "button_poll_cls");
  175.     device_destroy(button_poll_class, MKDEV(major, 0));
  176.     class_destroy(button_poll_class);
  177. }

  178. module_init(button_poll_init);
  179. module_exit(button_poll_exit);

  180. MODULE_LICENSE("GPL");

2.测试程序如下

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <poll.h>


  6. int main(int argc, char **argv)
  7. {
  8.     int fd;
  9.     unsigned char key_val;
  10.     int ret;
  11.     
  12.     struct pollfd fds[1];
  13.     
  14.     fd = open("/dev/button_poll", O_RDWR);
  15.     if (fd < 0)
  16.     {
  17.         printf("can't open!\n");
  18.         return 0;
  19.     }
  20.     
  21.     fds[0].fd = fd;
  22.     fds[0].events = POLLIN;
  23.     
  24.     while(1)
  25.     {
  26.         ret = poll(fds, 1, 5000);//查询时间5000ms
  27.         if (ret == 0)
  28.         {
  29.             printf("time out\n");
  30.         }
  31.         else
  32.         {
  33.             read(fd, &key_val, 1);
  34.             printf("key_val = 0x%x\n", key_val);
  35.         }
  36.     }    
  37.     return 0;
  38. }

3.测试结果:5000ms内没有按键按下的话,打印"time out\n";若有按键按下,ret不为0,执行else里的分支,读取并打印按键值


阅读(940) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~