昨天我们已经实现了中断查询的方式实现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 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');
上一篇:【改进】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
下一篇:IMX257实现GPIO-查询按键驱动程序
推荐阅读最新更新时间:2024-11-12 23:04
设计资源 培训 开发板 精华推荐
- LT8631IFE 400kHz、3.3V、1A 降压转换器的典型应用电路
- AD9238BCP-20EBZ,用于 AD9238、2 通道、10 位、20 MSPS 模数转换器的评估板
- EVAL-RS485FD8EBZ,用于 ADM4855 半双工 RS-485 收发器的评估板,采用 8 引脚 SOIC 封装
- AR0331SRSC00SUCAH-GEVB:3.5 MP Sunex DSL945D 1/3" iLCC CIS HB
- 使用 Analog Devices 的 LTC3130IMSE 的参考设计
- KIT33814AEEVBE,具有 MC33814 两缸小型发动机控制 IC 的评估套件
- LTC2376-16、16 位、250ksps、低功率 SAR ADC 的典型应用电路
- EVAL-CN0300-EB1Z,基于 ADuCM360 的评估板,使用 ARM Cortex-M3 的 12 位、4-20mA 环路供电热电偶测量系统
- SP7662 典型应用,12 至 3.3V/12A 同步降压稳压器
- CN0312