韦东山驱动视频笔记——2.字符设备驱动程序之中断方式的按键驱动程序

linux内核版本:linux-2.6.30.4

目的:当有按键按下和松开时,在终端输出不同的键值

原理:假设我们现在已经加载(insmod)了third_drv.ko,当我们进入main函数后,可以打开设备节点"/dev/buttons",然后进入while循环,接着系统调用read,内核经过一系列的处理,进入到我们的驱动程序的read函数(third_drv_read),这时候如果没有按键按下,应用程序就会停在wait_event_interruptible处休眠,程序就不会向下面跑了,假如在某个时间点我们按下了按键,就会触发中断,调用中断处理函数(buttons_irq),经过读取按键的引脚的电平高低来判断是按下还是松开,然后给key_val赋不同的值,最后唤醒等待队列,然后重新调用wait_event_interruptible,此时ev_press = 1,就不会再休眠,所以可以继续执行,就把按键值返回了用户空间,所以我们的应用程序中的key_val得到了按键值。

  1 #include <linux/module.h>  
  2 #include <linux/kernel.h>  
  3 #include <linux/fs.h>  
  4 #include <linux/init.h>  
  5 #include <linux/delay.h>  
  6 #include <asm/uaccess.h>  
  7 #include <asm/irq.h>  
  8 #include <asm/io.h>  
  9 #include <linux/device.h>  
 10 #include <linux/irq.h>  
 11 #include <linux/interrupt.h>  
 12 #include <mach/regs-gpio.h>  
 13   
 14   
 15 static struct class *third_drv_class;  
 16 static struct class_device  *third_drv_class_dev;  
 17   
 18 static volatile unsigned long *gpfcon;  
 19 static volatile unsigned long *gpfdat;  
 20 static int major;  
 21   
 22 struct pin_desc   
 23 {  
 24     unsigned int pin;  
 25     unsigned int key_val;  
 26 };  
 27   
 28 static unsigned char key_val;  
 29   
 30 static struct pin_desc pins_desc[4] =   
 31 {  
 32     {S3C2410_GPF1, 0x01},  
 33     {S3C2410_GPF4, 0x02},  
 34     {S3C2410_GPF2, 0x03},  
 35     {S3C2410_GPF0, 0x04},  
 36 };  
 37   
 38 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
 39 static volatile int ev_press = 0;  
 40   
 41 static irqreturn_t buttons_irq(int irq, void *dev_id)  
 42 {  
 43     struct pin_desc *pin = (struct pin_desc *)dev_id;  
 44     unsigned int pinval;  
 45     pinval = s3c2410_gpio_getpin(pin->pin);  
 46   
 47     if (pinval)  
 48     {  
 49         //松开  
 50         key_val = 0x80 | pin->key_val;  
 51     }  
 52     else  
 53     {  
 54         //按下  
 55         key_val = pin->key_val;  
 56     }  
 57   
 58     wake_up_interruptible(&button_waitq);  
 59     ev_press = 1;  
 60       
 61     return IRQ_HANDLED;  
 62 }  
 63   
 64   
 65 static int third_drv_open(struct inode *inode, struct file *file)  
 66 {  
 67     request_irq(IRQ_EINT1, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S1", &pins_desc[0]);  
 68     request_irq(IRQ_EINT4, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S2", &pins_desc[1]);  
 69     request_irq(IRQ_EINT2, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S3", &pins_desc[2]);  
 70     request_irq(IRQ_EINT0, buttons_irq, IRQ_TYPE_EDGE_BOTH, "S4", &pins_desc[3]);  
 71     return 0;  
 72 }  
 73   
 74   
 75 static ssize_t third_drv_read(struct file *file, char __user *buf,  
 76             size_t count, loff_t *ppos)  
 77 {  
 78     if (count != 1)  
 79         return -EINVAL;  
 80     /*如果没有按键动作,休眠*/  
 81     wait_event_interruptible(button_waitq, ev_press);  
 82       
 83   
 84     /*如果有按键动作发生,返回键值*/  
 85     copy_to_user(buf, &key_val, 1);  
 86     ev_press = 0;  
 87     return 1;  
 88 }  
 89   
 90 static int third_drv_release(struct inode *inode, struct file *file)  
 91 {  
 92     free_irq(IRQ_EINT1, &pins_desc[0]);  
 93     free_irq(IRQ_EINT4, &pins_desc[1]);  
 94     free_irq(IRQ_EINT2, &pins_desc[2]);  
 95     free_irq(IRQ_EINT0, &pins_desc[3]);  
 96     return 0;  
 97 }  
 98   
 99   
100 static struct file_operations third_fops = {  
101     .owner = THIS_MODULE,  
102     .open = third_drv_open,  
103     .read = third_drv_read,  
104     .release  = third_drv_release,  
105 };  
106   
107 int third_init()  
108 {  
109     int ret;  
110     major = register_chrdev(0, "third_drv", &third_fops);  
111     third_drv_class = class_create(THIS_MODULE, "third_drv");  
112     device_create(third_drv_class, NULL, MKDEV(major, 0), NULL, "buttons");  
113   
114     gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);  
115     gpfdat = gpfcon + 1;  
116       
117     return 0;  
118 }  
119 static void third_exit()  
120 {  
121     unregister_chrdev(major, "third_drv");  
122     device_destroy(third_drv_class, MKDEV(major, 0));  
123     class_destroy(third_drv_class);  
124     iounmap(gpfcon);  
125 }  
126   
127 module_init(third_init);  
128 module_exit(third_exit);  
129   
130 MODULE_LICENSE("GPL");

测试程序:

 1 #include <sys/types.h>  
 2 #include <sys/stat.h>  
 3 #include <fcntl.h>  
 4 #include <stdio.h>  
 5   
 6 /* thirddrvtest  
 7   */  
 8 int main(int argc, char **argv)  
 9 {  
10     int fd;  
11     unsigned char key_val;  
12     int cnt = 0;  
13       
14     fd = open("/dev/buttons", O_RDWR);  
15     if (fd < 0)  
16     {  
17         printf("can't open!\n");  
18     }  
19   
20     while (1)  
21     {  
22         read(fd, &key_val, 1);  
23         printf("key_val === 0x%x\n", key_val);  
24           
25     }  
26       
27     return 0;  
28 }  

运行效果:


 

posted @ 2013-08-08 11:17  linux_rookie  阅读(510)  评论(0编辑  收藏  举报