Linux kernel · Linux utilities

New GPIO User Space Subsystem since kernel 4.8

General Purpose Input/Output (GPIO)  是一個可以軟體彈性控制的數位訊號, 可供使用者透過軟體控制自由使用. 在嵌入式平台上算是很常見到的介面.

GPIO 應用:

一般來說可將 GPIO 透過軟體設成以下狀態以完成特定目的:
√ Input
  • 用來讀取 Input 資料 (通常為 high or low, 對接的可能為 push button 這類設備)
√ Output
  • 可讀寫 output 之值 (對接的可能為 LED, Buzzer, Power PIN 這類設備)

note: 因為電路設計的關係, GPO 不一定為 active – high (“1” 代表 “active”, 預設值), 有可能為 active-low (“0” 代表 “active”). 所以這邊需要根據電路設計將設定寫入 device tree 中. 可參考include/dt-bindings/gpio/gpio.h 中的定義

√ IRQ
  • 用來處理 IRQs 相關 (通常為 wakeup 事件)
√ 其他
  • bit banging – 用軟體來模擬硬體的行為. 也就是透過程式來控制 GPIO 以模擬 I2C, SPI 等等硬體訊號
  • 設定成 特定裝置的 write protect PIN

詳情可見下表

2018-02-01_150034.png


提供 GPIO 介面的裝置:

GPIO 這個介面可由下列裝置來提供
√ System-on-Chip (SOC) processors
  • SoC 上的 PIN 通常都是 multi-function PIN, 而其中大部份都能夠設定成 GPIO 來使用
√ Programmable logic devices (like FPGAs)
√ Peripheral module
  • PMIC
  • Audio codecs
  • watchdog
√ Expanders
  • 透過 I2C or SPI 介面來外接 expanders 以拓展 GPIO 數量

 


GPIO User Space Subsystem in Linux 

目前 GPIO 在 Linux 實作框架共有下列兩種
 GPIO numbers /sys/class/gpio (傳統方法, 不建議使用)

過往傳統都是使用 sysfs 來對 GPIO 操作, 一般使用方式如下:

1. 先算好 GPIO number

2. 開啟 GPIO

  • echo {number} >/sys/class/gpio/export

3. 設定 GPIO direction

  • echo “out” > /sys/class/gpio/gpio{number} /direction

4. 設定 Output value

  • echo 1 > /sys/class/gpio/gpio{number}/value

5. 關閉 GPIO

  • echo {number} >/sys/class/gpio/unexport

但以上操作容易造成下列問題:

  • 多個程式可同時存取 sysfs 底下的 GPIO 相關操作
  • 若程式不正常結束, GPIO 不會被關閉
  • GPIO 的 number 會因為開機順序而有所變動
  • 此外, 由下圖可知, 單一 GPIO 下的屬性多又雜, 除了權限皆固定外, 存取 value or event 方式也很麻煩  – 需要以 polling 方式來搭配 lseek or reopen

圖片1.png


  GPIO descriptors /dev/gpiochipN (建議使用)  –  kernel 4.8 開始支援
為了解決之前的議題, kernel 4.8 合併了新的 GPIO 設計架構. 導入 file descriptor 的概念來操作 GPIO 相關動作. 以一個 device file 為一個 gpiochip 的設計概念, 透過 system call – ioctl/ read/ write/ poll 來存取/ 設定 GPIO 相關資料. 可見下列範例 [9]
2018-02-02_104644.png
基於不重新造輪子的概念, 現在想要在新架構下存取 GPIO, 可透過 libgpiod [7].
圖片2.png
 libgpiod 除了含 library 外, 也寫好下列執行檔方便使用者直接進行操作. 至於用法就不一一介紹了
  • gpiodetect – 確認系統上有哪些 GPIO 裝置, 並列出 label 以及 GPIO line 數量

圖片3.png

  • gpiofind – 依照名稱來找尋 GPIO line
  • gpioget – 從 GPIO 裝置上讀取 line 的值
  • gpioset – 從 GPIO 裝置上設定 line 的值
  • gpioinfo – 列出指定的 GPIO 裝置上所有 GPIO line 資訊. 若不指定, 則列出所有 GPIO 裝置資訊

圖片4.png

  • gpiomon – 監控 GPIO line 上的事件 (使用 poll 函式)

心得: 

 透過 libgpiod 能夠更方便的在新版 GPIO 架構下操作存取 GPIO 相關資料, 避免傳統方式造成無論是使用上的複雜性或者方便性議題. 此外, 此工具也已放進 Debian [10] 中.

References:

[1]: Learn More About Linux’s New GPIO User Space Subsystem & Libgpiod

https://www.cnx-software.com/2017/11/03/learn-more-about-linuxs-new-gpio-user-space-subsystem-libgpiod/

[2]: New GPIO Interface for User Space

https://schd.ws/hosted_files/osseu17/88/elce2017_new_GPIO_interface.pdf

[3] General purpose input/output

https://en.wikipedia.org/wiki/General-purpose_input/output

[4] Bit banging

https://en.wikipedia.org/wiki/Bit_banging

[5] https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio.txt

[6] https://www.kernel.org/doc/Documentation/gpio/

[7] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/

[8] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=61f922db72216b00386581c851db9c9095961522

[9] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/gpio/lsgpio.c

[10] https://packages.debian.org/sid/gpiod

 

 

發表迴響