1、基礎知識:
1)系統調用是作業系統核心和應用程式之間的介面,裝置驅動程式是作業系統核心和機器硬體之間的接
口。裝置驅動程式為應用程式屏蔽了硬體細節,在應用程式看來硬體只是一個裝置檔案,應用程式可以
像操作普通檔案一樣對硬體裝置進行操作。裝置驅動是核心的一部分。
2)驅動程式完成以下功能:
——對裝置初始化和釋放;
——把資料從核心傳送到硬體和從硬體讀取資料;
——讀取應用程式傳送給裝置檔案的資料和回送應用程式請求的資料;
——檢測和處理裝置出現的錯誤。
3)上層應用程式運行在使用者模式(非特權模式,Ring 3),代碼被嚴格約束執行。如不能執行硬體IO指
令。所有的這些被阻止的操作如果想運行必須通過陷阱門來請求作業系統核心。
4)作業系統核心運行在核心模式(特權模式,Ring 0),可以執行所有有效CPU指令。包括IO操作,
可訪問任何記憶體區。
5)整個硬體系統資源在驅動程式面前是赤裸裸的,驅動可以使用所有系統資源,編寫驅動程式時我們必
須格外小心驅動代碼的邊界條件,確保它們不會損壞整個作業系統。
2、Windows支援的驅動:
1)虛擬設備驅動程式(Virtual Device Driver):Windows3.1(Windows95/98/Me)
2)核心模式驅動程式(Kernel Mode Driver):Windows NT
3)Win32驅動程式模型(Win32 Driver Mode):從Windows98開始使用。
其中WDM是目前主流,然而在WinCE系統中,由於硬體資源有限和嵌入式系統的特點,對其的支援非常有
限。
3、WinCE系統驅動簡介:
1)WinCE畢竟是一個嵌入式系統,有其自身的特殊性,為了提高運行效率,所有驅動皆為動態連結程式庫,
驅動實現中可以調用所有標準的API。而在其他Windows系統中可能的驅動檔案還有.vxd, .sys和動態鏈
接庫。
2)WinCE驅動從結構上講分為本地驅動(Native Driver)和流介面驅動(Stream Driver)。
——本地驅動主要用於低級、內建的裝置。實現它們的介面並不統一,而是針對不同類型的裝置相應設
計。因此開發過程相對複雜,沒有固定的模式,一般做法是通過移植、定製現有的驅動範例來實現。
——流介面驅動是最基本的一種驅動結構,它的介面是一組固定的流介面函數,具有很高的通用性,
WinCE的所有驅動程式都可以通過這種方式來實現。流介面驅動程式通過檔案系統調用從裝置管理員和應
用程式接收命令。該驅動程式封裝了將這些命令轉換為它所控制的裝置上的適當操作所需的全部資訊。
流介面驅動是動態連結程式庫,由一個叫做裝置管理程式的特殊應用程式載入、管理和卸載。與本地
驅動程式相比,所有流介面驅動程式使用同一組介面函數集,包括實現函數:XXX_Init、XXX_Deinit、
XXX_Open、XXX_Close、XXX_Read、XXX_Write、XXX_PowerUp、XXX_PowerDown、XXX_Seek、
XXX_IOControl,這些函數與硬體打交道。使用者函數:CreateFile、DeviceIoControl、 ReadFile、
WriteFile,這些函數方便使用者使用驅動程式。
3)WinCE下驅動的載入方式:
——通過GWES(Graphics, Windowing, and Events Subsystem):主要載入與顯示和輸入有關的驅動,
如滑鼠、鍵盤驅動等。這些驅動一般為本地驅動。
——通過裝置管理員:兩種結構的驅動都載入,載入的本地驅動主要由PCMCIA Host Controller,USB
Host Controller driver,主要是匯流排類的驅動;流介面驅動主要有音頻驅動,串並口驅動。
——動態載入:前兩者都是系統啟動時載入的,動態載入則允許裝置掛載上系統時將驅動調入核心,主
要有外接板卡驅動,USB裝置驅動等。
4、流介面驅動函數介紹:
1)DWORD XXX_Init(LPCTSTR pContext, LPCVOID lpvBusContext);
pContext:指向一個字串,包含註冊表中該流介面活動索引值的路徑
lpvBusContext:
該函數是驅動掛載後第一個被執行的。主要負責完成對裝置的初始化操作和驅動的安全性檢查。由
ActiveDeviceEx通過裝置管理員調用。其傳回值一般是一個資料結構指標,作為函數參數傳遞給其他流
介面函數。
2)BOOL XXX_Deinit(DWORD hDeviceContext);
hDeviceContext:XXX_Init的傳回值。
整個驅動中最後執行。用來停止和卸載裝置。由DeactivateDevice觸發裝置管理員調用。成功返回TRUE
。
3)DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode , DWORD ShareMode);
hDeviceContext:XXX_Init的傳回值。
AccessCode:訪問模式標誌,讀、寫或其他。
ShareMode:驅動的共用方式標誌。
開啟裝置,為後面的操作初始化資料就夠,準備相應的資源。應用程式通過CreateFile函數間接調用之
。返回一個結構指標,用於區分哪個應用程式調用了驅動,這個值還作為參數傳遞給其他介面函數
XXX_Read、XXX_Write、XXX_Seek、XXX_IOControl。
4)BOOL XXX_Close(DWORD hOpenContext);
hOpenContext:XXX_Open傳回值。
關閉裝置,釋放資源。由CloseHandle函數間接調用。
5)DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count);
hOpenContext:XXX_Open傳回值。
pBuffer:緩衝區指標,接收資料。
Count:緩衝區長度。
由ReadFile函數間接調用,用來讀取裝置上的資料。返回讀取的實際資料位元組數。
6)DWORD XXX_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count);
hOpenContext:XXX_Open傳回值。
pBuffer:緩衝區指標,接收資料。
Count:緩衝區長度。
由WriteFile函數間接調用,把資料寫到裝置上,返回實際寫入的資料數。
7)BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE
pBufOut, DWORD dwLenOut, PDWORD pdwActualOut);
hOpenContext:XXX_Open傳回值。
dwCode:控制命令字。
pdwActualOut:實際輸出資料長度。
用於向裝置發送命令,應用程式通過DeviceIoControl調用來實現該功能。要調用這個介面還需要在應用
層和驅動之間建立一套相同的命令,通過宏定義CTL_CODE(DeviceType, Function, Method, Access來實
現。如:
#define IOCTL_INIT_PORTS " CTL_CODE
(FILE_DEVICE_UNKNOWN,0X801,METHOD_BUFFERED,FILE_ANY_ACCESS)
8)void XXX_PowerDown(DWORD hDeviceContext);
hDeviceContext:XXX_Init的傳回值。
負責裝置的上電控制。
9)void XXX_PowerUp(DWORD hDeviceContext);
hDeviceContext:XXX_Init的傳回值。
負責裝置的斷電控制
10)DWORD IOC_Seek(DWORD hOpenContext, long Amount, WORD Type)
hOpenContext:XXX_Open傳回值。
Amount:指標的位移量。
Type:指標的位移方式。
將裝置的資料指標指向特定的位置,應用程式通過SetFilePointer函數間接調用。不是所有裝置的屬性
上都支援這項功能。
5、流介面驅動的載入和註冊表設定:
系統啟動時啟動裝置管理程式,裝置管理程式讀取HKEY_LOCAL_MACHINE"Drivers"BuiltIn鍵的內容並加
載已列出的流介面驅動程式。因此註冊表對於驅動的載入有著關鍵作用。下面是一個例子:
【HKEY_LOCAL_MACHINE"Drivers"BuiltI"IOControler】
“Prefix”=”XXX”
“Dll”=”drivername.dll”
其中,“Prefix”=“XXX”中的XXX要和XXX_Init等函數中的一樣。CreateFile建立的驅動名首碼也必
須和它們一致。
6、驅動程式的編寫、編譯及其相關目錄、設定檔的格式和修改:
1)首先必須在PB相應平台的的driver目錄下建立要建立的驅動所在的目錄。如在x:"Wince420
"platform"smdk2410"drivers目錄下建立一個IOCtrol目錄。
2)修改Drivers目錄下的dirs檔案。
3)建立驅動源檔案XXX.c,在該檔案中實現上述流介面函數。並且加入DLL入口函數:
BOOL DllEntry(HINSTANCE hinstDll, /*@parm Instance pointer. */
DWORD dwReason, /*@parm Reason routine is called. */
LPVOID lpReserved /*@parm system parameter. */
)
4)建立Makefile和Sources和.def檔案,控制編譯。
5)使用CEC Editor修改cec檔案,編譯添加的新特性。
6)複製新產生的4個檔案到Release目錄下,修改註冊表檔案platform.reg和platform.bib檔案。
7)Make Image。
8)DownLoad Image
一般我們在驅動程式中需用LocalAlloc保留一Block Storage空間,然後用LocalCopy將I/O連接埠映射到該地址上,以後就可以訪問該保留下來的地址了。
而 對中斷的處理各種裝置不盡相同。如果是一個內建裝置(Built In),一般在oalintr.h檔案中定義一個新的中斷,OAL層中加上對該中斷的處理。然後在驅動程式的Init函數中用CreateEvent建立 一個事件,調用InterruptInitialize 將定義好的中斷與建立的事件相關聯,再建立一個線程,在該線程中調用WaitforSingleObject等待該事件,當該裝置有中斷髮生時,這個事件 就被觸發,WaitforSingleOjbect返回,線程被運行,我們就可以處理該中斷。
OAL中所新加的對該中斷的處理就是所謂的ISR之內容,而這個線程就是所說的IST。
其它
1.CE下同名裝置不能大於10
CE5.0中已經沒有這個問題了,
以前的版本可以這樣做:
只給上層輸出一個裝置,
然後用一個IOCTL去開啟一個個的物理裝置
這樣就可以做到不受任何限制了
2.MDD與PDD
一個驅動程式通常會被分成硬體相關(PDD)與硬體無關(MDD)層兩部分。
當然,這種分層不是必須的,只是採用這種分層以後可以少寫很多代碼,因為微軟提供了很多驅動程式的MDD。即使CE中沒有我們所寫的驅動程式的範例,採用這種結構以後,當需要寫第二個程式時,就可以重用它的代碼,就可以提高開發效率。
MDD是提供同類型的裝置(比如串口)都會有的功能,這樣PDD基本上就只有寄存器操作了。
像串口的中斷處理,Read/Write函數,其大部分代碼都是在MDD中實現的,
不同的串口實現中只需要提供一些實際操作寄存器的函數
不同的驅動程式,其MDD與PDD的介面不盡相同,
所以,當我們面對一個具體的驅動程式時,需要查協助弄清楚需要提供哪些函數
3 XXX_Init函數的返回控制代碼
通常,這個控制代碼是驅動程式自己儲存資料的一個指標,
我們在Init返回時告訴上層程式,以後上層調用其它函數(例如Open)時,
會將這個值傳入,這樣,我們就可以訪問自己的一些私人資料。
當然,也可以返回一個任意的非0值
對於一個裝置驅動程式,系統不用的層會有不同的控制代碼。
我們在XXX_Init中返回的控制代碼儲存在裝置管理員中,別的程式中應該是看不到的,
而用CreateFile也會得到一個檔案控制代碼,這個儲存在哪我不知道,
但和前者是不一樣的。
也就是說不同層的軟體所關心的控制代碼也會不一樣
4.DEBUGMSG與RETAILMSG的區別
它們都是輸出調試資訊用的,
區別是:
DEBUGMSG只在DEBUG版中有效,RELEASE版中它被定義成了NULL
RETAILMSG在DEBUG和RELEASE版中都可以輸出,
而且DEBUGMSG可以在運行時刻用DEBUZONE控制要不要輸出資訊。
在ship build 時,RETAILMSG 和DEBUGMSG都無效
5. 顯視屏出現了上下兩個案頭,應該是:
螢幕大小設成了只有實際大小的一半(高度).
就是說你螢幕高是600,而你驅動程式中設定的高度是300.
當然,也可以修改程式使其下半部分輸出黑色.
地址分配:
對於ARM來說,有虛擬位址和物理地址之分,對於WINCE來說,也有虛擬位址和物理地址之分. 可以這麼說,ARM的虛擬位址就是WINCE系統的物理地址.
32 位的OS總共有4G的虛擬位址空間,WINCE也不例外. 其中,0x00000000~0x80000000是Application Space; 0x80000000~0xffffffff是System Reserved. 系統的物理地址就在System Reserved的這段,只能在KERNEL MODE訪問. 那麼,當APPLICATION和DRIVER(都是運行在USER MODE)要訪問這些在System Reserved位址區段的硬體寄存器或MEMORY怎麼辦呢? 只好再建立一層映射關係,在Application Space裡分配一段空間,把它映射到System Reserved裡的地址上,這就是VirtualAlloc/Copy和MmMapIoSpace乾的事情
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/loongdao777/archive/2008/05/22/2470066.aspx