2019-04-24
關鍵字: rk平台控制GPIO功能、rk串口控制引腳電平
本篇文章介紹了如何通過串口來控制 RK3128、RK3288 平台的 GPIO 。
我們可以很便捷地通過串口命令來控制 RK 的 CPU 芯片的 GPIO。
首先通過串口進入到以下目錄,注意要提升我們的權限到 root
cd /sys/class/gpio
通常在這個目錄至少能看到 export 和 unexport 兩個文件,筆者的開發板這個目錄有如下文件
shell@rk312x:/sys/class/gpio # ll --w------- root root 4096 2016-01-21 16:50 export lrwxrwxrwx root root 2016-01-21 16:50 gpiochip0 -> .. lrwxrwxrwx root root 2016-01-21 16:50 gpiochip128 -> lrwxrwxrwx root root 2016-01-21 16:50 gpiochip32 -> . lrwxrwxrwx root root 2016-01-21 16:50 gpiochip64 -> . lrwxrwxrwx root root 2016-01-21 16:50 gpiochip96 -> . --w------- root root 4096 2016-01-21 16:50 unexport
然后映射我們需要操作的 GPIO 端口號出來
echo 33 > export
不知道對應的端口號是多少? 看這里
執行完后,可以看到能多出一個目錄出來
--w------- root root 4096 2016-01-21 17:00 export lrwxrwxrwx root root 2016-01-21 17:00 gpio33 -> ../../devices/20008000.pinctrl/gpio/gpio33 ...
如果您發現您在執行完命令后並沒有如期多出一個映射目錄出來,請戳這里
然后我們就可以通過操作這個目錄里面的文件來達到控制 GPIO 功能的目的了。
比如我們可以查詢一下這個 GPIO 口當前的方向以及電平值
shell@rk312x:/sys/class/gpio # cat gpio33/direction in shell@rk312x:/sys/class/gpio # cat gpio33/value 0
如果要更改電平,可以有如下操作
shell@rk312x:/sys/class/gpio # echo out > gpio33/direction shell@rk312x:/sys/class/gpio # echo 1 > gpio33/value
這一套流程組合起來即為
echo xx > /sys/class/gpio/export echo out > /sys/class/gpio/gpioxx/direction echo 1 > /sys/class/gpio/gpioxx/value
各個 GPIO 的端口值是通過查表和計算得出來的。
我們知道 GPIO 通常分為好幾組,如 GPIO1, GPIO2, GPIO3 ...
那我們的計算公式即為
num = 32 * GPIO_X + PORT
GPIO_X 即為 GPIO 的組號,其對應關系如下
GPIO0 --> 0 GPIO1 --> 1 GPIO2 --> 2 ...
而 PORT 的值如下表所示
#define GPIO_A0 0 #define GPIO_A1 1 #define GPIO_A2 2 #define GPIO_A3 3 #define GPIO_A4 4 #define GPIO_A5 5 #define GPIO_A6 6 #define GPIO_A7 7 #define GPIO_B0 8 #define GPIO_B1 9 #define GPIO_B2 10 #define GPIO_B3 11 #define GPIO_B4 12 #define GPIO_B5 13 #define GPIO_B6 14 #define GPIO_B7 15 #define GPIO_C0 16 #define GPIO_C1 17 #define GPIO_C2 18 #define GPIO_C3 19 #define GPIO_C4 20 #define GPIO_C5 21 #define GPIO_C6 22 #define GPIO_C7 23 #define GPIO_D0 24 #define GPIO_D1 25 #define GPIO_D2 26 #define GPIO_D3 27 #define GPIO_D4 28 #define GPIO_D5 29 #define GPIO_D6 30 #define GPIO_D7 31
舉個例子,假如我們要控制 gpio2_d4 引腳,則其端口號為
2 * 32 + 28 = 92
假如我們要控制 gpio0_a1 引腳,則其端口號為
0 * 32 + 1 = 1
一個 GPIO 引腳必須要處於一種 “完全自由” 的狀態下才能夠在串口中對它進行控制。
換句話說就是如果您要操作的 GPIO 引腳在 dts 或 dtsi 文件中操作過它,那么就無法通過串口來控制了。通過這種特性也可以檢測我們在配置文件中對某引腳的控制是否起到效果了。
關於這種設定可以參考下 rk 官方給出的關於 gpio 的說明文檔,這里貼出一部分關鍵說明如下

Sysfs 中的路徑 -------------- 在/sys/class/gpio 中有 3 類入口: - 用於在用戶空間控制 GPIO 的控制接口; - GPIOs 本身;以及 - GPIO 控制器 ("gpio_chip" 實例)。 除了這些標准的文件,還包含“device”符號鏈接。 控制接口是只寫的: /sys/class/gpio/ "export" ... 用戶空間可以通過寫其編號到這個文件,要求內核導出 一個 GPIO 的控制到用戶空間。 例如: 如果內核代碼沒有申請 GPIO #19,"echo 19 > export" 將會為 GPIO #19 創建一個 "gpio19" 節點。 "unexport" ... 導出到用戶空間的逆操作。 例如: "echo 19 > unexport" 將會移除使用"export"文件導出的 "gpio19" 節點。 GPIO 信號的路徑類似 /sys/class/gpio/gpio42/ (對於 GPIO #42 來說), 並有如下的讀/寫屬性: /sys/class/gpio/gpioN/ "direction" ... 讀取得到 "in" 或 "out"。這個值通常運行寫入。 寫入"out" 時,其引腳的默認輸出為低電平。為了確保無故障運行, "low" 或 "high" 的電平值應該寫入 GPIO 的配置,作為初始輸出值。 注意:如果內核不支持改變 GPIO 的方向,或者在導出時內核代碼沒有 明確允許用戶空間可以重新配置 GPIO 方向,那么這個屬性將不存在。 "value" ... 讀取得到 0 (低電平) 或 1 (高電平)。如果 GPIO 配置為 輸出,這個值允許寫操作。任何非零值都以高電平看待。 如果引腳可以配置為中斷信號,且如果已經配置了產生中斷的模式 (見"edge"的描述),你可以對這個文件使用輪詢操作(poll(2)), 且輪詢操作會在任何中斷觸發時返回。如果你使用輪詢操作(poll(2)), 請在 events 中設置 POLLPRI 和 POLLERR。如果你使用輪詢操作 (select(2)),請在 exceptfds 設置你期望的文件描述符。在 輪詢操作(poll(2))返回之后,既可以通過 lseek(2)操作讀取 sysfs 文件的開始部分,也可以關閉這個文件並重新打開它來讀取數據。 "edge" ... 讀取得到“none”、“rising”、“falling”或者“both”。 將這些字符串寫入這個文件可以選擇沿觸發模式,會使得輪詢操作 (select(2))在"value"文件中返回。 這個文件僅有在這個引腳可以配置為可產生中斷輸入引腳時,才存在。 "active_low" ... 讀取得到 0 (假) 或 1 (真)。寫入任何非零值可以 翻轉這個屬性的(讀寫)值。已存在或之后通過"edge"屬性設置了"rising" 和 "falling" 沿觸發模式的輪詢操作(poll(2))將會遵循這個設置。 GPIO 控制器的路徑類似 /sys/class/gpio/gpiochip42/ (對於從#42 GPIO 開始實現控制的控制器),並有着以下只讀屬性: /sys/class/gpio/gpiochipN/ "base" ... 與以上的 N 相同,代表此芯片管理的第一個 GPIO 的編號 "label" ... 用於診斷 (並不總是只有唯一值) "ngpio" ... 此控制器所管理的 GPIO 數量(而 GPIO 編號從 N 到 N + ngpio - 1) 大多數情況下,電路板的文檔應當標明每個 GPIO 的使用目的。但是那些編號並不總是 固定的,例如在擴展卡上的 GPIO會根據所使用的主板或所在堆疊架構中其他的板子而 有所不同。在這種情況下,你可能需要使用 gpiochip 節點(盡可能地結合電路圖)來 確定給定信號所用的 GPIO 編號。
這份文檔位於
./kernel/Documentation/zh_CN/gpio.txt
參考: RK3288 GPIO 輸出問題