孫 帥,李傳璽
(航天科工深圳集團有限公司 南京分公司,江蘇 南京 211100)
?
嵌入式Linux下SPI總線驅動程序設計
孫 帥,李傳璽
(航天科工深圳集團有限公司 南京分公司,江蘇 南京 211100)
給出了一種提高軟件使用效率的設計方法,以SPI驅動程序為例,通過外設和處理器相分離的設計思想,在外設模型和處理器模型之間增加一層虛擬總線,達到降低外設驅動與主機控制器驅動耦合的目的。實際測試結果表明,該方法實現(xiàn)了主機和外設任意組合的功能,具備較高的應用價值。
SPI總線;設備驅動; Linux; 嵌入式
Linux操作系統(tǒng)在嵌入式領域得到廣泛的應用,不僅是因為良好的內核性能,更是展示了其在開源上的優(yōu)勢[1],使得符合驅動規(guī)范的外設器件,均能得到操作系統(tǒng)的有效支持。然而,由于外設器件種類繁多,且外設驅動和處理器結構相關[2-3],若驅動程序移植在不同的處理器上,將導致驅動軟件存在多個版本,這給產品開發(fā)和系統(tǒng)維護帶來了較大的困難。
為提高外設驅動程序的使用效率,降低設備驅動和處理器結構的耦合程度,本文以Linux設備驅動模型為基礎,用設備和處理器相分離的思想設計串行外設接口SPI(Serial Peripheral Interface)驅動[4],在外設驅動和處理器驅動之間增加一層SPI虛擬總線,該總線對內對外隱藏了對端的不確定性,使得外設驅動與主機控制器驅動不相關,實現(xiàn)主機和外設任意組合的功能。最后通過嵌入式平臺的測試,驗證了該虛擬總線的隔離功能。
在Linux非總線結構的驅動中,用戶應用程序訪問SPI物理設備需要經過內核空間的相關調用[5],如圖1中不含虛線部分。內核的設備協(xié)議驅動層需要了解外設的通信協(xié)議和數(shù)據(jù)結構,并負責SPI功能的具體實現(xiàn)[6]。而總線驅動結構則是以Linux設備驅動模型為基礎[7],采用設備和處理器相分離的思想,在硬件設備和內核協(xié)議驅動之間增加一層SPI虛擬總線,分離出設備協(xié)議驅動層關于硬件的功能,如圖1中的虛線部分。SPI總線由SPI核心接口層和SPI控制器驅動層組成。
圖1 SPI虛擬總線結構
SPI核心接口層提供核心數(shù)據(jù)結構的相關定義、SPI控制器驅動和設備驅動的注冊、注銷管理等API[8]。其與具體的處理器平臺無關:向下屏蔽了物理總線控制器的差異,規(guī)范統(tǒng)一的訪問策略和接口參數(shù);向上提供了統(tǒng)一的協(xié)議,以便內核空間的設備協(xié)議驅動層通過總線進行數(shù)據(jù)收發(fā)。SPI控制器驅動層負責將上層協(xié)議驅動的數(shù)據(jù)按SPI總線的時序要求發(fā)送給設備,并從設備收到的數(shù)據(jù)返回給上層的協(xié)議驅動[9]。SPI控制器驅動為系統(tǒng)中每條SPI總線實現(xiàn)相應的讀寫方法,同時負責管理具體的硬件資源,諸如DMA、中斷向量等。
2.1 SPI核心接口層
SPI核心接口層主要包含spi_master、spi_device和spi_driver這3個數(shù)據(jù)結構。spi_master結構用于表示SPI控制器,其規(guī)定了總線編號、控制器的片選信號、工作模式、消息鏈表以及消息隊列[10];spi_device結構用于描述SPI設備,包括片選索引、數(shù)據(jù)單位、中斷編號等信息;spi_driver結構則對應spi_device操作方法的實現(xiàn)[11]。當系統(tǒng)加載模塊時,內核首先通過spi_register_master( )注冊spi_master結構到系統(tǒng)中,然后調用spi_register_board_info( )將每個spi_board_info掛在全局鏈表變量上,以遍歷已經注冊到系統(tǒng)中的控制器,匹配相應的控制器并獲取同名的spi_master結構指針,隨后通過spi_new_device( )向系統(tǒng)增加SPI設備,最終調用spi_register_driver( )完成spi_driver的注冊。
2.2 SPI控制器驅動層
SPI控制器驅動層主要包含platform_device和platform_devic[12]兩個數(shù)據(jù)結構。在platform_device中定義了控制器所需的寄存器地址、DMA通道資源、中斷編號和設備名稱。其中,設備名稱用于匹配相應的控制器驅動[13]。platform_device對應platform_device平臺驅動的操作方法。以飛思卡爾IMX為例,在系統(tǒng)初始化階段,SPI控制器以mxs-spi為名稱通過mxs_get_device( )向系統(tǒng)注冊平臺設備[14],同時mxs_spi_init( )以mxs-spi為名稱向系統(tǒng)添加平臺驅動。平臺總線匹配platform_device和platform_device,觸發(fā)probe( )函數(shù)回調以完成SPI控制器的注冊過程[15]。至此,連接內核設備協(xié)議和硬件外設的SPI虛擬總線創(chuàng)建完成。
2.3 SPI模型的初始化
在初始化階段,spi_init( )向系統(tǒng)注冊一個名為SPI的總線類型,同時為SPI控制器注冊名為spi_master的設備類,使文件系統(tǒng)類型創(chuàng)建節(jié)點文件sys/bus/spi、sys/class/spi_master,表明SPI總線中spi_bus_type結構的match字段指向了spi_match_device( )函數(shù),該函數(shù)用于匹配SPI總線上的設備和驅動。同時,SPI設備和其驅動通過總線互相進行匹配[16],使得設備能夠找到正確的驅動程序進行控制和驅動。
static int __init spi_init(void)
{
buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
status = bus_register(&spi_bus_type); //注冊SPI的總線類型
status = class_register(&spi_master_class); //注冊spi_master的設備類
}
通過上述對SPI虛擬總線的分析和創(chuàng)建,本章節(jié)以飛思卡爾的IMX平臺為例,測試SPI總線及其外設的連接狀態(tài)。其中,外設為74HC595,定義命名為spidev的設備平臺,設備驅動的數(shù)據(jù)結構如下
static struct spi_driver spidev_spi_driver = {
.driver = {
.name ="spidev",
.owner =THIS_MODULE,
},
.probe =spidev_probe,//探測并匹配相應的外設
};
IMX正常啟動后,登入系統(tǒng)并切換到總線級的目錄下進行觀測,如圖2所示。Linux在總線視圖的目錄中自動創(chuàng)建SPI目錄,該目錄下注冊名為SPI1.0的總線,這層總線使用名為spidev的驅動,而驅動最終又指向名為SPI1.0的總線,表明SPI1.0總線創(chuàng)建成功并具備掛載外設的功能。
圖2 使用終端觀測到的SPI虛擬總線
進入設備級的目錄后,如圖3所示。外設已映射到名為SPI1.0的總線,并使用序號1的控制器以及控制器的第1個片選信號。該外設已綁定名為spidev的驅動,掛載到 /bus/spi的子系統(tǒng)中,這與在總線級目錄下觀測的結果一致。
圖3 使用終端觀測SPI總線連接的外設信息
提出了一種提高SPI驅動使用效率的設計方法,以Linux設備驅動模型為基礎,在外設驅動和處理器驅動之間增加SPI虛擬總線,實現(xiàn)主機和外設任意組合的功能。經過測試,使用本方法設計的SPI驅動,降低設備驅動和處理器結構的耦合程度,且工作性能穩(wěn)定,具備一定的工程實用性。
[1] Jonatban Corbet.Linux設備驅動程序[M].3版.魏永明,耿岳,鐘書毅,譯.北京:中國電力出版社,2012.
[2] 楊俊成.嵌入式Linux設備驅動程序框架的研究[J].核電子學與探測技術,2011,31(2):243-244.
[3] 胥霜霞.嵌入式Linux下Z85C30芯片設備驅動程序設計[J].電子科技,2014,27(5):116-117.
[4] 朱恩亮.Linux環(huán)境下USB設備驅動程序設計[J].電子
科技,2016,29(1):108-109.
[5] 宋寶華.Linux設備驅動開發(fā)詳解[M].北京:人民郵電出版社,2008.
[6] 孟浩依然.Linux內核SPI總線驅動分析[EB/OL].(2012-12-11) [2015-09-06]http://www.cnblogs.com/liugf05/archive/2012/12/03/2800457.html.
[7] Marcus E,Stern H.高可用性系統(tǒng)設計[M].汪青青,盧祖英,譯.北京:清華大學出版社,2005.
[8] Droid Phone.Linux SPI總線和設備驅動架構[EB/OL].(2014-04-12)[2015-02-16]http://blog.csdn.net/droidphone.
[9] Gene S.Getting Linux for your board[M].New York:Willy Press,2010.
[10] 劉剛.Linux系統(tǒng)移植[M].北京:清華大學出版社,2011.
[11] 孫天澤.嵌入式設計及Linux驅動開發(fā)指南[M].2版.北京:電子工業(yè)出版社,2007.
[12] Matthew N,Stone R.Linux程序設計[M].2版.楊曉蕓,譯.北京:機械工業(yè)出版社,2002.
[13] Daniel P Bovet.Understanding the Linux kernel[M].北京:中國電力出版社,2007.
[14] 王鎮(zhèn)道,胡贊民,陳迪平.基于ARM&Linux平臺IIC驅動程序的設計[J].微計算機信息,2011(5):1-3.
[15] 廣州致遠.嵌入式Linux開發(fā)教程[EB/OL].(2014-06-04)[2016-03-12]http://www.zlg.cn/ipc/down/down/id/92.html.
[16] 徐瑩彗.ARM9嵌入式系統(tǒng)設計-基于S3C2410與Linux[M].北京:北京航空航天大學出版社,2007.
SPI Bus Driver Under Embedded Linux Programming
SUN Shuai, LI Chuanxi
(Nanjing Company,Aerospace Science and Industry Group (Shenzhen) Co. LTD.,Nanjing 211100,China)
Presents a design method of increasing the service efficiency of the software, the SPI driver, for example, through the design idea of separating peripherals and processor, add a layer between peripherals model and processor model virtual bus, to reduce the coupling of the peripheral drive and the host controller driver. The actual test results show that this method can realize the function of the host and peripherals in any combination has higher application value.
SPI bus; device drivers; Linux; the embedded
2016- 10- 26
孫帥(1984-),男,碩士,工程師。研究方向:航天飛行控制計算機。李傳璽(1980-),男,碩士,工程師。研究方向:航天電力儀器。
10.16180/j.cnki.issn1007-7820.2017.08.027
TN919.71;TP316.2
A
1007-7820(2017)08-099-03