WinCE流設備驅動簡介及GPIO驅動的實現

轉自:http://blog.csdn.net/nanjianhui/archive/2008/07/18/2674753.aspx

 

流設備驅動實際上就是導出標準的流接口函數的驅動,這是文檔上面的定義。在WinCE中,所有的流設備都導出流設備接口,這樣WinCE中的Device Manager可以加載和管理這些流設備驅動。

流設備驅動的架構如圖:

 

 

首先我聲明一下,這個圖是我抄的,呵呵。在WinCE啓動的時候,OAL(OAL.exe)首先加載kernel.dll,然後kernel.dll加載device.dlldevice.dll會加載devmgr.dlldevmgr.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:移動的字節數

              TypeFILE_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:輸入Buffersize

              pBufOut:輸出Buffer

              dwLenOut:輸出Buffersize

              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 SHK

            ENDIF

 

 

       應該就這些了。上面的例子是我在項目中實際做過的,當時有個客戶想通過應用程序直接操作GPIO,所以我就給他們寫了這個驅動。只要具備一些WinCEBSP的基礎知識,看懂上面的內容應該很簡單。由於是我做過的項目,所以上面的一些路徑,名稱等設置都是基於我所使用的BSP的,僅供大家參考。

發佈了20 篇原創文章 · 獲贊 2 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章