桂宇琛李彥梅劉昊天郭 玉
(1.安慶師范大學(xué)物理與電氣工程學(xué)院;2.安慶師范大學(xué)數(shù)學(xué)與計(jì)算科學(xué)學(xué)院 安徽安慶 246133)
隨著科技的發(fā)展,嵌入式產(chǎn)品越來越豐富,從小孩的玩具,到航空科技,隨處可見嵌入式設(shè)備。而對(duì)于嵌入式系統(tǒng),目前世界上使用廣泛的就是linux系統(tǒng)[1]。由于其自由,開源,Linux是使用用戶最多的操作系統(tǒng),它也是一個(gè)強(qiáng)大的多用戶、多任務(wù)操作系統(tǒng),支持多種處理器架構(gòu),具有可靠的系統(tǒng)安和良好的可移植性,所以成為了嵌入式開發(fā)系統(tǒng)的首選。
一個(gè)嵌入式產(chǎn)品分為硬件和軟件兩個(gè)部分[2],而其主要架構(gòu)如下圖 1所示:應(yīng)用層主要是軟件,硬件層是外接的器件。在下圖中設(shè)備驅(qū)動(dòng)層是具體硬件相關(guān)的實(shí)現(xiàn),也是驅(qū)動(dòng)開發(fā)中主要完成的部分。輸入核心層主要提供一些API供設(shè)備驅(qū)動(dòng)層調(diào)用,通過這些API設(shè)備驅(qū)動(dòng)層上報(bào)的數(shù)據(jù)就可以傳遞到事件處理層。事件處理層負(fù)責(zé)創(chuàng)建設(shè)備文件以及將上報(bào)的事件傳遞到用戶空間。
圖1 嵌入式產(chǎn)品的架構(gòu)圖
對(duì)于一個(gè)嵌入式產(chǎn)品,硬件也是必不可少的部分,操作系統(tǒng)為了去驅(qū)動(dòng)硬件,就需要將驅(qū)動(dòng)硬件的方法融入內(nèi)核中[3]。為了達(dá)到融合,設(shè)備驅(qū)動(dòng)中就需要設(shè)計(jì)面向操作系統(tǒng)的接口。不同的操作系統(tǒng),接口的格式就不同,這些接口由操作系統(tǒng)規(guī)定。本文使用Linux3.14內(nèi)核的操作系統(tǒng),針對(duì)i2C總線驅(qū)動(dòng)編寫,做了一個(gè)詳細(xì)的介紹。
i2C通信協(xié)議相對(duì)于SPI和UART通信方式,有這占用接口少,速度快的特點(diǎn)。SPI通信需要四條線才能實(shí)現(xiàn)和CPU芯片通信,也就是占用了CPU芯片四個(gè)引腳。而UART通信方式雖然也只占兩條線,但是他沒有時(shí)序作為參考,通信的速度不能太快,否則會(huì)增加出錯(cuò)的概率,所以為了兼顧速度和所占用的資源,i2C通信方式無疑是最好的選擇。所以i2C通信在嵌入式中應(yīng)用廣泛,很多傳感器都會(huì)選擇i2C通信協(xié)議實(shí)現(xiàn)和CPU芯片實(shí)現(xiàn)數(shù)據(jù)交互。比如我們使用的MPU6050和溫度傳感器ML75等。
操作系統(tǒng)為了使用這些傳感器就需要編寫驅(qū)動(dòng)程序[4]??紤]到傳感器設(shè)備是基于i2C總線而寫的,而不是直接使用platform總線,所以需要i2C控制器驅(qū)動(dòng)和傳感器設(shè)備驅(qū)動(dòng)同時(shí)工作。傳感器的驅(qū)動(dòng)基本都是一樣,但是CPU芯片由于生產(chǎn)的公司不同,設(shè)計(jì)的i2C控制器就不同,這就導(dǎo)致了一個(gè)問題。每使用一個(gè)公司的芯片,就需要去編寫一次驅(qū)動(dòng),而很多工作重復(fù)性很高,為了提高效率,也就是考慮到移植問題,提出了一種i2C子系統(tǒng)的編寫模式,將i2C控制器驅(qū)動(dòng)和從設(shè)備驅(qū)動(dòng)分離,以提高驅(qū)動(dòng)的移植性。下圖2描述了i2C子系統(tǒng)的設(shè)計(jì)框架和原理。
圖2 i2C子系統(tǒng)的設(shè)計(jì)框架和原理
從上圖可以看出將i2C控制器驅(qū)動(dòng)器和從設(shè)備驅(qū)動(dòng)分離,而linux內(nèi)核為了使i2C控制器驅(qū)動(dòng)和從設(shè)備驅(qū)動(dòng)能夠更好的匹配,設(shè)定了一個(gè)標(biāo)準(zhǔn),就是在I2C控制器和從設(shè)備驅(qū)動(dòng)之間加入了一個(gè)標(biāo)準(zhǔn)的函數(shù)接口層i2c_core.c。i2C控制器由芯片生產(chǎn)商提供,不同的廠家可以不同,但是必須要提供統(tǒng)一的接口給從設(shè)備調(diào)用,這樣就規(guī)范了i2C子系統(tǒng)的驅(qū)動(dòng)編寫,給工程師的使用帶來了便利[5]。從上面的框架圖中可以看出,linux不僅規(guī)范了i2C控制器驅(qū)動(dòng)的編寫,在linux內(nèi)核中i2c-dev.c已經(jīng)實(shí)現(xiàn)實(shí)現(xiàn)好了通用的IIC從設(shè)備驅(qū)動(dòng),所以我們編寫的驅(qū)動(dòng)可以使用linux提供的通用的i2C控制器驅(qū)動(dòng),我們也可以自定義去編寫。下面就詳細(xì)的闡述從這兩個(gè)方面去編寫i2C子系統(tǒng)驅(qū)動(dòng)。
i2C通用驅(qū)動(dòng)會(huì)為SOC芯片上的每一個(gè)i2C控制器生成一個(gè)設(shè)備號(hào)為89的設(shè)備節(jié)點(diǎn),用戶空間可以通過i2c設(shè)備節(jié)點(diǎn),訪問i2c控制器。每個(gè)i2c控制器的編號(hào)從0開始,對(duì)應(yīng)i2c設(shè)備文件的次設(shè)備號(hào)[6]。使用通用的i2C控制器驅(qū)動(dòng),首先就要配置linux內(nèi)核,linux3.14版本通用的驅(qū)動(dòng)在文件i2c-dev.c,我們要將該文件編譯進(jìn)內(nèi)核。i2c-dev.c實(shí)現(xiàn)的從設(shè)備驅(qū)動(dòng)中,并不包括實(shí)際的從設(shè)備操作方法。它只是在提供給應(yīng)用層一個(gè)設(shè)備文件,通過這個(gè)設(shè)備文件就可以找到特定的i2c控制器設(shè)備,。而i2c-dev.c的通用從設(shè)備驅(qū)動(dòng)操作i2c從設(shè)備分為下面三個(gè)步驟:
1.首先確定從設(shè)備是由哪一個(gè)i2c控制器控制。
2.通過i2c控制器的設(shè)備文件,找到i2c控制器。
3.我么將i2c從設(shè)備的信息,發(fā)送給i2c控制器,然后i2c控制器收到從設(shè)備的信息后,解析從設(shè)備的信息,從而發(fā)出i2c總線時(shí)序,這樣就可以和i2c從設(shè)備通信。
而在應(yīng)用層對(duì)應(yīng)硬件信息的描述,linux定義了一個(gè)特定的結(jié)構(gòu)體i2c_msg,用于描述i2c從設(shè)備的硬件信息,然后調(diào)用ioctrl函數(shù)將找個(gè)結(jié)構(gòu)體傳遞到i2c控制器,控制器會(huì)進(jìn)行解析,然后做出相應(yīng)的應(yīng)答。
從上面的分析可知,linux提供的通用I2C控制器驅(qū)動(dòng),為了達(dá)到通用的效果,linux內(nèi)核提供的i2C控制器驅(qū)動(dòng)就沒有具體的硬件信息,僅僅是封裝了一些函數(shù)通用的函數(shù),如open,read,write,ioctl。應(yīng)用層的工程師需要在應(yīng)用層填寫從設(shè)備的硬件信息,然后通過函數(shù)去調(diào)用底層驅(qū)動(dòng)接口。雖然這樣做很便捷,但是給應(yīng)用層的工程師帶來了開發(fā)的難度,他們不僅要了解應(yīng)用層的開發(fā)知識(shí),還需要知道硬件的知識(shí),去了解電路圖和芯片手冊(cè)。
自定義從設(shè)備驅(qū)動(dòng),就是將從設(shè)備的驅(qū)動(dòng)封裝在底層,然后提供一些應(yīng)用工程師熟悉的函數(shù)接口,應(yīng)用層不需要管是什么從設(shè)備,不用關(guān)心i2C總線上接的什么傳感器,他們只需要調(diào)用相應(yīng)的函數(shù)就可以了,這樣就給應(yīng)用層的開發(fā)帶來了便利。
i2c從設(shè)備驅(qū)動(dòng)是基于i2c總線而編寫的,對(duì)于總線編寫驅(qū)動(dòng)的原理,我們使用“總線”“設(shè)備”“驅(qū)動(dòng)”的框架去闡述[7]。arm芯片為了提高驅(qū)動(dòng)的移植性,提出了AMBA總線的標(biāo)準(zhǔn),工程師根據(jù)這個(gè)標(biāo)準(zhǔn)去編寫驅(qū)動(dòng),而不是根據(jù)自己去定義,這些總線都是標(biāo)準(zhǔn)的,所有的SOC芯片都是一樣的。外圍設(shè)備按照速度的不同掛載在SOC內(nèi)部的不同速度總線上。如表1所示列出了部分總線:
表1 總線分類表
同樣為了提高移植性,驅(qū)動(dòng)和設(shè)備分離,驅(qū)動(dòng)中不包含硬件信息,而在設(shè)備描述硬件信息。總線會(huì)維護(hù)兩條鏈表,分別管理設(shè)備和驅(qū)動(dòng),當(dāng)一個(gè)設(shè)備被注冊(cè)到總線上的時(shí)候,總線會(huì)根據(jù)其名字搜索對(duì)應(yīng)的驅(qū)動(dòng),如果找到就將設(shè)備信息導(dǎo)入驅(qū)動(dòng)程序并執(zhí)行驅(qū)動(dòng);當(dāng)一個(gè)驅(qū)動(dòng)被注冊(cè)到平臺(tái)總線的時(shí)候,總線也會(huì)搜索設(shè)備??傊?,平臺(tái)總線負(fù)責(zé)將設(shè)備信息和驅(qū)動(dòng)代碼匹配,這樣就可以做到驅(qū)動(dòng)和設(shè)備信息的分離[8]。注冊(cè)設(shè)備的流程圖和注冊(cè)驅(qū)動(dòng)的流程圖如下圖所示:
圖3 注冊(cè)設(shè)備的流程圖
注冊(cè)設(shè)備的時(shí)候,一旦注冊(cè)進(jìn)內(nèi)核,內(nèi)核就會(huì)根據(jù)設(shè)備的名字去找同名的驅(qū)動(dòng),如本文設(shè)定的設(shè)備名字為led,那么內(nèi)核就會(huì)去驅(qū)動(dòng)鏈表中找led名字的驅(qū)動(dòng),發(fā)現(xiàn)目標(biāo)匹配成功后就會(huì)調(diào)用驅(qū)動(dòng)的probe函數(shù)。這個(gè)函數(shù)的作用就是獲取匹配后的硬件資源并注冊(cè)字符設(shè)備。同樣,在注冊(cè)驅(qū)動(dòng)的時(shí)候,內(nèi)核也會(huì)根據(jù)這個(gè)驅(qū)動(dòng)的名字led去設(shè)備鏈表上同名的設(shè)備。同樣在匹配成功后調(diào)用probe函數(shù)。
圖4 注冊(cè)驅(qū)動(dòng)的流程圖
驅(qū)動(dòng)和設(shè)備文件是通過文件進(jìn)行匹配,也就是如果要想設(shè)備和驅(qū)動(dòng)最終能夠互相匹配,就必須將設(shè)備的名字和驅(qū)動(dòng)的名字設(shè)置為一樣的。若驅(qū)動(dòng)提供了id_table,則那設(shè)備名和id_table進(jìn)行比較。若驅(qū)動(dòng)沒有提供id_table,則直接使用驅(qū)動(dòng)名和設(shè)備名進(jìn)行匹配。
本文基于linux3.14內(nèi)核,分析了i2c子系統(tǒng)的原理和實(shí)現(xiàn)框架,最后將驅(qū)動(dòng)移植到硬件平臺(tái)上,并且編寫測(cè)試程序,成功讀取了MUP6050里關(guān)于加速度的相關(guān)參數(shù)。
[1]宋寶華.Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解[M].北京:人民郵電出版社,2010.
[2]胡祖寶,董國通.基于S3C2440的嵌入式Linux內(nèi)核移植及字符設(shè)備驅(qū)動(dòng)開發(fā)[J].工業(yè)控制計(jì)算機(jī),2015,28(12).
[3]Dong Yu Zhang.Design of Touch Screen Driver Based on Linux[J].KeyEngineeringMaterials,2011,1104(467):818-822.
[4]王新勇.基于ARM的Linux驅(qū)動(dòng)開發(fā)研究[D].南昌:江西理工大學(xué),2011.
[5]XuDongChen,LingChengKong,ZhiHuaZhang,DanWang,Tao Mei.Design of USB Interface Driver for WSNs Node Tester Based on Embedded Linux[J].Applied Mechanics and Materials,2011,1069(40):266-271.
[6]Peter H.Welch,Herman W.Roebbers,Jan F.Broenink,Frederick R.M.Barnes,Carl G.Ritson,Adam T.Sampson,Gardiner S.Stiles,Brian Vinter,Arjen Klomp,Herman Roebbers,Ruud Derwig,Leon Bouwmeester.Designing a Mathematically Verified ICDeviceDriverUsingASD[M].IOSPress:2009.
[7]王巖,王子牛.嵌入式Linux設(shè)備驅(qū)動(dòng)程序開發(fā)[J].貴州工業(yè)大學(xué)學(xué)報(bào)(自然科學(xué)版),2008,37(1).
[8]汪海兵.嵌入式Linxu的研究與應(yīng)用[D].昆明:昆明理工大學(xué),2002.