Chinaunix首页 | 论坛 | 博客
  • 博客访问: 477059
  • 博文数量: 100
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 955
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-21 09:30
文章分类

全部博文(100)

文章存档

2017年(1)

2016年(16)

2015年(83)

我的朋友

分类: 嵌入式

2015-07-03 14:52:33

TQ210共有8个通用按键,分别连接XEINT0~5(即GH0_0~GPH0_5)和XENIT22~23(即GPH2_6、GPH2_7),

韦东山第2个驱动是死循环查询按键
第3个是中断法+等待队列(阻塞),当应用程序读按键值时,如果没有按键按下,则app进入休眠,当有按键按下,驱动中的中断服务程序,唤醒app,从而获取按键值。
第4个是poll机制。中断法有个缺点:app的读操作一直是存在的,加入poll机制可以让app在有按键按下的时候才执行读按键操作。
当应用程序读按键值时,如果没有按键按下,则app并不会立即进入休眠,而是当5秒之内都没有按键按下时,app才进入休眠。
第5个增加异步通知
第6个增加信号量操作(互斥锁、原子操作)
第7个增加输入子系统

代码很简单,先看看加了poll机制的代码.
button_drv.c:

点击(此处)折叠或打开

  1. /*
  2.  * linux/drivers/char/gec210_buttons.c
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License version 2 as
  6.  * published by the Free Software Foundation.
  7.  */

  8. #include <linux/module.h>
  9. #include <linux/kernel.h>
  10. #include <linux/fs.h>
  11. #include <linux/init.h>
  12. #include <linux/delay.h>
  13. #include <linux/poll.h>
  14. #include <linux/irq.h>
  15. #include <asm/irq.h>
  16. #include <asm/io.h>
  17. #include <linux/interrupt.h>
  18. #include <asm/uaccess.h>
  19. #include <mach/hardware.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/cdev.h>
  22. #include <linux/miscdevice.h>

  23. #include <mach/map.h>
  24. #include <mach/gpio.h>
  25. #include <mach/regs-clock.h>
  26. #include <mach/regs-gpio.h>

  27. #include <linux/gpio.h>//gpio结构体的定义
  28. #include <linux/sched.h>//
  29. // #include <linux/wait.h>

  30. #define DEVICE_NAME        "buttons"

  31. struct button_desc {
  32.     int gpio;
  33.     int number;
  34.     char *name;    
  35.     struct timer_list timer;
  36. };

  37. static struct button_desc buttons[] = {
  38.     { S5PV210_GPH0(0), 0, "KEY0" },
  39.     { S5PV210_GPH0(1), 1, "KEY1" },
  40.     { S5PV210_GPH0(2), 2, "KEY2" },
  41.     { S5PV210_GPH0(3), 3, "KEY3" },
  42.     { S5PV210_GPH0(4), 4, "KEY4" },
  43.     { S5PV210_GPH0(5), 5, "KEY5" },
  44.     { S5PV210_GPH2(6), 6, "KEY6" },
  45.     { S5PV210_GPH2(7), 7, "KEY7" },
  46. };

  47. static volatile char key_values[] = {
  48.     '0', '0', '0', '0', '0', '0', '0', '0'
  49. };

  50. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

  51. static volatile int ev_press = 0;

  52. //使用定时器消抖
  53. static void gec210_buttons_timer(unsigned long _data)
  54. {
  55.     struct button_desc *bdata = (struct button_desc *)_data;
  56.     int down;
  57.     int number;
  58.     unsigned tmp;

  59.     tmp = gpio_get_value(bdata->gpio);

  60.     /* active low */
  61.     down = !tmp;
  62.     printk("KEY %d: %08x\n", bdata->number, down);

  63.     number = bdata->number;
  64.     if (down != (key_values[number] & 1)) {
  65.         key_values[number] = '0' + down;

  66.         ev_press = 1;
  67.         wake_up_interruptible(&button_waitq);
  68.     }
  69. }

  70. //定时器中断
  71. static irqreturn_t button_interrupt(int irq, void *dev_id)
  72. {
  73.     struct button_desc *bdata = (struct button_desc *)dev_id;

  74.     mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(40));

  75.     return IRQ_HANDLED; // return 1
  76. }

  77. static int gec210_buttons_open(struct inode *inode, struct file *file)
  78. {
  79.     int irq;
  80.     int i;
  81.     int err = 0;    
  82.     //注册8个中断
  83.     for (i = 0; i < ARRAY_SIZE(buttons); i++) {
  84.         if (!buttons[i].gpio)
  85.             continue;

  86.         setup_timer(&buttons[i].timer, gec210_buttons_timer,
  87.                 (unsigned long)&buttons[i]);
  88.         //从io获取中断信号线
  89.         irq = gpio_to_irq(buttons[i].gpio);
  90.         //申请按键中断, 边沿触发中断
  91.         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
  92.                 buttons[i].name, (void *)&buttons[i]);
  93.         if (err)
  94.             break;
  95.     }

  96.     if (err) {
  97.         i--;
  98.         for (; i >= 0; i--) {
  99.             if (!buttons[i].gpio)
  100.                 continue;

  101.             irq = gpio_to_irq(buttons[i].gpio);
  102.             disable_irq(irq);
  103.             free_irq(irq, (void *)&buttons[i]);

  104.             del_timer_sync(&buttons[i].timer);
  105.         }

  106.         return -EBUSY;
  107.     }

  108.     ev_press = 1;
  109.     return 0;
  110. }

  111. static int gec210_buttons_close(struct inode *inode, struct file *file)
  112. {
  113.     int irq, i;

  114.     for (i = 0; i < ARRAY_SIZE(buttons); i++) {
  115.         if (!buttons[i].gpio)
  116.             continue;

  117.         irq = gpio_to_irq(buttons[i].gpio);
  118.         free_irq(irq, (void *)&buttons[i]);

  119.         del_timer_sync(&buttons[i].timer);
  120.     }

  121.     return 0;
  122. }

  123. static int gec210_buttons_read(struct file *filp, char __user *buff,
  124.         size_t count, loff_t *offp)
  125. {
  126.     unsigned long err;

  127.     if (!ev_press) {
  128.         if (filp->f_flags & O_NONBLOCK)
  129.             return -EAGAIN;
  130.         else
  131.             wait_event_interruptible(button_waitq, ev_press);
  132.     }

  133.     ev_press = 0;

  134.     err = copy_to_user((void *)buff, (const void *)(&key_values),
  135.             min(sizeof(key_values), count));

  136.     return err ? -EFAULT : min(sizeof(key_values), count);
  137. }

  138. static unsigned int gec210_buttons_poll( struct file *file,
  139.         struct poll_table_struct *wait)
  140. {
  141.     unsigned int mask = 0;

  142.     poll_wait(file, &button_waitq, wait);
  143.     if (ev_press)
  144.         mask |= POLLIN | POLLRDNORM;

  145.     return mask;
  146. }

  147. static struct file_operations dev_fops = {
  148.     .owner        = THIS_MODULE,
  149.     .open        = gec210_buttons_open,
  150.     .release    = gec210_buttons_close,
  151.     .read        = gec210_buttons_read,
  152.     .poll        = gec210_buttons_poll,
  153. };

  154. static struct miscdevice misc = {
  155.     .minor        = MISC_DYNAMIC_MINOR,
  156.     .name        = DEVICE_NAME,
  157.     .fops        = &dev_fops,
  158. };

  159. static int __init button_dev_init(void)
  160. {
  161.     int ret;

  162.     ret = misc_register(&misc);

  163.     printk(DEVICE_NAME"\tinitialized\n");

  164.     return ret;
  165. }

  166. static void __exit button_dev_exit(void)
  167. {
  168.     misc_deregister(&misc);
  169. }

  170. module_init(button_dev_init);
  171. module_exit(button_dev_exit);

  172. MODULE_LICENSE("GPL");
  173. MODULE_AUTHOR("GEC Inc.");
buttontest.c:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/ioctl.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <sys/select.h>
  9. #include <sys/time.h>
  10. #include <errno.h>

  11. #define ARRY_SIZE(x) (sizeof(x)/sizeof(x[0]))

  12. int main(int argc , char **argv)
  13. {
  14.     int button_fd ;
  15.     char current_button_value[8]={0}; //板载八个按键 key2-9
  16.     char prior_button_value[8]={0};        //用于保存按键的前键值
  17.     
  18.     button_fd = open("/dev/buttons",O_RDONLY);
  19.     if(button_fd <0){
  20.         perror("open device :");
  21.         exit(1);        
  22.     }

  23.     while(1){
  24.         int i ;
  25.         
  26.         if (read(button_fd, current_button_value, sizeof(current_button_value)) != sizeof(current_button_value)) {
  27.             perror("read buttons:");
  28.             exit(1);
  29.         }

  30.         for(i = 0;i < ARRY_SIZE(current_button_value);i++){
  31.             if(prior_button_value[i] != current_button_value[i]){        //判断当前获得的键值与上一的键值是否一致,以判断按键有没有被按下或者释放
  32.                 prior_button_value[i] = current_button_value[i];        
  33.                 
  34.                 switch(i){
  35.                     case 0:    
  36.                         printf("BACK \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  37.                         break;
  38.                     case 1:
  39.                         printf("HOME \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  40.                         break;
  41.                     case 2:
  42.                         printf("MENU \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  43.                         break;
  44.                     case 3:
  45.                         printf("UP \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  46.                         break;
  47.                     case 4:
  48.                         printf("DOWN \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  49.                         break;
  50.                     case 5:
  51.                         printf("ENTER\t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  52.                         break;
  53.                     case 6:
  54.                         printf("LEFT\t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  55.                         break;
  56.                     case 7:
  57.                         printf("RIGHT \t%s\n",current_button_value[i]=='0'?"Release":"Pressed");
  58.                         break;
  59.                     default:
  60.                         printf("\n");
  61.                         break;
  62.                 }
  63.             }
  64.         }
  65.     
  66.     }

  67.     return 0;
  68. }
Makefile:

点击(此处)折叠或打开

  1. KERN_DIR = /home/richard/work/kernel/linux-3.10.80
  2. obj-m += button_drv.o

  3. all:
  4.     make -C $(KERN_DIR) M=`pwd` modules
  5.     arm-linux-gnueabi-gcc -o buttontest buttontest.c
  6. clean:
  7.     rm -rf *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd .*.o.* .*.ko.*



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

edaplayer2019-08-19 11:58:36

chen8633201:我测试程序的时候,打开设备文件,提示错误open device :: Device or resource busy,这个是什么原因?

设备被占用了吧,看看是不是之前打开的状态没有释放

回复 | 举报

chen86332012019-07-18 23:25:05

我测试程序的时候,打开设备文件,提示错误open device :: Device or resource busy,这个是什么原因?

edaplayer2015-07-04 01:48:54

看了一下,第7个驱动是定时器消抖按键驱动

edaplayer2015-07-03 15:50:43

文中有个小错误,第7个驱动不是输入子系统,不记得是互斥锁还是什么了,第8个才是输入子系统