GPIO使用總結


一、GPIO重要概念

要想操作GPIO引腳,需要先把所用引腳配置成GPIO功能,這個通過pinctrl子系統來實現。然后可以根據設置的引腳的方向來讀取引腳的值和設置輸出值。GPIO子系統存在之前,我們驅動需要在代碼中配置寄存器來使用GPIO引腳。再BSP工程師實現好GPIO子系統后,我們就可以在設備樹中指定GPIO引腳,在驅動中使用GPIO子系統的標准函數來獲取GPIO、設置GPIO方向、讀取/設置GPIO的值。這樣的驅動代碼是於單板無關的。

 

二、GPIO內核相關文檔

Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt
Documentation\gpio\gpio.txt
Documentation\devicetree\bindings\gpio\gpio.txt

 

三、GPIO設備樹配置

1. BSP工程師實現的gpio驅動,驅動工程師直接在設備樹中配置使用。

//client節點
device {
    led-gpios = <組, 哪個幾個,flag>; //"組"是必須要有的元素,為gpio控制器的描述,這里除了組之外還有幾個域是由組中的#gpio-cells的值決定的。
};

//service端,設備樹中對一個gpio控制器的表示:
gpio1 {
    ......
    gpio-controller;
    #gpio-cells = <2>; //表示client使用gpio1這一組中的某個引腳時,除了組之外還需要使用2個整數來表示。
};

2. 舉個例子:

foo_device {
    compatible = "acme,foo";
    ......
    led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH> /*red*/ //一般這里可能為&gpioX
        <&gpio 16 GPIO_ACTIVE_HIGH> /*green*/
        <&gpio 17 GPIO_ACTIVE_HIGH>; /*blue*/
    
    power-gpios = <&gpio, 1 GPIO_ACTIVE_LOW>; //注意這里使用了avtive_low屬性了
};

驅動代碼中:

gpiod_get_index(dev, "led", 0, GOIOD_OUT_HIGH); //取出設備樹中名為led的gpio中的第0個引腳,也就是red。
gpiod_get_index(dev, "led", 1, GOIOD_OUT_HIGH); //取出第1個

若在設備樹中只定義了一個引腳,就可以使用:

gpiod_get(dev, "power", GPIO_OUTPUT_HIGH); //把這個設備下名為power的那個引腳給取出來。

 

三、在驅動中使用GPIO

1.GPIO子系統有兩套接口

(1) 一是基於描述符(descriptor-based)的,相關api函數都是以"gpiod_"為前綴,它使用gpio_desc結構來表示一個引腳。
(2) 另一種是老(legency)的,相關api函數都是以"gpio_"為前綴,它使用一個整數來表示一個引腳。

要操作一個引腳,首先要get引腳,然后設置方向,然后讀取、寫值。

2.列舉操作GPIO常使用的函數

//1.獲取GPIO
gpiod_get  //legency為gpio_request
gpiod_get_index
gpiod_get_array //legency為gpio_request_array
devm_gpiod_get
devm_gpiod_get_index
devm_gpiod_get_array

//2.設置方向
gpiod_direction_input  //legency為gpio_direction_input
gpiod_direction_output //legency為gpio_direction_input

//3.讀值、寫值
gpiod_get_value //legency為gpio_get_value
gpiod_set_value //legency為gpio_set_value

//4.釋放GPIO
gpio_free //gpio_free
gpiod_put //gpio_free_array
gpiod_put_array
devm_gpiod_put
devm_gpiod_put_array

  前綴為"devm_"的含義是設備資源管理,這是一種自動釋放資源的機制。它的思想是“資源是屬於設備的,設備不存在時資源就可以自動釋放”。在Linux驅動開發過程中,先申請了GPIO,再申請內存,如果內存申請失敗,那么在返回之前就需要先釋放GPIO資源。如果使用的是devm相關函數,在內存申請失敗時可以直接返回,設備的銷毀函數會自動地釋放已經申請了的GPIO資源。建議使用devm相關函數操作GPIO。

3.如何通過GPIO號來使用GPIO

比如要通過gpio號來操作原理圖上的GPIO5_14這個gpio引腳,那么得先知道這個gpio引腳的number是多少。那么得先找到gpio5組的基gpio number是多少。

/sys/class/gpio/# ls
export gpio30 gpiochip0 gpiochip32 gpiochip64 gpiochip96 gpiochip128 gpiochip504 unexport //gpiochip96 這一組gpio的基gpio號是96
/sys/class/gpio/gpiochip128# ls
base device label ngpio power subsystem uevent
/sys/class/gpio/gpiochip128# cat label //可以看出設備樹節點名為gpio@20ac000,20ac000就是這一組gpio寄存器的基地址,可通過它查看每一組gpio的基gpio號
20ac000.gpio
/sys/class/gpio/gpiochip128# cat base //表示這一組gpio的基gpio號為128
128
/sys/class/gpio/gpiochip128# cat ngpio //表示這一組gpio的個數
32

在dtsi文件中檢索20ac000就可以看到如下設備樹配置,所以知道gpio5這一組gpio的基gpio號是128

gpio5: gpio@20ac000 {
    compatible = "fsl,im6ul-gpio", "fsl,imx35-gpio";
    reg = <0x020ac000 0x4000>;
    interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <0x2>;
    interrupt-controller;
    #interrupt-cells = <0x2>;
};

那么GPIO5_14,其gpio號就是128+14=142,然后可以將這個gpio給導出來,設置其方向,配置其值,進行驗證。

/sys/class/gpio# echo 142 > export
/sys/class/gpio# ls
export unexport gpio142  ... //此時可以看到多了一個gpio142目錄
/sys/class/gpio/gpio142# ls
active_low direction power uevent device edge subsystem value //此時可以cat active_low 看是否具有active_low屬性
/sys/class/gpio/gpio142# echo in > direction //設置為輸入引腳
/sys/class/gpio/gpio142# cat value //讀取其值
1
/sys/class/gpio# echo 142 > unexport //取消映射

如果某個引腳已經被使用了,再次export就會報錯:“resource busy”。算出引腳號后就可以在驅動中使用legency函數來通過gpio號來操作gpio引腳了。

注意: Qcom平台,如果內核級驅動程序通過of_get_named_gpio()函數或類似函數獲取,請求並使用該GPIO,則無法將該GPIO導出以進行sysfs控制。


五、active_low屬性

  注意,設置的邏輯電平並不一定等於物理電平,因為有active_low屬性,若在獲取GPIO的時候指定了active_low屬性,那么設置為1就是低電平,設置為0才是高電平。但是也有一些函數直接忽略active_low屬性,整理如下:

unction(example)               active-low屬性        物理電平
gpiod_set_raw_value(desc, 0)    don't care             0
gpiod_set_raw_value(desc, 1)    don't care             1
gpiod_set_value(desc, 0)        是                     1
gpiod_set_value(desc, 0)        否                     0
gpiod_set_value(desc, 1)        是                     0
gpiod_set_value(desc, 1)        否                     1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM