coding无法使用浏览器打开,必须用git工具下载:
git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
参考资料:
Linux-4.9.88/arch/arm/boot/dts/100ask_imx6ull-14x14.dts
Linux-5.4/arch/arm/boot/dts/stm32mp15xx-100ask.dtsi
linux-4.9.88/arch/arm/boot/dts/100ask_imx6ull_qemu.dts
属性:
compatible = "gpio-keys";
autorepeat
: 表示自动重复,按下按键不松开,驱动会自动重复上报按键值gpios
:使用哪个GPIOinterrupts
:对应的中断linux,code
:对应的按键值gpios
和interrupts
至少要保留一个,不能都省略debounce-interval
: 消除抖动的间隔,单位:ms,默认是5msgpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
user1 {
label = "User1 Button";
gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
gpio-key,wakeup;
linux,code = <KEY_1>;
};
user2 {
label = "User2 Button";
gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
gpio-key,wakeup;
linux,code = <KEY_2>;
};
};
joystick {
compatible = "gpio-keys";
#size-cells = <0>;
button-0 {
label = "usr_button0";
linux,code = <KEY_A>;
interrupt-parent = <&gpiog>;
interrupts = <3 IRQ_TYPE_EDGE_RISING>;
};
button-1 {
label = "usr_button1";
linux,code = <KEY_ENTER>;
interrupt-parent = <&gpiog>;
interrupts = <2 IRQ_TYPE_EDGE_RISING>;
};
};
gpio-keys@0 {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>;
status = "okay";
Key0{
label = "Key 0";
gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_1>;
};
};
gpio-keys@1 {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_key1>;
status = "okay";
Key0{
label = "Key 1";
gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_2>;
};
};
gpio_keys_gpio_isr
:设备树中的用gpios
来描述用到的引脚gpio_keys_irq_isr
:设备树中的用interrupts
来描述用到的引脚理想状况是:按下、松开按键,各产生一次中断,也只产生一次中断。 但是对于机械开关,它的金属弹片会反复震动。GPIO电平会反复变化,最后才稳定。一般是几十毫秒才会稳定。 如果不处理抖动的话,用户只操作一次按键,会发生多次中断,驱动程序可能会上报多个数据。
怎么处理按键抖动?
显然第1种方法太耗时,违背“中断要尽快处理”的原则,你的系统会很卡。
怎么使用定时器?看下图:
核心在于:在GPIO中断中并不立刻记录按键值,而是修改定时器超时时间,10ms后再处理。 如果10ms内又发生了GPIO中断,那就认为是抖动,这时再次修改超时时间为10ms。 只有10ms之内再无GPIO中断发生,那么定时器的函数才会被调用。 在定时器函数中上报按键值。
有个变量key_pressed,用来表示当前按键状态:初始值是false,表示按键没有被按下。
input_event(input, EV_KEY, button->code, 1); input_sync(input);
input_event(input, EV_KEY, button->code, 0); input_sync(input);
IMX6ULL、STM32MP157的出厂系统都已经配置的GPIO按键。 可以执行以下命令确认设备节点:
cat /proc/bus/input/devices
然后执行hexdump /dev/input/event?
(?表示某个数值),并且操作按键来观察输出信息。
也可以在QEMU上做实验:原理图如下:
在Ubuntu中执行:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull-qemu/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin
QEMU的内核里已经配置了GPIO按键的设备树,只需要编译出gpio_keys驱动程序即可。
配置内核:执行make menuconfig
-> Device Drivers
-> Input device support
-> Generic input layer
-> Keyboards
<M> GPIO Buttons
book@100ask:~/100ask_imx6ull-qemu$ cd linux-4.9.88
book@100ask:~/100ask_imx6ull-qemu/linux-4.9.88$ make modules
成功的话,可以得到:
drivers/input/keyboard/gpio_keys.ko
复制到如下目录:
$ cp drivers/input/keyboard/gpio_keys.ko ~/nfs_rootfs/
在Ubuntu中执行:
$ cd ubuntu-18.04_imx6ul_qemu_system
$ ./qemu-imx6ull-gui.sh
在QEMU中执行:
$ mount -t nfs -o nolock,vers=3 10.0.2.2:/home/book/nfs_rootfs /mnt
$ insmod /mnt/gpio_keys.ko
$ cat /proc/bus/input/devices // 确认设备节点
$ hexdump /dev/input/event3
在QEMU的GUI界面操作:
x6ull-gui.sh
#### 4.5 挂载NFS、实验
在QEMU中执行:
```shell
$ mount -t nfs -o nolock,vers=3 10.0.2.2:/home/book/nfs_rootfs /mnt
$ insmod /mnt/gpio_keys.ko
$ cat /proc/bus/input/devices // 确认设备节点
$ hexdump /dev/input/event3
在QEMU的GUI界面操作: