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

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

    昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费。


    本文中,我们在前面按键查询驱动程序的基础上来修改。


    大概介绍一下设计思路吧:


    和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPIO模式,然后申请GPIO引脚的内存,


接着,当我们应用程序使用ioctl函数的gpio_input命令时,将所有的GPIO引脚设置为输入,并且22K上拉模式,当应用程序使用read函数读取时,如果按键没有按下,则会在read函数中睡眠(可被中断唤醒),交出CPU的使用权,当按键按下时,首先会在中断程序中进行唤醒操作,在read函数中接着运行,读取GPIO引脚的电平,并且将数据从内核空间传递到用户空间中,并且打印出来。


    最后,当我们不要用驱动程序时,rsmod会调用exit函数,释放所有我们已经申请的GPIO资源。


    好了,大概的思路就是这样,和前面的查询驱动程序,差不多,只不过就加了一个中断,和睡眠而已。


附上驱动程序代码:


  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 

 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 //interrupt head

 39 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);

 40 static volatile unsigned char ev_press;  

 41 

 42 static int major=0;

 43 

 44 //auto to create device node

 45 static struct class *drv_class = NULL;

 46 static struct class_device *drv_class_dev = NULL;

 47 

 48 

 49 /* 应用程序对设备文件/dev/key_query执行open(...)时,

 50  * 就会调用key_open函数*/

 51 static int key_open(struct inode *inode, struct file *file)

 52 {

 53     printk('<0>function open!nn');

 54     

 55     return 0;

 56 }

 57 

 58 /* 中断程序key_irq */

 59 static irqreturn_t key_irq(int irq, void *dev_id)

 60 {

 61     //发生了中断

 62     printk('<0>function interrupt key_irq!nn');

 63     ev_press = 1;

 64     wake_up_interruptible(&key_interrupt_wait);

 65 

 66     return IRQ_RETVAL(IRQ_HANDLED);

 67 }

 68 

 69 

 70 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

 71 {

 72     int ret;

 73     //nt cnt=0;

 74     unsigned char key_vals[8];

 75 

 76     //如果按键没有按下,没有中断,休眠

 77     wait_event_interruptible(key_interrupt_wait,ev_press);

 78 

 79     // reading the pins value

 80     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;

 81     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;

 82     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;

 83     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;

 84     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;

 85     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;

 86     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;

 87     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;

 88     

 89     ret = copy_to_user(buff,key_vals,sizeof(key_vals));

 90     if(ret){

 91         ;

 92     }

 93     ev_press = 0;

 94     //printk('<0>%04d key pressed: %d %d %d %d %d %d %d %dn',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]); 

 95 

 96     return sizeof(key_vals);

 97 }

 98 

 99 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

100 {

101     printk('<0>function write!nn');

102     

103     return 1;

104 }

105 

106 static int  key_release(struct inode *inode, struct file *filp)

107 {

108     printk('<0>function release!nn');

109     //释放中断

110     free_irq(IOMUX_TO_IRQ(GPIO2_21), (void *)1);

111     //free_irq(IOMUX_TO_IRQ(GPIO3_15), (void *)1);

112     free_irq(IOMUX_TO_IRQ(GPIO2_11), (void *)1);

113     free_irq(IOMUX_TO_IRQ(GPIO2_10), (void *)1);

114     free_irq(IOMUX_TO_IRQ(GPIO2_9), (void *)1);

115     //free_irq(IOMUX_TO_IRQ(GPIO2_8), (void *)1);

116     free_irq(IOMUX_TO_IRQ(GPIO2_7), (void *)1);

117     free_irq(IOMUX_TO_IRQ(GPIO2_6), (void *)1);

118     return 0;

119 }

120 

121 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

122 {

123     int ret;

124     printk('<0>function ioctl!nn');

125     switch (command) {

126         case key_input:    

127             //设置所有的引脚为输入

128             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));

129             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));

130             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));

131             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));

132             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));

133             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));

134             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));

135             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));

136             printk('<0>have setting all pins to gpio input mod !n');

137             //设置GPIO引脚为上拉模式

138             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

139             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

140             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

141             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

142             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

143             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

144             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

145             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

146 

147             //设置GPIO引脚中断  ,下降沿触发

148             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_7', (void *)1);

149             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_6', (void *)1);

150             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_9', (void *)1);

151             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_10', (void *)1);

152             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_11', (void *)1);

153             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_21', (void *)1);

154             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO3_15', (void *)1);

155             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_8', (void *)1);

156             printk('<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !n');

157 

158             break;

159         case version:

160             printk('<0>hello,the version is 0.1.0nn');

[1] [2]
关键字:GPIO  IRQ  中断按键 引用地址:IMX257实现GPIO-IRQ中断按键驱动程序

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

推荐阅读最新更新时间:2024-11-17 10:31

IMX257 混杂设备miscdevice驱动程序
在Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述)。miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同。 所有的miscdevice设备形成了一个链表,对设备访问时内核根据次设备号查找对应的miscdevice设备,然后调用其file_operations结构中注册的文件操作接口进行操作。 在内核中用struct miscdevice表示miscdevice设备,然后调用其file_operations结构中注册的文件操作接口进行操作。miscdevice的API实现在drivers/char/misc.c中。 一、混杂设备介绍 1. miscdevi
[单片机]
<font color='red'>IMX257</font> 混杂设备miscdevice驱动程序
STM32CUBEMX(4)--GPIO输出
概述 本篇文章主要介绍如何使用STM32CubeMX对红外波形进行GPIO输出,并LED显示。 硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板: 选择芯片型号 配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示: 配置时钟树 STM32F0的最高主频到48M,所以配置48即可: GPIO口配置 左键点击需要配置的端口,选择GPIO_Output模式。这里我们配置的端口位PB10和PB11。 配置完如下图所示。 详细参数配置,如下图,完成后点击OK。 生成工程设置 注意在生产工程设置中不能出现中文,不然
[单片机]
STM8 寄存器操作GPIO
硬件平台:stm8s103 编译环境:IAR for stm8 #include iostm8s103f3.h #include intrinsics.h int main(void) { // 初始化端口D. PD_ODR_ODR4 = 0; //PD4输出低电平 PD_DDR_DDR4 = 1; //设置D端口,位4输出 PD_CR1_C14 = 1; //引脚设置为上拉输出 PD_CR2_C24 = 1; //设置10MHz输出(翻转速度) while (1) { PD_ODR_ODR4 = 1; // PD4输出高电平 // PD_O
[单片机]
一文全面掌握stm32的GPIO知识
1 初学者重要提示 本文主要是以stm32H7系列为主。 对于不使用的引脚,推荐设置为模拟模式,悬空即可。 GPIO的速度等级高的时候,最好使能IO补偿单元。 2 GPIO功能简介 STM32H7的GPIO特性如下: 输出状态:开漏/推挽 + 上拉/下拉电阻。 通过输出数据寄存器(GPIOx_ODR)或者外设(GPIO设置为复用模式时)输出数据。 GPIO速度等级设置。 输入状态:浮空,上拉/下拉,模拟。 通过输入数据寄存器(GPIOx_IDR)或者外设(GPIO设置为复用模式)输入数据。 通过寄存器GPIOx_BSRR实现对寄存器GPIOx_ODR的位操作。 通过配置寄存器GPIOx_LCKR的锁机制,实现冻结IO口配置。
[单片机]
一文全面掌握stm32的<font color='red'>GPIO</font>知识
IMX257 输入子系统
一、输入子系统 1.输入子系统结构体定义 struct input_dev{ const char *name; 设备名 const char *phys; 设备在系统中路径 const char *uniq; struct input_id id; 用于匹配input hander参数 unsigned long propbit ; unsigned long evbit ; //设备所支持事件类型,主要有EV_SYNC,EV_KEY,EV_REL,EV_ABS等 unsigned long keybit ; //按键所对应的位图 unsigned long relbit ; //相对坐标对应位图 u
[单片机]
<font color='red'>IMX257</font> 输入子系统
MSP430按键中断
#include msp430f149.h typedef unsigned char uchar; typedef unsigned int uint; #define keyin (P1IN & 0X0F) #define wei_h P5OUT |= BIT5 #define wei_l P5OUT &= BIT5 #define duan_l P6OUT &= ~BIT6 #define duan_h P6OUT |= BIT6 uchar table = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x7
[单片机]
STM32F4学习笔记之GPIO(使用固件库)
1.使能GPIO的AHB时钟,使用函数: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE); 2.配置GPIO工作模式用GPIO_Init()函数 数据类型说明 typedef struct { uint32_t GPIO_Pin; //引脚配置 GPIOMode_TypeDef GPIO_Mode; //GPIO_Mode_IN(输入),GPIO_Mode_OUT(输出),GPIO_Mode_AF(备用),GPIO_Mode_AN(模拟) GPIOSpeed_TypeDef GPIO_Speed;// GPIO_Speed_2MHz,GPIO_Spe
[单片机]
STM32之GPIO笔记
1 STM32的输入输出管脚有下面8种可能的配置:(4输入+2输出+2复用输出) ① 浮空输入_IN_FLOATING ② 带上拉输入_IPU ③ 带下拉输入_IPD ④ 模拟输入_AIN ⑤ 开漏输出_OUT_OD ⑥ 推挽输出_OUT_PP ⑦ 复用功能的推挽输出_AF_PP ⑧ 复用功能的开漏输出_AF_OD 1.1 I/O口的输出模式下,有3种输出速度可选(2MHz、10MHz和50MHz),这个速度是指I/O口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在I/O口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动
[单片机]
小广播
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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