適用於使用者空間的 GPIO Sysfs 介面

警告

此 API 已被GPIO 字元裝置使用者空間 API廢棄,且 ABI 文件已移至ABI 檔案 obsolete/sysfs-gpio

新的開發應使用GPIO 字元裝置使用者空間 API,並鼓勵現有開發儘快遷移,因為此 API 將來會被移除。

此介面在遷移期間將繼續維護,但新功能只會新增到新的 API 中。

廢棄的 sysfs ABI

使用“gpiolib”實現者框架的平臺可以選擇配置一個 sysfs 使用者介面來訪問 GPIO。這與 debugfs 介面不同,因為它提供對 GPIO 方向和值的控制,而不僅僅是顯示 GPIO 狀態摘要。此外,它可以在沒有除錯支援的生產系統上存在。

如果系統有適當的硬體文件,使用者空間例如可以知道 GPIO #23 控制用於保護快閃記憶體中引導載入器段的防寫線。系統升級過程可能需要暫時移除該保護,首先匯入一個 GPIO,然後改變其輸出狀態,接著更新程式碼,最後重新啟用防寫。在正常使用中,GPIO #23 永遠不會被觸及,核心也無需瞭解它。

同樣,根據適當的硬體文件,在某些系統上,使用者空間 GPIO 可以用於確定標準核心無法瞭解的系統配置資料。對於某些任務,簡單的使用者空間 GPIO 驅動程式可能就是系統真正所需的全部。

注意

請勿濫用 sysfs 來控制已具有適當核心驅動程式的硬體。請閱讀使用 GPIO 的子系統驅動程式以避免在使用者空間中重複造核心的輪子。

我是認真的。真的。

Sysfs 中的路徑

/sys/class/gpio 中有三種條目:

  • 用於獲取使用者空間對 GPIO 控制的介面;

  • GPIO 本身;以及

  • GPIO 控制器(“gpio_chip”例項)。

這些是除了包括“device”符號連結在內的標準檔案之外的。

控制介面是隻寫(write-only)的

/sys/class/gpio/

“export”...

使用者空間可以透過將 GPIO 號寫入此檔案來請求核心將 GPIO 的控制權匯出到使用者空間。

示例:“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) 將返回。如果使用 poll(2),請設定事件 POLLPRI 和 POLLERR。如果使用 select(2),請在 exceptfds 中設定檔案描述符。poll(2) 返回後,使用 pread(2) 讀取偏移量為零的值。或者,可以 lseek(2) 到 sysfs 檔案的開頭並讀取新值,或者關閉檔案並重新開啟以讀取值。

“edge”...

讀取時為“none”、“rising”、“falling”或“both”。寫入這些字串以選擇在“value”檔案上進行 poll(2) 操作時將使其返回的訊號邊沿。

此檔案僅在引腳可以配置為中斷生成輸入引腳時存在。

“active_low”...

讀取時為 0(假)或 1(真)。寫入任何非零值以反轉值屬性,無論是讀取還是寫入。現有和後續的 poll(2) 透過 edge 屬性對“上升”和“下降”邊沿的支援配置將遵循此設定。

GPIO 控制器的路徑類似於 /sys/class/gpio/gpiochip42/(用於實現從 #42 開始的 GPIO 的控制器),並具有以下只讀屬性:

/sys/class/gpio/gpiochipN/

“base”...

與 N 相同,此晶片管理的第一個 GPIO

“label”...

用於診斷(不總是唯一的)

“ngpio”...

此晶片管理多少個 GPIO(N 到 N + ngpio - 1)

在大多數情況下,板級文件應該涵蓋 GPIO 的用途。然而,這些編號並不總是穩定的;子卡上的 GPIO 可能會因所使用的基板或堆疊中的其他卡而異。在這種情況下,您可能需要使用 gpiochip 節點(可能結合原理圖)來確定給定訊號應使用的正確 GPIO 編號。

從核心程式碼匯出

核心程式碼可以顯式管理已使用 gpio_request() 請求的 GPIO 的匯出。

/* export the GPIO to userspace */
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);

/* reverse gpiod_export() */
void gpiod_unexport(struct gpio_desc *desc);

/* create a sysfs link to an exported GPIO node */
int gpiod_export_link(struct device *dev, const char *name,
              struct gpio_desc *desc);

在核心驅動程式請求一個 GPIO 後,它只能透過gpiod_export()在 sysfs 介面中可用。驅動程式可以控制訊號方向是否可以改變。這有助於驅動程式防止使用者空間程式碼意外破壞重要的系統狀態。

這種顯式匯出有助於除錯(透過使某些實驗更容易),或者可以提供一個始終存在的介面,適合作為板級支援包的一部分進行文件化。

GPIO 匯出後,gpiod_export_link()允許從 sysfs 中的其他位置建立指向 GPIO sysfs 節點的符號連結。驅動程式可以使用此功能在 sysfs 中其自己的裝置下提供帶有描述性名稱的介面。