君子應知進退方,時機不到且隱藏。
妝未梳成未見客,勢弱稍時斂鋒芒。
腹隱良謀待機至,東山再起鬥志昂。
遙想曹劉煮酒事,高明劉備扮愚郎。
一、 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。