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.0nn');
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:
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!nn',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!nn',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');
附上应用程序代码:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
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 outn');
41 else{
42 read(fd,key_val,1);
43 printf('%04d key pressed: 0x%xn',cnt++,key_val[0]);
44 }
45 }
46 return 0;
二、改进 原子操作
由于前面的代码中信号量自减和检测信号量不是同时进行的,可能被打断,虽然概率很小,但是,也是有可能会发生。
为了避免这个问题,这里我们使用原子操作来实现信号量的改变。
所谓原子操作,就是不可被打断,从而保证了前面我们所说到的问题。
具体方法如下。
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
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19
20 #include 'mx257_gpio.h'
21 #include 'mx25_pins.h'
22 #include 'iomux.h'
上一篇:【改进定时器】IMX257实现GPIO-IRQ定时器消抖驱动程序
下一篇:【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
推荐阅读最新更新时间:2026-03-15 05:02
- LTC3890HUH 高效双路 8.5V/3.3V 输出降压转换器的典型应用电路
- 使用 ROHM Semiconductor 的 BD4841 的参考设计
- 使用 ON Semiconductor 的 KA7805AE 的参考设计
- LTC1258CS8-4.1 低功率、低电压电源基准的典型应用电路
- LT8309 的典型应用 - 次级侧同步整流器驱动器
- AM1G-0515DH30Z ±15V 1 瓦 DC/DC 转换器的典型应用
- 具有 ATxmega32E5 参考设计的 DALI 从站
- TDA8932B D 类音频功率放大器的对称电源立体声 SE 配置
- 使用 Diodes Incorporated 的 ZXCD1010EQ16 的参考设计
- BB-BONE-WTHR-01,BeagleBone Weather Cape 为 BeagleBone 提供天气数据,包括温度、气压、湿度和环境光



嵌入式系统技术与设计
非常经典的关于LLC的杨波博士论文
VI-27WIU






京公网安备 11010802033920号