【嵌入式Linux驱动开发】二十一、Linux内核自带的KEY驱动探索

  君子应知进退方,时机不到且隐藏。
  妆未梳成未见客,势弱稍时敛锋芒。
  腹隐良谋待机至,东山再起斗志昂。
  遥想曹刘煮酒事,高明刘备扮愚郎。


一、 Linux 内核自带 KEY 驱动使能

  进入Linux内核源码根目录下,输入make menuconfig打开图形配置界面,按照以下路径打开KEY驱动配置项:

  • Device Drivers -> Input device support -> Keyboards (INPUT_KEYBOARD [=y]) -> GPIO Buttons

在这里插入图片描述

  • Device Drivers -> Input device support -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])

在这里插入图片描述

  选中以后就会在.config 文件中出现“ CONFIG_KEYBOARD_GPIO=y”这一行, Linux 内核就会根据这一行来将 KEY 驱动文件编译进 Linux 内核。,打开.config 文件,会找到“CONFIG_KEYBOARD_GPIO=y”这一行,如图所示:

在这里插入图片描述

  重新编译 Linux 内核,然后使用新编译出来的 zImage 镜像启动开发板。【替换方法,这里也不在赘述】

二、Linux内核自带KEY驱动分析

  Linux 内核自带的 KEY 驱动文件为drivers/input/keyboard/gpio_keys.c, gpio_keys.c 采用了 platform 驱动框架,在 KEY 驱动上使用了 input 子系统实现。在 gpio_keys.c 文件中找到如下所示内容:

static const struct of_device_id gpio_keys_of_match[] = {
	{ .compatible = "gpio-keys", },
	{ },
};

static struct platform_driver gpio_keys_device_driver = {
	probe = gpio_keys_probe,
	remove = gpio_keys_remove,
	driver = {
		name = "gpio-keys",
		pm = &gpio_keys_pm_ops,
		of_match_table = of_match_ptr(gpio_keys_of_match),
	}
};

static int __init gpio_keys_init(void)
{
	return platform_driver_register(&gpio_keys_device_driver);
}

static void __exit gpio_keys_exit(void)
{
	platform_driver_unregister(&gpio_keys_device_driver);
}

  根据上述代码,可以看到 KEY 驱动的匹配表,compatible 内容为“gpio-keys”,因此设备树中的 KEY 设备节点的 compatible 属性值也要为“ gpio-keys”。

   Linux 内核自带的 gpio_keys.c 驱动文件思路和我们前面编写的 keyinput.c 驱动文件基本一致。都是申请和初始化 input_dev,设置事件,向 Linux 内核注册 input_dev。最终在按键中断服务函数或者消抖定时器中断服务函数中上报事件和按键值。

三、设备树节点编写

  文档 Documentation/devicetree/bindings/input/gpio-keys.txt 详细的讲解了 Linux 自带驱动对应的设备树节点该如何编写,我们在编写设备节点的时候要注意以下几点:

  • ①、节点名字为“ gpio-keys”。
  • ②、 gpio-keys 节点的 compatible 属性值一定要设置为“ gpio-keys”。
  • ③、所有的 KEY 都是 gpio-keys 的子节点,每个子节点可以用如下属性描述自己:
    • gpios: KEY 所连接的 GPIO 信息。
    • interrupts: KEY 所使用 GPIO 中断信息,不是必须的,可以不写。
    • label: KEY 名字
    • linux,code: KEY 要模拟的按键
  • ④、如果按键要支持连按的话要加入 autorepeat。

  根据上面的要求创建对应的设备节点,设备节点内容如下所示:

gpio-keys {
	compatible = "gpio-keys";
	autorepeat;
	
	key0 {
		label = "GPIO Key Enter";
		linux,code = <KEY_ENTER>;
		gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
	};
};

  这里我们将开发板上的 KEY 按键设置为“ EKY_ENTER”这个按键,也就是回车键,效果和键盘上的回车键一样。后面学习 LCD 驱动的时候需要用到此按键,因为 Linux 内核设计的 10 分钟以后 LCD关闭,也就是黑屏,就跟我们用电脑或者手机一样,一定时间以后关闭屏幕。这里将开发板上的 KEY 按键注册为回车键,当 LCD 黑屏以后直接按一下 KEY 按键即可唤醒屏幕,就跟当电脑熄屏以后按下回车键即可重新打开屏幕一样。

  最后设置 KEY 所使用的 IO 为 GPIO5_IO1,一定要检查一下设备树看看此 GPIO 有没有被用到其他外设上,如果有的话要删除掉相关代码!

  重新编译设备树,然后用新编译出来的 dtb 启动 Linux 系统,系统启动以后查看/dev/input 目录,看看多了哪些文件。

在这里插入图片描述

多了event3 这个文件,该文件就是 KEY 对应的设备文件。,使用hexdump 命令来查看/dev/input/event1 文件,输入如下命令:

hexdump /dev/input/event3

然后按下开发板上的按键,终端输出下图所示内容:
在这里插入图片描述
如果按下 KEY 按键以后会在终端上输出上图所示的信息那么就表示 Linux 内核的按键驱动工作正常。

如果发现按下 KEY 按键以后没有反应,那么请检查一下三方面:

  • ①、是否使能 Linux 内核 KEY 驱动。
  • ②、设备树中 gpio-keys 节点是否创建成功。
  • ③、在设备树中是否有其他外设也使用了 KEY 按键对应的 GPIO,但是我们并没有删除掉这些外设信息。检查 Linux 启动 log 信息,看看是否有类似下面这条信息:gpio-keys gpio_keys: Failed to request GPIO 1, error -16上述信息表示 GPIO 1 申请失败,失败的原因就是有其他的外设正在使用此 GPIO。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章