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

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-06 15:11:07

首先定义一个定时器button_timer
在init入口函数中初始化该定时器、定义定时器处理函数、add_timer
按下按键后,发生中断,在中断服务函数中不再处理中断,而是修改定时器的超时时间为10ms,超时后触发定时器处理函数来处理中断(读取按键值等过程)。

    若按键按下后不断有抖动导致中断发生,这些中断将使得中断服务程序不断的重新修改定时器的超时时间为10ms,由于各个抖动之间的时间间隙不太可能超过10ms,所以抖动过程中不会触发触发定时器处理函数来处理中断,这期间的按键值也不会被读取。最后一个抖动结束后,由于没有新的中断来修改定时器超时时间,经过10ms后定时器超时,触发定时器处理函数来处理中断,读取按键值。

驱动程序代码如下

点击(此处)折叠或打开

  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_stab_class;
  32. static int major;

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

  36. static struct fasync_struct *button_async;

  37. static struct timer_list button_timer;//定时器

  38. //static atomic_t canopen = ATOMIC_INIT(1); //定义原子变量并初始化为1

  39. static DEFINE_SEMAPHORE(button_lock); //linux-2.6.36后DECLARE_MUTEX换成了DEFINE_SEMAPHORE

  40. struct pin_desc {
  41.     unsigned int pin;
  42.     unsigned int button_val;
  43. };

  44. static unsigned char button_val;

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

  53. static struct pin_desc *irq_pd;

  54. /*中断服务函数*/
  55. /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 ...*/
  56. /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 ...*/
  57. static irqreturn_t button_stab_irq(int irq, void *dev_id)
  58. {
  59.     /* 10ms后启动定时器 */
  60.     irq_pd = (struct pin_desc *)dev_id;
  61.     mod_timer(&button_timer, jiffies+HZ/100);  //jiffies是系统的定时器时间,HZ/100表示10ms 
  62.     return IRQ_HANDLED;
  63. }

  64. static void button_timer_function(unsigned long data)
  65. {
  66.     struct pin_desc * pindesc = irq_pd;
  67.     unsigned int pinval;

  68.     if (!pindesc)
  69.         return;
  70.   
  71.     pinval = gpio_get_value(pindesc->pin);

  72.     if (pinval)
  73.     {
  74.         /* 松开 */
  75.         button_val = 0x80 | pindesc->button_val;
  76.     }
  77.     else
  78.     {
  79.         /* 按下 */
  80.         button_val = pindesc->button_val;
  81.     }

  82.     ev_press = 1; /* 表示中断发生了 */

  83.     wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
  84.   
  85.     kill_fasync (&button_async, SIGIO, POLL_IN);//通过这个函数去发送信号给应用程序
  86. }


  87. static int button_stab_open(struct inode *inode, struct file *file)
  88. {
  89.     int ret;
  90.         
  91. #if 0    
  92.     if (!atomic_dec_and_test(&canopen))
  93.     {
  94.         atomic_inc(&canopen);
  95.         return -EBUSY;
  96.     }
  97. #endif        

  98.     if (file->f_flags & O_NONBLOCK)
  99.     {
  100.         if (down_trylock(&button_lock))
  101.             return -EBUSY;
  102.     }
  103.     else
  104.     {
  105.         /* 获取信号量 */
  106.         down(&button_lock);
  107.     }
  108.     
  109.         
  110.     /*request_irq注册中断
  111.      *第一个参数是中断号,也是中断处理函数button_stab的第一个参数
  112.      *第二个参数是中断处理函数
  113.      *第三个参数是中断触发方式
  114.      *第四个参数是设备名称
  115.      *第五个参数是设备ID,也是中断处理函数button_stab的第二个参数
  116.      */
  117.     ret = request_irq(IRQ_EINT(0), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k1", &pins_desc[0]);
  118.     if (ret){
  119.         printk("request IRQ_EINT(0) error!\n");
  120.         free_irq(IRQ_EINT(0), &pins_desc[0]);
  121.     }    
  122.     ret = request_irq(IRQ_EINT(1), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k2", &pins_desc[1]);
  123.     if (ret){
  124.         printk("request IRQ_EINT(1) error!\n");
  125.         free_irq(IRQ_EINT(1), &pins_desc[1]);
  126.     }
  127.         
  128.     ret = request_irq(IRQ_EINT(2), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k3", &pins_desc[2]);
  129.     if (ret){
  130.         printk("request IRQ_EINT(2) error!\n");
  131.         free_irq(IRQ_EINT(2), &pins_desc[2]);
  132.     }
  133.         
  134.     ret = request_irq(IRQ_EINT(3), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k4", &pins_desc[3]);
  135.     if (ret){
  136.         printk("request IRQ_EINT(3) error!\n");
  137.         free_irq(IRQ_EINT(3), &pins_desc[3]);
  138.     }
  139.         
  140.     ret = request_irq(IRQ_EINT(4), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k5", &pins_desc[4]);
  141.     if (ret){
  142.         printk("request IRQ_EINT(4) error!\n");
  143.         free_irq(IRQ_EINT(4), &pins_desc[4]);
  144.     }
  145.         
  146.     ret = request_irq(IRQ_EINT(5), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k6", &pins_desc[5]);
  147.     if (ret){
  148.         printk("request IRQ_EINT(5) error!\n");
  149.         free_irq(IRQ_EINT(5), &pins_desc[5]);
  150.     }
  151.     return 0;
  152. }

  153. static ssize_t button_stab_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
  154. {
  155.     if (size != 1)
  156.         return -EINVAL;
  157.     
  158.     if (file->f_flags & O_NONBLOCK)
  159.     {
  160.         if (!ev_press)
  161.             return -EAGAIN;
  162.     }
  163.     else
  164.     {    
  165.         /* 如果没有按键动作, 休眠 */
  166.         /*ev_press=0时休眠,ev_press=1时继续向下执行程序*/
  167.         wait_event_interruptible(button_waitq, ev_press);
  168.     }
  169.         
  170.     /* 如果有按键动作, 返回键值 */
  171.     if( copy_to_user(buf, &button_val, 1) ){
  172.         printk("error in function ‘copy_to_user’ !\n");
  173.             return -EFAULT;
  174.     }
  175.     
  176.     ev_press = 0;
  177.     return 0;
  178. }

  179. static ssize_t button_stab_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  180. {
  181.     return 0;
  182. }

  183. static int button_stab_release(struct inode *inode, struct file *file)
  184. {    
  185.     //atomic_inc(&canopen);
  186.     free_irq(IRQ_EINT(0), &pins_desc[0]);    
  187.     free_irq(IRQ_EINT(1), &pins_desc[1]);
  188.     free_irq(IRQ_EINT(2), &pins_desc[2]);
  189.     free_irq(IRQ_EINT(3), &pins_desc[3]);
  190.     free_irq(IRQ_EINT(4), &pins_desc[4]);
  191.     free_irq(IRQ_EINT(5), &pins_desc[5]);
  192.     up(&button_lock);
  193.     
  194.     return 0;
  195. }

  196. static unsigned button_stab_poll(struct file *file, poll_table *wait)
  197. {
  198.     unsigned int mask = 0;
  199.     poll_wait(file, &button_waitq, wait); // 不会立即休眠

  200.     if (ev_press)
  201.         mask |= POLLIN | POLLRDNORM;

  202.     return mask;
  203. }

  204. static int button_stab_fasync (int fd, struct file *filp, int on)
  205. {
  206.     printk("driver: button_stab_fasync\n");
  207.     return fasync_helper (fd, filp, on, &button_async);
  208. }

  209. static struct file_operations button_stab_fops = {
  210.     .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
  211.     .open = button_stab_open,
  212.     .read = button_stab_read,
  213.     .write = button_stab_write,
  214.     .release = button_stab_release,
  215.     .poll = button_stab_poll,
  216.     .fasync     = button_stab_fasync,    
  217. };

  218. static int button_stab_init(void)
  219. {
  220.     init_timer(&button_timer);//初始化定时器
  221.     button_timer.function = button_timer_function;//设置定时器处理函数
  222.     add_timer(&button_timer);
  223.     
  224.     major = register_chrdev(0, "button_stab_dev", &button_stab_fops);//注册,告诉内核
  225.     button_stab_class = class_create(THIS_MODULE, "button_stab_cls");
  226.     device_create(button_stab_class, NULL, MKDEV(major, 0), NULL, "button_stab");/* /dev/button_stab */
  227.     
  228.     return 0;
  229. }

  230. static void button_stab_exit(void)
  231. {
  232.     unregister_chrdev(major, "button_stab_cls");
  233.     device_destroy(button_stab_class, MKDEV(major, 0));
  234.     class_destroy(button_stab_class);
  235. }

  236. module_init(button_stab_init);
  237. module_exit(button_stab_exit);

  238. MODULE_LICENSE("GPL");


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