我在看资料的基础上加以整改,把程序记录下来以便于日后查看。
DEMO板上的按键原理图
按键对应的芯片引脚为:
GPIO2_6 对应 /* Bank2 */ 中 #define PINID_SSP0_DATA6 MXS_PIN_ENCODE(2, 6)
以此类推
GPIO2_5 对应 /* Bank2 */ 中 #define PINID_SSP0_DATA5 MXS_PIN_ENCODE(2, 5)
GPIO2_4 对应 /* Bank2 */ 中 #define PINID_SSP0_DATA4 MXS_PIN_ENCODE(2, 4)
GPIO1_18对应 /* Bank1 */ 中 #define PINID_LCD_D18 MXS_PIN_ENCODE(1, 18)
GPIO1_17对应 /* Bank1 */ 中#define PINID_LCD_D17 MXS_PIN_ENCODE(1, 17)
具体可以查看内核中芯片引脚:
linux-2.6.35.3/arch/arm/mach-mx28/mx28_pins.h
/* Bank 1 */
define PINID_LCD_D00 MXS_PIN_ENCODE(1, 0)
define PINID_LCD_D01 MXS_PIN_ENCODE(1, 1)
define PINID_LCD_D02 MXS_PIN_ENCODE(1, 2)
define PINID_LCD_D03 MXS_PIN_ENCODE(1, 3)
define PINID_LCD_D04 MXS_PIN_ENCODE(1, 4)
define PINID_LCD_D05 MXS_PIN_ENCODE(1, 5)
define PINID_LCD_D06 MXS_PIN_ENCODE(1, 6)
define PINID_LCD_D07 MXS_PIN_ENCODE(1, 7)
define PINID_LCD_D08 MXS_PIN_ENCODE(1, 8)
define PINID_LCD_D09 MXS_PIN_ENCODE(1, 9)
define PINID_LCD_D10 MXS_PIN_ENCODE(1, 10)
define PINID_LCD_D11 MXS_PIN_ENCODE(1, 11)
define PINID_LCD_D12 MXS_PIN_ENCODE(1, 12)
define PINID_LCD_D13 MXS_PIN_ENCODE(1, 13)
define PINID_LCD_D14 MXS_PIN_ENCODE(1, 14)
define PINID_LCD_D15 MXS_PIN_ENCODE(1, 15)
define PINID_LCD_D16 MXS_PIN_ENCODE(1, 16)
define PINID_LCD_D17 MXS_PIN_ENCODE(1, 17)
define PINID_LCD_D18 MXS_PIN_ENCODE(1, 18)
define PINID_LCD_D19 MXS_PIN_ENCODE(1, 19)
define PINID_LCD_D20 MXS_PIN_ENCODE(1, 20)
define PINID_LCD_D21 MXS_PIN_ENCODE(1, 21)
define PINID_LCD_D22 MXS_PIN_ENCODE(1, 22)
define PINID_LCD_D23 MXS_PIN_ENCODE(1, 23)
define PINID_LCD_RD_E MXS_PIN_ENCODE(1, 24)
define PINID_LCD_WR_RWN MXS_PIN_ENCODE(1, 25)
define PINID_LCD_RS MXS_PIN_ENCODE(1, 26)
define PINID_LCD_CS MXS_PIN_ENCODE(1, 27)
define PINID_LCD_VSYNC MXS_PIN_ENCODE(1, 28)
define PINID_LCD_HSYNC MXS_PIN_ENCODE(1, 29)
define PINID_LCD_DOTCK MXS_PIN_ENCODE(1, 30)
define PINID_LCD_ENABLE MXS_PIN_ENCODE(1, 31)
/* Bank 2 */
define PINID_SSP0_DATA0 MXS_PIN_ENCODE(2, 0)
define PINID_SSP0_DATA1 MXS_PIN_ENCODE(2, 1)
define PINID_SSP0_DATA2 MXS_PIN_ENCODE(2, 2)
define PINID_SSP0_DATA3 MXS_PIN_ENCODE(2, 3)
define PINID_SSP0_DATA4 MXS_PIN_ENCODE(2, 4)
define PINID_SSP0_DATA5 MXS_PIN_ENCODE(2, 5)
define PINID_SSP0_DATA6 MXS_PIN_ENCODE(2, 6)
define PINID_SSP0_DATA7 MXS_PIN_ENCODE(2, 7)
define PINID_SSP0_CMD MXS_PIN_ENCODE(2, 8)
define PINID_SSP0_DETECT MXS_PIN_ENCODE(2, 9)
define PINID_SSP0_SCK MXS_PIN_ENCODE(2, 10)
define PINID_SSP1_SCK MXS_PIN_ENCODE(2, 12)
define PINID_SSP1_CMD MXS_PIN_ENCODE(2, 13)
define PINID_SSP1_DATA0 MXS_PIN_ENCODE(2, 14)
define PINID_SSP1_DATA3 MXS_PIN_ENCODE(2, 15)
define PINID_SSP2_SCK MXS_PIN_ENCODE(2, 16)
define PINID_SSP2_MOSI MXS_PIN_ENCODE(2, 17)
define PINID_SSP2_MISO MXS_PIN_ENCODE(2, 18)
define PINID_SSP2_SS0 MXS_PIN_ENCODE(2, 19)
define PINID_SSP2_SS1 MXS_PIN_ENCODE(2, 20)
define PINID_SSP2_SS2 MXS_PIN_ENCODE(2, 21)
define PINID_SSP3_SCK MXS_PIN_ENCODE(2, 24)
define PINID_SSP3_MOSI MXS_PIN_ENCODE(2, 25)
define PINID_SSP3_MISO MXS_PIN_ENCODE(2, 26)
define PINID_SSP3_SS0 MXS_PIN_ENCODE(2, 27)
下面直接上代码:
imx_key.c
/* GPIO Driver driver for EasyARM-iMX283 */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/ioctl.h> #include <linux/delay.h> #include <linux/bcd.h> #include <linux/capability.h> #include <linux/rtc.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include <linux/gpio.h> #include <linux/slab.h> #include </usr/src/linux-2.6.35.3/arch/arm/mach-mx28/mx28_pins.h> #include <linux/list.h> #include<linux/init.h> #include<linux/module.h> #include<mach/gpio.h> #include<asm/io.h> #include"/usr/src/linux-2.6.35.3/arch/arm/mach-mx28/mx28_pins.h" #include "/usr/src/linux-2.6.35.3/arch/arm/plat-mxs/include/mach/pinctrl.h" #include "/usr/src/linux-2.6.35.3/arch/arm/mach-mx28/include/mach/mx28.h" #include<linux/fs.h> #include <linux/io.h> #include<asm/uaccess.h> #include<linux/miscdevice.h> #include<linux/irq.h> #include<linux/sched.h> #include<linux/interrupt.h> #include<linux/timer.h> #include <linux/input.h> #include <linux/time.h> #include <linux/list.h> #include <linux/irqreturn.h> #include <linux/errno.h> #define GPIO_1 MXS_PIN_TO_GPIO(PINID_LCD_D17) #define GPIO_2 MXS_PIN_TO_GPIO(PINID_LCD_D18) #define GPIO_3 MXS_PIN_TO_GPIO(PINID_SSP0_DATA4) #define GPIO_4 MXS_PIN_TO_GPIO(PINID_SSP0_DATA5) #define GPIO_5 MXS_PIN_TO_GPIO(PINID_SSP0_DATA6) struct input_dev *inputdev; struct imx28x_key_struct { int key_code; /* 按键能产生的键值*/ int gpio; /* 按键连接的GPIO*/ struct work_struct work; /* 按键的工作队列*/ }; struct imx28x_key_struct keys_list[] ={ {.key_code = KEY_A, .gpio = GPIO_1}, {.key_code = KEY_B, .gpio = GPIO_2}, {.key_code = KEY_C, .gpio = GPIO_3}, {.key_code = KEY_D, .gpio = GPIO_4}, {.key_code = KEY_E, .gpio = GPIO_5} }; static void imx28x_scankeypad(struct work_struct *_work){ struct imx28x_key_struct *key_tmp = container_of(_work, struct imx28x_key_struct, work); int gpio = key_tmp->gpio; int code= key_tmp->key_code; while(!gpio_get_value(gpio)){ mdelay(10); } input_report_key(inputdev, code, 0); input_sync(inputdev); } static irqreturn_t imx28x_key_intnerrupt(int irq, void *dev_id){ int i = (int)dev_id; int gpio = keys_list[i].gpio;/* 获取按键的GPIO*/ int code = keys_list[i].key_code; udelay(5); if (gpio_get_value(gpio)) { return IRQ_HANDLED; } input_report_key(inputdev, code, 1);/* 先报告键按下事件*/ input_sync(inputdev); schedule_work(&(keys_list[i].work));/* 提交工作队列,实现中断的下半部处理*/ printk("key down \n"); //return IRQ_RETVAL(IRQ_HANDLED); return IRQ_HANDLED; } static void __exit iMX28x_key_exit(void){ int i = 0; int irq_no; for (i = 0; i < sizeof(keys_list)/sizeof(keys_list[0]); i++) { irq_no = gpio_to_irq(keys_list[i].gpio);/* 为每个按键释放GPIO*/ free_irq(irq_no, (void *)i); input_unregister_device(inputdev); printk("EasyARM-i.MX28x key driver remove \n"); } } static int __devinit iMX28x_key_init(void) { int i = 0, ret = 0; int irq_no = 0; int code, gpio; inputdev = input_allocate_device(); /* 为输入设备驱动对象申请内存空间*/ if (!inputdev) { return -ENOMEM; } inputdev->name = "EasyARM-i.MX28x_key"; set_bit(EV_KEY, inputdev->evbit); /* 设置输入设备支持按键事件*/ for (i = 0; i < sizeof(keys_list)/sizeof(keys_list[0]); i++) { code = keys_list[i].key_code; gpio = keys_list[i].gpio; INIT_WORK(&(keys_list[i].work), imx28x_scankeypad); set_bit(code, inputdev->keybit); gpio_free(gpio); ret = gpio_request(gpio, "key_gpio"); if (ret) { printk("request gpio failed %d \n", gpio); return -EBUSY; } gpio_direction_input(gpio); irq_no = gpio_to_irq(gpio); set_irq_type(gpio, IRQF_TRIGGER_FALLING); ret = request_irq(irq_no, imx28x_key_intnerrupt, IRQF_DISABLED, "imx28x_key", (void *)i); if(ret){ printk("request irq faile %d!\n", irq_no); return -EBUSY; } } input_register_device(inputdev);/* 注册设备驱动*/ printk("EasyARM-i.MX28x key driver up \n"); return 0; } module_init(iMX28x_key_init); module_exit(iMX28x_key_exit); MODULE_AUTHOR("EasyARM28xx By jiaochengliang"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("gpio button interrupt module");
编写Makefile
PWD:=$(shell pwd) obj-m:=imx_key.o module-objs := imx_key.o KERNEL_SRC = /usr/src/linux-2.6.35.3/ KDIR:=$(KERNEL_SRC) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf *.ko *.order *.symvers *.cmd *.o *.mod.c *.tmp_versions .*.cmd .tmp_versions
make一下,生成的 .ko文件挂载到板子上
insmod imx_key.ko
测试下,输出
这里的问题:1、按键去抖用延时
2、处理事件在中断中
3、就是在卸载模块后,个别按键还在作用中
文章来源: imx287按键处理第一篇:原始版本