SPI即Serial Peripheral Interface 的縮寫,是一種四線制的同步串行通信接口,用來連接微控制器、傳感器、存儲設備,SPI設備分為主設備和從設備兩種,用於通信和控制的四根線分別是:
CS: 片選信號;
SCK : 時鍾信號;
MISO :主設備的數據輸入、從設備的數據輸出腳;
MOSI : 主設備的數據輸出、從設備的數據輸入腳;
CPU或SOC一般都是工作在主設備模式,所以,目前的Linux內核版本中,只是實現了主模式的驅動框架。
1 硬件架構
主設備對應SoC芯片中的SPI控制器,一個SoC中可能存在多個SPI控制器,如上圖所示,SoC芯片中有3個SPI控制器。每個SPI控制器可以連接多個SPI從設備,每個從設備有各自獨立的CS引腳。每個從設備共享另外三個信號引腳:SCLK、MISO、MOSI。任何時刻,只有一個CS引腳處於有效狀態,與該有效CS引腳連接的設備此時可以與主設備(SPI控制器)通信,其它的從設備處於等待狀態,並且它們的3個引腳必須處於高阻狀態。
2 時序圖
按照時鍾信號和數據信號之間的相位關系,SPI有4種工作時序模式:
我們用CPOL表示時鍾信號的初始電平的狀態,CPOL為0表示時鍾信號初始狀態為低電平,為1表示時鍾信號的初始電平是高電平。另外,我們用CPHA來表示在那個時鍾沿采樣數據,CPHA為0表示在首個時鍾變化沿采樣數據,而CPHA為1則表示要在第二個時鍾變化沿來采樣數據。內核用CPOL和CPHA的組合來表示當前SPI需要的工作模式:
(1)CPOL=0,CPHA=1 模式0
(2)CPOL=0,CPHA=1 模式1
(3)CPOL=1,CPHA=0 模式2
(4)CPOL=1,CPHA=1 模式3
3 linux內核spi軟件架構
(1)SPI控制器驅動程序
SPI控制器不用關心設備的具體功能,它只負責把上層協議驅動准備好的數據按SPI總線的時序要求發送給SPI設備,同時把從設備收到的數據返回給上層的協議驅動,因此,內核把SPI控制器的驅動程序獨立出來。SPI控制器驅動負責控制具體的控制器硬件,諸如DMA和中斷操作等等,因為多個上層的協議驅動可能會通過控制器請求數據傳輸操作,所以,SPI控制器驅動同時也要負責對這些請求進行隊列管理,保證先進先出的原則。
(2)SPI通用接口封裝層
為了簡化SPI驅動程序的編程工作,同時也為了降低協議驅動程序和控制器驅動程序的耦合程度,內核把控制器驅動和協議驅動的一些通用操作封裝成標准的接口,加上一些通用的邏輯處理操作,組成了SPI通用接口封裝層。這樣的好處是,對於控制器驅動程序,只要實現標准的接口回調API,並把它注冊到通用接口層即可,無需直接和協議層驅動程序進行交互。而對於協議層驅動來說,只需通過通用接口層提供的API即可完成設備和驅動的注冊,並通過通用接口層的API完成數據的傳輸,無需關注SPI控制器驅動的實現細節。
(3)SPI協議驅動程序
上面我們提到,控制器驅動程序並不清楚和關注設備的具體功能,SPI設備的具體功能是由SPI協議驅動程序完成的,SPI協議驅動程序了解設備的功能和通信數據的協議格式。向下,協議驅動通過通用接口層和控制器交換數據,向上,協議驅動通常會根據設備具體的功能和內核的其它子系統進行交互,例如,和MTD層交互以便把SPI接口的存儲設備實現為某個文件系統,和TTY子系統交互把SPI設備實現為一個TTY設備,和網絡子系統交互以便把一個SPI設備實現為一個網絡設備,等等。當然,如果是一個專有的SPI設備,我們也可以按設備的協議要求,實現自己的專有協議驅動。
(4)SPI通用設備驅動程序
有時候,考慮到連接在SPI控制器上的設備的可變性,在內核沒有配備相應的協議驅動程序,對於這種情況,內核為我們准備了通用的SPI設備驅動程序,該通用設備驅動程序向用戶空間提供了控制SPI控制的控制接口,具體的協議控制和數據傳輸工作交由用戶空間根據具體的設備來完成,在這種方式中,只能采用同步的方式和SPI設備進行通信,所以通常用於一些數據量較少的簡單SPI設備。
參考博文: