GPIO驅動框架

2021-09-19 18:04:59 字數 3417 閱讀 7603

一、前言

作為乙個工作多年的系統工程師,免不了做兩件事情:培訓新員工和給新員工分配任務。對於那些剛剛從學校出來的學生,一般在開始的時候總是分配一些非常簡單的任務,例如gpio driver、led driver。往往cpu datasheet的關於gpio或者io ports的章節都是比較簡單的,非常適合剛入行的工程師。雖然gpio子系統相關的硬體比較簡單,沒有複雜的協議,不過,對於軟體抽象而言,其分層次的軟體思想是每個嵌入式軟體工程師需要掌握的內容。

我更傾向使用gpio系統這個名字來代替gpio driver這個名字,gpio driver僅僅包含了pin signal狀態控制和讀取的內容,而gpio系統包括了pin multiplexing、pin configuration、gpio control、gpio interrupt control等內容。本文主要是以3.14核心作為例子,講述linux kernel中gpio系統的軟體框架。

二、gpio相關硬體有哪些差異

嵌入式工程師總是要處理各種各樣的target board,每個target board上的gpio總是存在不同,例如:

1、和cpu的連線方式不同

對於arm的嵌入式硬體平台,soc本身可以提供大量的io port,soc上的gpio controller是通過soc的匯流排(amba)連線到cpu的。對於嵌入式系統而言,除了soc的io port,一些外設晶元也可能會提供io port,例如:

(1)有些key controller晶元、codec或者pmu的晶元會提供i/o port

(2)有些專用的io expander晶元可以擴充套件16個或者32個gpio

從硬體角度看,這些io和soc提供的那些io完全不同,cpu和io expander是通過i2c(也有可能是spi等其他型別的bus)連線的,在這種情況下,訪問這些soc之外的gpio需要i2c的操作,而控制soc上的gpio只需要寫暫存器的操作。不要小看這個不同,寫乙個soc memory map的暫存器非常快,但是通過i2c來操作io就不是那麼快了,甚至,如果匯流排繁忙有可能阻塞當前程序,這種情況下,核心同步機制必須有所區別(如果操作gpio可能導致sleep,那麼同步機制不能採用spinlock)。

2、訪問方式不同

soc片內的gpio controller和soc片外的io expander的訪問當然不一樣,不過,即便都是soc片內的gpio controller,不同的arm晶元,其訪問方式也不完全相同,例如:有些soc的gpio controller會提供乙個暫存器來控制輸出電平。向暫存器寫1就是set high,向暫存器寫0就是set low。但是有些soc的gpio controller會提供兩個暫存器來控制輸出電平。向其中乙個暫存器寫一就是set high,向另外乙個暫存器寫一就是set low。

3、配置方式不同

即便是使用了同樣的硬體(例如都使用同樣的某款soc),不同硬體系統上gpio的配置不同。在乙個系統上配置為輸入,在另外的系統上可能配置為輸出。

4、gpio特性不同。這些特性包括:

(1)是否能觸發中斷。對乙個soc而言,並非所有的io port都支援中斷功能,可能某些處理器只有一兩組gpio有中斷功能。

(2)如果能夠觸發中斷,那麼該gpio是否能夠將cpu從sleep狀態喚醒

(3)有些有軟體可控的上拉或者下拉電阻的特性,有的gpio不支援這種特性。在設定為輸入的時候,有的gpio可以設定debouce的演算法,有的則不可以。

5、多功能復用

有的gpio就是單純的作為乙個gpio出現,有些gpio有其他的復用的功能。例如io expander上的gpio只能是gpio,但是soc上的某個gpio除了做普通的io pin腳,還可以是spi上clock訊號線。

三、硬體功能分類

arm based soc的datasheet中總有乙個章節叫做gpio controller(或者i/o ports)的章節來描述如何配置、使用soc的引腳。雖然gpio controller的硬體描述中充滿了大量的暫存器的描述,但是這些暫存器的功能大概分成下面三個類別:

(1)引腳功能配置。例如該i/o pin是乙個普通的gpio還是一些特殊功能引腳(例如memeory bank上cs訊號)。

(2)引腳特性配置。例如pull-up/down電阻的設定,drive-strength的設定等。

2、如果一組gpio被配置成spi,那麼這些pin腳被連線到了spi controller,如果配置成gpio,那麼控制這些引腳的就是gpio controller。通過訪問gpio controller的暫存器,軟體可以:

(1)配置gpio的方向

(2)如果是輸出,可以配置high level或者low level

(3)如果是輸入,可以獲取gpio引腳上的電平狀態

3、如果一組gpio有中斷控制器的功能,雖然控制暫存器在datasheet中的i/o ports章節描述,但是實際上這些gpio已經被組織成了乙個interrupt controller的硬體block,它更像是乙個gpio type的中斷控制器,通過訪問gpio type的中斷控制器的暫存器,軟體可以:

(1)中斷的enable和disable(mask和unmask)

(2)觸發方式

(3)中斷狀態清除

四、如何通過軟體抽象來掩蓋硬體差異

傳統的gpio driver是負責上面三大類的控制,而新的linux kernel中的gpio subsystem則用三個軟體模組來對應上面三類硬體功能:

(1)pin control subsystem。驅動pin controller硬體的軟體子系統。

(2)gpio subsystem。驅動gpio controller硬體的軟體子系統。

(3)gpio interrupt chip driver。這個模組是作為乙個interrupt subsystem中的乙個底層硬體驅動模組存在的。本文主要描述前兩個軟體模組,具體gpio interrupt chip driver以及interrupt subsystem請參考本站其他相關文件。

1、pin control subsystem block diagram

下圖描述了pin control subsystem的模組圖:

底層的pin controller driver是硬體相關的模組,初始化的時候會向pin control core模組註冊pin control裝置(通過pinctrl_register這個bootom level inte***ce)。pin control core模組是乙個硬體無關模組,它抽象了所有pin controller的硬體特性,僅僅從使用者(各個driver就是pin control subsystem的使用者)角度給出了top level的介面函式,這樣,各個driver不需要關注pin controller的底層硬體相關的內容。

2、gpio subsystem block diagram

下圖描述了gpio subsystem的模組圖:

基本上這個軟體框架圖和pin control subsystem是一樣的,其軟體抽象的思想也是一樣的,當然其內部具體的實現不一樣,我們會在後續的文章中描述。

(四)GPIO驅動小車

四 gpio驅動小車 gpio,上圖 樹莓派實物四個usb口對著自己的時候,40個引腳就是如圖的順序 在這裡插入描述 gpio有兩套編碼。我用的是bcm編碼 python 寫法 四個引腳自己選吧,我選的是最下面幾個。python import rpi.gpio as gpio gpio.setmod...

用DMA直接驅動GPIO,實現GPIO最高輸出速率

先上圖 stm32f303晶元,72m的主頻 可以看到gpio的達到了14.4m的翻轉速率,再來上 rcc ahbperiphclockcmd rcc ahbperiph gpioc,enable gpioc moder 0x55555555 gpioc ospeedr 0xfffffff gpio...

用DMA直接驅動GPIO,實現GPIO最高輸出速率

用dma直接驅動gpio,實現gpio最高輸出速率 先上圖 stm32f303晶元,72m的主頻 可以看到gpio的達到了14.4m的翻轉速率,再來上 rcc ahbperiphclockcmd rcc ahbperiph gpioc,enable gpioc moder 0x55555555 gp...