WindowsCE6.0中断实验过程
----利用键盘控制LED的驱动程序
1.实验目的:通过本次试验学习WindowsCE6.0的中断处理的过程以及熟悉在驱动程序中运行中断的编程。
2.我对WindowsCE6.0中断的理解:
Windows®CE将中断处理分成两个步骤:中断服务程序ISR和中断服务线程IST。如果中断被使能,则当中断产生时,内核将调用该中断注册的ISR,ISR执行完后将返回系统中断号,内核检查系统中断号并且设置相关的事件,内核设置相关事件后,相应的IST将开始执行。
3.Windows®CE的处理流程:
(1)如果一个驱动程序要处理一个中断,那么驱动程序首先要建立一个事件(CreateEvent),然后调用InterruptInitialize将该事件与中断号绑定,这一步会使能该中断,OAL中的OEMInerrupteEnable会被调用,如果该函数不返回true的话,InterruptInitialize就会失败。然后驱动程序中的IST就可以使用WaitForSingleObject函数来等待中断的发生。
(2)当一个硬件中断发生之后,操作系统陷入异常,中断向量指示进入CE的异常处理程序,该异常处理程序然后调用OAL的OEMInterruptHandler函数,该函数检测硬件之后,将硬件中断转换为软件的中断号,返回给系统。该中断号就是上面提到的InterruptInitialize中使用的那个中断号。系统得到该中断号之后,就会找到该中断号对应的事件,并唤醒等待相应事件的线程(IST),然后IST就可以在用户态进行中断处理。处理完成之后,IST需要调用InterruptDone来告诉操作系统中断处理结束,操作系统调用OAL中的OEMInterruptDone函数,最后完成中断的处理。
4.在驱动中安装中断的方法:
首先,在驱动中通过CreateEvent()函数创建一个Event内核对象,然后通过InterruptInitialize()
函数负责把某个逻辑中断号与这个Event内核对象关联起来。当中断发生时,操作系统负责引发此
Event事件,函数的原型如下:
InterruptInitialize(DWORDidInt, //SYSINTR中断号
HANDLEhEvent, //与该中断相关联的事件句柄
LPVOIDpvData, //传给OEMInterruptEnable缓冲指针
DWORDcbData, //缓冲区的大小
)
然后通过CreatThread()函数来来创建一个线程,在线程函数中用WaitForSingleObject()来阻塞
当前的线程,等待某个Event内核对象标识的事件发生。当中断发生后,OAL层就会返回逻辑中断,
与逻辑中断相关联的Event事件就会被触发,被阻塞的中断线程函数就会就绪开始工作。
InterruptDonce()函数用来告诉操作系统,对该中断的处理已完成,操作系统可重新开启该中断。
5.步骤:
1.在vs2005里面新建一个DLL的子项目MyKey,在F:/WINCE600/PLATFORM/SMDK6410/SRC/DRIVERS/目录下
2.添加MyKey.c和MyKey.h文件,编辑源程序,如下:
MyKey.h:
#ifndef _MYKEY_H
#define _MYKEY_H
#ifdef __cplusplus
Extern"C"{
#endif
typedefstruct{
volatileS3C6410_GPIO_REG*pGPIOregs;
BOOLFlagExitThrd;
}KEY_PUBLIC_CONTEXT,*PKEY_PUBLIC_CONTEXT;
#ifdef __cplusplus
}
#endif
#endif
MyKey.c:
#include<windows.h>
#include<nkintr.h>
#include<pm.h>
#include<nkintr.h>
#include<bsp.h>
#include<s3c6410.h>
#include<s3c6410_vintr.h>
#include<DrvLib.h>
#include"MyKey.h"
#defineLed1Mask 0x01
#defineLed2Mask 0x02
#defineLed3Mask 0x04
#defineLed4Mask 0x08
#defineLedAllMask 0x0F
#defineButt1Mask 0x01
#defineButt2Mask 0x02
#defineButt3Mask 0x04
#defineButt4Mask 0x08
#defineButt5Mask 0x10
#defineButt6Mask 0x20
static KEY_PUBLIC_CONTEXT *pPublicKey=NULL;
staticvolatileUINT32 dwLedFlag=1;
UINT32g_SysIntr1=0;
UINT32g_SysIntr2=0;
HANDLEg_hEvent1=NULL;
HANDLEg_hThread1=NULL;
HANDLEg_hEvent2=NULL;
HANDLEg_hThread2=NULL;
/******************************************************************************
*
* MyKeybuttoneventthread
*
*******************************************************************************/
INTWINAPIButton1Thread(void)
{
RETAILMSG(1,(TEXT("Button1ThreadEntered!/r/n")));
while(!pPublicKey->FlagExitThrd)
{
UINT16ch;
RETAILMSG(1,(TEXT("Button1KEY_Read:KEYDeviceReadSuccessfully./r/n")));
ch=(UINT16)pPublicKey->pGPIOregs->GPNDAT;
RETAILMSG(1,(TEXT("Button1ReadValue:0x%x/n"),ch));
RETAILMSG(1,(TEXT("Button1Thread!/r/n")));
WaitForSingleObject(g_hEvent1,INFINITE);
if(pPublicKey->FlagExitThrd)
break;
RETAILMSG(1,(TEXT("Button1ThreadStartRunning!/r/n")));
if(dwLedFlag==1)
{
dwLedFlag=0;
pPublicKey->pGPIOregs->GPMDAT|=LedAllMask;
RETAILMSG(1,(TEXT("Button1pressed---LedALLOn:/r/n")));
}
else
{
dwLedFlag=1;
pPublicKey->pGPIOregs->GPMDAT&=~LedAllMask;
RETAILMSG(1,(TEXT("Button1pressed---LedALLOff:/r/n")));
}
InterruptDone(g_SysIntr1);
}
RETAILMSG(1,(TEXT("KEY:KEYButton1ThreadExiting/r/n")));
return0;
}//Key_Button1Thread()
INTWINAPIButton2Thread(void)
{
DWORDLedNum=1;
RETAILMSG(1,(TEXT("Button2ThreadEntered!/r/n")));
while(!pPublicKey->FlagExitThrd)
{
UINT16ch;
RETAILMSG(1,(TEXT("Button2KEY_Read:KEYDeviceReadSuccessfully./r/n")));
ch=(UINT16)pPublicKey->pGPIOregs->GPNDAT;
RETAILMSG(1,(TEXT("Button2ReadValue:0x%x/n"),ch));
RETAILMSG(1,(TEXT("Button2Thread!/r/n")));
WaitForSingleObject(g_hEvent2,INFINITE);
if(pPublicKey->FlagExitThrd)
break;
RETAILMSG(1,(TEXT("Button2ThreadStartRunning!/r/n")));
if(LedNum==1)
{
LedNum=2;
pPublicKey->pGPIOregs->GPMDAT|=Led1Mask;
RETAILMSG(1,(TEXT("Button2pressed---Led1on:/r/n")));
}
elseif(LedNum==2)
{
LedNum=3;
pPublicKey->pGPIOregs->GPMDAT|=Led2Mask;;
RETAILMSG(1,(TEXT("Button2pressed---Led2On:/r/n")));
}
elseif(LedNum==3)
{
LedNum=4;
pPublicKey->pGPIOregs->GPMDAT|=Led3Mask;;
RETAILMSG(1,(TEXT("Button2pressed---Led3On:/r/n")));
}
elseif(LedNum==4)
{
LedNum=0;
pPublicKey->pGPIOregs->GPMDAT|=Led4Mask;;
RETAILMSG(1,(TEXT("Button2pressed---Led4On:/r/n")));
}
else
{
LedNum=1;
pPublicKey->pGPIOregs->GPMDAT&=~LedAllMask;;
RETAILMSG(1,(TEXT("Button2pressed---LedALLoff:/r/n")));
}
InterruptDone(g_SysIntr2);
}
RETAILMSG(1,(TEXT("KEY:KEYButton2ThreadExiting/r/n")));
return0;
}//Key_Button2Thread()
BOOLKEY_Deinit(DWORDdwContext)
{
RETAILMSG(1,(TEXT("KEY_DeInit:dwContext=0x%x/r/n/n"),dwContext));
//informISTexitstatus
pPublicKey->FlagExitThrd=TRUE;
//freevirtualmemory
if(pPublicKey->pGPIOregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicKey->pGPIOregs);
pPublicKey->pGPIOregs=NULL;
}
if(g_hEvent1)
{
SetEvent(g_hEvent1);
InterruptDisable(g_SysIntr1);
CloseHandle(g_hEvent1);
}
if(g_hEvent2)
{
SetEvent(g_hEvent2);
InterruptDisable(g_SysIntr2);
CloseHandle(g_hEvent2);
}
//Waitforthreadstofinish
WaitForSingleObject(g_hThread1,INFINITE);
if(g_hThread1)
CloseHandle(g_hThread1);
WaitForSingleObject(g_hThread2,INFINITE);
if(g_hThread2)
CloseHandle(g_hThread2);
LocalFree(pPublicKey);
return(TRUE);
}
PKEY_PUBLIC_CONTEXTKEY_Init(DWORDdwContext)
{
LPTSTRActivePath=(LPTSTR)dwContext;//HKLM/Drivers/Active/xx
BOOLbResult=TRUE;
DWORDdwHwIntr=0;
RETAILMSG(1,(TEXT("KEY_Init:dwContext=0x%x/r/n"),dwContext));
RETAILMSG(1,(TEXT("[KEY]ActivePath:%s/n"),ActivePath));
if(!(pPublicKey=(PKEY_PUBLIC_CONTEXT)LocalAlloc(LPTR,sizeof(KEY_PUBLIC_CONTEXT))))
{
RETAILMSG(1,(TEXT("[KEY]Can'tnotallocateforKEYContext/n")));
returnNULL;
}
//GPIOVirtualalloc
pPublicKey->pGPIOregs=(volatileS3C6410_GPIO_REG*)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO,sizeof(S3C6410_GPIO_REG),FALSE);
if(pPublicKey->pGPIOregs==NULL)
{
RETAILMSG(1,(TEXT("[KEY]ForpGPIOregs:DrvLib_MapIoSpacefailed!/r/n")));
bResult=FALSE;
gotoCleanUp;
}
//禁止上下拉
pPublicKey->pGPIOregs->GPMPUD=0x00000000;
//GPM0-GPM3设置成输出
pPublicKey->pGPIOregs->GPMCON=0x00001111;
//LED0-3熄灭
pPublicKey->pGPIOregs->GPMDAT=0x0;
//设置EINT0中断
//禁止GPN0和GPN1上下拉
pPublicKey->pGPIOregs->GPNPUD&=~0x0F;
//GPN0-1设置成外中断
pPublicKey->pGPIOregs->GPNCON|=0x0a;
//使能外中断EINT0-EINT1
pPublicKey->pGPIOregs->EINT0MASK&=~0x3;
//EINT0-1下降沿触发中断
pPublicKey->pGPIOregs->EINT0CON0|=0x2;
do
{
//Button1Thread
pPublicKey->FlagExitThrd=FALSE;
g_hEvent1=CreateEvent(NULL,FALSE,FALSE,NULL);
g_SysIntr1=SYSINTR_UNDEFINED;
dwHwIntr=IRQ_EINT0;
if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&dwHwIntr,sizeof(DWORD),&g_SysIntr1,sizeof(DWORD),NULL))
{
RETAILMSG(1,(TEXT("[KEY]FailedtorequesttheKEYsysintr./n")));
g_SysIntr1=SYSINTR_UNDEFINED;
bResult=FALSE;
break;
}
if(!InterruptInitialize(g_SysIntr1,g_hEvent1,NULL,0))
{
RETAILMSG(1,(TEXT("[KEY]KEYInterruptInitializationfailed!!!/n")));
bResult=FALSE;
break;
}
g_hThread1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Button1Thread,NULL,0,NULL);
if(g_hThread1==NULL)
{
RETAILMSG(1,(TEXT("[KEY]KeyButtonThreadcreationerror!!!/n")));
bResult=FALSE;
break;
}
//Button2Thread
g_hEvent2=CreateEvent(NULL,FALSE,FALSE,NULL);
g_SysIntr2=SYSINTR_UNDEFINED;
dwHwIntr=IRQ_EINT1;
if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&dwHwIntr,sizeof(DWORD),&g_SysIntr2,sizeof(DWORD),NULL))
{
RETAILMSG(1,(TEXT("[KEY]FailedtorequesttheKEYsysintr./n")));
g_SysIntr2=SYSINTR_UNDEFINED;
bResult=FALSE;
break;
}
if(!InterruptInitialize(g_SysIntr2,g_hEvent2,NULL,0))
{
RETAILMSG(1,(TEXT("[KEY]KEYInterruptInitializationfailed!!!/n")));
bResult=FALSE;
break;
}
g_hThread2=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Button2Thread,NULL,0,NULL);
if(g_hThread2==NULL)
{
RETAILMSG(1,(TEXT("[KEY]KeyButton2Threadcreationerror!!!/n")));
bResult=FALSE;
break;
}
}while(0);
RETAILMSG(1,(TEXT("--[KEY]KEY_InitFunction/r/n")));
if(bResult)
{
returnpPublicKey;
}
else
{
returnNULL;
}
CleanUp:
if(!bResult)
{
if(pPublicKey->pGPIOregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicKey->pGPIOregs);
pPublicKey->pGPIOregs=NULL;
}
returnNULL;
}
}
DWORDKEY_Open(DWORDdwData,DWORDdwAccess,DWORDdwShareMode)
{
RETAILMSG(1,(TEXT("KEY_Open:KEYDeviceOpenSuccessfully./r/n")));
return(dwData);
}
BOOLKEY_Close(DWORDHandle)
{
RETAILMSG(1,(TEXT("KEY_Close:KEYDeviceCloseSuccessfully./r/n")));
return(TRUE);
}
DWORDKEY_Read(DWORDHandle,LPVOIDpBuffer,DWORDdwNumBytes)
{
UINT16ch;
DWORDresult;
RETAILMSG(1,(TEXT("KEY_Read:KEYDeviceReadSuccessfully./r/n")));
ch=(UINT16)pPublicKey->pGPIOregs->GPNDAT;
if((ch&Butt1Mask)!=0)
{
result=1;
RETAILMSG(1,(TEXT("Button1pressed:/r/n")));
}
elseif((ch&Butt2Mask)!=0)
{
result=2;
RETAILMSG(1,(TEXT("Button2pressed:/r/n")));
}
else
{
result=-1;
RETAILMSG(1,(TEXT("NoButtonpressed:/r/n")));
}
dwNumBytes=result;
return(dwNumBytes);
}
DWORDKEY_Write(DWORDHandle,LPCVOIDpBuffer,DWORDdwNumBytes)
{
RETAILMSG(1,(TEXT("BTN_Write:KEYDeviceWriteSuccessfully./r/n")));
return(TRUE);
}
DWORDKEY_Seek(DWORDHandle,longlDistance,DWORDdwMoveMethod)
{
return(DWORD)-1;
}
voidKEY_PowerDown(void)
{
return;
}
voidKEY_PowerUp(void)
{
return;
}
BOOLKEY_IOControl(DWORDhOpenContext,DWORDdwCode,PBYTEpBufIn,DWORDdwLenIn,PBYTEpBufOut,DWORDdwLenOut,PDWORDpdwActualOut)
{
RETAILMSG(1,(TEXT("BTN_IOControl:/r/n")));
return(TRUE);
}
/*******************************************************************************
*DLL入口函数
*******************************************************************************/
BOOL
DllEntry(
HINSTANCEhinstDll,
DWORDdwReason,
LPVOIDlpReserved
)
{
if(dwReason==DLL_PROCESS_ATTACH)
{
DEBUGMSG(1,(TEXT("[MyKey]ProcessAttach/r/n")));
}
if(dwReason==DLL_PROCESS_DETACH)
{
DEBUGMSG(1,(TEXT("[MyKey]ProcessDetach/r/n")));
}
return(TRUE);
}
3.编写配置文件,包括如下文件sources,MyKey.def,makefile如下:
技巧:可以到其他驱动程序目录下拷贝在加以修改
Sources:
RELEASETYPE=PLATFORM
PREPROCESSDEFFILE=1
TARGETNAME=MyKey
TARGETTYPE=DYNLINK
DEFFILE=MyKey.def
DLLENTRY=DllEntry
TARGETLIBS=/
$(_PROJECTROOT)/cesysgen/sdk/lib/$(_CPUINDPATH)/coredll.lib/
$(_TARGETPLATROOT)/lib/$(_CPUINDPATH)/DriverLib.lib
SOURCES=/
MyKey.c
MyKey.def:
LIBRARYMyKey
EXPORTS
KEY_Init
KEY_Deinit
KEY_Open
KEY_Close
KEY_Read
KEY_Write
KEY_Seek
KEY_IOControl
KEY_PowerDown
KEY_PowerUp
Makefile:
!INCLUDE$(_MAKEENVROOT)/makefile.def
4.修改整体项目的配置文件,以便加入我们的驱动到系统中
(1)。platform.bib文件:添加如下一句到文件的合适位置
MyKey.dll$(_FLATRELEASEDIR)/MyKey.dllNKSHK
(2)。Platform.reg注册表文件:添加如下
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MyKey]
"Prefix"="KEY"
"DLL"="MyKey.dll"
"Order"=dword:4
"Index"=dword:1
(3)。修改上层目录的Dirs文件,根据需要添加如下一句:
DIRS=/
DrvLib/
...
WIFI_SDIO/
MyKey 注:这是添加到此文件的内容。
5.编译建立此驱动。注意:这里只需要编译驱动目录就可以了,不需要重新编译整个系统。
: