天天看點

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

還是按照s5pv210的學習順序來,我們首先解決按鍵問題。tq335x有六個使用者按鍵,分别是上、下、左、右、enter和esc。開始我想到的是跟學習s5pv210時一樣,編寫輸入子系統驅動解決按鍵問題,但是浏覽driver/input/keyboard目錄時意外的發現了gpio-keys.c,大體上看下該驅動程式,其功能是實作了通用的gpio按鍵。再去看了下dts,發現dts中有對gpio-keys的引用,于是猜到,新的核心不需要自己編寫輸入子系統驅動,可以通過配置dts直接解決按鍵問題。本人最終通過實驗證明了這個猜想,下面是實驗筆記及本人的一些了解。

(1)确定gpio管腳

通過檢視tq335x的原理圖可以看到,tq335x的6個按鍵分别接在gpio1的20~25管腳上,原理圖如下:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

(2)檢視原有的dts配置

進行dts檔案修改之前可以閱讀下核心相關文檔,在documentation/devicetree/目錄下有很多關于devicetree的記載,其實,這些第一手的資料才是最具參考價值的資料。我還沒來得及系統的閱讀這些文檔,急于實作功能,僅閱讀了gpio-key和pinmux相關的部分就開始了修改工作,這是浮躁的表現,大家不要養成這種惡習啊!

通過仔細閱讀原dts檔案可以發現am335x-evm開發闆上有個gpio矩陣鍵盤和gpio的音量+、音量-鍵,且矩陣鍵盤和音量鍵與tq335x的按鍵管腳有沖突,是以,删除這兩組配置并重新添加适應tq335x按鍵的配置。修改後的dts代碼片段如下:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

gpio_keypad: gpio_keyad@0{  

    compatible = "gpio-keys";  

    #address-cells = <1>;  

    #size-cells = <0>;  

    autorepeat;  

    switch@1 {  

        label = "up";  

        linux,code = <103>;  

        gpios = <&gpio1 20 gpio_active_low>;  

        gpio-key,wakeup;  

    };  

    switch@2 {  

        label = "down";  

        linux,code = <108>;  

        gpios = <&gpio1 21 gpio_active_low>;  

    switch@3 {  

        label = "left";  

        linux,code = <105>;  

        gpios = <&gpio1 22 gpio_active_low>;  

    switch@4 {  

        label = "right";  

        linux,code = <106>;  

        gpios = <&gpio1 23 gpio_active_low>;  

    switch@5 {  

        label = "enter";  

        linux,code = <28>;  

        gpios = <&gpio1 24 gpio_active_low>;  

    switch@6 {  

        label = "esc";  

        linux,code = <1>;  

        gpios = <&gpio1 25 gpio_active_low>;  

};  

其中,linux,code後面對應的是linux标準的鍵值,可以在linux系統中找到,路徑是:/usr/include/linux/input.h。

由于這六個按鍵使用的是gpio管腳,還需要通過後面的pinmux配置下gpio相關寄存器。同樣的,删除gpio矩陣鍵盤和音量鍵相關的配置,添加使用tq335x的配置,修改後的代碼片段如下:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

&am33xx_pinmux {  

pinctrl-names = "default";  

pinctrl-0 = <&clkout2_pin>;  

gpio_key_pins: gpio_keys_s0 {  

    pinctrl-single,pins = <  

        0x50 (pin_input_pullup | mux_mode7) /* gpmc_a3.gpio1_20 */  

        0x54 (pin_input_pullup | mux_mode7) /* gpmc_a5.gpio1_21 */  

        0x58 (pin_input_pullup | mux_mode7) /* gpmc_a6.gpio1_22 */  

        0x5c (pin_input_pullup | mux_mode7) /* gpmc_a7.gpio1_23 */  

        0x60 (pin_input_pullup | mux_mode7) /* gpmc_a8.gpio1_24 */  

        0x64 (pin_input_pullup | mux_mode7) /* gpmc_a9.gpio1_25 */  

    >;  

i2c0_pins: pinmux_i2c0_pins {  

        0x188 (pin_input_pullup | mux_mode0)    /* i2c0_sda.i2c0_sda */  

        0x18c (pin_input_pullup | mux_mode0)    /* i2c0_scl.i2c0_scl */  

需要注意的是,pinctrl-0後與矩陣鍵盤和音量鍵相關的配置項名稱也要删除,對于phandler,目前還沒有看懂什麼意思,這裡先讓按鍵功能正常,之後再去詳細的研究dts。學習dts的時候也會來寫筆記的。

(3)重新編譯dts

與之前編譯dts的方法一樣:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

make arch=arm cross_compile=arm-linux-gnueabi- tq335x.dtb  

(4)用新的dtb啟動核心

将新的tq335x.dtb拷貝到sd卡的boot目錄下(可以直接覆寫掉原來的)并給開發闆上電,同時按任意鍵使u-boot進入指令行模式,使用指令啟動核心:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

load mmc 0 ${fdtaddr} /boot/tq335x.dtb  

load mmc 0 ${loadaddr} /boot/zimage  

load mmc 0 ${rdaddr} /boot/ramdisk.img  

bootz ${loadaddr} ${rdaddr} ${fdtaddr}  

(5)測試按鍵

從終端上無法直接看到按鍵效果,不過可以同hexdump指令來測試按鍵功能是否正常,使用方法如下:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

hexdump /dev/input/event0  

由于gpio-keys驅動将按鍵事件映射到了/dev/input/event0裝置節點上,是以,對該裝置節點使用hexdump工具可以讀取到按鍵事件。執行上述指令後按鍵,可以從終端上看到輸出。我按照上、下、左、右、enter和esc的順序短按這六個鍵,可以看到如下log:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

@tq335x #hexdump /dev/input/event0   

0000000 4b7c 386d f9b4 0005 0001 0067 0001 0000  

0000010 4b7c 386d f9b4 0005 0000 0000 0000 0000  

0000020 4b7c 386d 80c4 0008 0001 0067 0000 0000  

0000030 4b7c 386d 80c4 0008 0000 0000 0000 0000  

0000040 4b7d 386d 09f8 0008 0001 006c 0001 0000  

0000050 4b7d 386d 09f8 0008 0000 0000 0000 0000  

0000060 4b7d 386d 1005 000a 0001 006c 0000 0000  

0000070 4b7d 386d 1005 000a 0000 0000 0000 0000  

0000080 4b7f 386d 1304 000d 0001 0069 0001 0000  

0000090 4b7f 386d 1304 000d 0000 0000 0000 0000  

00000a0 4b80 386d 48e6 0000 0001 0069 0000 0000  

00000b0 4b80 386d 48e6 0000 0000 0000 0000 0000  

00000c0 4b80 386d f340 000a 0001 006a 0001 0000  

00000d0 4b80 386d f340 000a 0000 0000 0000 0000  

00000e0 4b80 386d cd6f 000c 0001 006a 0000 0000  

00000f0 4b80 386d cd6f 000c 0000 0000 0000 0000  

0000100 4b81 386d a2d7 0007 0001 001c 0001 0000  

0000110 4b81 386d a2d7 0007 0000 0000 0000 0000  

0000120 4b81 386d b39d 0009 0001 001c 0000 0000  

0000130 4b81 386d b39d 0009 0000 0000 0000 0000  

0000140 4b82 386d 5aa3 0002 0001 0001 0001 0000  

0000150 4b82 386d 5aa3 0002 0000 0000 0000 0000  

0000160 4b82 386d 4bf3 0004 0001 0001 0000 0000  

0000170 4b82 386d 4bf3 0004 0000 0000 0000 0000  

通過hexdump工具看到的數字是16進制的。由于linux的input_event事件定義如下:

AM335x(TQ335x)學習筆記——GPIO按鍵驅動移植

struct input_event {  

    struct timeval time;  

    __u16 type;  

    __u16 code;  

    __s32 value;  

結合之前設定的linux,code分析可知,hexdump列印的各列資料含義如下:

第一列:行号

第2~5列:輸入事件時間戳,即結構體中的time。

第6列:輸入事件類型,即結構體中的type。

第7列:按鍵的鍵值,即結構體中的code。

第8列:按鍵的狀态,即結構體中的value,1表示按下,0表示松開。

細心的朋友會發現,按下并松開一個按鍵後能看到四行資料,這是由于每個input_event後會接一個linux同步事件,從上述log可以看到,同步事件的type,code,value都為0。

到這裡,就完成了tq335x的按鍵驅動移植。雖然過程很簡單,但已經體會到了dts的好處。對于一些通用的功能,可以不修改核心源碼、不重新編譯核心,僅修改dts配置就能實作所需的功能,如這裡的gpio按鍵功能。dts方式啟動核心有着巨大的優勢,必須弄清dts的編寫規則,以後會記錄dts相關的筆記的。

繼續閱讀