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

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

2015-02-18 李海沿

 

一、使用struct pin_desc 管理按键的值

1.定义结构体

2.将前面我们申请中断时写的(void *)1修改为 &pins_desc[n]

在ioctl中,设置中断中修改

在key_release中释放中修改

3.在中断程序中利用我们定义的struc pins_desc判断并得到按键的值

4.得到按键键值后,唤醒程序,在read函数中返回键值

 

附上驱动源程序:

 

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

 

结果如图所用 insmod key_interrupt.ko

后台运行应用程序 ./test/key_test &

查看中断 cat /proc/interrupts

ps,查看我们后台的进程号,使用kill函数时,驱动程序会自动进入release函数,释放中断号。

 

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