•在BSP的Drivers目录下,创建新驱动程序的目录,比如MyDriver
•修改dirs文件,在变量DIRS中增加新目录MyDriver
•创建文件Sources,内容如下:
view plaincopy to clipboardprint?
01.TARGETNAME=MyDriver
02.RELEASETYPE=PLATFORM
03.TARGETTYPE=DYNLINK
04.DEFFILE=MyDriver.def
05.DLLENTRY=DllEntry
06.TARGETLIBS= $(_COMMONSDKROOT)/lib/$(_CPUINDPATH)/coredll.lib
07.
08.SOURCES=MyDriver.c
TARGETNAME=MyDriver
RELEASETYPE=PLATFORM
TARGETTYPE=DYNLINK
DEFFILE=MyDriver.def
DLLENTRY=DllEntry
TARGETLIBS= $(_COMMONSDKROOT)/lib/$(_CPUINDPATH)/coredll.lib
SOURCES=MyDriver.c
•创建文件Makefile.inc,内容如下:
view plaincopy to clipboardprint?
01.#
02.# DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source
03.# file to this component. This file merely indirects to the real make file
04.# that is shared by all the components of Windows CE.
05.#
06.!INCLUDE $(_MAKEENVROOT)/makefile.def
#
# 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,内容如下:
view plaincopy to clipboardprint?
01.LIBRARY MyDriver
02.
03.EXPORTS XXX_Init
04. XXX_Deinit
05. XXX_Open
06. XXX_Close
07. XXX_Read
08. XXX_Write
09. XXX_Seek
10. XXX_PowerDown
11. XXX_PowerUp
12. XXX_IOControl
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,内容如下:
view plaincopy to clipboardprint?
01.#include <windows.h>
02.#include <Devload.h>
03.
04.
05.BOOL XXX_Deinit(DWORD hDeviceContext)
06.{
07. return TRUE;
08.}
09.
10.DWORD XXX_Init(ULONG RegistryPath)
11.{
12. HKEY hKey;
13.
14. RETAILMSG(1, (TEXT("XXX_Init/n")));
15. hKey = OpenDeviceKey((LPCTSTR) RegistryPath);
16. if(!hKey)
17. {
18. RETAILMSG(1, (TEXT("Failed to open devkeypath,/r/n")));
19. }
20. else
21. {
22. /* Read values from registry if needed */
23. RegCloseKey(hKey);
24. }
25.
26. return TRUE;
27.}
28.
29.
30.BOOL WINAPI DllEntry(HINSTANCE DllInstance, ULONG Reason, LPVOID Reserved)
31.{
32. RETAILMSG(1, (TEXT("MyDriver: DllEntry/n")));
33. return TRUE;
34.}
35.
36.
37.VOID XXX_PowerUp(DWORD hDeviceContext)
38.{
39.}
40.
41.
42.VOID XXX_PowerDown(DWORD hDeviceContext)
43.{
44.}
45.
46.
47.DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
48.{
49. return hDeviceContext;
50.}
51.
52.
53.BOOL XXX_Close(DWORD hOpenContext)
54.{
55. return TRUE;
56.}
57.
58.
59.DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
60.{
61. return 0;
62.}
63.
64.
65.DWORD XXX_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
66.{
67. return 0;
68.}
69.
70.
71.DWORD XXX_Seek(DWORD hOpenContext, long Amount, DWORD Type)
72.{
73. return 0;
74.}
75.
76.
77.BOOL XXX_IOControl
78.(
79. DWORD hOpenContext,
80. DWORD dwCode,
81. PBYTE pBufIn,
82. DWORD dwLenIn,
83. PBYTE pBufOut,
84. DWORD dwLenOut,
85. PDWORD pdwActualOut
86.)
87.{
88. BOOL RetVal = TRUE;
89.
90. switch(dwCode)
91. {
92. default: RetVal = FALSE; break;
93. }
94.
95. return RetVal;
96.}
#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中,加入此驱动:
view plaincopy to clipboardprint?
01.MyDriver.dll $(_FLATRELEASEDIR)/MyDriver.dll NK K
MyDriver.dll $(_FLATRELEASEDIR)/MyDriver.dll NK K
•在platform.reg或者project.reg中,设置此驱动为BuildIn类型,自动加载:
view plaincopy to clipboardprint?
01.[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MyDriver]
02. "Dll"="MyDriver.dll"
03. "Order"=dword:4
04. "Prefix"="XXX"
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MyDriver]
"Dll"="MyDriver.dll"
"Order"=dword:4
"Prefix"="XXX"
至此,一个没有实现任何功能的驱动完成了,下面描述如何在驱动中使用中断。
•创建中断线程函数(IST),在线程中申请并等待中断:
view plaincopy to clipboardprint?
01.static DWORD WINAPI MyInterruptThread(LPVOID p)
02.{
03. DWORD RetVal = 0;
04. HANDLE hEvent;
05. DWORD SysintrValue;
06. DWORD IRQ = MYDRIVER_IRQ;
07.
08. /* Create an Event */
09. hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
10.
11. /* Register with the Kernel */
12. KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &IRQ, sizeof(DWORD), &SysintrValue, sizeof(DWORD), NULL);
13. RetVal = InterruptInitialize(SysintrValue, hEvent, NULL, 0);
14.
15. /* Set the Thread Priority */
16. CeSetThreadPriority(GetCurrentThread(), 150);
17.
18. while(1)
19. {
20. /* Wait for the Event to be Signaled */
21. RetVal = WaitForSingleObject(hEvent, 2000);
22.
23. if(RetVal == WAIT_OBJECT_0)
24. {
25. /*
26. * Service the Interrupt
27. * In this case suspend the device
28. */
29. SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
30.
31. /* Tell the Kernel that the Interrupt has been Serviced */
32. InterruptDone(SysintrValue);
33. }
34. else if(RetVal == WAIT_TIMEOUT)
35. {
36. /*
37. * Optional, provide a way to stop the thread when the driver unloads
38. * This is optional because the driver may never unload
39. */
40. if(StopThreads) break;
41. }
42. }
43.
44. /* When and if the driver unloads and the thread exits release resources */
45. InterruptDisable(SysintrValue);
46. CloseHandle(hEvent);
47. KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &SysintrValue, sizeof(DWORD), NULL, 0, NULL);
48.
49. return 0;
50.}
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,加入线程启动代码:
view plaincopy to clipboardprint?
01.HANDLE hthrd;
02.
03.// Start thread
04.hthrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MyInterruptThread,NULL,0,NULL);
05.// Since we don't need the handle, close it now.
06.CloseHandle(hthrd);
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都会获得信号:
view plaincopy to clipboardprint?
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 );
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)
本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/noodies/archive/2009/06/26/4299694.aspx