《Pinctrl和GPIO子系統的使用》


1.參考文檔

a. 內核 Documentation\devicetree\bindings\Pinctrl\ 目錄下:
Pinctrl-bindings.txt

b. 內核 Documentation\gpio 目錄下:
Pinctrl-bindings.txt

c. 內核 Documentation\devicetree\bindings\gpio 目錄下:
gpio.txt

  

2.Pinctrl子系統概念

  linux下的pintcrl和gpio子系統就類似於ST的“BSP庫”。引入“設備樹”之后,使用一個外設時,對於pin引腳的初始化和管理,只需通過設備樹描述即可,然后由pin子系統管理;對於gpio則由gpio子系統管理。
  因此,與CPU引腳“關聯”的設備驅動,最終都會調用pincrtl和gpio子系統。二者是設備驅動的基礎,這二者也是一個設備驅動。
  CPU的gpio引腳除了的方向、速度、上下拉、驅動能力等基本的電氣特性外,一般會包括復用功能,即該引腳既可以作為普通gpio,還可能復位為i2c引腳、uart引腳等。如果采用直接配置寄存器的方式進行驅動開發,會非常繁瑣,每更改一個功能就得重新翻閱手冊配一遍寄存器,另一方面還可能存在“沖突”問題,比如該引腳已被復用為i2c在使用,但被驅動工程師忽略了,再去使用該gpio時會導致未知預期的問題。引入pintctrl子系統就可以解決諸如此類問題,結合設備樹的使用,只需把pin信息在設備樹描述清楚,即由pinctrl子系統介入管理。
 
  從設備樹開始學習 Pintrl 會比較容易。
  主要參考文檔是:內核 Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt。
  這會涉及 2 個對象:pin controller、client device。
  前者提供服務:可以用它來復用引腳、配置引腳。
  后者使用服務:聲明自己要使用哪些引腳的哪些功能,怎么配置它們。
 
2.1 pin controller
  在芯片手冊里你找不到 pin controller,它是一個軟件上的概念,你可以認為它對應IOMUX──用來復用引腳,還可以配置引腳(比如上下拉電阻等)。
  注意,pin controller 和 GPIO Controller 不是一回事,前者控制的引腳可用於 GPIO 功能、I2C 功能;后者只是把引腳配置為輸出、輸出等簡單的功能。
 
2.2 client device
  “客戶設備”,誰的客戶?Pinctrl 系統的客戶,那就是使用 Pinctrl 系統的設備,使用引腳的設備。它在設備樹里會被定義為一個節點,在節點里聲明要用哪些引腳。
  下面這個圖就可以把幾個重要概念理清楚:   上圖中,左邊是 pincontroller 節點,右邊是 client device 節點:
pin state:
  對於一個“client device”來說,比如對於一個 UART 設備,它有多個“狀態”:default、sleep等,那對應的引腳也有這些狀態。
  怎么理解?
  比如默認狀態下,UART 設備是工作的,那么所用的引腳就要復用為 UART 功能。
  在休眠狀態下,為了省電,可以把這些引腳復用為 GPIO 功能;或者直接把它們配置輸出高電平。
  上圖中,pinctrl-names 里定義了 2 種狀態:default、sleep。
  第 0 種狀態用到的引腳在 pinctrl-0 中定義,它是 state_0_node_a,位於 pincontroller 節點中。
  第 1 種狀態用到的引腳在 pinctrl-1 中定義,它是 state_1_node_a,位於 pincontroller 節點中。
  當這個設備處於 default 狀態時,pinctrl 子系統會自動根據上述信息把所用引腳復用為uart0 功能。
  當這這個設備處於 sleep 狀態時,pinctrl 子系統會自動根據上述信息把所用引腳配置為高電平
 
groups 和 function:
  一個設備會用到一個或多個引腳,這些引腳就可以歸為一組(group);
  這些引腳可以復用為某個功能:function。
  當然:一個設備可以用到多能引腳,比如 A1、A2 兩組引腳,A1 組復用為 F1 功能,A2組復用為 F2 功能。
 
Generic pin multiplexing node 和 Generic pin configuration node:
  在上圖左邊的 pin controller 節點中,有子節點或孫節點,它們是給 client device 使用的。
  可以用來描述復用信息:哪組(group)引腳復用為哪個功能(function);
  可以用來描述配置信息:哪組(group)引腳配置為哪個設置功能(setting),比如上拉、下拉等。
 
注意:pin controller 節點的格式,沒有統一的標准!!!!每家芯片都不一樣
 
 
3.GPIO系統
  pinctrl子系統主要是管理pin的電氣屬性和復用功能,而gpio子系統則是管理gpio的申請釋放、控制輸入輸出、io中斷等功能。gpio子系統屏蔽了gpio相關寄存器的配置過程,換而提供了常用的接口函數給驅動工程師使用,方便gpio相關的驅動開發。 

gpio子系統功能

  • 對於驅動層,屏蔽gpio寄存器配置細節,提供統一gpio操作接口
  • 對於BSP層,統一框架,方便不同CPU接入,只需更換pinctrl子系統的驅動
3.1 GPIO子系統常用函數
  gpio子系統對於驅動層的API位於“/kernel/include/linux/gpio.h”中。
(1)檢查gpio是否可用
int gpio_is_valid(int number); 
number:	gpio序號
返回:	可用返回true,不可用返回false

  

(2)申請使用一個gpio

使用一個gpio前,必須向內核申請該gpio。
int gpio_request(unsigned gpio, const char *label)
gpio:	待申請gpio序號
label:gpio命名
返回:	成功返回0,失敗返回負數

  

(3)釋放已申請gpio

如果不使用該gpio,則需要釋放,否則其他模塊申請不到該gpio序號。
int gpio_free(unsigned gpio)
gpio:待釋放gpio序號
返回:成功返回0,失敗返回負數

  

(4)設置gpio輸入模式

int gpio_direction_input(unsigned gpio)
gpio:待設置gpio序號
返回:成功返回0,失敗返回負數

  

(5)設置gpio輸出模式
void gpio_set_value(unsigned gpio, int value)
gpio:待設置gpio序號
value:默認輸出狀態

  

(6)讀取 gpio狀態

int gpio_get_value(unsigned int gpio)
gpio:待讀取gpio序號
返回:成功返回gpio狀態(1/0),失敗返回負數

  

(7)設置 gpio狀態

void gpio_set_value(unsigned int gpio, int value)
gpio:待設置gpio序號
value:待設置值

  

(8)中斷號映射

int gpio_to_irq(unsigned gpio)
gpio:待設置gpio序號
返回:成功返回中斷號,失敗返回負數

  

如果使用該 GPIO 時,不會動態的切換輸入輸出,建議在開始時就設置好 GPIO 輸出方向,后面拉高拉低時使用 gpio_set_value()接口,而不建議使用gpio_direction_output(), 因為 gpio_direction_output 接口里面有 mutex 鎖,對中斷上下文調用會有錯誤異常,且相比 gpio_set_value,gpio_direction_output 所做事情更多,浪費。 





 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 


免責聲明!

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



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