WinCE流裝置驅動簡介及GPIO驅動的實現(轉載 ARM-WINCE)
流裝置驅動實際上就是匯出標準的流介面函數的驅動,這是文檔上面的定義。在WinCE中,所有的流裝置都匯出流裝置介面,這樣WinCE中的Device Manager可以載入和管理這些流裝置驅動。
流裝置驅動的架構
首先我聲明一下,這個圖是我抄的,呵呵。在WinCE啟動的時候,OAL(OAL.exe)首先載入kernel.dll,然後kernel.dll載入device.dll,device.dll會載入devmgr.dll,devmgr.dll實際上就是Device Manager模組,他會負責流裝置的載入,卸載和互動操作。這個可以看出的。
再來說說應用程式,一般應用程式要通過檔案系統介面來訪問裝置。首先調用CreateFile開啟裝置並獲得相應的控制代碼,然後通過檔案系統介面調用ReadFile或者WriteFile來訪問相應的流裝置驅動,或者通過DeviceIoControl直接存取。無論哪種方式,都是要通過Device Manager才能訪問到相應的裝置驅動,如。
不知道上面的架構解釋清楚了沒有,下面介紹一下流裝置驅動的介面函數:
1. DWORD XXX_Init(LPCTSTR pContext, DWORD dwBusContext):
該函數用於初始化一個流裝置驅動,在裝置被載入的時候調用,調用成功後會返回一個控制代碼。
pContext:在Active註冊表鍵路徑下的一個字串 dwBusContext:不常用,這裡可以設為0
2. BOOL XXX_Deinit(DWORD hDeviceContext):
卸載一個裝置驅動。
hDeviceContext:裝置驅動的控制代碼,在XXX_Init調用時返回的
3. DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode):
開啟一個裝置。
hDeviceContext:裝置驅動的控制代碼,在XXX_Init調用時返回的
AccessCode:存取權限代碼,一般是唯讀或者唯寫或者讀寫
ShareMode:共用模式,是否支援共用或者獨享
4. BOOL XXX_Close(DWORD hOpenContext):
關閉一個裝置。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
5. DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count):
從裝置上面讀取資料。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
pBuffer:存放資料的Buffer
Count:讀取資料的位元組數
6. DWORD XXX_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count):
寫資料到裝置上面。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
pBuffer:存放資料的Buffer
Count:寫入資料的位元組數
7. DWORD XXX_Seek(DWORD hOpenContext, long Amount, WORD Type):
行動裝置中的資料指標。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
Amount:移動的位元組數
Type:FILE_BEGIN表示從頭移動
FILE_CURRENT表示從當前位置移動
FILE_END表示從末尾往前移動
8. void XXX_PowerUp(DWORD hOpenContext):
開啟裝置電源。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
9. void XXX_PowerDown(DWORD hOpenContext):
關閉裝置電源。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
10. BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut):
裝置IO控制操作函數。
hDeviceContext:裝置驅動的控制代碼,在XXX_Open調用時返回的
dwCode:作業碼
pBufIn:輸入Buffer
dwLenIn:輸入Buffer的size
pBufOut:輸出Buffer
dwLenOut:輸出Buffer的size
pdwActualOut:實際輸出的位元組數
11. BOOL XXX_PreClose(DWORD hOpenContext):
標記一個正要關閉的控制代碼為無效,並喚醒所有正在休眠的線程
hDeviceContext:裝置驅動的控制代碼,在XXX_Init調用時返回的
12. BOOL XXX_PreDeinit(DWORD hDeviceContext):
標記一個裝置執行個體為無效,並喚醒所有休眠的線程
hDeviceContext:裝置驅動的控制代碼,在XXX_Init調用時返回的
上面這些函數就是流裝置驅動的所有介面函數,理解起來應該不難。下面介紹一個實際的流裝置驅動的例子,是基於WinCE6.0的(和WinCE5.0比一些設定檔稍有不同)。這裡介紹的是一個操作GPIO的流裝置驅動並介紹具體添加流裝置驅動的步驟:
(1) 更改BSP工程檔案,添加GPIO驅動的選項:
在BSP目錄下面的”CATALOG”檔案夾下面找到”BspName.pbcxml”並用記事本開啟,然後添加GPIO驅動的選項,首先找到<BSP>…</BSP>並在裡面添加下面一行:
<BspItemId>Item:Cirrus Logic:bsp_ep94xx_gpio_ep9407_EP94xx</BspItemId>
然後在< CatalogFile >…</CatalogFile>中添加下面的驅動描述:
<Item Id="Item:Cirrus Logic:bsp_ep94xx_gpio_ep9407_EP94xx">
<Title>GPIO</Title>
<Description>GPIO Driver</Description>
<Type>BspSpecific</Type>
<Variable>BSP_EP94XX_GPIO</Variable>
<Location>Device Drivers</Location>
<SourceCode>
<Title>$(_WINCEROOT)\PLATFORM\EP94XX\SRC\DRIVERS\gpio</Title>
<Path>$(_WINCEROOT)\PLATFORM\EP94XX\SRC\DRIVERS\gpio</Path>
</SourceCode>
</Item>
上面實際上添加了GPIO驅動,環境變數為BSP_EP94XX_GPIO,原始碼位於路徑”\Platform\EP94XX\SRC\DRIVERS\gpio”下面。
(2) 建立GPIO驅動檔案夾並更改dir檔案:
進入”\Platform\EP94XX\SRC\DRIVERS\”目錄,建立一個名為”gpio”的檔案夾,這個檔案夾包含GPIO驅動。然後開啟dirs檔案,在末尾添加”gpio”。
(3) 開發GPIO驅動:
進入”\Platform\EP94XX\SRC\Drivers\gpio”並建立gpio.c檔案,在檔案中封裝相應的流裝置介面函數,如下:
GPI_Init(..)
GPI_DeInit(..)
GPI_Read(..)
GPI_Write(..)
…
可以在GPI_Read函數中讀取GPIO的狀態,在GPI_Write函數中設定GPIO的狀態,當然也可以通過GPI_IoControl函數來實現。
然後在該路徑下面建立makefile檔案,並在裡麵包含下面一行就可以了:
!INCLUDE $(_MAKEENVROOT)\makefile.def
接下來建立模組匯出檔案gpio.def,具體內容如下:
LIBRARY GPIO_LIB
EXPORTS
DllEntry
GPI_Init
GPI_Deinit
GPI_Open
GPI_Close
GPI_Read
GPI_Write
GPI_Seek
GPI_IOControl
GPI_PowerDown
GPI_PowerUp
最後建立用於編譯的sources檔案,具體內容如下:
!ifndef BSP_EP94XX_GPIO
SKIPBUILD=1
!endif
TARGETNAME=gpio
RELEASETYPE=PLATFORM
TARGETTYPE=DYNLINK
TARGETLIBS= \
$(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib
DLLENTRY=DllEntry
SOURCES= gpio.c
(4) 添加GPIO驅動的註冊表配置:
開啟”\PLATFORM\EP94XX\files\”目錄下的platform.reg檔案,添加下面的配置:
IF BSP_EP94XX_GPIO
; Add these entries to your registry to enable the gpio device
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
"prefix"="GPI"
"Dll"="gpio.dll"
"Order"=dword:1
ENDIF
(5) 添加驅動模組到NK中
開啟”\PLATFORM\EP94XX\files\”目錄下的platform.bib檔案,添加如下內容:
IF BSP_EP94XX_GPIO
gpio.dll $(_FLATRELEASEDIR)\gpio.dll NK SH
ENDIF
應該就這些了。上面的例子是我在項目中實際做過的,當時有個客戶想通過應用程式直接操作GPIO,所以我就給他們寫了這個驅動。只要具備一些WinCE的BSP的基礎知識,看懂上面的內容應該很簡單。由於是我做過的項目,所以上面的一些路徑,名稱等設定都是基於我所使用的BSP的,僅供大家參考。
本文來自CSDN部落格,轉載出處:http://blog.csdn.net/nanjianhui/archive/2008/07/18/2674753.aspx