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

发布者:MysticalGarden最新更新时间:2024-08-16 来源: cnblogs关键字:信号量  中断按键 手机看文章 扫描二维码
随时随地手机看文章

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: nn');

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;

47 }



二、改进 原子操作

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

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

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

具体方法如下。

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 //error: 'TASK_INTERRUPTIBLE' undeclared 

 17 #include

 18 #include

 19 

 20 #include 'mx257_gpio.h'

 21 #include 'mx25_pins.h'

 22 #include 'iomux.h'

[1] [2] [3] [4] [5] [6] [7] [8]
关键字:信号量  中断按键 引用地址:【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

上一篇:【改进定时器】IMX257实现GPIO-IRQ定时器消抖驱动程序
下一篇:【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

推荐阅读最新更新时间:2026-03-15 05:02

【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
按键驱动程序中,如果不使用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 *fil
[单片机]
【改进Poll定时查询】<font color='red'>IMX257</font>实现<font color='red'>GPIO-IRQ</font><font color='red'>中断</font><font color='red'>按键</font><font color='red'>获取</font><font color='red'>键值</font>驱动程序
按键中断部分的理解
初始准备 初始化串口 初始化Tx、Rx对应的GPIO引脚 设置1个停止位,8位数据位 发送和接收都是polling 禁止modem、afc 波特率设置 初始化按键中断(在key.c中:以中断方式处理按键) 外部中断对应的GPIO设置 中断触发模式 中断允许 清挂起,清除是写1 绑定好异常向量表、初始化中断控制器 绑定异常向量表 禁止所有中断 选择中断类型为IRQ 清VICxADDR 绑定isr到中断控制器硬件 使能中断 运行过程: 程序运行----- 按键按下-------- 硬件自动跳转到异常向量表的IRQ中断部分 -------- 由于向量表这里写的是IRQ_handle的函数地址,所以又发生一次跳转 ---
[单片机]
【GD32H757Z海棠派开发板使用手册】第三讲 EXTI-按键中断检测实验
3.1实验内容 通过本实验主要学习以下内容: EXTI中断原理; 按键中断检测原理; 3.2实验原理 3.2.1NVIC中断向量控制器 介绍EXTI之前,首先为各位读者介绍NVIC中断向量控制器,NVIC为M7内核组件,用于实现高效的异常和中断处理。NVIC可以支持抢占以及咬尾中断,具有多达217种外设中断以及4位中断优先等级配置(最多支持16个中断有限等级),当中断或异常产生时,系统自动将当前处理器工作状态压栈,在执行完中断服务子程序(ISR) 后自动将其出栈。 有关NVIC中断相关配置函数可参考gd32h7xx_misc.c,其中主要有以下几个函数,其功能简介如下表所示。 3.2.2EXTI中断原理 EXTI为外部中
[单片机]
【GD32H757Z海棠派开发板使用手册】第三讲 EXTI-<font color='red'>按键</font><font color='red'>中断</font>检测实验
专题2-通过按键中断\2440按键中断编程lesson2
1、程序优化 修改Makefile 把main.c里面的mmu代码复制到mmu.c并修改如下 main.c的修改 由于在bootloader当中一般不会使用MMU,所以 main.c 加入led.c文件 makefile 2440中断源初始化 打开开发板底板与核心板原理图 底板 比如K1对应EINT1,然后到核心板去搜EINT1 然后去2440芯片手册去找到GPF这一组IO口 创建一个button.c,加入到makefile里面去button.o 按键初始化 编写button.c文件 #define GPFCON (volatile unsigned long *)0x56000050
[单片机]
专题2-通过<font color='red'>按键</font>玩<font color='red'>中断</font>\2440<font color='red'>按键</font><font color='red'>中断</font>编程lesson2
Linux驱动之按键驱动编写(中断方式)
1、查看原理图,确定需要控制的IO端口 打开原理图,确定需要控制的IO端口为GPF0、GPF2、GPG3、GPG11。可以看到它的中断号为IRQ_EINT0、IRQ_EINT2、IRQ_EINT11、IRQ_EINT19 2、查看芯片手册,确定IO端口的寄存器地址,可以看到因为用了两组GPIO端口,所以它的基地址分别为0x56000050、0x56000060。中断方式的寄存器基地址为0x56000088、0x5600008c、0x56000090 3、编写驱动代码,编写驱动代码的步骤如下: 1)、编写出口、入口函数。代码如下,具体说明参考Linux驱动之LED驱动编写 static int second_
[单片机]
Linux驱动之<font color='red'>按键</font>驱动编写(<font color='red'>中断</font>方式)
msp432快速入门第六节之按键扫描和GPIO中断操作
(一)按键扫描 (1)配置引脚 在按键扫描这一节,仅需要配置好引脚即可,打开TI的GPIO驱动库,可以看到GPIO设置函数H文件如下: 在这个函数上方有对函数的说明: 解释为:该函数配置MSP432的GPIO引脚为输入模式,没有指明被配置的引脚是否被上拉或者下拉,当然如果需要配置输入上拉或者输入下拉需要使用此函数配置: 在这里我们直接使用普通配置,配置引脚为输入即可。 如下进行引脚初始化:(板载两个按键,一左一右均可以使用,注意复位键是在上面的) //key pin init void Key_Init(void) { GPIO_setAsInputPinWithPullUpResistor(KEY_LEFT
[单片机]
msp432快速入门第六节之<font color='red'>按键</font>扫描和GPIO<font color='red'>中断</font>操作
10.80c51外部中断 按键翻转LED
外部中断0 在我理解,外部中断要用的话,首先得开启总中断开关即(EA=1),而后打开外部中断允许(即EX0=1),最后选择外部中断触发方式(IT0,为0则为低电平触发,为1则为下降沿触发),以下为外部中断0的实现按键按下LED灯状态翻转的作用。 外部中断0实现代码如下(已注释) #include reg52.h typedef unsigned char u8; typedef unsigned int u16; sbit k3=P3^2;//开始以为随便一个按键都有用,没用后发现得把按键接在中断端口上,用外部中断 // 0则需接在P32口上 sbit led=P2^0; void delay(u16
[单片机]
10.80c51外部<font color='red'>中断</font> <font color='red'>按键</font>翻转LED
2440裸机程序——按键中断
工程当中需要添加 S3C2440A.s ;2440lib.c;main.c;keyscan.c这段四个程序。 主程序: /********************************************************************************************* * File name: main.c * Author: ZXL * Description: 按下按键,相应的LED灯点亮且蜂鸣器响,由于触发了外部中断,通过串口向电脑发送是哪一个外部中断源触发了中断。 * History: 2013.5.6 ***********************************
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved