由於模擬流接口驅動,不涉及具體的硬件平臺,整個過程在Windows中模擬。
BSP:SMDK2410
1.首先寫一個簡單的驅動,即一個DLL,實現規定的幾個流接口標準函數。(可以用Windows CE Stream Driver Wizard程序生成)
2.把上面的工程拷到WINCE500/PLATFORM/SMDK2410/SRC/DRIVERS下面,並修改dirs文件。dirs中指明瞭要編譯且添加到最終鏡像中的各個目錄。
3.修改Parameters View選項卡Emulator下的platform.reg
[HKEY_LOCAL_MACHINE/drivers/BuiltIn/SimpleDriver]
"Dll" = "SimpleDriver.dll"
"Prefix" = "DRV"
"Index" = dword:1
"Order" = dword:0
"FriendlyName" = "SimpleDriver"
"Icotl" = dword:0
4.修改修改Parameters View選項卡Emulator下的platform.bib。該文件表示最終被Copy到鏡像中的文件(默認指定的文件應該出現在WCE的windows/目錄下)
SimpleDriver.dll $(_FLATRELEASEDIR)/SimpleDriver.dll NK SH
5.生成Emulator鏡像
6.使用Platform Builder新建一個APPlication,TestSimpleDriver
在新建程序WinMain中添加:
HANDLE m_hDrv;
WCHAR str[200];
m_hDrv=CreateFile(L"DRV1:",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(m_hDrv==INVALID_HANDLE_VALUE)
{
int nRet=GetLastError();
_itow(nRet,str,10);
MessageBox(NULL,str,L"F",MB_OK);
MessageBox(NULL,L"DRV",L"F",MB_OK);
}
else
MessageBox(NULL,L"CreateFile Succeed",L"S",MB_OK);
注意:一定是DRV1:,要有1和冒號
7.單獨編譯Application,把application共享到Emulator即可運行Application
也可以這樣子:
下面的方法會在最終的鏡像中加入對應的文件和應用程序:
修改platform.bib文件:
如下圖所示,雙擊platform.bib文件,並在該文件尾部添加如下內容:
SimpleDriver.dll E:/EVC/TestDRV/ARMV4Re1/testdrv.dll NK SH
TestSimpleDriver. exe E: /EVC/TestDRVApp/ARMV4Dbg/testdrv. exe NK U
通過這種方法就可以使用EVC編寫驅動和測試程序,在加入到PB中了,而不用使用PB來編寫驅動和測試程序了
8.查看運行狀況.當wince系統啓動完畢之後,在PB的tool菜單下,選擇Remote Process Viewer,定位Device.exe,看看SimpleDriver.Dll是否被系統加載了.
也可以用Remote Registry Editor的BuildIn 和 Action鍵來查看
其他:如果把鏡像下載到箱子裏,可以使用RETAILMSG或者OutputDebugString等把信息輸出到串口
另外到處的SDK安裝後EVC不能使用了,因爲相應EVC Emulator不能使用,尚待解決。
SimpleDriver的主要代碼
#include <windows.h>
#include <types.h>
static BYTE g_Tmp = 0; /* 暫存數據變量 */
static DWORD g_OpenCount = 0; /* 驅動打開計數器 */
/*******************************************************************************************
函數名稱: DllEntry
描 述: 驅動程序動態庫入口
輸入參數:
輸出參數:
返 回:
*******************************************************************************************/
BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("DRV: DLL_PROCESS_ATTACH./r/n"))); /* 提示動態庫加載 */
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
case DLL_PROCESS_DETACH:
RETAILMSG(1, (TEXT("DRV: DLL_PROCESS_DETACH./r/n"))); /* 提示動態庫卸載 */
break;
}
return (TRUE);
}
/*******************************************************************************************
函數名稱: DRV_Init
描 述: 驅動程序初始化函數
輸入參數: DWORD dwContext: 設備管理器傳遞給本驅動的參數, 通常爲流接口驅動在註冊表內的位置
輸出參數: 無
返 回: 驅動程序句柄
*******************************************************************************************/
DWORD DRV_Init(DWORD dwContext)
{
RETAILMSG(1, (TEXT("::: DRV_Init./r/n"))); /* 提示驅動加載 */
g_Tmp = 0; /* 初始化全局變量的值 */
g_OpenCount = 0;
return 1; /* 返回一個不爲零的數表示成功 */
}
/*******************************************************************************************
函數名稱: DRV_Deinit
描 述: 驅動程序卸載函數
輸入參數: DWORD dwContext: 驅動程序句柄
輸出參數: 無
返 回: FALSE: 失敗 TRUE: 成功
*******************************************************************************************/
BOOL DRV_Deinit(DWORD dwContext)
{
RETAILMSG(1, (TEXT(":: DRV_Deinit./r/n"))); /* 提示驅動卸載 */
g_Tmp = 0; /* 恢復全局變量的值 */
g_OpenCount = 0;
return TRUE;
}
/*******************************************************************************************
函數名稱: DRV_Open
描 述: 打開驅動程序
輸入參數: DWORD hDeviceContext: 設備驅動程序引用實例句柄
DWORD AccessCode : 訪問請求代碼,是讀和寫的組合
DWORD ShareMode : 共享模式
輸出參數:
返 回: 驅動程序引用事例句柄
*******************************************************************************************/
DWORD DRV_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
RETAILMSG(1, (TEXT("::: DRV_Open./r/n"))); /* 提示驅動打開 */
// 不允許多個應用程序打開本驅動
if (g_OpenCount != 0)
{
RETAILMSG(1, (TEXT("DRV Open failed./r/n")));/* 提示驅動打開失敗 */
return 0;
}
g_OpenCount++; /* 驅動打開計數器加1 */
return g_OpenCount; /* 必須返回一個不爲空的句柄 */
}
/*******************************************************************************************
函數名稱: DRV_Close
描 述: 驅動程序關閉函數
輸入參數: DWORD hOpenContext:驅動程序引用事例句柄
輸出參數: 無
返 回: FALSE: 失敗 TRUE: 成功
*******************************************************************************************/
BOOL DRV_Close(DWORD hOpenContext)
{
RETAILMSG(1, (TEXT("::: DRV_Close./r/n"))); /* 提示驅動關閉 */
if (g_OpenCount != 0)
g_OpenCount--; /* 驅動打開計數減1 */
return TRUE;
}
/*******************************************************************************************
函數名稱: DRV_IOControl
描 述: 驅動程序 I/O 請求
輸入參數:
輸出參數:
返 回: TRUE: 成功 FALSE: 失敗
*******************************************************************************************/
BOOL DRV_IOControl(DWORD hOpenContext,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
RETAILMSG(1, (TEXT("::: DRV_IOControl./r/n"))); /* 提示I/O請求函數執行 */
return TRUE;
}
/*******************************************************************************************
函數名稱: DRV_Read
描 述: 從本驅動讀取數據
輸入參數: DWORD hOpenContext: 驅動程序引用事例句柄
DWORD Count : 要讀的字節數
輸出參數: LPVOID pBuffer : 接收緩衝區
返 回: 實際讀到的字節數
*******************************************************************************************/
DWORD DRV_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
uchar *pReadBuffer;
RETAILMSG(1, (TEXT("::: DRV_Read./r/n"))); /* 提示執行讀函數 */
if ((pBuffer == NULL) || (Count <= 0))
{ /* 讀函數入口參數錯誤 */
RETAILMSG(1, (TEXT("::: DRV_Read() parameter is error./r/n")));
return 0;
}
// 映射地址空間
pReadBuffer = MapPtrToProcess(pBuffer, GetCallerProcess());
*pReadBuffer = g_Tmp; /* 返回數據 */
return 1; /* 返回讀取的字節數 */
}
/*******************************************************************************************
函數名稱: DRV_Write
描 述: 向本驅動寫入數據
輸入參數: DWORD hOpenContext: 驅動程序引用事例句柄
LPVOID pBuffer : 發送緩衝區
DWORD Count : 要寫入的字節數
輸出參數: 無
返 回: 實際寫入的字節數
*******************************************************************************************/
DWORD DRV_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count)
{
uchar *pWriteBuffer;
RETAILMSG(1, (TEXT("::: DRV_Write./r/n"))); /* 提示執行寫函數 */
if ((pBuffer == NULL) || (Count <= 0))
{ /* 寫函數入口參數錯誤 */
RETAILMSG(1, (TEXT("::: DRV_Write() parameter is error./r/n")));
return 0;
}
// 獲取應用程序地址空間數據指針
pWriteBuffer = MapPtrToProcess((LPVOID)pBuffer, GetCallerProcess());
g_Tmp = *pWriteBuffer; /* 保存數據 */
return 1;
}
/*******************************************************************************************
函數名稱: DRV_Seek
描 述: 對設備的數據指針進行操作,本驅動不支持該函數
輸入參數:
輸出參數:
返 回:
*******************************************************************************************/
DWORD DRV_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
RETAILMSG(1, (TEXT("::: DRV_Seek./r/n"))); /* 提示執行本函數 */
return 0;
}
/*******************************************************************************************
函數名稱: DRV_PowerUp
描 述: 電源上電驅動處理函數
輸入參數:
輸出參數:
返 回: 無
*******************************************************************************************/
void DRV_PowerUp(void)
{
RETAILMSG(1, (TEXT("::: DRV_PowerUp./r/n"))); /* 提示執行本函數 */
}
/*******************************************************************************************
函數名稱: DRV_PowerDown
描 述: 電源下電驅動處理函數
輸入參數:
輸出參數:
返 回: 無
*******************************************************************************************/
void DRV_PowerDown(void)
{
RETAILMSG(1, (TEXT("::: DRV_PowerDown./r/n"))); /* 提示執行本函數 */
}