引言 Windows CE是一個(gè)開(kāi)放的、可升級、可裁減的32位實(shí)時(shí)嵌入式操作系統,具有可靠性好、實(shí)時(shí)性高、內核體積小的特點(diǎn),廣泛應用于工業(yè)控制、信息家電、移動(dòng)通信、汽車(chē)電子、個(gè)人電子消費品等領(lǐng)域。最新版本W(wǎng)indows Em-bedded CE 6.0于2006年11月發(fā)布,其特點(diǎn)有:最大進(jìn)程數量到32K,且每個(gè)進(jìn)程有最大2 GB的虛擬內存空間;將關(guān)鍵的驅動(dòng)程序、文件系統和圖形界面管理器移到了內核中,大大減少了CPU在內核態(tài)和用戶(hù)態(tài)間切換造成的性能損失等。 LPC3250是NXP半導體公司(由Philips公司成立)推出的帶有矢量浮點(diǎn)協(xié)處理器的ARM926EJ-SCPU內核的微控制器。它具有豐富的外圍接口,包括7個(gè)UART,其中4個(gè)是標準UART,另外3個(gè)是高速UART,都帶有64字節的接收和發(fā)送FIFO,最高可支持的速率達921 600 b/s。為了實(shí)現低功耗,LPC3250采用NXP半導體先進(jìn)的開(kāi)發(fā)技術(shù)來(lái)優(yōu)化內在功率,并使用增強型的軟件控制結構使基于功率管理的應用得到優(yōu)化。在同時(shí)要求高性能和低功耗的嵌入式應用中,運行Win-dows CE的LPC3250平臺將會(huì )有很好的市場(chǎng)前景,對于最常用到的串口的驅動(dòng)開(kāi)發(fā)顯得尤為重要。 1 WindOWS CE的串口驅動(dòng)模型 基于Windows CE有兩種驅動(dòng)程序模型:本機設備驅動(dòng)程序和流接口驅動(dòng)程序。串口驅動(dòng)就屬于分層的流接口驅動(dòng)程序。分層驅動(dòng)程序將設備的驅動(dòng)程序分為兩層:平臺相關(guān)驅動(dòng) PDD(Platform Dependence Driver)層和模型設備驅動(dòng)MDD(Model Device Driver)層。PDD層由特定于給定硬件設備或平臺的代碼組成,很多時(shí)候用戶(hù)需要根據具體平臺修改;MDD層包含平臺無(wú)關(guān)的代碼,它通過(guò)實(shí)現一些操作系統預先定義的接口來(lái)實(shí)現某一類(lèi)設備的通用功能,通常由微軟提供。操作系統與MDD層之間通過(guò)DDI(設備驅動(dòng)接口)進(jìn)行交互。MDD層也實(shí)現了中斷處理線(xiàn)程IST,并定義一些與PDD層的接口函數,這些接口函數稱(chēng)為DDSI(設備驅動(dòng)服務(wù)接口)。 用%_WINCEROOT%來(lái)表示W(wǎng)indows CE的安裝根目錄,符合‘550工業(yè)規范的串口驅動(dòng)源碼主要位于\%_WINCEROOT%\PUBLIC\COMMON\OAK\DRIVERS\SERIAL下,主要看表1所列的一些重要文件。 ![]() 如圖1所示,串口應用程序通過(guò)設備管理器調用mdd.c中MDD層的標準流設備驅動(dòng)接口COM_XXX,在COM_XXX中通過(guò)結構體 HW_INDEP_INFO中HWOBJ結構體調用串口硬件操作函數HWxxx;然后在cserpdd.cpp中GetSeri-alObject函數通過(guò)HW_VTBL類(lèi)型數組IoVTb1將HWxxx映射為Serxxx系列函數,Serxxx系列函數則調用CSerialPDD類(lèi)中的成員函數(其中的純虛函數由CserialP-DD的繼承類(lèi)CP-dd16550實(shí)現,真正與物理底層操作的是CPdd16550的數據成員CReg16550中的 Write_XXX、Read_XXX函數);最終通過(guò)調用WRITE_PORT_UCHAR和READ_PORT_UCHAR系統函數來(lái)實(shí)現。 ![]() 2 WinCE6.0下的LPC3250串口驅動(dòng)程序開(kāi)發(fā) Windows CE的串口驅動(dòng)程序開(kāi)發(fā)中最重要的是兩點(diǎn):配置串口相關(guān)的寄存器和處理中斷。配置寄存器,包括實(shí)現與物理底層操作的函數,將寄存器地址映射到內核進(jìn)程的虛擬地址,在串口操作的不同階段配置好各種寄存器;處理中斷,包括將物理中斷映射為系統中斷,將中斷與事件綁定,中斷發(fā)生時(shí)進(jìn)行相應的中斷處理。 LPC3250串口與‘550工業(yè)規范的串口有差異,為了保證程序的通用性和盡量減少代碼量,在實(shí)現LPC3250串口驅動(dòng)程序時(shí),需要繼承 CPdd16550和CReg16550類(lèi),根據實(shí)際的硬件特性實(shí)現它們的純虛函數并擴展其虛函數的功能,配置硬件相關(guān)的寄存器和修改相關(guān)代碼。首先實(shí)現 CReg16550的繼承類(lèi)CRegLPC32xx,主要實(shí)現與物理底層操作的函數Write_xxx和Read_xxx,對串口寄存器進(jìn)行讀寫(xiě)操作。這里要注意的是LPC3250串口寄存器地址間隔是32位,而不是標準的8位;CPdd16550的繼承類(lèi)Clpc32xxPdd16550UART本質(zhì)還是個(gè)抽象類(lèi),同時(shí)為標準串口和高速串口服務(wù),要重新實(shí)現Init、GetDivisorO-{Rate、GetWaterMark、 MapHardware、CreateHardwareAc-cess、CreateSerialObject、DeleteSerialObject等函數,其他的函數可以直接調用CPdd16550的成員函數,只需要修改相關(guān)串口寄存器的宏定義。 在Clpc32xxPdd16550UART的Init函數中,GetIsrInfo以串口的Active注冊表鍵為依據查出物理中斷號,并保存在 DDKISRINFO結構體的dwlrq成員中。KernelloCon-trol函數將物理中斷號轉換為邏輯中斷號,符合條件就將邏輯中斷號回寫(xiě)到注冊表中。相關(guān)代碼如下: ![]() 接著(zhù)調用父類(lèi)CPdd16550的Init函數,創(chuàng )建中斷服務(wù)線(xiàn)程(IST)事件,并通過(guò)InterruptInitialize函數將事件與邏輯中斷號關(guān)聯(lián)起來(lái),最后調用CreateHardwareAccess和MapHardware函數將串口基地址及相關(guān)寄存器片內地址映射到內核進(jìn)程的虛擬地址。 在MapHardware中,用GetWindowInfo根據串口的Active注冊表鍵獲得串口的全部I/O端口和內存地址信息,然后用 MmMapIoSpace函數將串口物理地址和相關(guān)控制寄存器地址轉換成內核進(jìn)程的虛擬地址,以便后面對寄存器進(jìn)行操作,部分代碼如下: ![]() CreateHardwareAccess函數根據MapHardware得到的m_pBaseAddress,構造一個(gè)CRegLPC32xx類(lèi)實(shí)例,然后調用CRegLPC32xx類(lèi)的Init函數確保串口控制器硬件進(jìn)入穩定的工作狀態(tài)。 根據LPC3250的數據手冊,設置標準UART的波特率需要設置小數波特率預分頻器和UART波特率發(fā)生器。當不用小數波特率預分頻器(即X=Y=1) 時(shí),將標準UART的{Baudrate,DLM:DLL}的值定義一個(gè)數組BaudPairs[]。GetDivisorOfRate根據這個(gè)數組得到分頻系數,然后調用父類(lèi)的成員函數SetBaudRate便可設置波特率。高速UART的波特率類(lèi)似,只是波特率計算公式和分頻系數與標準UART不同。 用GetWaterMark得到接收器FIFO的觸發(fā)深度,分別為16、32、48和60位,然后在CPdd16550的InitReceive中設置FIFO控制寄存器,默認的FIFO觸發(fā)深度是32位。 Clpc32xxPdd16550UART是個(gè)抽象類(lèi),實(shí)現通用功能,具體的要分別由繼承的標準串口Clpc32xxPdd16550Stan- dardUART類(lèi)和高速串口Clpc32xxPdd16550HighUART類(lèi)實(shí)現。在各自初始化時(shí),主要是配置各種寄存器,實(shí)現具體硬件差異化,包括:配置UART時(shí)鐘控制寄存器、時(shí)鐘模式寄存器和時(shí)鐘選擇寄存器,分別使能UART時(shí)鐘、設置自動(dòng)時(shí)鐘模式、選擇相應的時(shí)鐘源作為分頻器的輸入時(shí)鐘;禁止UART3 Modem和UART6 IrDA功能;禁止UART的回送功能。 特別要強調的是關(guān)于中斷的處理,串口驅動(dòng)中斷可以用動(dòng)態(tài)映射,也可以用靜態(tài)映射。在OEMInter-ruptHandler、 Clpc32xxPdd16550UART::Init、CPdd16550::Init、CPdd16550::ThreadRun等處加入調試打印信息,可以較快地找到問(wèn)題所在,確定硬件中斷是否映射為系統中斷、系統中斷與中斷事件是否綁定、中斷產(chǎn)生時(shí)是否進(jìn)入相應的處理程序。中斷處理好了,串口驅動(dòng)就基本完成了。 上述工作結束后,就要添加串口的注冊表。以串口3為例,主要是設置動(dòng)態(tài)鏈接庫DLL、設備基地址、中斷號、前綴名、被加載的順序等。根據注冊表的 DeviceArrayIn-dex、CreateSerialObject就可以構造標準串口或高速串口類(lèi)實(shí)例了, DeleteSerialObject在退出驅動(dòng)時(shí)刪除實(shí)例。具體代碼如下: ![]() ![]() 在廣州致遠電子有限公司的SmartARM3250開(kāi)發(fā)板上,通過(guò)WinCE的串口應用程序與上位PC機進(jìn)行發(fā)送接收實(shí)驗,本驅動(dòng)已經(jīng)實(shí)現標準串口最高460 800 b/s、高速串口最高921 600 b/s的穩定傳輸。 結語(yǔ) 本文介紹了WinCE6.0下的串口驅動(dòng)模型,結合LPC3250的硬件情況,詳細說(shuō)明了串口驅動(dòng)開(kāi)發(fā)過(guò)程,包括配置串口相關(guān)的寄存器和處理中斷中重要函數的實(shí)現,以及注冊表和Source文件編寫(xiě)等。本驅動(dòng)程序在廣州致遠電子有限公司的SmartARM3250開(kāi)發(fā)板上實(shí)驗成功。在串口驅動(dòng)開(kāi)發(fā)中所用的思路,對其他類(lèi)似的驅動(dòng)設計有較高的參考價(jià)值。 參考文獻 1. 周毓林,寧楊,陸貴強,等.Windows CE.NET內核定制及應用程序開(kāi)發(fā)[M].北京:電子工業(yè)出版社,2005. 2. NXP Semiconductor Inc.Draft LPC32x0 User manual,2008. 3. 周立功,等.ARM&WinCE實(shí)驗與實(shí)踐:基于S3C2410[M].北京:北京航空航天大學(xué)出版社,2007. 4. 何宗鍵.Windows CE嵌入式系統[M].北京:北京航空航天大學(xué)出版社,2006. 5. 李大為.Windows CE工程實(shí)踐完全解析[M].北京:中國電力出版社,2008. 6. 李真芳,王書(shū)茂,趙建軍,等.基于WINCE&S3C2410的多串口移植技術(shù)[J].微計算機信息,2008,24(11). 作者:李維 謝云(廣東工業(yè)大學(xué)) 來(lái)源:《單片機與嵌入式系統應用》 2009(8) |