Lover雪儿
想念时,就看看天空,无论距离有多远,我们总在同一片天空下!

【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

2015-02-18 李海沿

前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序

这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开。

 

一、首先在前面代码的基础上来一个简单的信号

1.定义一个全局的整形变量

2.在打开函数中,每次进入打开函数canopen都自减1,

3.当我们不使用时,在realease 中canopen自加1

 

4.这样就实现了一个简单的信号量,我们编译,测试

当我们使用两个应用程序来同时打开设备时,看看会发生什么:

可以发现,由于我们后台已经打开一个应用程序了,所以,如果此时我们再用另外一个应用程序打开的话,则会报错,can't open

好了,到这里,我们已经基本上实现了一个简陋的信号量程序。

附上驱动代码

 

  1 /******************************
  2     linux key_query
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/kernel.h>
  7 #include <linux/delay.h>
  8 #include <linux/types.h>
  9 #include <linux/ioctl.h>
 10 #include <linux/gpio.h>
 11 #include <linux/fs.h>
 12 #include <linux/device.h>
 13 #include <linux/uaccess.h>
 14 #include <linux/irq.h>
 15 #include <linux/wait.h>
 16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared 
 17 #include <linux/interrupt.h>
 18 #include <linux/poll.h>
 19 
 20 #include "mx257_gpio.h"
 21 #include "mx25_pins.h"
 22 #include "iomux.h"
 23 
 24 #define Driver_NAME "key_interrupt"
 25 #define DEVICE_NAME "key_interrupt"
 26 
 27 #define GPIO2_21    MX25_PIN_CLKO
 28 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
 29 #define GPIO2_10    MX25_PIN_A24
 30 #define GPIO2_11    MX25_PIN_A25
 31 #define GPIO2_8     MX25_PIN_A22
 32 #define GPIO2_9     MX25_PIN_A23
 33 #define GPIO2_6     MX25_PIN_A20
 34 #define GPIO2_7     MX25_PIN_A21
 35 //command
 36 #define key_input     0
 37 #define version        1
 38 //定义各个按键按下的键值
 39 struct pin_desc{
 40     unsigned int pin;
 41     unsigned int key_val;
 42 };
 43 //当按键按下时,键值分别为 以下值
 44 struct pin_desc pins_desc[8] = {
 45     {GPIO2_6,    0x01},
 46     {GPIO2_7,    0x02},
 47     {GPIO2_8,    0x03},
 48     {GPIO2_9,    0x04},
 49     {GPIO2_10,    0x05},
 50     {GPIO2_11,    0x06},
 51     {GPIO2_21,    0x07},
 52     {GPIO3_15,    0x08},
 53 };
 54 //定义一个全局变量,用于保存按下的键值
 55 static unsigned int key_val;
 56 
 57 //信号量定义
 58 static int canopen = 1;
 59 
 60 //interrupt head
 61 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
 62 static volatile unsigned char ev_press;  
 63 
 64 static int major=0;
 65 
 66 //auto to create device node
 67 static struct class *drv_class = NULL;
 68 static struct class_device *drv_class_dev = NULL;
 69 
 70 
 71 /* 应用程序对设备文件/dev/key_query执行open(...)时,
 72  * 就会调用key_open函数*/
 73 static int key_open(struct inode *inode, struct file *file)
 74 {
 75     printk("<0>function open!\n\n");
 76     if(--canopen != 0)
 77     {
 78         canopen ++;
 79         return -EBUSY;
 80     }    
 81 
 82     return 0;
 83 }
 84 
 85 /* 中断程序key_irq */
 86 static irqreturn_t key_irq(int irq, void *dev_id)
 87 {
 88     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
 89     //发生了中断
 90     //printk("<0>function interrupt key_irq!\n\n");
 91     //获取按键键值
 92     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
 93         /* 按下 */
 94         key_val = pindesc->key_val;
 95     }else{
 96         key_val = 0x80 | pindesc->key_val;
 97     }
 98     printk("<0>get key 0x%x",key_val);    
 99     ev_press = 1;
100     wake_up_interruptible(&key_interrupt_wait);
101 
102     return IRQ_RETVAL(IRQ_HANDLED);
103 }
104 
105 
106 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
107 {
108     int ret;
109     //如果按键没有按下,没有中断,休眠
110     //wait_event_interruptible(key_interrupt_wait,ev_press);
111 
112     ret = copy_to_user(buff,&key_val,sizeof(key_val));
113     if(ret){
114         ;
115     }
116     ev_press = 0;
117     return sizeof(key_val);
118 
119     //int cnt=0;
120     //unsigned char key_vals[8];
121 
122     /*
123     // reading the pins value
124     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
125     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
126     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
127     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
128     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
129     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
130     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
131     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
132     
133     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 
134     */
135 }
136 
137 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
138 {
139     printk("<0>function write!\n\n");
140     
141     return 1;
142 }
143 
144 static int  key_release(struct inode *inode, struct file *filp)
145 {
146     canopen ++;    
147     printk("<0>function release!\n\n");
148     //释放中断
149     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);
150     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
151     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);
152     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);
153     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);
154     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
155     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);
156     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);
157     return 0;
158 }
159 
160 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
161 {
162     int ret;
163     printk("<0>function ioctl!\n\n");
164     switch (command) {
165         case key_input:    
166             //设置所有的引脚为输入
167             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
168             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
169             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
170             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
171             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
172             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
173             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
174             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
175             printk("<0>have setting all pins to gpio input mod !\n");
176             //设置GPIO引脚为上拉模式
177             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
178             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
179             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
180             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
181             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
182             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
183             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
184             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
185 
186             //设置GPIO引脚中断  ,下降沿触发
187             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
188             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
189             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
190             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
191             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
192             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
193             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
194             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
195             printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !\n");
196 
197             break;
198         case version:
199             printk("<0>hello,the version is 0.1.0\n\n");
200             break;
201         default:
202               printk("<0>command error \n");
203             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");
204             printk("<0>command: <key_input> <version>\n\n");
205             return -1;
206     }
207     return 0;    
208 }
209 static unsigned key_poll(struct file *file,poll_table *wait)
210 {
211     unsigned int mask = 0;
212     //程序不立即睡眠,而是继续等待
213     poll_wait(file,&key_interrupt_wait,wait);
214     //如果按键按下
215     if(ev_press)
216         mask |= POLLIN | POLLRDNORM;
217 
218     return mask;
219 }
220 
221 /* 这个结构是字符设备驱动程序的核心
222  * 当应用程序操作设备文件时所调用的open、read、write等函数,
223  * 最终会调用这个结构中指定的对应函数
224  */
225 static struct file_operations key_fops = {
226     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
227     .open   =   key_open,     
228     .read    =    key_read,       
229     .write    =    key_write,       
230     .release=   key_release,
231     .ioctl  =   key_ioctl,    
232     .poll   =   key_poll,
233 };
234     
235 /*
236  * 执行insmod命令时就会调用这个函数 
237  */
238 static int __init  key_irq_init(void)
239 {
240     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
241     //register and mknod
242     major = register_chrdev(0,Driver_NAME,&key_fops);
243     drv_class = class_create(THIS_MODULE,Driver_NAME);
244     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
245 
246     //set all pins to GPIO mod  ALF5
247     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
248     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
249       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
250        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
251     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
252     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
253     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
254     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
255     //request IOMUX GPIO
256     gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
257      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
258      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
259        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
260     gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
261      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
262       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
263     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
264     
265 
266     return 0;
267 }
268 
269 /*
270  * 执行rmmod命令时就会调用这个函数 
271  */
272 static void __exit key_irq_exit(void)
273 {
274     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
275 
276     unregister_chrdev(major,Driver_NAME);
277     device_unregister(drv_class_dev);
278     class_destroy(drv_class);
279 
280     /* free gpios */
281     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
282     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
283     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
284     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
285     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
286     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
287     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
288     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
289 
290     gpio_free(IOMUX_TO_GPIO(GPIO2_21));
291     gpio_free(IOMUX_TO_GPIO(GPIO3_15));
292     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
293     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
294     gpio_free(IOMUX_TO_GPIO(GPIO2_8));
295     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
296     gpio_free(IOMUX_TO_GPIO(GPIO2_6));
297     gpio_free(IOMUX_TO_GPIO(GPIO2_7));
298 
299 }
300 
301 /* 这两行指定驱动程序的初始化函数和卸载函数 */
302 module_init(key_irq_init);
303 module_exit(key_irq_exit);
304 
305 /* 描述驱动程序的一些信息,不是必须的 */
306 MODULE_AUTHOR("Lover雪");
307 MODULE_VERSION("0.1.0");
308 MODULE_DESCRIPTION("IMX257 key Driver");
309 MODULE_LICENSE("GPL");
View Code

 

附上应用程序代码:

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include <termios.h>
 8 #include <errno.h>
 9 #include <limits.h>
10 #include <asm/ioctls.h>
11 #include <time.h>
12 #include <pthread.h>
13 #include <poll.h>
14 
15 #include "mx257_gpio.h"
16 
17 #define key_input     0
18 #define version       1
19 
20 
21 int main(int argc, char **argv)
22 {
23     int fd;
24     int i=0,cnt=0;
25     unsigned char key_val[1];
26     struct pollfd fds[1];    
27     int ret;
28     fd = open("/dev/key_interrupt",O_RDWR );
29     if(fd < 0){
30         printf("can't open !!!\n");
31     }
32     ioctl(fd,version,NULL);
33     ioctl(fd,key_input,NULL);
34 
35     fds[0].fd = fd;
36     fds[0].events = POLLIN;
37     while(1){
38         ret = poll(fds,1,5000);
39         if(ret == 0)
40             printf("time out\n");
41         else{
42             read(fd,key_val,1);
43             printf("%04d key pressed: 0x%x\n",cnt++,key_val[0]);    
44         }
45     }
46     return 0;
47 }
View Code

 

二、改进 原子操作

由于前面的代码中信号量自减和检测信号量不是同时进行的,可能被打断,虽然概率很小,但是,也是有可能会发生。

为了避免这个问题,这里我们使用原子操作来实现信号量的改变。

所谓原子操作,就是不可被打断,从而保证了前面我们所说到的问题。

具体方法如下。

atomic_t v = ATOMIC_INIT(0);        //定义原子信号v,并且赋初值为0

atomic_read(atomic_t *v);            //返回原子变量的值

void atomic_inc(atomic_t *v);            //原子变量增加1

void atomic_dec(atomic_t *v);        //原子变量减少1

int atomic_dec_and_test(atomic_t *v);

    //自减操作后测试是否为0,为0则返回true,否则返回false

驱动程序中修改如下:

 

1. 定义原子信号canopen,并且赋初值1

2.在open函数中检测信号量是否为1,否则就无法打开。

3.在释放函数中信号量值加1

 

4.编译和测试,可以发现结果和上面的代码一样

 

附上驱动程序源程序:

 

  1 /******************************
  2     linux key_query
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/kernel.h>
  7 #include <linux/delay.h>
  8 #include <linux/types.h>
  9 #include <linux/ioctl.h>
 10 #include <linux/gpio.h>
 11 #include <linux/fs.h>
 12 #include <linux/device.h>
 13 #include <linux/uaccess.h>
 14 #include <linux/irq.h>
 15 #include <linux/wait.h>
 16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared 
 17 #include <linux/interrupt.h>
 18 #include <linux/poll.h>
 19 
 20 #include "mx257_gpio.h"
 21 #include "mx25_pins.h"
 22 #include "iomux.h"
 23 
 24 #define Driver_NAME "key_interrupt"
 25 #define DEVICE_NAME "key_interrupt"
 26 
 27 #define GPIO2_21    MX25_PIN_CLKO
 28 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
 29 #define GPIO2_10    MX25_PIN_A24
 30 #define GPIO2_11    MX25_PIN_A25
 31 #define GPIO2_8     MX25_PIN_A22
 32 #define GPIO2_9     MX25_PIN_A23
 33 #define GPIO2_6     MX25_PIN_A20
 34 #define GPIO2_7     MX25_PIN_A21
 35 //command
 36 #define key_input     0
 37 #define version        1
 38 //定义各个按键按下的键值
 39 struct pin_desc{
 40     unsigned int pin;
 41     unsigned int key_val;
 42 };
 43 //当按键按下时,键值分别为 以下值
 44 struct pin_desc pins_desc[8] = {
 45     {GPIO2_6,    0x01},
 46     {GPIO2_7,    0x02},
 47     {GPIO2_8,    0x03},
 48     {GPIO2_9,    0x04},
 49     {GPIO2_10,    0x05},
 50     {GPIO2_11,    0x06},
 51     {GPIO2_21,    0x07},
 52     {GPIO3_15,    0x08},
 53 };
 54 //定义一个全局变量,用于保存按下的键值
 55 static unsigned int key_val;
 56 
 57 //信号量定义
 58 //static int canopen = 1;
 59 //定义原子信号量
 60 static atomic_t canopen = ATOMIC_INIT(1);    //定义原子信号canopen,并且赋初值1
 61 
 62 //interrupt head
 63 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
 64 static volatile unsigned char ev_press;  
 65 
 66 static int major=0;
 67 
 68 //auto to create device node
 69 static struct class *drv_class = NULL;
 70 static struct class_device *drv_class_dev = NULL;
 71 
 72 
 73 /* 应用程序对设备文件/dev/key_query执行open(...)时,
 74  * 就会调用key_open函数*/
 75 static int key_open(struct inode *inode, struct file *file)
 76 {
 77     printk("<0>function open!\n\n");
 78     //if(--canopen != 0)
 79     if(!atomic_dec_and_test(&canopen))    
 80     {
 81         //canopen ++;
 82         atomic_inc(&canopen);
 83         return -EBUSY;
 84     }    
 85 
 86     return 0;
 87 }
 88 
 89 /* 中断程序key_irq */
 90 static irqreturn_t key_irq(int irq, void *dev_id)
 91 {
 92     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
 93     //发生了中断
 94     //printk("<0>function interrupt key_irq!\n\n");
 95     //获取按键键值
 96     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
 97         /* 按下 */
 98         key_val = pindesc->key_val;
 99     }else{
100         key_val = 0x80 | pindesc->key_val;
101     }
102     printk("<0>get key 0x%x",key_val);    
103     ev_press = 1;
104     wake_up_interruptible(&key_interrupt_wait);
105 
106     return IRQ_RETVAL(IRQ_HANDLED);
107 }
108 
109 
110 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
111 {
112     int ret;
113     //如果按键没有按下,没有中断,休眠
114     //wait_event_interruptible(key_interrupt_wait,ev_press);
115 
116     ret = copy_to_user(buff,&key_val,sizeof(key_val));
117     if(ret){
118         ;
119     }
120     ev_press = 0;
121     return sizeof(key_val);
122 
123     //int cnt=0;
124     //unsigned char key_vals[8];
125 
126     /*
127     // reading the pins value
128     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
129     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
130     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
131     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
132     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
133     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
134     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
135     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
136     
137     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 
138     */
139 }
140 
141 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
142 {
143     printk("<0>function write!\n\n");
144     
145     return 1;
146 }
147 
148 static int  key_release(struct inode *inode, struct file *filp)
149 {
150     //canopen ++;    
151     atomic_inc(&canopen);
152     printk("<0>function release!\n\n");
153     //释放中断
154     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);
155     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
156     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);
157     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);
158     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);
159     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
160     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);
161     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);
162     return 0;
163 }
164 
165 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
166 {
167     int ret;
168     printk("<0>function ioctl!\n\n");
169     switch (command) {
170         case key_input:    
171             //设置所有的引脚为输入
172             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
173             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
174             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
175             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
176             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
177             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
178             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
179             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
180             printk("<0>have setting all pins to gpio input mod !\n");
181             //设置GPIO引脚为上拉模式
182             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
183             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
184             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
185             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
186             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
187             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
188             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
189             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
190 
191             //设置GPIO引脚中断  ,下降沿触发
192             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
193             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
194             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
195             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
196             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
197             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
198             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
199             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
200             printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !\n");
201 
202             break;
203         case version:
204             printk("<0>hello,the version is 0.1.0\n\n");
205             break;
206         default:
207               printk("<0>command error \n");
208             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");
209             printk("<0>command: <key_input> <version>\n\n");
210             return -1;
211     }
212     return 0;    
213 }
214 static unsigned key_poll(struct file *file,poll_table *wait)
215 {
216     unsigned int mask = 0;
217     //程序不立即睡眠,而是继续等待
218     poll_wait(file,&key_interrupt_wait,wait);
219     //如果按键按下
220     if(ev_press)
221         mask |= POLLIN | POLLRDNORM;
222 
223     return mask;
224 }
225 
226 /* 这个结构是字符设备驱动程序的核心
227  * 当应用程序操作设备文件时所调用的open、read、write等函数,
228  * 最终会调用这个结构中指定的对应函数
229  */
230 static struct file_operations key_fops = {
231     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
232     .open   =   key_open,     
233     .read    =    key_read,       
234     .write    =    key_write,       
235     .release=   key_release,
236     .ioctl  =   key_ioctl,    
237     .poll   =   key_poll,
238 };
239     
240 /*
241  * 执行insmod命令时就会调用这个函数 
242  */
243 static int __init  key_irq_init(void)
244 {
245     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
246     //register and mknod
247     major = register_chrdev(0,Driver_NAME,&key_fops);
248     drv_class = class_create(THIS_MODULE,Driver_NAME);
249     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
250 
251     //set all pins to GPIO mod  ALF5
252     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
253     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
254       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
255        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
256     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
257     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
258     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
259     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
260     //request IOMUX GPIO
261     gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
262      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
263      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
264        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
265     gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
266      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
267       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
268     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
269     
270 
271     return 0;
272 }
273 
274 /*
275  * 执行rmmod命令时就会调用这个函数 
276  */
277 static void __exit key_irq_exit(void)
278 {
279     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
280 
281     unregister_chrdev(major,Driver_NAME);
282     device_unregister(drv_class_dev);
283     class_destroy(drv_class);
284 
285     /* free gpios */
286     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
287     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
288     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
289     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
290     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
291     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
292     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
293     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
294 
295     gpio_free(IOMUX_TO_GPIO(GPIO2_21));
296     gpio_free(IOMUX_TO_GPIO(GPIO3_15));
297     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
298     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
299     gpio_free(IOMUX_TO_GPIO(GPIO2_8));
300     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
301     gpio_free(IOMUX_TO_GPIO(GPIO2_6));
302     gpio_free(IOMUX_TO_GPIO(GPIO2_7));
303 
304 }
305 
306 /* 这两行指定驱动程序的初始化函数和卸载函数 */
307 module_init(key_irq_init);
308 module_exit(key_irq_exit);
309 
310 /* 描述驱动程序的一些信息,不是必须的 */
311 MODULE_AUTHOR("Lover雪");
312 MODULE_VERSION("0.1.0");
313 MODULE_DESCRIPTION("IMX257 key Driver");
314 MODULE_LICENSE("GPL");
View Code

 

 

三、改进 信号量

前面的代码中,如果驱动程序已经有一个应用程序在使用是,如果是另一个驱动程序再次来申请,则会报错can't open直接退出,我们如何让其不退出呢,而是在等待队列中等待信号量呢?

 

使用信号量,方法如下:

struct semaphore sem;        //定义信号量

void sema_init(struct semaphore *sem, int val);    //初始化信号量

void init_MUTEX(struct semaphore *sem);            //初始化信号量为0

void down(struct semaphore *sem);                //获取信号量

int down_interruptible(struct semaphore *sem);    

int down_trylock(struct semaphore *sem);            //获取信号量,不成功则返回

void up(struct semaphore *sem);                    //释放信号量

 

操作步骤:

1.定义信号量

2.在init函数中初始化信号量

3.和前面一样在open函数中申请信号量

4.在release函数中释放信号量

5.编译测试

可以发现,当第二个应用程序去申请信号量时,并不会像前面一样直接退出,而是一直在等待信号量到来。

附上驱动程序代码:

 

  1 /******************************
  2     linux key_query
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/kernel.h>
  7 #include <linux/delay.h>
  8 #include <linux/types.h>
  9 #include <linux/ioctl.h>
 10 #include <linux/gpio.h>
 11 #include <linux/fs.h>
 12 #include <linux/device.h>
 13 #include <linux/uaccess.h>
 14 #include <linux/irq.h>
 15 #include <linux/wait.h>
 16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared 
 17 #include <linux/interrupt.h>
 18 #include <linux/poll.h>
 19 
 20 #include "mx257_gpio.h"
 21 #include "mx25_pins.h"
 22 #include "iomux.h"
 23 
 24 #define Driver_NAME "key_interrupt"
 25 #define DEVICE_NAME "key_interrupt"
 26 
 27 #define GPIO2_21    MX25_PIN_CLKO
 28 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
 29 #define GPIO2_10    MX25_PIN_A24
 30 #define GPIO2_11    MX25_PIN_A25
 31 #define GPIO2_8     MX25_PIN_A22
 32 #define GPIO2_9     MX25_PIN_A23
 33 #define GPIO2_6     MX25_PIN_A20
 34 #define GPIO2_7     MX25_PIN_A21
 35 //command
 36 #define key_input     0
 37 #define version        1
 38 //定义各个按键按下的键值
 39 struct pin_desc{
 40     unsigned int pin;
 41     unsigned int key_val;
 42 };
 43 //当按键按下时,键值分别为 以下值
 44 struct pin_desc pins_desc[8] = {
 45     {GPIO2_6,    0x01},
 46     {GPIO2_7,    0x02},
 47     {GPIO2_8,    0x03},
 48     {GPIO2_9,    0x04},
 49     {GPIO2_10,    0x05},
 50     {GPIO2_11,    0x06},
 51     {GPIO2_21,    0x07},
 52     {GPIO3_15,    0x08},
 53 };
 54 //定义一个全局变量,用于保存按下的键值
 55 static unsigned int key_val;
 56 
 57 //信号量定义
 58 //static int canopen = 1;
 59 //定义原子信号量
 60 //static atomic_t canopen = ATOMIC_INIT(1);    //定义原子信号canopen,并且赋初值1
 61 //定义信号量
 62 struct semaphore canopen;        //定义一个信号量
 63 
 64 //interrupt head
 65 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
 66 static volatile unsigned char ev_press;  
 67 
 68 static int major=0;
 69 
 70 //auto to create device node
 71 static struct class *drv_class = NULL;
 72 static struct class_device *drv_class_dev = NULL;
 73 
 74 
 75 /* 应用程序对设备文件/dev/key_query执行open(...)时,
 76  * 就会调用key_open函数*/
 77 static int key_open(struct inode *inode, struct file *file)
 78 {
 79     printk("<0>function open!\n\n");
 80     down(&canopen);    //申请信号量    
 81     //if(--canopen != 0)
 82     /*if(!atomic_dec_and_test(&canopen))    
 83     {
 84         //canopen ++;
 85         atomic_inc(&canopen);
 86         return -EBUSY;
 87     }*/    
 88 
 89     return 0;
 90 }
 91 
 92 /* 中断程序key_irq */
 93 static irqreturn_t key_irq(int irq, void *dev_id)
 94 {
 95     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
 96     //发生了中断
 97     //printk("<0>function interrupt key_irq!\n\n");
 98     //获取按键键值
 99     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
100         /* 按下 */
101         key_val = pindesc->key_val;
102     }else{
103         key_val = 0x80 | pindesc->key_val;
104     }
105     printk("<0>get key 0x%x",key_val);    
106     ev_press = 1;
107     wake_up_interruptible(&key_interrupt_wait);
108 
109     return IRQ_RETVAL(IRQ_HANDLED);
110 }
111 
112 
113 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
114 {
115     int ret;
116     //如果按键没有按下,没有中断,休眠
117     //wait_event_interruptible(key_interrupt_wait,ev_press);
118 
119     ret = copy_to_user(buff,&key_val,sizeof(key_val));
120     if(ret){
121         ;
122     }
123     ev_press = 0;
124     return sizeof(key_val);
125 
126     //int cnt=0;
127     //unsigned char key_vals[8];
128 
129     /*
130     // reading the pins value
131     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
132     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
133     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
134     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
135     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
136     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
137     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
138     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
139     
140     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 
141     */
142 }
143 
144 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
145 {
146     printk("<0>function write!\n\n");
147     
148     return 1;
149 }
150 
151 static int  key_release(struct inode *inode, struct file *filp)
152 {
153     //canopen ++;    
154     //atomic_inc(&canopen);
155     up(&canopen);
156     printk("<0>function release!\n\n");
157     //释放中断
158     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);
159     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
160     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);
161     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);
162     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);
163     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
164     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);
165     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);
166     return 0;
167 }
168 
169 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
170 {
171     int ret;
172     printk("<0>function ioctl!\n\n");
173     switch (command) {
174         case key_input:    
175             //设置所有的引脚为输入
176             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
177             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
178             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
179             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
180             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
181             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
182             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
183             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
184             printk("<0>have setting all pins to gpio input mod !\n");
185             //设置GPIO引脚为上拉模式
186             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
187             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
188             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
189             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
190             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
191             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
192             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
193             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
194 
195             //设置GPIO引脚中断  ,下降沿触发
196             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
197             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
198             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
199             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
200             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
201             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
202             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
203             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
204             printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !\n");
205 
206             break;
207         case version:
208             printk("<0>hello,the version is 0.1.0\n\n");
209             break;
210         default:
211               printk("<0>command error \n");
212             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");
213             printk("<0>command: <key_input> <version>\n\n");
214             return -1;
215     }
216     return 0;    
217 }
218 static unsigned key_poll(struct file *file,poll_table *wait)
219 {
220     unsigned int mask = 0;
221     //程序不立即睡眠,而是继续等待
222     poll_wait(file,&key_interrupt_wait,wait);
223     //如果按键按下
224     if(ev_press)
225         mask |= POLLIN | POLLRDNORM;
226 
227     return mask;
228 }
229 
230 /* 这个结构是字符设备驱动程序的核心
231  * 当应用程序操作设备文件时所调用的open、read、write等函数,
232  * 最终会调用这个结构中指定的对应函数
233  */
234 static struct file_operations key_fops = {
235     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
236     .open   =   key_open,     
237     .read    =    key_read,       
238     .write    =    key_write,       
239     .release=   key_release,
240     .ioctl  =   key_ioctl,    
241     .poll   =   key_poll,
242 };
243     
244 /*
245  * 执行insmod命令时就会调用这个函数 
246  */
247 static int __init  key_irq_init(void)
248 {
249     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
250     //register and mknod
251     major = register_chrdev(0,Driver_NAME,&key_fops);
252     drv_class = class_create(THIS_MODULE,Driver_NAME);
253     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
254     sema_init(&canopen,1);    //初始化信号量为1
255 
256     //set all pins to GPIO mod  ALF5
257     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
258     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
259       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
260        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
261     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
262     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
263     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
264     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
265     //request IOMUX GPIO
266     gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
267      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
268      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
269        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
270     gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
271      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
272       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
273     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
274     
275 
276     return 0;
277 }
278 
279 /*
280  * 执行rmmod命令时就会调用这个函数 
281  */
282 static void __exit key_irq_exit(void)
283 {
284     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
285 
286     unregister_chrdev(major,Driver_NAME);
287     device_unregister(drv_class_dev);
288     class_destroy(drv_class);
289 
290     /* free gpios */
291     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
292     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
293     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
294     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
295     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
296     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
297     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
298     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
299 
300     gpio_free(IOMUX_TO_GPIO(GPIO2_21));
301     gpio_free(IOMUX_TO_GPIO(GPIO3_15));
302     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
303     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
304     gpio_free(IOMUX_TO_GPIO(GPIO2_8));
305     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
306     gpio_free(IOMUX_TO_GPIO(GPIO2_6));
307     gpio_free(IOMUX_TO_GPIO(GPIO2_7));
308 
309 }
310 
311 /* 这两行指定驱动程序的初始化函数和卸载函数 */
312 module_init(key_irq_init);
313 module_exit(key_irq_exit);
314 
315 /* 描述驱动程序的一些信息,不是必须的 */
316 MODULE_AUTHOR("Lover雪");
317 MODULE_VERSION("0.1.0");
318 MODULE_DESCRIPTION("IMX257 key Driver");
319 MODULE_LICENSE("GPL");
View Code

 

 

四、改进 应用程序不阻塞,属性O_NONBLOCK

 

实现不阻塞操作,在开打开文件是,要加入属性O_NONBLOCK

1.在应用程序中:加入属性O_NONBLOCK

 

2.接下来就是在驱动程序中实现对O_NONBLOCK的解析

首先注释前面信号量操作相关的代码:

在read函数中,我们用file结构体来获取我们的flag

if(filp->f_flags & O_NONBLOCK)            //判断是否设置O_NONBLOCK

如果定义了,则不再会运行代码

wait_event_interruptible(key_interrupt_wait,ev_press);

那也就不会阻塞

 

3.为了让应用程序不会运行太快,这里增加一个延时5s

 

4.编译测试

 

 附上驱动程序代码:

  1 /******************************
  2     linux key_query
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/kernel.h>
  7 #include <linux/delay.h>
  8 #include <linux/types.h>
  9 #include <linux/ioctl.h>
 10 #include <linux/gpio.h>
 11 #include <linux/fs.h>
 12 #include <linux/device.h>
 13 #include <linux/uaccess.h>
 14 #include <linux/irq.h>
 15 #include <linux/wait.h>
 16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared 
 17 #include <linux/interrupt.h>
 18 #include <linux/poll.h>
 19 
 20 #include "mx257_gpio.h"
 21 #include "mx25_pins.h"
 22 #include "iomux.h"
 23 
 24 #define Driver_NAME "key_interrupt"
 25 #define DEVICE_NAME "key_interrupt"
 26 
 27 #define GPIO2_21    MX25_PIN_CLKO
 28 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
 29 #define GPIO2_10    MX25_PIN_A24
 30 #define GPIO2_11    MX25_PIN_A25
 31 #define GPIO2_8     MX25_PIN_A22
 32 #define GPIO2_9     MX25_PIN_A23
 33 #define GPIO2_6     MX25_PIN_A20
 34 #define GPIO2_7     MX25_PIN_A21
 35 //command
 36 #define key_input     0
 37 #define version        1
 38 //定义各个按键按下的键值
 39 struct pin_desc{
 40     unsigned int pin;
 41     unsigned int key_val;
 42 };
 43 //当按键按下时,键值分别为 以下值
 44 struct pin_desc pins_desc[8] = {
 45     {GPIO2_6,    0x01},
 46     {GPIO2_7,    0x02},
 47     {GPIO2_8,    0x03},
 48     {GPIO2_9,    0x04},
 49     {GPIO2_10,    0x05},
 50     {GPIO2_11,    0x06},
 51     {GPIO2_21,    0x07},
 52     {GPIO3_15,    0x08},
 53 };
 54 //定义一个全局变量,用于保存按下的键值
 55 static unsigned int key_val;
 56 
 57 //信号量定义
 58 //static int canopen = 1;
 59 //定义原子信号量
 60 //static atomic_t canopen = ATOMIC_INIT(1);    //定义原子信号canopen,并且赋初值1
 61 //定义信号量
 62 //struct semaphore canopen;        //定义一个信号量
 63 
 64 //interrupt head
 65 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
 66 static volatile unsigned char ev_press;  
 67 
 68 static int major=0;
 69 
 70 //auto to create device node
 71 static struct class *drv_class = NULL;
 72 static struct class_device *drv_class_dev = NULL;
 73 
 74 
 75 /* 应用程序对设备文件/dev/key_query执行open(...)时,
 76  * 就会调用key_open函数*/
 77 static int key_open(struct inode *inode, struct file *file)
 78 {
 79     printk("<0>function open!\n\n");
 80 //    down(&canopen);    //申请信号量    
 81     //if(--canopen != 0)
 82     /*if(!atomic_dec_and_test(&canopen))    
 83     {
 84         //canopen ++;
 85         atomic_inc(&canopen);
 86         return -EBUSY;
 87     }*/    
 88 
 89     return 0;
 90 }
 91 
 92 /* 中断程序key_irq */
 93 static irqreturn_t key_irq(int irq, void *dev_id)
 94 {
 95     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
 96     //发生了中断
 97     //printk("<0>function interrupt key_irq!\n\n");
 98     //获取按键键值
 99     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
100         /* 按下 */
101         key_val = pindesc->key_val;
102     }else{
103         key_val = 0x80 | pindesc->key_val;
104     }
105     printk("<0>get key 0x%x",key_val);    
106     ev_press = 1;
107     wake_up_interruptible(&key_interrupt_wait);
108 
109     return IRQ_RETVAL(IRQ_HANDLED);
110 }
111 
112 
113 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
114 {
115     int ret;
116     if(filp->f_flags & O_NONBLOCK){
117         if(!ev_press)
118             return -EAGAIN;
119     }else{
120     //如果按键没有按下,没有中断,休眠
121         wait_event_interruptible(key_interrupt_wait,ev_press);
122     }
123     ret = copy_to_user(buff,&key_val,sizeof(key_val));
124     if(ret){
125         ;
126     }
127     ev_press = 0;
128     return sizeof(key_val);
129 
130     //int cnt=0;
131     //unsigned char key_vals[8];
132 
133     /*
134     // reading the pins value
135     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
136     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
137     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
138     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
139     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
140     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
141     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
142     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
143     
144     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 
145     */
146 }
147 
148 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
149 {
150     printk("<0>function write!\n\n");
151     
152     return 1;
153 }
154 
155 static int  key_release(struct inode *inode, struct file *filp)
156 {
157     //canopen ++;    
158     //atomic_inc(&canopen);
159     //up(&canopen);
160     printk("<0>function release!\n\n");
161     //释放中断
162     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);
163     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
164     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);
165     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);
166     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);
167     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
168     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);
169     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);
170     return 0;
171 }
172 
173 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
174 {
175     int ret;
176     printk("<0>function ioctl!\n\n");
177     switch (command) {
178         case key_input:    
179             //设置所有的引脚为输入
180             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
181             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
182             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
183             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
184             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
185             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
186             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
187             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
188             printk("<0>have setting all pins to gpio input mod !\n");
189             //设置GPIO引脚为上拉模式
190             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
191             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
192             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
193             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
194             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
195             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
196             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
197             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
198 
199             //设置GPIO引脚中断  ,下降沿触发
200             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
201             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
202             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
203             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
204             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
205             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
206             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
207             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
208             printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !\n");
209 
210             break;
211         case version:
212             printk("<0>hello,the version is 0.1.0\n\n");
213             break;
214         default:
215               printk("<0>command error \n");
216             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");
217             printk("<0>command: <key_input> <version>\n\n");
218             return -1;
219     }
220     return 0;    
221 }
222 static unsigned key_poll(struct file *file,poll_table *wait)
223 {
224     unsigned int mask = 0;
225     //程序不立即睡眠,而是继续等待
226     poll_wait(file,&key_interrupt_wait,wait);
227     //如果按键按下
228     if(ev_press)
229         mask |= POLLIN | POLLRDNORM;
230 
231     return mask;
232 }
233 
234 /* 这个结构是字符设备驱动程序的核心
235  * 当应用程序操作设备文件时所调用的open、read、write等函数,
236  * 最终会调用这个结构中指定的对应函数
237  */
238 static struct file_operations key_fops = {
239     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
240     .open   =   key_open,     
241     .read    =    key_read,       
242     .write    =    key_write,       
243     .release=   key_release,
244     .ioctl  =   key_ioctl,    
245     .poll   =   key_poll,
246 };
247     
248 /*
249  * 执行insmod命令时就会调用这个函数 
250  */
251 static int __init  key_irq_init(void)
252 {
253     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
254     //register and mknod
255     major = register_chrdev(0,Driver_NAME,&key_fops);
256     drv_class = class_create(THIS_MODULE,Driver_NAME);
257     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
258     //sema_init(&canopen,1);    //初始化信号量为1
259 
260     //set all pins to GPIO mod  ALF5
261     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
262     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
263       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
264        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
265     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
266     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
267     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
268     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
269     //request IOMUX GPIO
270     gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
271      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
272      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
273        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
274     gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
275      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
276       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
277     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
278     
279 
280     return 0;
281 }
282 
283 /*
284  * 执行rmmod命令时就会调用这个函数 
285  */
286 static void __exit key_irq_exit(void)
287 {
288     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
289 
290     unregister_chrdev(major,Driver_NAME);
291     device_unregister(drv_class_dev);
292     class_destroy(drv_class);
293 
294     /* free gpios */
295     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
296     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
297     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
298     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
299     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
300     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
301     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
302     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
303 
304     gpio_free(IOMUX_TO_GPIO(GPIO2_21));
305     gpio_free(IOMUX_TO_GPIO(GPIO3_15));
306     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
307     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
308     gpio_free(IOMUX_TO_GPIO(GPIO2_8));
309     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
310     gpio_free(IOMUX_TO_GPIO(GPIO2_6));
311     gpio_free(IOMUX_TO_GPIO(GPIO2_7));
312 
313 }
314 
315 /* 这两行指定驱动程序的初始化函数和卸载函数 */
316 module_init(key_irq_init);
317 module_exit(key_irq_exit);
318 
319 /* 描述驱动程序的一些信息,不是必须的 */
320 MODULE_AUTHOR("Lover雪");
321 MODULE_VERSION("0.1.0");
322 MODULE_DESCRIPTION("IMX257 key Driver");
323 MODULE_LICENSE("GPL");
View Code

 

附上应用程序代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include <termios.h>
 8 #include <errno.h>
 9 #include <limits.h>
10 #include <asm/ioctls.h>
11 #include <time.h>
12 #include <pthread.h>
13 #include <poll.h>
14 
15 #include "mx257_gpio.h"
16 
17 #define key_input     0
18 #define version       1
19 
20 
21 int main(int argc, char **argv)
22 {
23     int fd;
24     int i=0,cnt=0;
25     unsigned char key_val[1];
26     struct pollfd fds[1];    
27     int ret;
28     fd = open("/dev/key_interrupt",O_RDWR | O_NONBLOCK);
29     if(fd < 0){
30         printf("can't open !!!\n");
31     }
32     ioctl(fd,version,NULL);
33     ioctl(fd,key_input,NULL);
34 
35     fds[0].fd = fd;
36     fds[0].events = POLLIN;
37     while(1){
38         ret = poll(fds,1,5000);
39         printf("%04d key pressed: 0x%x\n",cnt++,key_val[0]);    
40         sleep(5);
41         /*if(ret == 0)
42             printf("time out\n");
43         else{
44             read(fd,key_val,1);
45             printf("%04d key pressed: 0x%x\n",cnt++,key_val[0]);    
46         }*/
47     }
48     return 0;
49 }
View Code

 

 

总结一下:

 

 

前面的这几种方法都是很简单的,如果熟练了单片机程序的话,在驱动程序的基础上理解这个信号量,是很简单的,加油!

 

对了,差点忘了,今天是除夕,在这里给爱好者们拜一个年:

新年快乐!祝大家学习顺利,心想事成,happy new year!!!

 

posted on 2015-02-18 22:39  Lover雪儿  阅读(582)  评论(0编辑  收藏  举报