我在看资料的基础上加以整改,把程序记录下来以便于日后查看。
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、就是在卸载模块后,个别按键还在作用中