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

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

2015-02-18 李海沿

按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值。

同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回。

我们在linux查看帮助:

从帮助中的说明得知,

poll, ppoll - wait for some event on a file descriptor

poll就是监控某个设备的事件。

修改驱动程序

1.增加头文件 #include <linux/poll.h>

2.增加key_poll 方法


static unsigned key_poll(struct file *file,poll_table *wait)

file_opreation中增加:


.poll = key_poll,

3.在key_poll函数中设置函数不睡眠

4.此时可以把以前的read函数中的中断睡眠代码注释掉

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

修改应用程序

1.我们首先包含头文件 #include <poll.h>

2.定义结构体


struct pollfd fds[1]; //方括号中为要监控的设备数量

fds[0].fd = fd; //加入要监控的设备描述符

fds[0].events = POLLIN;

3. 监控的结果是 POLLIN

POLLIN There is data to read.

从帮助得知,一旦时间发送就意思有消息读取,接着,一旦我们poll监控到数据,我们就开始read函数来读取数据。

附上修改后的应用程序代码:

 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 }

运行程序:

可以发现,其实程序时不断的在查询,每5秒之内若是没有时间发生则打印time out,若是有时间发生,则立即读取内核空间的键值。

既然是不断的查询,那我们来看一下,它是不是很耗费CPU资源呢:

后台运行,使用top命令查看cpu使用率

可以发现,函数在不断的运行,每过5s打印time out

使用top命令,查看cpu资源

可以发现,虽然这个程序没有使用中断休眠函数,也是在不断的查询,但是使用poll后,cpu几乎不占用。

kill 杀死后台程序

时间: 2024-10-02 21:31:15

20150218【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序的相关文章

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

[改进信号量]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序 这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开. 一.首先在前面代码的基础上来一个简单的信号 1.定义一个全局的整形变量 2.在打开函数中,每次进入打开函数canopen都自减1, 3.当我们不使用时,在realease 中canopen自加1 4.这样就实现了一个简单的信号量,我们编译,测试 当我们使用两个应用程序来

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

[改进]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 /***********

使用pymysql进行定时查询数据不更新的原因及解决方式

用python写了一个小脚本定时查询数据库,输出查询结果并写入文件,发现每次查询的结果都是相同的,但是数据库确实在更新数据. 原因: REPEATABLE READ The default isolation level for InnoDB. It prevents any rows that are queried from being changed by other transactions, thus blocking non-repeatable reads but not phan

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

IMX257实现GPIO-IRQ中断按键驱动程序 2015-02-18 李海沿 ????昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费. ????本文中,我们在前面按键查询驱动程序的基础上来修改. ????大概介绍一下设计思路吧: ????和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPI

solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据

solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据 上一节我们完成了solr连接数据库,细心的朋友会发现一个问题,就是solr其实和语言没有任何关系,配置完成后任何语言都可以直接调用,本章我们主要对solr的查询做出讲解,然后就是新接触的人最关心的.net如何获取solr中的数据. 本节我准备了一个300万左右的数据表,为大家做演示 然后我们开始配置schema.xml 文件: <field name="id" type="string

js根据url查询字符串里的键名获取其值

先来运行结果 下面是页面代码 testJsGetUrlAttribute.html <script> var rout = getUrlAttribute('rout'); if(null!=rout) { alert(rout); } /** * 20150514 14:30 * 作者:Ro * 根据url查询字符串里的键名获取其值 */ function getUrlAttribute(parameName) { //location.search是从当前URL的?号开始的字符串,即查询字

在sqlite中执行&#39;in&#39;查询操作,如何使用selectionargs匹配多个值

在安卓开发中,经常使用到sqlite作为本地持久化存储的解决方案.在androidSDK中,已经为我们提供了各种各样的增.删.改.查的api,尽管我们可以自己写sql语句然后执行db.rawsql(sql,null)方法,但这种方法有一些风险,那就是拼接的关键字有可能是非法的,这样会造成很多意想不到并且很危险的后果.因此,建议使用sdk提供的api来做数据库操作,android已经为我们屏蔽了这一层风险. 在使用sqlite查询时,我们经常会使用"in"操作符来进行查询,如 selec

GPIO外部中断

STM32的"中断"机制很复杂,看了PM(Cortex-m4)和RM,对它只了解了一个大概.首先,与"中断"相关的术语就有 exception, interrupt, event 三个.Cortex-m4核中包含一个NVIC控制器,用于处理 exception.而 interrupt 是属于 exception 之一种,其它 exception 类型包括 SysTick等.interrupt 又叫作IRQ. STM32之中.Cortex-m4核之外的"中断

标准app基础模板建立-活动管理-定时服务-键值对存储-日志工具

一.建立工程 1.建立一个空白的工程,名称为ModelApp. 2.在main-java下新建package,起名com.jiaweiqiang.tools,用于放置通用工具类. 二.建立得到全局变量的Application类 1.在tools中新建MyApplication类,用于存储全局context和其他程序需要的通用变量. public class MyApplication extends Application { private static Context context; pr