張愛(ài)民,梁書(shū)劍,付健
(總參謀部通信訓(xùn)練基地,宣化075100)
張愛(ài)民(講師),研究方向?yàn)檐娪脽o(wú)線(xiàn)通信與網(wǎng)絡(luò)、通信抗干擾技術(shù)。梁書(shū)劍(講師),研究方向?yàn)檐娪脽o(wú)線(xiàn)通信;付健(講師),研究方向?yàn)橥ㄐ趴垢蓴_技術(shù)。
Windows CE是Microsoft公司專(zhuān)門(mén)針對(duì)嵌入式產(chǎn)品領(lǐng)域開(kāi)發(fā)的嵌入式操作系統(tǒng)。該系統(tǒng)是一種緊湊、高效、可伸縮的32位操作系統(tǒng),主要面向各種嵌入式系統(tǒng)和產(chǎn)品。它的模塊化設(shè)計(jì)使嵌入式系統(tǒng)和應(yīng)用程序開(kāi)發(fā)者能夠方便地加以定制,以適應(yīng)一系列產(chǎn)品(例如消費(fèi)類(lèi)電子設(shè)備、專(zhuān)用工業(yè)控制器和嵌入式通信設(shè)備等)的需要。GPIO是端口的擴(kuò)展器,當(dāng)微控制器或者芯片沒(méi)有足夠的I/O端口,或者當(dāng)系統(tǒng)需要用遠(yuǎn)端串行通信端口時(shí),GPIO能夠提供額外的控制和監(jiān)視功能[1]。用戶(hù)可以通過(guò)GPIO與硬件工作,例如點(diǎn)亮LED、控制蜂鳴器、控制 LCD顯示和鍵盤(pán)的輸入等。所以GPIO的應(yīng)用極為廣泛,但是這些都需要驅(qū)動(dòng)的支持。
Windows CE的所有驅(qū)動(dòng)程序都可以通過(guò)流接口驅(qū)動(dòng)來(lái)實(shí)現(xiàn),GPIO驅(qū)動(dòng)程序開(kāi)發(fā)也通過(guò)流接口驅(qū)動(dòng)來(lái)實(shí)現(xiàn)。流接口驅(qū)動(dòng)是最基本的一種驅(qū)動(dòng)結(jié)構(gòu),它的接口是一組固定的流接口函數(shù)。流接口驅(qū)動(dòng)可以把外設(shè)抽象成一個(gè)文件,過(guò)程是:應(yīng)用程序調(diào)用操作系統(tǒng)的 API函數(shù),操作系統(tǒng)通過(guò)驅(qū)動(dòng)接口調(diào)用驅(qū)動(dòng)程序的硬件操作函數(shù)來(lái)完成對(duì)硬件的操作。
流接口函數(shù)包括 XXX_Init、XXX_Deinit、XXX_Open 、XXX_Close 、XXX_Read 、XXX_Write、XXX_PowerUp 、XXX_PowerDown、XXX_IOControl、XXX_Seek 、XXX_PreClose、XXX_PreDeinit。其中,XXX表示設(shè)備名的前綴,它非常重要,因?yàn)樵O(shè)備管理器在注冊(cè)表中通過(guò)前綴來(lái)識(shí)別設(shè)備。流接口驅(qū)動(dòng)是動(dòng)態(tài)鏈接庫(kù),由設(shè)備管理程序的特殊應(yīng)用程序加載、管理和卸載。在實(shí)際的開(kāi)發(fā)中,用設(shè)備的前綴名來(lái)代替XXX。例如:GPIO設(shè)備的前綴名可以是GIO,相應(yīng)地要實(shí)現(xiàn)的DLL接口為GIO_Init、GIO_Read 、GIO_IOControl等。其中,XXX_Init用于初始化必要的資源、內(nèi)存映射和IST(中斷服務(wù)線(xiàn)程)。XXX_IOControl為設(shè)備的特定操作提供擴(kuò)展接口,對(duì)于大多數(shù)的驅(qū)動(dòng),GPIO主要操作都在這里,它會(huì)被應(yīng)用層的API函數(shù)調(diào)用來(lái)獲得或者設(shè)置狀態(tài)。應(yīng)用程序通過(guò)調(diào)用XXX_IOControl函數(shù)并傳入不同的操作碼,實(shí)現(xiàn)GPIO的各種功能。而在應(yīng)用程序里對(duì)應(yīng)的文件API函數(shù)有ActivateDeviceEx、RegisterDevice、CreateFile、DeviceIoControl、ReadFile、WriteFile、CloseHandle、SetFilePointer等 。
流接口驅(qū)動(dòng)既可以是不分層的架構(gòu),也可以是分層架構(gòu)[2]。同時(shí),流接口驅(qū)動(dòng)既可以管理內(nèi)建設(shè)備,也可以管理安裝設(shè)備;既可以在設(shè)備啟動(dòng)時(shí)加載,也可以在需要時(shí)動(dòng)態(tài)加載。流接口驅(qū)動(dòng)的架構(gòu)如圖1所示。
Samsung公司基于ARM11內(nèi)核的SC36410處理器包含了17個(gè)GP端口,從GPA到GPQ共187針。這些I/O大部分是可以復(fù)用的,可以作為輸入口、輸出口和特殊功能口,不同的功能通過(guò)各自的配置控制寄存器GPxCON選擇來(lái)實(shí)現(xiàn)。配置好相應(yīng)的控制寄存器后就可以選擇相應(yīng)數(shù)據(jù)寄存器GPxDAT進(jìn)行讀寫(xiě)數(shù)據(jù)。GPxDAT用來(lái)選擇是否使用內(nèi)部上拉電阻,當(dāng)引腳被設(shè)置為輸入時(shí),讀此寄存器可知引腳的狀態(tài)是高電平還是低電平;當(dāng)引腳被設(shè)置為輸出時(shí),寫(xiě)此寄存器可令該引腳為高電平或者低電平。以SC36410的GPM端口為例來(lái)介紹GPIO驅(qū)動(dòng)的開(kāi)發(fā)。通過(guò)查閱SC36410手冊(cè)看到GPMCON的地址為0x7F008820,GPMDAT的地址為0x7F008824,GPMPUD的地址為0x7F008828。GPM端口包括6針(GPM[5:0]),每針的輸入/輸出由GPM0到GPM5寄存器分別確定??刂萍拇嫫鱃PM0設(shè)置為0000時(shí),表明GPM[0]引腳為輸入腳;控制寄存器 GPM0設(shè)置為 0001時(shí),表明GPM[0]引腳為輸出腳。其他引腳操作完全類(lèi)似。
圖1 流接口驅(qū)動(dòng)的架構(gòu)
Windows CE有虛擬地址和物理地址之分,程序訪(fǎng)問(wèn)的地址都是虛擬地址。要訪(fǎng)問(wèn)硬件的物理地址,驅(qū)動(dòng)程序必須將設(shè)備的物理地址映射到IST正在運(yùn)行的地址空間,完成物理地址到虛擬地址的映射[3]。函數(shù)VirtualAlloc、VirtualCopy和VirtualFree是Windows CE的內(nèi)核函數(shù),具有同樣功能的CEDDK函數(shù)MmMapIoSpace和UnMmMap-IoSpace也可以完成地址映射。添加如下語(yǔ)句:
經(jīng)過(guò)地址映射后,結(jié)構(gòu)體變量指針v_pIOPregs就可以訪(fǎng)問(wèn)GPM的寄存器了。
Windows CE里設(shè)備驅(qū)動(dòng)程序本質(zhì)上是一些動(dòng)態(tài)鏈接庫(kù)(DLL),它們向內(nèi)核提供一些入口函數(shù),這樣設(shè)備管理器就可以通過(guò)這些函數(shù)與具體的硬件設(shè)備進(jìn)行通信。GPIO驅(qū)動(dòng)的入口函數(shù)為DllMain。DllMain是一個(gè)可選的DLL入口方式,在進(jìn)程和線(xiàn)程初始化或終止時(shí)以及調(diào)用LoadLibrary或FreeLibrary之后被系統(tǒng)調(diào)用,DllMain函數(shù)如下所示:
Windows CE加載設(shè)備驅(qū)動(dòng)時(shí),產(chǎn)生DLL_PROCESS_ATTACH調(diào)用DllMain,初始化設(shè)備,分配所需資源,并且開(kāi)啟ISR和IST;當(dāng)卸載設(shè)備驅(qū)動(dòng)時(shí),產(chǎn)生DLL_PROCESS_DETACH,調(diào)用DllMain,關(guān)閉設(shè)備并釋放它占用的各種資源[4]。
加載設(shè)備驅(qū)動(dòng)的具體步驟如下:
①新建GPM_Driver.cpp文件,添加一些頭文件和完善接口函數(shù)的內(nèi)容:在GPM_Init()函數(shù)中完成虛擬地址映射,在GPM_Deinit()中釋放虛擬地址空間和各種資源。代碼如下:
在GPM_IOControl()函數(shù)中實(shí)現(xiàn)了GPIO的大部分操作,按照SC36410手冊(cè)的說(shuō)明和要求使I/O控制代碼識(shí)別要完成的操作。GPMCON控制寄存器的輸入/輸出配置,GPMDAT負(fù)責(zé)數(shù)據(jù)寄存器的讀寫(xiě),部分代碼如下:
②創(chuàng)建GPM_Driver.DEF文件,提供驅(qū)動(dòng)接口。
配置驅(qū)動(dòng)程序的具體步驟如下:
①為使Windows CE生成內(nèi)核映像時(shí)自動(dòng)將GPM_Driver.dll加入到系統(tǒng)內(nèi)核映像,在platform.bib文件中添加如下內(nèi)容:
②在platform.reg文件中添加如下內(nèi)容,當(dāng)Win-dows CE啟動(dòng)時(shí),就會(huì)自動(dòng)加載該驅(qū)動(dòng)了。
③新建Makefile文件,并添加內(nèi)容如下:!INCLUDE$(_MAKEENVROOT)makefile.def
④配置sources文件。把其他驅(qū)動(dòng)程序的sources文件復(fù)制過(guò)來(lái),在文件某些位置替換為GPM_Driver的內(nèi)容。
⑤在X:WINCE600PLATFORMSMDK6410SRCDRIVERS的dirs文件下,X代表Windows CE的安裝盤(pán)符,按照文件格式添加GPM_Driver。
⑥對(duì)驅(qū)動(dòng)程序進(jìn)行編譯,生成的GPM_Driver.dll會(huì)自動(dòng)加入到操作系統(tǒng)內(nèi)核映像,最終生成NK.bin文件,下載到目標(biāo)板后即可被頂層的應(yīng)用程序API函數(shù)調(diào)用,實(shí)現(xiàn)GPIO的輸入/輸出等功能。這樣,GPM便可以實(shí)現(xiàn)控制LED發(fā)光、蜂鳴器發(fā)出聲響等功能了。
Windows CE已經(jīng)成為廣泛應(yīng)用的嵌入式操作系統(tǒng),本文以SC36410的GPM端口為例,主要介紹了Windows CE下GPIO驅(qū)動(dòng)程序的開(kāi)發(fā)方法,分析了GPIO流接口驅(qū)動(dòng)程序的開(kāi)發(fā)原理,主要包括建立DLL項(xiàng)目、編寫(xiě)一些輸入/輸出函數(shù)和寄存器,以及配置驅(qū)動(dòng)程序等,對(duì)Windows CE下GPIO驅(qū)動(dòng)編寫(xiě)具有一定的參考價(jià)值。
[1]周建設(shè).Windows CE設(shè)備驅(qū)動(dòng)及BSP開(kāi)發(fā)指南[M].北京:中國(guó)電力出版社,2009.
[2]張冬泉,譚南林.Windows CE開(kāi)發(fā)實(shí)例精粹[M].北京:電子工業(yè)出版社,2008.
[3]胡秀鳳,丁承君,張明路,等.Windows CE下GPIO驅(qū)動(dòng)程序的設(shè)計(jì)與應(yīng)用[J].微計(jì)算機(jī)信息,2009,25(6-2);140-141.
[4]趙振中,徐家愷.基于WindowsCE的GPIO鍵盤(pán)驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)[J].科學(xué)技術(shù)與工程,2008,8(6);1598-1600.
[5]楊澤輝,徐燕玲,劉碧君,等.基于嵌入式 WinCE的GPIO驅(qū)動(dòng)開(kāi)發(fā)[J].太原科技大學(xué)學(xué)報(bào),2010,31(6);446-448.
單片機(jī)與嵌入式系統(tǒng)應(yīng)用2011年9期