您的位置:首页 > 其它

如何开发一个WinCE 6的流设备驱动

2009-06-26 09:44 579 查看
在BSP的Drivers目录下,创建新驱动程序的目录,比如MyDriver

修改dirs文件,在变量DIRS中增加新目录MyDriver

创建文件Sources,内容如下:

TARGETNAME=MyDriver
RELEASETYPE=PLATFORM
TARGETTYPE=DYNLINK
DEFFILE=MyDriver.def
DLLENTRY=DllEntry
TARGETLIBS= $(_COMMONSDKROOT)/lib/$(_CPUINDPATH)/coredll.lib

SOURCES=MyDriver.c


创建文件Makefile.inc,内容如下:

#
# DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the components of Windows CE.
#
!INCLUDE $(_MAKEENVROOT)/makefile.def


创建文件MyDriver.def,内容如下:

LIBRARY         MyDriver

EXPORTS         XXX_Init
XXX_Deinit
XXX_Open
XXX_Close
XXX_Read
XXX_Write
XXX_Seek
XXX_PowerDown
XXX_PowerUp
XXX_IOControl


创建文件MyDriver.c,内容如下:

#include <windows.h>
#include <Devload.h>

BOOL XXX_Deinit(DWORD hDeviceContext)
{
return TRUE;
}

DWORD XXX_Init(ULONG RegistryPath)
{
HKEY	hKey;

RETAILMSG(1, (TEXT("XXX_Init/n")));
hKey = OpenDeviceKey((LPCTSTR) RegistryPath);
if(!hKey)
{
RETAILMSG(1, (TEXT("Failed to open devkeypath,/r/n")));
}
else
{
/* Read values from registry if needed */
RegCloseKey(hKey);
}

return TRUE;
}

BOOL WINAPI DllEntry(HINSTANCE DllInstance, ULONG Reason, LPVOID Reserved)
{
RETAILMSG(1, (TEXT("MyDriver: DllEntry/n")));
return TRUE;
}

VOID XXX_PowerUp(DWORD hDeviceContext)
{
}

VOID XXX_PowerDown(DWORD hDeviceContext)
{
}

DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
return hDeviceContext;
}

BOOL XXX_Close(DWORD hOpenContext)
{
return TRUE;
}

DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
return 0;
}

DWORD XXX_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
return 0;
}

DWORD XXX_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
return 0;
}

BOOL XXX_IOControl
(
DWORD	hOpenContext,
DWORD	dwCode,
PBYTE	pBufIn,
DWORD	dwLenIn,
PBYTE	pBufOut,
DWORD	dwLenOut,
PDWORD	pdwActualOut
)
{
BOOL	RetVal = TRUE;

switch(dwCode)
{
default:	RetVal = FALSE; break;
}

return RetVal;
}


在platform.bib或者project.bib中,加入此驱动:

MyDriver.dll $(_FLATRELEASEDIR)/MyDriver.dll  NK  K


在platform.reg或者project.reg中,设置此驱动为BuildIn类型,自动加载:

[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MyDriver]
"Dll"="MyDriver.dll"
"Order"=dword:4
"Prefix"="XXX"


至此,一个没有实现任何功能的驱动完成了,下面描述如何在驱动中使用中断。

创建中断线程函数(IST),在线程中申请并等待中断:

static DWORD WINAPI MyInterruptThread(LPVOID p)
{
DWORD	RetVal = 0;
HANDLE	hEvent;
DWORD	SysintrValue;
DWORD	IRQ = MYDRIVER_IRQ;

/* Create an Event */
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

/* Register with the Kernel */
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &IRQ, sizeof(DWORD), &SysintrValue, sizeof(DWORD), NULL);
RetVal = InterruptInitialize(SysintrValue, hEvent, NULL, 0);

/* Set the Thread Priority */
CeSetThreadPriority(GetCurrentThread(), 150);

while(1)
{
/* Wait for the Event to be Signaled */
RetVal = WaitForSingleObject(hEvent, 2000);

if(RetVal == WAIT_OBJECT_0)
{
/*
* Service the Interrupt
* In this case suspend the device
*/
SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);

/* Tell the Kernel that the Interrupt has been Serviced */
InterruptDone(SysintrValue);
}
else if(RetVal == WAIT_TIMEOUT)
{
/*
* Optional, provide a way to stop the thread when the driver unloads
* This is optional because the driver may never unload
*/
if(StopThreads) break;
}
}

/* When and if the driver unloads and the thread exits release resources */
InterruptDisable(SysintrValue);
CloseHandle(hEvent);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &SysintrValue, sizeof(DWORD), NULL, 0, NULL);

return 0;
}


驱动Dll被加载后,系统首先调用DllEntry,随后调用XXX_Init。修改XXX_Init,加入线程启动代码:

HANDLE hthrd;

// Start thread
hthrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MyInterruptThread,NULL,0,NULL);
// Since we don't need the handle, close it now.
CloseHandle(hthrd);


如果驱动只需要处理一个中断,WaitForSingleObject可以处理得很好,如果有多个中断需要处理时,能依葫芦画瓢,创建多个event,每个event注册一个中断,然后使用WaitForMultipleObjects吗?很遗憾,虽然WinCE支持WaitForMultipleObjects,但对于注册到中断的event,只允许等待一个,考虑到中断处理程序所要求的高性能,为了避免进入死锁,当event数目大于1时,WaitForMultipleObjects将会失败,GetLastError返回参数无效的错误代码(是的,如果只有一个event,WaitForMultipleObjects仍然会成功)。

在这种情况下,一种解决方法是,创建多个IST,每个IST处理一个中断。

此外,还有另一种更好的方法,就是把同一个event注册到多个中断,然后使用WaitForSingleObject等待此event,每个中断被触发时,event都会获得信号:

int i;
HANDLE hEvent;

// Create an Event
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

// Init all interrupt to a event
for(i=0; i<MY_INT_COUNT; i++)
{
// Register with the Kernel
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irqs[i], sizeof(DWORD), &intrs[i], sizeof(DWORD), NULL) ;
InterruptInitialize( intrs[i], hEvent, NULL, 0 );
}

.
.
.
.

// When and if the driver unloads and the thread exits release resources
for(i=0;i<MY_INT_COUNT;i++)
{
InterruptDisable( intrs[i]);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &intrs[i], sizeof(DWORD), NULL, 0, NULL);
}

CloseHandle( hEvent );


(参考了Bruce Eitman的文章,http://geekswithblogs.net/BruceEitman/Default.aspx)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: