【改进信号量】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!!!

转载于:https://www.cnblogs.com/lihaiyan/p/4295961.html

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

  1. 20150218【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

    [改进Poll定时查询]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用 ...

  2. 高通驱动实现 GPIO 中断上报键值

    高通驱动实现 GPIO 中断上报键值 一. 确认keycode值,同步修改上层键值映射表 Tips 1: 选择一个好的键值的好处 Tips 2: 如何确认驱动代是否ok 二. 驱动代码编写 三.代码调 ...

  3. linux驱动的中断函数,嵌入式Linux驱动开发(四)——字符设备驱动之中断方式以及中断方式获取按键值...

    之前我们完成了关于通过查询的方式获取按键键值的驱动程序,可以参考:嵌入式Linux开发--裸板程序之中断控制器. 虽然读取键值没有什么问题,但是测试程序占用CPU过高,一直在不断的查询,资源消耗过大, ...

  4. 【STM32F429开发板用户手册】第19章 STM32F429的GPIO应用之按键FIFO

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255 第19章       STM32F429的GPIO应用之按键FIF ...

  5. 【STM32F407开发板用户手册】第19章 STM32F407的GPIO应用之按键FIFO

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255 第19章       STM32F407的GPIO应用之按键FIF ...

  6. 【STM32H7教程】第19章 STM32H7的GPIO应用之按键FIFO

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第19章       STM32H7的GPIO应用之按键FIF ...

  7. 【STM32H7教程】第19章 STM32H7的GPIO应用之按键FIFO

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第19章       STM32H7的GPIO应用之按键 ...

  8. 20150217 IMX257实现GPIO-IRQ中断按键驱动程序

    IMX257实现GPIO-IRQ中断按键驱动程序 2015-02-17 李海沿 昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有 ...

  9. 设备树之GPIO和中断实例

    概述 设备树不仅仅描述常规硬件信息,还可以描述中断,GPIO,DMA,PINCTRL,时钟,电源管理等内核基础设施信息及其使用情况,下面重点介绍中断,GPIO等结点属性 中断控制器 对于中断控制器结点 ...

最新文章

  1. 【尚硅谷】大厂必备技术之JUC并发编程——笔记总结
  2. Spring Cloud Bus 消息总线介绍
  3. ubuntu19.10安装haroopad软件
  4. 如何在计算机上阅读漫画书
  5. php stmp 授权码问题,PHPmailer 使用网易126发送邮件的问题
  6. 信息学奥赛一本通 提高篇 第六部分 数学基础 第1章 快速幂
  7. vSphere4.1升级到vSphere5.0连载之一
  8. 《穿越计算机的迷雾》
  9. 阿里云邮箱企业版与个人版区别大吗?
  10. Cesium之【空间面积】测量
  11. Type-C PD充电简介
  12. 2016年腾讯实习生校园招聘-电面2
  13. linux 域名判断 跳转,Nginx判断不同的域名指向不同的root路径实例
  14. App逆向|一个案例教你如何进行APP逆向
  15. C++异常类型以及多级catch匹配
  16. 中学生应具备的良好的学习习惯
  17. dk编程真好玩 python_皮皮学编程(1):从Scratch到Python
  18. python对excel筛选提取文本中数字_详解利用python提取pdf文本数字
  19. Cadence OrCad Capture新建工程的方法
  20. 如何在PPT中插入Visio文件

热门文章

  1. Max3成功刷入原生Android,小米Max 2用户类原生系统福利:第三方开发者为其适配LineageOS...
  2. android自动添加包,android nfc写入应用程序包名与网址 自动打开应用程序与网址...
  3. 奥比中光Orbbec Astra-Mini RGB-D 3D体感摄像头在ROS(indigo)使用简介
  4. linux跑wrf.exe程序的前提,用WRF模型进行气象模拟入门(3)——WRF的运行
  5. 解析html xml最好的模块,解析--import--htmllib--xml
  6. 【原创】Java获取CPU占用率、内存占用率最简单的方式
  7. 电脑文件被误删?360文件恢复工具,免费的文件恢复软件
  8. 手绘计算机比赛海报,手绘海报大赛专题计划.doc
  9. 最小可行产品MVP - 从源头杜绝浪费
  10. C语言新建文件写入数据