龔松顯,張愛民
(總參通信訓(xùn)練基地 教研部科研所,河北 宣化 075100)
基于ARM 開發(fā)板的GPIO 端口功能擴(kuò)展具有高度的靈活性,降低了系統(tǒng)的復(fù)雜程度和成本,是目前在嵌入式設(shè)備上常用的開發(fā)技術(shù)之一.WinCE 下GPIO 端口驅(qū)動(dòng)大多采用流接口驅(qū)動(dòng)的方式進(jìn)行開發(fā),其過程涉及驅(qū)動(dòng)動(dòng)態(tài)鏈接庫的生成、Platform Builder 開發(fā)工具中源代碼配置和WinCE 內(nèi)核鏡像配置,整個(gè)過程較為繁瑣復(fù)雜.在實(shí)際項(xiàng)目的開發(fā)中,很多WinCE 程序僅需對(duì)GPIO 端口進(jìn)行簡(jiǎn)單的控制,如若仍采用流接口的驅(qū)動(dòng)開發(fā)方式,將造成整個(gè)項(xiàng)目開發(fā)效率的降低,項(xiàng)目的工程框架也將變得臃腫冗余.文章通過分析WinCE 操作系統(tǒng)的地址映射機(jī)制,借鑒單片機(jī)端口驅(qū)動(dòng)的開發(fā)思路,實(shí)現(xiàn)了在WinCE 程序中對(duì)GPIO 端口的直接驅(qū)動(dòng),簡(jiǎn)化了此情況下的開發(fā)流程,使開發(fā)者能專注于WinCE 程序本身的設(shè)計(jì),提高了開發(fā)效率.
1.1 設(shè)計(jì)步驟簡(jiǎn)述 對(duì)于常用的基于流驅(qū)動(dòng)的GPIO 端口驅(qū)動(dòng)設(shè)計(jì)方法及原理,各種文獻(xiàn)及資料中已經(jīng)介紹很多[1],這里不再贅述,其設(shè)計(jì)步驟要點(diǎn)簡(jiǎn)述如下:
(1)按照流驅(qū)動(dòng)的設(shè)計(jì)方法,創(chuàng)建相關(guān)的.cpp 文件、.h 文件和.def 文件以供生成驅(qū)動(dòng)程序的動(dòng)態(tài)鏈接庫.
(2)創(chuàng)建相關(guān)提供注冊(cè)信息的.reg 文件以供在WinCE 注冊(cè)表中注冊(cè)GPIO 驅(qū)動(dòng)程序.
(3)在Platform Builder 的相關(guān)目錄下,配置Dirs 文件、Makefile 文件、Sources 文件和Platform.bib 文件中的相關(guān)參數(shù),Platform Builder 在編譯時(shí)按照配置的參數(shù)編譯驅(qū)動(dòng)程序并將其整合到內(nèi)核鏡像中.
(4)使用Platform Builder 編譯環(huán)境編譯驅(qū)動(dòng)程序和WinCE 內(nèi)核,編譯成功之后即得到按照硬件平臺(tái)定制的含有驅(qū)動(dòng)程序動(dòng)態(tài)鏈接庫的內(nèi)核鏡像文件,當(dāng)WinCE 啟動(dòng)時(shí),該驅(qū)動(dòng)會(huì)被自動(dòng)加載.
1.2 存在的問題 基于以上描述,如果在WinCE 程序中僅需對(duì)端口進(jìn)行簡(jiǎn)單控制,流接口驅(qū)動(dòng)程序設(shè)計(jì)方法中存在以下兩個(gè)問題:
(1)在實(shí)現(xiàn)流驅(qū)動(dòng)程序時(shí),需要按照流驅(qū)動(dòng)的設(shè)計(jì)方法來實(shí)現(xiàn)相關(guān)的流接口函數(shù)并生成動(dòng)態(tài)鏈接庫.在該過程中,即使是簡(jiǎn)單的端口控制功能也需要遵循流驅(qū)動(dòng)固定的實(shí)現(xiàn)框架,開發(fā)步驟不靈活.
(2)驅(qū)動(dòng)程序和WinCE 內(nèi)核的整合以及相關(guān)配置文件的編寫全部依托Platform Builder 編譯環(huán)境,開發(fā)者需要較為熟悉Platform Builder 編譯環(huán)境的使用,但在實(shí)際工程項(xiàng)目的開發(fā)中,大多數(shù)開發(fā)者對(duì)其使用基本上處于簡(jiǎn)單的模仿層次,使用入門門檻較高.
2.1 設(shè)計(jì)方法原理 在單片機(jī)程序設(shè)計(jì)中,可以通過直接訪問端口對(duì)應(yīng)的寄存器來實(shí)現(xiàn)對(duì)端口的驅(qū)動(dòng).在ARM 程序設(shè)計(jì)中,在無操作系統(tǒng)存在的情況下,例如在ADS 編譯環(huán)境下,依然可以采用類似的方法,通過對(duì)端口的相關(guān)寄存器的訪問來驅(qū)動(dòng)GPIO 端口[2].如果ARM 芯片中已移植了WinCE 操作系統(tǒng),由于WinCE 操作系統(tǒng)的內(nèi)存保護(hù)機(jī)制,WinCE 應(yīng)用程序是不能直接訪問GPIO 端口的物理內(nèi)存地址的,故在WinCE 程序中對(duì)端口的物理地址進(jìn)行訪問就會(huì)導(dǎo)致程序異常.在另一方面,WinCE 系統(tǒng)提供了如圖1 所示的地址映射機(jī)制,可以將ARM 芯片的端口物理地址映射為程序進(jìn)程空間的某一虛擬內(nèi)存地址,此時(shí)由于端口的物理地址和程序的進(jìn)程空間地址是一一映射的關(guān)系,通過對(duì)虛擬地址的操作,實(shí)質(zhì)上就能夠完成對(duì)GPIO 端口的控制,達(dá)到驅(qū)動(dòng)物理端口的目的和效果,程序開發(fā)思路實(shí)質(zhì)與單片機(jī)保持一致.
圖1 WinCE 系統(tǒng)中物理地址和進(jìn)程地址映射示意圖
2.2 方法實(shí)現(xiàn)要點(diǎn)步驟 在WinCE 中,主要通過VirtualAlloc 和VirtualCopy 兩個(gè)函數(shù)來實(shí)現(xiàn)端口物理地址到程序進(jìn)程空間虛擬地址的映射[3]:VirtualAlloc 函數(shù)負(fù)責(zé)申請(qǐng)一塊虛擬內(nèi)存空間,VirtualCopy 函數(shù)將一段物理內(nèi)存映射到已申請(qǐng)的虛擬空間中.成功調(diào)用以上兩個(gè)函數(shù)后,只需要在WinCE 程序中適當(dāng)?shù)牡胤綄?duì)映射后的虛擬地址進(jìn)行訪問即可實(shí)現(xiàn)對(duì)GPIO 端口的直接驅(qū)動(dòng).筆者以飛凌S3C2440 開發(fā)板為例,創(chuàng)建了一個(gè)WinCE 對(duì)話框程序,點(diǎn)擊相關(guān)按鈕可以點(diǎn)亮(熄滅)相應(yīng)的LED 燈,圖2 是本程序的截圖.
圖2 程序的運(yùn)行界面
程序中相關(guān)的要點(diǎn)代碼及解釋如下(暫不考慮程序的異常處理).
(1)端口映射
VirtualAlloc 函數(shù)調(diào)用成功后,將在WinCE 應(yīng)用程序的進(jìn)程空間中保留一段虛擬內(nèi)存地址,并將該地址的值返回給指針變量v_IOPreg.
上面的VirtualCopy 函數(shù)將PB 端口的物理地址(S3C2440A_BASE_REG_PA_IOPORT>>8)映射到了虛擬地址v_IOPreg 上,此時(shí)端口的物理地址和進(jìn)程的虛擬地址之間是一一對(duì)應(yīng)的關(guān)系.
在WinCE 的SDK 中,MmMapIoSpace 函數(shù)亦能實(shí)現(xiàn)以上端口映射的功能[4],實(shí)質(zhì)上,MmMapIoSpace函數(shù)就是VirtualAlloc 函數(shù)和VirtualCopy 函數(shù)的一個(gè)簡(jiǎn)單封裝.對(duì)于MmMapIoSpace 函數(shù)的具體使用可參考MSDN,這里不再贅述.
(2)端口訪問
按照對(duì)PB 端口寄存器的訪問方式[5],通過對(duì)虛擬地址v_IOPreg 的操作實(shí)現(xiàn)了對(duì)LED1 燈的控制,其它3 個(gè)LED 燈的控制代碼與之類似,這里不再給出.
2.3 設(shè)計(jì)方法的優(yōu)點(diǎn) 與基于流驅(qū)動(dòng)的設(shè)計(jì)方法相比,采用WinCE 程序直接驅(qū)動(dòng)GPIO 端口的設(shè)計(jì)方法,開發(fā)者不需要設(shè)計(jì)、編譯驅(qū)動(dòng)程序的動(dòng)態(tài)鏈接庫,也不需要使用Platform Builder 對(duì)內(nèi)核進(jìn)行配置和編譯,完全脫離了流接口固定的實(shí)現(xiàn)框架和對(duì)Platform Builder 編譯環(huán)境的使用,直接在WinCE 程序中實(shí)現(xiàn)了對(duì)端口的驅(qū)動(dòng),方法快速有效.在程序的開發(fā)方式及調(diào)試上,該設(shè)計(jì)方法與常規(guī)的WinCE 程序設(shè)計(jì)方法無任何差別,在對(duì)GPIO 端口的控制上,也與單片機(jī)的開發(fā)思路實(shí)質(zhì)一致.在對(duì)端口驅(qū)動(dòng)要求比較簡(jiǎn)單、需要驅(qū)動(dòng)的端口數(shù)量較少的情況下,該方法簡(jiǎn)單易行.
本文介紹了在WinCE 程序中對(duì)GPIO 端口進(jìn)行簡(jiǎn)單驅(qū)動(dòng)的一種設(shè)計(jì)方法,避開了驅(qū)動(dòng)動(dòng)態(tài)鏈接庫的編寫和對(duì)Platform Builder 編譯環(huán)境的使用,是對(duì)常用的GPIO 端口驅(qū)動(dòng)設(shè)計(jì)方法的簡(jiǎn)化,對(duì)于類似的GPIO 驅(qū)動(dòng)程序開發(fā),具有一定的借鑒意義.
[1]羅家兵,滕少華,張巍,等.WinCE.NET 下流接口驅(qū)動(dòng)研究與實(shí)現(xiàn)[J].微計(jì)算機(jī)信息,2007,23(9):229-292.
[2]周建設(shè).Windows CE 設(shè)備驅(qū)動(dòng)及BSP 開發(fā)指南[M].北京:中國電力出版社,2009.
[3]楊澤輝,徐燕玲,劉碧君,等.基于嵌入式WinCE 的GPIO 驅(qū)動(dòng)開發(fā)[J].太原科技大學(xué)學(xué)報(bào),2010,31(6):446-448.
[4]林濤.嵌入式操作系統(tǒng)Windows CE 的研究[J].微計(jì)算機(jī)信息,2006,2-6:91-93.
[5]張歡,鈕文良.Windows CE 系統(tǒng)開發(fā)基礎(chǔ)與實(shí)例[M].北京:中國電力出版社,2010.