張 東 許弟建
摘 要:編寫(xiě)聯(lián)系操作系統(tǒng)和相應(yīng)硬件設(shè)備的驅(qū)動(dòng)程序至關(guān)重要。在Platform Builder 4.2開(kāi)發(fā)環(huán)境下,基于流接口驅(qū)動(dòng)程序模型,詳細(xì)闡述嵌入式操作系統(tǒng)Win CE下EP9315芯片的SPI接口的驅(qū)動(dòng)程序設(shè)計(jì)方法,就設(shè)計(jì)步驟、虛擬地址映射實(shí)現(xiàn)和關(guān)鍵程序代碼編寫(xiě)等進(jìn)行具體分析,并論述驅(qū)動(dòng)程序與EVC編程環(huán)境下SPI應(yīng)用程序之間的關(guān)系。驅(qū)動(dòng)程序和相應(yīng)應(yīng)用程序能正確運(yùn)行于優(yōu)龍的FS_EP9315開(kāi)發(fā)平臺(tái)。實(shí)踐證明,該方法正確可行。
關(guān)鍵詞:嵌入式操作系統(tǒng);Win CE;SPI;驅(qū)動(dòng)程序
中圖分類(lèi)號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:B
文章編號(hào):1004-373X(2009)10-069-04
Design of EP9315-SPI Driver Based on Win CE
ZHANG Dong1,XU Dijian2
(1.Chongqing University of Arts and Sciences,Chongqing,402160,China;2.Chongqing University of Science and Technology,Chongqing,401331,China)
Abstract: It is very important to compile driver connecting operating system with corresponded hardware device.Based on stream interface driver model,the design of SPI driver in embedded operating system Win CE in development environment of platform builder 4.2 and design method are introduced and analysed,realizing virtual address map,key code and the relationship between driver and SPI application program in EVC program environment is discussed.Driver and corresponded application program can be operated on FS_EP9315 development platform of ucdragon rightly.Experience indicates the methord is right and feasible.
Keywords:embedded operating system;Win CE;SPI;driver program
0 引 言
嵌入式是“以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ),軟硬件可裁剪,適合應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗嚴(yán)格要求的計(jì)算機(jī)系統(tǒng)”。Windows CE.NET是Microsoft推出的功能強(qiáng)大的緊湊、高效、可伸縮的32位嵌入式操作系統(tǒng),主要面對(duì)各種各樣嵌入式系統(tǒng)的產(chǎn)品[1,2]。
該系統(tǒng)具有多線(xiàn)程、多任務(wù)、完全搶占式的特點(diǎn),是為各種具有嚴(yán)格資源限制的硬件系統(tǒng)所設(shè)計(jì)的。為了將操作系統(tǒng)和硬件設(shè)備連接起來(lái),硬件和軟件的驅(qū)動(dòng)聯(lián)系就顯得很重要。SPI是一種高速、全雙工、同步的通信總線(xiàn),在芯片的管腳上只占用4根線(xiàn),節(jié)約了芯片的管腳,同時(shí)為PCB的布局節(jié)省了空間,提供了方便,正是出于這種簡(jiǎn)單易用的特性,現(xiàn)在越來(lái)越多的芯片都集成了這種通信協(xié)議。SPI的工作模式有兩種:主模式和從模式,SPI總線(xiàn)可以配置成單主單從、單主多從、互為主從。為了充分利用芯片的SPI接口進(jìn)行相應(yīng)的驅(qū)動(dòng)程序設(shè)計(jì)以及應(yīng)用程序設(shè)計(jì),通用方法的研究就顯得十分重要。
1 Win CE提供的驅(qū)動(dòng)模型
Win CE操作系統(tǒng)支持兩種類(lèi)型的驅(qū)動(dòng)程序,一種為本地驅(qū)動(dòng)程序,是把設(shè)備驅(qū)動(dòng)程序作為獨(dú)立的任務(wù)實(shí)現(xiàn)的,直接在頂層任務(wù)中實(shí)現(xiàn)硬件操作,因此有明確和專(zhuān)一的目的。本地驅(qū)動(dòng)程序適合于那些集成到Win CE平臺(tái)的設(shè)備,諸如鍵盤(pán)、觸摸屏等設(shè)備。另一種是具有定制接口的流接口驅(qū)動(dòng)程序,它是一般類(lèi)型的設(shè)備驅(qū)動(dòng)程序,為用戶(hù)一級(jí)的動(dòng)態(tài)鏈接庫(kù)(DLL)文件,用來(lái)實(shí)現(xiàn)一組固定的函數(shù)稱(chēng)為“流接口函數(shù)”,這些流接口函數(shù)使得應(yīng)用程序可以通過(guò)文件系統(tǒng)訪(fǎng)問(wèn)這些驅(qū)動(dòng)程序。這里論述的SPI驅(qū)動(dòng)就屬于流接口驅(qū)動(dòng)。
2 SPI驅(qū)動(dòng)程序的設(shè)計(jì)
2.1 EP9315芯片及SPI接口簡(jiǎn)介
EP9315是一款基于ARM920T,由Cirrus Logic公司生產(chǎn)的工業(yè)級(jí)芯片[3,4] ,內(nèi)帶MMU,16 KB的指令Cache,16 KB的數(shù)據(jù)Cache和數(shù)學(xué)協(xié)處理器,主頻為200 MHz,系統(tǒng)總線(xiàn)為100 MHz。該芯片擁有一組SPI接口,利用它可方便實(shí)現(xiàn)與外圍SPI器件進(jìn)行通信,可大大簡(jiǎn)化工程應(yīng)用的硬件設(shè)計(jì)軟件。
SPI驅(qū)動(dòng)程序采用Win CE流驅(qū)動(dòng)的標(biāo)準(zhǔn)形式。下面從驅(qū)動(dòng)程序具體設(shè)計(jì)步驟以及驅(qū)動(dòng)代碼的編寫(xiě)兩個(gè)方面做較為詳細(xì)的闡述。
2.2 SPI驅(qū)動(dòng)程序設(shè)計(jì)步驟
在Platform Builder 4.2下設(shè)計(jì)Win CE流接口驅(qū)動(dòng)程序可按照以下步驟進(jìn)行[5-7]:
(1) 在C:\Win CE420\PLATFORM\ep931x\drivers目錄下新建一個(gè)目錄SPI;
(2) 從其他驅(qū)動(dòng)目錄下復(fù)制makefile文件到SPI目錄下;
(3) 用文本編輯器建立4個(gè)文本文件,文件名分別為SPI.c,SPI.h,SPI.def和sources;
(4) 編輯目錄C:\Win CE420\PLATFORM\ep931x\driver下的dirs文件。用文本編輯器打開(kāi)該文件,找到“DIRS=”等式,在該等式最后添加一行, 如下面所示:
DIRS=…
SPI
(5) 在Platform Builder 4.2中打開(kāi)Platform.bib文件,在該文件最后和FILES之前加入一行,指明在生成Windows CE內(nèi)核映射時(shí)自動(dòng)將SPI.dll加入到內(nèi)核映像中,添加內(nèi)容如下:
SPI.dll MYM(_FLATRELEASEDIR) SPI.dll NK SH
(6)具體的流接口驅(qū)動(dòng)程序跟注冊(cè)表密不可分,在Platform Builder 4.2中打開(kāi)platform.reg文件,在該文件最后加入如下所示注冊(cè)表信息,以使在生成操作系統(tǒng)映像時(shí),Platform Builder將注冊(cè)表信息加入到注冊(cè)表中。在Platform.reg中添加內(nèi)容如下:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\SPI]
"Prefix"=" SPI "
"Dll"=" SPI.dll"
"FriendlyName"=" SPI Driver"
"Index"=dword:1
"Order"=dword:0
(7) 為了通知Windows CE驅(qū)動(dòng)的函數(shù),需要在SPI.def文件中指出要導(dǎo)出的函數(shù),編寫(xiě)內(nèi)容如下:
LIBRARYSPI
EXPORTS
SPI_Init
SPI _Deinit
SPI _Open
SPI _Close
SPI _Read
SPI _Write
…
其中LIBRARY表示該驅(qū)動(dòng)的動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)名稱(chēng),EXPORTS段后面列出要從驅(qū)動(dòng)的動(dòng)態(tài)鏈接庫(kù)文件中導(dǎo)出的函數(shù)名稱(chēng)。
(8) 編輯sources文件的內(nèi)容,告訴編輯器和連接器如何編譯及連接本驅(qū)動(dòng)程序。
TARGETNAME=SPI
RELEASETYPE=PLATFORM
TARGETTYPE=DYNLINK
TARGETLIBS= MYM(_COMMONSDKROOT) \lib\MYM(_CPUINDPATH)\coredll.lib
DEFFILE=MYM(TARGETNAME).def
PREPROCESSDEFFILE=1
DLLENTRY=DllEntry
SOURCES=SPI.c
FILE_VIEW_INCLUDES_FOLDER=SPI.h
(9) 改寫(xiě)并導(dǎo)入新的ep931x.cec文件
在C:\Win CE420\PLATFORM\ep931x\bspfiles文件夾下,打開(kāi)并改寫(xiě)ep931x.cec文件。
在Platform builder 4.2環(huán)境下,刪除原來(lái)的cec文件,并導(dǎo)入添加SPI部分后的ep931x.cec文件。在catalog窗口中選擇SPI驅(qū)動(dòng)加入到要編譯的映像中。
至此,SPI驅(qū)動(dòng)程序的框架已經(jīng)搭建完畢,剩下的工作就按照流接口驅(qū)動(dòng)要求編寫(xiě)驅(qū)動(dòng)程序代碼。
2.3 驅(qū)動(dòng)代碼編寫(xiě)
每個(gè)流接口驅(qū)動(dòng)程序必須實(shí)現(xiàn)1組標(biāo)準(zhǔn)函數(shù),用來(lái)完成標(biāo)準(zhǔn)的文件I/O函數(shù)和電源管理函數(shù),這些函數(shù)提供給Win CE操作系統(tǒng)的內(nèi)核使用。
SPI流接口驅(qū)動(dòng)程序重點(diǎn)要實(shí)現(xiàn)的dll接口函數(shù)如下:
SPI_Init:驅(qū)動(dòng)程序加載函數(shù);
SPI_Deinit:驅(qū)動(dòng)程序卸載函數(shù);
SPI_Open:驅(qū)動(dòng)程序打開(kāi)函數(shù);
SPI_Close:驅(qū)動(dòng)程序關(guān)閉函數(shù);
SPI_Write:寫(xiě)函數(shù);
SPI_Read:寫(xiě)函數(shù)。
下面重點(diǎn)對(duì)SPI _Init,SPI _Write兩個(gè)函數(shù)做闡述,其他函數(shù)代碼可參照相關(guān)資料編寫(xiě)。
(1) SPI_Init函數(shù)設(shè)計(jì)。
在Win CE中,程序訪(fǎng)問(wèn)的地址都是虛擬地址,因此要訪(fǎng)問(wèn)硬件物理地址,必須將物理地址空間映射到虛擬空間。
在SPI_Init函數(shù)中,首先通過(guò)函數(shù)VirtualAlloc()和VirtualCopy(),把EP9315芯片中針對(duì)SPI的物理地址和操作系統(tǒng)的虛擬空間聯(lián)系起來(lái)。在其他流接口函數(shù)中,即可對(duì)申請(qǐng)到的虛擬地址進(jìn)行操作,按照Win CE中的流驅(qū)動(dòng)模型進(jìn)行驅(qū)動(dòng)的編寫(xiě),對(duì)虛擬地址空間的操作就相當(dāng)于對(duì)芯片的物理地址進(jìn)行操作[1]。SPI_Init的函數(shù)中,有關(guān)地址映射如下實(shí)現(xiàn):
① 在SPI.h頭文件中定義數(shù)據(jù)結(jié)構(gòu)。
EP9315芯片SPI寄存器物理地址分配如表1所示[5],包括控制寄存器、數(shù)據(jù)寄存器、狀態(tài)寄存器、頻率設(shè)置寄存器、與中斷有關(guān)的寄存器。
因而定義的數(shù)據(jù)結(jié)構(gòu)為:
#define IOP_BASE0x808A0000
typedef struct {
// SPI PORT
unsigned int rSPICR0;
unsigned int rSPICR1;
unsigned int rSPIDR;
unsigned int rSPISR;
unsigned int rSPICPSR;
unsigned int rSPIIIR;
unsigned int rSPIICR;
}IOPreg;
② 在SPI_Init()中地址映射實(shí)現(xiàn)。
地址映射通過(guò)VirtualCopy()和VirtualCopy()兩個(gè)函數(shù)實(shí)現(xiàn)。VirtualCopy()函數(shù)是Win CE中分配連續(xù)虛擬地址的API,利用該函數(shù)為SPI接口各個(gè)寄存器物理地址申請(qǐng)?zhí)摂M地址。VirtualCopy()函數(shù)負(fù)責(zé)把SPI接口各個(gè)寄存器物理地址映射到申請(qǐng)到的虛擬地址。
為方便驅(qū)動(dòng)程序調(diào)試,可利用ERRORMSG()函數(shù)在程序適當(dāng)位置加上一些調(diào)試信息,這些調(diào)試信息在驅(qū)動(dòng)程序運(yùn)行時(shí)可通過(guò)超級(jí)終端口輸出,方便驅(qū)動(dòng)程序調(diào)試。
結(jié)合EP9315的SPI接口,需要設(shè)置控制寄存器和波特率寄存器。
為實(shí)現(xiàn)對(duì)標(biāo)準(zhǔn)SPI接口的LED屏幕進(jìn)行顯示控制,需要配置EP9315的SPII總線(xiàn)為單主單從模式,可通過(guò)設(shè)置SPI接口控制寄存器實(shí)現(xiàn)。為調(diào)整LED的刷新頻率,可通過(guò)設(shè)置SPI接口頻率設(shè)置寄存器實(shí)現(xiàn)。
SPI_Init()中包含有如下重要代碼:
// VirtualAlloc()申請(qǐng)?zhí)摂M地址
v_pIOPregs = (volatile IOPreg *)VirtualAlloc(0,sizeof(IOPreg), MEM_RESERVE,PAGE_NOACCESS);
if (v_pIOPregs == NULL)
RetValue = FALSE;
else
{
// VirtualCopy()實(shí)現(xiàn)虛擬地址的映射
if (!VirtualCopy((PVOID)v_pIOPregs,
(PVOID)(IOP_BASE >> 8),sizeof(IOPreg),PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
RetValue = FALSE;
Else
// ERRORMSG()輸出調(diào)試信息
ERRORMSG(1,(TEXT("For IOPregs :VirtualCopy success!\r\n")));
//設(shè)置控制寄存器和波特率寄存器
v_pIOPregs->rSPICPSR = 0x18;
v_pIOPregs->rSPICR0 = 0x18;
(2) SPI_Write寫(xiě)函數(shù)設(shè)計(jì)。
文中涉及的工程需要通過(guò)EP9315的SPI接口,實(shí)現(xiàn)對(duì)一個(gè)帶有標(biāo)準(zhǔn)SPI接口的LED屏進(jìn)行寫(xiě)入數(shù)據(jù)操作,實(shí)現(xiàn)對(duì)LED屏的顯示控制。
下列寫(xiě)函數(shù)程序代碼中,通過(guò)MapPtrToProcess()獲取應(yīng)用程序編輯框中輸入的數(shù)據(jù):
v_pIOPregs->rSPIDR = *pWriteBuffer;
向SPI接口發(fā)送一個(gè)8位數(shù)據(jù)。通過(guò)一個(gè)for循環(huán)實(shí)現(xiàn)一個(gè)1 024(128×8) b的數(shù)據(jù)的發(fā)送,以滿(mǎn)足所涉及的LED屏數(shù)據(jù)位的要求。
具體程序代碼如下:
DWORD SPI_Write
(DWORD hOpenContext,LPVOID pBuffer,DWORD Count)
{uchar i;
uchar * pWriteBuffer;
…
pWriteBuffer=MapPtrToProcess(pBuffer,GetCallerProcess());
// Write 1024(=128x8) bits
for(i=0;i<128;i++)
{
while( (v_pIOPregs->rSPISR & 0x01) != 1 );
v_pIOPregs->rSPIDR = *pWriteBuffer;
}
// Wait to complete write data
while( (v_pIOPregs->rSPISR & 0x01) != 1 );
return 1;
}
上述寫(xiě)函數(shù)設(shè)計(jì)實(shí)現(xiàn)了對(duì)SPI接口的寫(xiě)操作,應(yīng)用程序通過(guò)調(diào)用該函數(shù),即可實(shí)現(xiàn)對(duì)帶有標(biāo)準(zhǔn)SPI接口的LED屏進(jìn)行顯示控制。對(duì)寫(xiě)函數(shù)進(jìn)行相關(guān)改動(dòng),即可設(shè)計(jì)出SPI_Read函數(shù),實(shí)現(xiàn)對(duì)SPI接口器件數(shù)據(jù)讀取操作,限于篇幅,在此不再贅述。
3 SPI應(yīng)用程序設(shè)計(jì)
設(shè)計(jì)的SPI驅(qū)動(dòng)程序是否正確,可在EVC 4.0環(huán)境下編寫(xiě)相關(guān)應(yīng)用程序驗(yàn)證。
編寫(xiě)SPI接口的應(yīng)用程序[5,8],可實(shí)現(xiàn)加載驅(qū)動(dòng)、卸載驅(qū)動(dòng)、打開(kāi)驅(qū)動(dòng)、關(guān)閉驅(qū)動(dòng)、接口功能設(shè)置、接口讀寫(xiě)等操作。在此僅編寫(xiě)了一個(gè)讀寫(xiě)SPI接口的應(yīng)用程序,以對(duì)前面設(shè)計(jì)的SPI_Init,SPI_Deinit,SPI_Open,SPI_Close,SPI_Write等流接口函數(shù)進(jìn)行驗(yàn)證。EVC 4.0編程環(huán)境下設(shè)計(jì)界面如圖1所示。
通過(guò)RegCreateKeyEx(),WRITE_REG_SZ(),WRITE_REG_DWORD()等函數(shù)創(chuàng)建注冊(cè)表,實(shí)現(xiàn)加載驅(qū)動(dòng);通過(guò)CreateFile()調(diào)用SPI_Open(),打開(kāi)驅(qū)動(dòng)程序;通過(guò)WriteFile()調(diào)用SPI_Write()實(shí)現(xiàn),對(duì)SPI接口的寫(xiě)入操作。通過(guò)ReadFile()調(diào)用SPI_Read(),實(shí)現(xiàn)對(duì)SPI接口的讀取操作。
由于篇幅關(guān)系,現(xiàn)僅列 “數(shù)據(jù)寫(xiě)入SPI”部分的關(guān)鍵代碼。其他代碼可參照相關(guān)資料編寫(xiě)。
void CGpioDlg::OnWrite()
{
DWORD actlen;
if(hFile==INVALID_HANDLE_VALUE)
{return; }
UpdateData(TRUE);
BOOL ret=WriteFile(hFile,&m;_WriteByte,1,&actlen;,NULL);
}
4 實(shí)驗(yàn)結(jié)果
在Platform Builder 4.2環(huán)境下編譯并下載內(nèi)核到優(yōu)龍公司的FS_EP9315開(kāi)發(fā)平臺(tái),Win CE運(yùn)行正常。在Win CE操作系統(tǒng)下運(yùn)行SPI應(yīng)用程序,在運(yùn)行界面的“寫(xiě)入SPI數(shù)據(jù)”下面的編輯窗口輸入待寫(xiě)入數(shù)據(jù)0x55,按“數(shù)據(jù)寫(xiě)入SPI”按鈕,能實(shí)現(xiàn)對(duì)SPI接口的寫(xiě)入操作。通過(guò)示波器觀察EP9315的SPI接口的輸出引腳、SSPTX1引腳,波形如圖2所示。由分析圖中的波形可知,高低電平間隔出現(xiàn),證明發(fā)送數(shù)據(jù)正確。
整個(gè)實(shí)驗(yàn)表明,上述設(shè)計(jì)方法正確可行,驅(qū)動(dòng)程序和應(yīng)用程序運(yùn)行正常。
5 結(jié) 語(yǔ)
這里主要論述了在嵌入式操作系統(tǒng)Win CE下SPI驅(qū)動(dòng)程序的開(kāi)發(fā)步驟及關(guān)鍵代碼的編寫(xiě),并對(duì)SPI應(yīng)用程序設(shè)計(jì)以及驅(qū)動(dòng)程序和應(yīng)用程序二者之間的聯(lián)系進(jìn)行對(duì)比分析。文中對(duì)其他流接口驅(qū)動(dòng)程序的設(shè)計(jì)和應(yīng)用程序的設(shè)計(jì)具有一定的指導(dǎo)意義。
參考文獻(xiàn)
[1]傅曦,陳黎.Windows CE.Net嵌入式開(kāi)發(fā)入門(mén)基于Xscae架構(gòu).北京:人民郵電出版社,2006.
[2]姜波.Windows CE.Net程序設(shè)計(jì).北京:機(jī)械工業(yè)出版社,2007.
[3]Cirrus Logic.EP9315 User′s Guild.2004.
[4]Cirrus Logic.EP9315 Date Sheet.2004.
[5]周立功.ARM&Win; CE實(shí)驗(yàn)與實(shí)踐.北京:北京航空航天大學(xué)出版社,2007.
[6]王小芳,王典洪,陳飛.基于Win CE的I2C驅(qū)動(dòng)程序設(shè)計(jì).單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2006(4):28-30.
[7]彭少武,宋娟.Windows CE的CAN總線(xiàn)驅(qū)動(dòng)程序設(shè)計(jì).單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2007(11):79-81.
[8]汪兵.EVC高級(jí)編程及其應(yīng)用開(kāi)發(fā)[M].北京:中國(guó)水利水電出版社,2005.
[9]孫豐軍,余春暄.SPI串行總線(xiàn)接口的Verilog實(shí)現(xiàn).現(xiàn)代電子技術(shù),2005,28(16):105-106,109.