Linux内核中按键驱动分为:较为复杂的【矩阵键盘keyboard Matrix】和简单的【按键驱动】。
【Matrix矩阵键盘】一般适用于多行多列多按键的情况,源码文件为:drivers/input/keyboard/matrix_keypad.c
【GPIO按键驱动】一般适用于少量按键,一个GPIO口对应一个按键的情况,源码文件为:driers/input/keyboard/gpio_keys.c
本次在imx6ul中实现矩阵键盘功能:Linux内核版本为4.1.15,cpu为imx6ul。
以下对矩阵键盘原理、源码、调试步骤等逐一进行分析,简单的单按键就暂时不写了。
一、功能实现(代码)
具体开发流程如下:
1.1 添加编译选项
内核源码根目录下执行make menuconfig,选中如下几个选项来添加Matrix相关编译选项:
Device Drivers --->
Input device support --->
<*> Event debugging (选中)
[*] Keyboards --->
<*> GPIO Buttons(选中)
<*> GPIO driven matrix keypad support(选中)
<*> IMX keypad support(选中)
选中后,save保存,exit退出,使用【make zImage】编译生成新的zImage,路径为:【arch/arm/boot/】
lsy@ubuntu18:~/linux-4.1.15$ ls arch/arm/boot/
bootp compressed dts Image install.sh Makefile zImage
将新的zImage拷贝并烧写到板卡中,重启板卡,然后正式开始进行开发工作。
备注:如果觉得编译整个zImage麻烦,也可以使用【make modules】单独编译模块,将drivers/input/keyboard/matrix_keypad.c文件编译生成对应的.ko模块,然后使用insmod或者modprob加载到板卡内核中来进行调试也行。
1.2 添加设备树节点
此处以【8行*3列】矩阵键盘为例
一定注意:Linux内核中定义矩阵键盘必须且只能为:【行GPIO输入,列GPIO输出】!!!不能搞错!!!
1.2.1 添加kpp节点
备注:本示例中的linux,keymap按键映射以较为容易理解、且直观的方式实现,内核驱动源码中的示例以及网上很多demo中写法都是形如0x02010058的写法,这样不太直观,不好理解,后面会对这种写法含义做出说明,两种写法都是可以的。
/*lsy*/
&kpp {
compatible = "gpio-matrix-keypad";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_key>;
debounce-delay-ms = <20>; /*防反跳延时,即:去抖延时*/
col-scan-delay-us = <400>; /*列扫描延时*/
/*8行*/
row-gpios = <&gpio2 11 GPIO_ACTIVE_LOW
&gpio2 12 GPIO_ACTIVE_LOW
&gpio2 10 GPIO_ACTIVE_LOW
&gpio2 8 GPIO_ACTIVE_LOW
&gpio2 9 GPIO_ACTIVE_LOW
&gpio2 13 GPIO_ACTIVE_LOW
&gpio2 14 GPIO_ACTIVE_LOW
&gpio2 15 GPIO_ACTIVE_LOW
>;
/*3列*/
col-gpios = <&gpio2 16 GPIO_ACTIVE_LOW
&gpio2 17 GPIO_ACTIVE_LOW
&gpio2 19 GPIO_ACTIVE_LOW
>;
/* 举例释义:MATRIX_KEY(0x2, 0x1, KEY_X)表示将【第2行1列的按键】映射为【KEY_X】 */
linux,keymap = <
/*row0*/
MATRIX_KEY(0x0, 0x0, KEY_LEFT)
MATRIX_KEY(0x0, 0x1, KEY_DOWN)
/* row1 */
MATRIX_KEY(0x1, 0x0, KEY_UP)
MATRIX_KEY(0x1, 0x1, KEY_RIGHT)
/* row2 */
MATRIX_KEY(0x2, 0x0, KEY_M)
MATRIX_KEY(0x2, 0x1, KEY_X)
MATRIX_KEY(0x2, 0x2, KEY_ENTER)
/*row3*/
MATRIX_KEY(0x3, 0x0, KEY_N)
MATRIX_KEY(0x3, 0x1, KEY_O)
MATRIX_KEY(0x3, 0x2, KEY_I)
/*row4*/
MATRIX_KEY(0x4, 0x0, KEY_7)
MATRIX_KEY(0x4, 0x1, KEY_8)
MATRIX_KEY(0x4, 0x2, KEY_9)
/*row5*/
MATRIX_KEY(0x5, 0x0, KEY_4)
MATRIX_KEY(0x5, 0x1, KEY_5)
MATRIX_KEY(0x5, 0x2, KEY_6)
/*row6*/
MATRIX_KEY(0x6, 0x0, KEY_1)
MATRIX_KEY(0x6, 0x1, KEY_2)
MATRIX_KEY(0x6, 0x2, KEY_3)
/*row7*/
MATRIX_KEY(0x7, 0x0, KEY_MINUS)
MATRIX_KEY(0x7, 0x1, KEY_0)
MATRIX_KEY(0x7, 0x2, KEY_DOT)
>;
gpio-activelow;
status = "okay";
};
1.2.2 在iomuxc中添加pinctrl_复用节点
&iomuxc {
......
/*lsy*/
pinctrl_key: kppgrp{
fsl,pins = <
/* row 8行 */
MX6UL_PAD_ENET2_TX_DATA0__GPIO2_IO11 0xb0b1
MX6UL_PAD_ENET2_TX_DATA1__GPIO2_IO12 0xb0b1
MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10 0xb0b1
MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08 0xb0b1
MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09 0xb0b1
MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13 0xb0b1
MX6UL_PAD_ENET2_TX_CLK__GPIO2_IO14 0xb0b1
MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0xb0b1
/* col 3列 */
MX6UL_PAD_SD1_CMD__GPIO2_IO16 0x70a1
MX6UL_PAD_SD1_CLK__GPIO2_IO17 0x70a1
MX6UL_PAD_SD1_DATA1__GPIO2_IO19 0x70a1
>;
};
.......