Linux下控制GPIO的三種方法

1. 應用空間控制gpio

1.1簡介

        在/sys/class/gpio/下有個export文件,向export文件寫入要操作的GPIO號,使得該GPIO的操作接口從內核空間暴露到用戶空間,GPIO的操作接口包括direction和value等,direction控制GPIO輸入或者輸出模式,而value可控制GPIO的狀態或者讀取狀態。

 
 
/sys/class/gpio/目錄下各個文件說明:
 
/sys/class/gpio/export文件用於通知系統需要導出控制的GPIO引腳編號;
 
/sys/class/gpio/unexport 用於通知系統取消導出;
 
/sys/class/gpio/gpioX/direction文件,可以寫入in(設置輸入方向)或out(設置輸出方向);
 
/sys/class/gpio/gpioX/value文件是可以讀寫GPIO狀態;
 
/sys/class/gpio/gpiochipX目錄保存系統中GPIO寄存器的信息,包括每個寄存器控制引腳的起始編號,寄存器名稱,引腳總數;其中X表示具體的引腳編號。
 
 

1.2操作gpio

        比如我要操作GPIO8_A6作爲高電平輸出有效, 那麼有以下三個操作:

1. 2.1 換算對應的gpio number

        可以通過/sys/kernel/debug/gpio查詢信息:

 
 
root@rk3288:/sys/kernel/debug # cat gpio
 
//snip
 
GPIOs 184-215, platform/ff770000.pinctrl, gpio6:
 
gpio-193 (? ) in hi
 
gpio-194 (? ) in hi
 
 
 
GPIOs 216-247, platform/ff770000.pinctrl, gpio7:
 
gpio-218 (enable ) out hi
 
gpio-219 (lcd_en ) in hi
 
gpio-220 (lcd_cs ) in hi
 
gpio-221 (gslX680 wake pin ) out hi
 
gpio-222 (gslX680 irq pin ) out lo
 
gpio-223 (headset_gpio ) in hi
 
gpio-233 (? ) in hi
 
gpio-234 (? ) in hi
 
GPIOs 248-279, platform/ff770000.pinctrl, gpio8:
 
 
 
GPIOs 280-311, platform/ff770000.pinctrl, gpio15:
 
 

        可以看到gpio8是以nubmer爲248開始, 那麼GPIO8_A6就是 248 + 6 = 254,接下來就可以導出gpio了。

 
 
root@rk3288:/sys/class/gpio # echo 254 > export
 
root@rk3288:/sys/class/gpio # ls
 
export
 
gpio254
 
 

1.2.2 設置成輸出

 
 
root@rk3288:/sys/class/gpio/gpio254 # echo out > direction
 
root@rk3288:/sys/class/gpio/gpio254 # cat direction
 
out
 
 

1.2.3 輸出高電平

 
 
root@rk3288:/sys/class/gpio/gpio254 # echo 1 > value
 
root@rk3288:/sys/class/gpio/gpio254 # cat value
 
 

1.3 總結

        這種方式一般不採用,爲了gpio使用的安全性,一般是不將gpio的使用權暴露給應用層的,即sys/class/下沒有gpio節點。

2. 內核空間控制gpio

        在內核空間控制gpio有兩種方法,第一種是通過調用gpiolib的接口來控制gpio;第二種是通過ioremap來控制gpio。

2.1 gpiolib控制gpio

2.1.1 gpiolib簡介

        Linux Kernel 中對 GPIO 資源進行了抽象,抽象出一個叫做 Gpiolib 的東西。

        中間層是 Gpiolib,用於管理系統中的 GPIO。Gpiolib 彙總了 GPIO 的通用操作,根據 GPIO 的特性,Gpiolib 對上(其他 Drivers)提供的一套統一通用的操作 GPIO 的軟件接口,屏蔽了不同芯片的具體實現。對下,Gpiolib 提供了針對不同芯片操作的一套 framework,針對不同芯片,只需要實現 Specific Chip Driver ,然後使用 Gpiolib 提供的註冊函數,將其掛接到 Gpiolib 上,這樣就完成了這一套東西。

2.1.2 Gpiolib 爲其他驅動提供的 APIs

 
 
int gpio_request(unsigned gpio, const char *label);
 
/*向內核申請 gpio,要使用 GPIO 首先應該向內核進行申請,返回 0,代表申請成功,
 
*可以進行後續操作*/
 
 
 
void gpio_free(unsigned gpio);
 
/*對應 gpio_request,是使用完gpio以後把gpio釋放掉*/
 
 
 
int gpio_direction_input(unsigned gpio);
 
/*設置 GPIO 爲輸入*/
 
 
 
int gpio_direction_output(unsigned gpio, int value);
 
/*設置 GPIO 爲輸出*/
 
 
 
int gpio_get_value(unsigned gpio);
 
/*讀取 GPIO 的值*/
 
 
 
int gpio_set_value(unsigned gpio);
 
/*設置 GPIO 的值*/
 
 

2.1.3 操作gpio

        功能和1.2一樣。

 
 
#define GPIO8_A6 254
 
ret = gpio_request(GPIO8_A6 , "gpio8_a6");
 
if (!ret) {
 
printk("request for gpio8_a6 failed:%d\n", ret);
 
return 0;
 
}
 
gpio_direction_output(GPIO8_A6 ,1);//設置GPIO8_A6爲輸出功能且輸出高電平
 
 

2.2 ioremap控制gpio

        這種方法會降低程序的可讀性,不建議使用。

        linux內核空間訪問的地址爲虛擬地址(3~4GB),故在內核空間操作某個寄存器時,需先通過ioremap函數將物理地址映射成虛擬地址。

        用ioremap() 獲取寄存器的地址:

 
 
unsigned int __iomem *base_addr1; //__iomem可選擇,告訴你爲虛擬地址
 
#define GPIO8_REGBASE (0x20A0000)
 
#define GPIO8_A6 (*(volatile unsigned int *)(base_addr1 + 6)) //指針unsigned int爲4字節,指針加1,字節加4
 
base_addr1 = ioremap(GPIO8_REGBASE, 0x14)
 
 

        通過 readl() 或者 writel() 函數直接操作映射後的地址:

 
 
GPIO8_A6 |= (1<<8);
 
 
 
int temp;
 
temp = readl(GPIO8_A6);
 
temp |= (1<<8);
 
writel(temp, GPIO8_A6);
 
 

        使用完後,取消映射:

iounmap(base_addr1);
 

3. 查看GPIO全部信息

 
 
cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins
 
 
 
Pinmux settings per pin
 
Format: pin (name): mux_owner gpio_owner hog?
 
pin 0 (gpio0-0): wireless-wlan (GPIO UNCLAIMED) function wireless-wlan group wifi-wake-host
 
pin 1 (gpio0-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 2 (gpio0-2): (MUX UNCLAIMED) gpio0:2
 
pin 3 (gpio0-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 4 (gpio0-4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 5 (gpio0-5): (MUX UNCLAIMED) gpio0:5
 
pin 6 (gpio0-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 7 (gpio0-7): (MUX UNCLAIMED) gpio0:7
 
pin 8 (gpio0-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 9 (gpio0-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 10 (gpio0-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
pin 11 (gpio0-11): ff050000.i2c (GPIO UNCLAIMED) function i2c1 group i2c1-xfer
 
pin 12 (gpio0-12): ff050000.i2c (GPIO UNCLAIMED) function i2c1 group i2c1-xfer
 
pin 13 (gpio0-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
 
 

        根據對比實驗,“MUX UNCLAIMED” 的意思好像是該複用引腳未被配置,僅個人小實驗,不具備絕對準確性。

 

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章