很开心,按键中断终于基本搞定了,下面将自己的心得分享下:
中断驱动书写流程:
1.编写本驱动库的入口函数。DllEntry()。
2.设置物理地址到虚拟地址映射。原因wince启动后是对虚拟地址操作。EINT_InitializeAddresses。
3.配置中断引脚EINT_ConfigInterruptPin()。
4.创建一个线程,指定线程函数,并获得句柄。gEINTIntread=CreateThread().
5.根据ISR获得一个SYSINTR(逻辑中断),所用函数为:KernelIoControl().WINCE提供IO请求命令
IOCTL_HAL_REQUSST_SYSINTR,用于请求该中断的中断逻辑号。
6.创建一个Event,并初始化为:自给动触发,未标识,并获得该句柄gReadKeyEvent[0]=CreateEvent(NULL,FALSE,FALSE,NULL).
7.将SYSINTR与一个Event内核时间关联起来,当中断发生时,引发该事件。InterruptInitialize().
8.等待时间的出发WaitForSingleObject().
9.处理中断过程。
10.通知内核中断处理完毕InterruptDone().
11.释放中断资源。KernelIoControl().WINCE提供IO请求命令IOCTL_HAL_RELEASE_SYSINTR,用于请求该中断的中断逻辑号。
注意:凡是程序中开发者主动申请的内存,句柄,事件等一定要记得释放。
中断之间的关系在分析:
外部设备通过CPU的中断引脚向CPU发送中断信号(IRQ),然后通过ISR映射,把IRQ转化成逻辑中断并返回给
内核,IST处理则负责中断的逻辑处理。
IRQ(Interrupt ReQuest ):物理中断请求。检测是否有中断产生。当中断发生的时候,ISR就会触发事件生效。
ISR(Interrupt Service Routine):中断服务例程,运行在内核中的一段代码,通常由OEM实现,ISR一般会给
返回一个SYSINTR(逻辑中断号)。也就是说,ISR必须把IRQ转换成逻辑中断号。
IST(Interrupt Service Thread):中断服务线程。IST也就是一个普通的用户态线程,处理大部分中断操作,
一般空闲,只有操作系统通知IST有中断发生时,IST才操作。
IST中常用的函数介绍:
InterruptInitialize()函数负责把某个逻辑中断号与一个Event内核对象关联起来。
WaitForSingleObject()阻塞当前线程,等待事件触发生效。
InterruptDone().告诉操作系统中断已经结束。
IST第一件事情就是使用CreateEnent()函数创建一个Event内核对象,并且使用InterruptInitialize()函数
把这个Event与一个逻辑中断相关联,这样中断发生的时候,操作系统就可以引发这一事件。
下面这个函数是我修改YC里面的,它里面的那个比较乱,很多函数没用,我也不知道上面意思,我把没用的删除掉了,测试后这个程序可以正常使用,我感觉YC里面的驱动很不负责,至少在初学者来说,写的很迷糊,理解起来有点困难,因此将精简的代码写出来,如果哪里错了,还忘各位给提醒下:
#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <tchar.h>
#include <cardserv.h>
#include <cardapi.h>
#include <tuple.h>
#include <devload.h>
#include <diskio.h>
#include <nkintr.h>
#include <windev.h>
#include "BSP.h"
#include "pwrbtn2440.h"
#define PRIVATE static
#define PUBLIC
//以下为一个函数指针
typedef DWORD (*PFN_SetSystemPowerState)(LPCWSTR, DWORD, DWORD);
PFN_SetSystemPowerState gpfnSetSystemPowerState;
PRIVATE HANDLE gPwrButtonIntrEvent;
PRIVATE HANDLE gPwrButtonIntrThread;
UINT32 g_PwrButtonIrq = IRQ_EINT0;
UINT32 g_PwrButtonSysIntr = SYSINTR_UNDEFINED;
UINT32 g_RebootButtonIrq = IRQ_EINT2;
UINT32 g_RebootButtonSysIntr = SYSINTR_UNDEFINED;
UINT32 g_BattFLTIrq = IRQ_BAT_FLT;
UINT32 g_BattFLTSysIntr = SYSINTR_UNDEFINED;
PRIVATE volatile S3C2440A_IOPORT_REG * v_pIOPregs;
volatile S3C2440A_PWM_REG * v_pPWMregs;
volatile S3C2440A_INTR_REG * v_pINTRregs;
PRIVATE VOID
PBT_EnableInterrupt(VOID)
{
//Pwr button
v_pIOPregs->GPFCON &= ~(0x3 << 0); /* Set EINT0(GPF0) as EINT0 */
v_pIOPregs->GPFCON |= (0x2 << 0);
v_pIOPregs->EXTINT0 &= ~(0x7 << 0); /* Configure EINT0 as Falling Edge Mode */
v_pIOPregs->EXTINT0 |= (0x2 << 0);
//SW_RESET button
v_pIOPregs->GPFCON &= ~(0x3 << 4); /* Set EINT2(GPF2) as EINT2 */
v_pIOPregs->GPFCON |= (0x2 << 4);
v_pIOPregs->EXTINT0 &= ~(0x7 << 8); /* Configure EINT2 as Falling Edge Mode */
v_pIOPregs->EXTINT0 |= (0x2 << 8);
}
PRIVATE BOOL PBT_IsPushed(VOID) //判断案件是否按下
{
return (( v_pIOPregs->GPFDAT & (1 << 0))? FALSE : TRUE);
}
PRIVATE BOOL PBT_InitializeAddresses(VOID) //该函数是分配对应的虚拟的GPIO.
{
BOOL RetValue = TRUE;
RETAILMSG(1, (TEXT(">>> PBT_initalization address..set../r/n")));
/* IO Register Allocation */
v_pIOPregs = (volatile S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pIOPregs == NULL)
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!/r/n")));
RetValue = FALSE;
}
else
{
if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!/r/n")));
RetValue = FALSE;
}
}
if (!RetValue)
{
RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!/r/n") ));
if (v_pIOPregs)
{
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
}
v_pIOPregs = NULL;
}
/* INTR Register Allocation */
v_pINTRregs = (volatile S3C2440A_INTR_REG *)VirtualAlloc(0, sizeof(S3C2440A_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pINTRregs == NULL)
{
ERRORMSG(1,(TEXT("For INTRregs : VirtualAlloc failed!/r/n")));
RetValue = FALSE;
}
else
{
if (!VirtualCopy((PVOID)v_pINTRregs, (PVOID)(S3C2440A_BASE_REG_PA_INTR >> 8), sizeof(S3C2440A_INTR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For INTRregs: VirtualCopy failed!/r/n")));
RetValue = FALSE;
}
}
if (!RetValue)
{
RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!/r/n") ));
if (v_pINTRregs)
{
VirtualFree((PVOID) v_pINTRregs, 0, MEM_RELEASE);
}
v_pINTRregs = NULL;
}
/* PWM Register Allocation */
return(RetValue);
}
DWORD
PBT_IntrThread(PVOID pArg) //线程
{
PBT_InitializeAddresses(); //分得虚拟的IO
RETAILMSG(1, (TEXT("::: ~~~~~INto~~~PBT_IntrThread~~~~~/r/n")));
PBT_EnableInterrupt(); //设置中断方式
gPwrButtonIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //创建事件
// Request a SYSINTR value from the OAL.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: PwrButton: Failed to request sysintr value for sw_reset button interrupt./r/n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO: PwrButton: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_PwrButtonIrq, g_PwrButtonSysIntr));
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_RebootButtonIrq, sizeof(UINT32), &g_RebootButtonSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: RebootButton: Failed to request sysintr value for sw_reset button interrupt./r/n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO: RebootButton: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_RebootButtonIrq, g_RebootButtonSysIntr));
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_BattFLTIrq, sizeof(UINT32), &g_BattFLTSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: BattFLT: Failed to request sysintr value for BattFLT interrupt./r/n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO: BattFLT: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_BattFLTIrq, g_BattFLTSysIntr));
if (!(InterruptInitialize(g_PwrButtonSysIntr, gPwrButtonIntrEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: PwrButton: Interrupt initialize failed./r/n")));
}
if (!(InterruptInitialize(g_RebootButtonSysIntr, gPwrButtonIntrEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: RebootButton: Interrupt initialize failed./r/n")));
}
if (!(InterruptInitialize(g_BattFLTSysIntr, gPwrButtonIntrEvent, 0, 0)))
{
RETAILMSG(1, (TEXT("ERROR: g_BattFLTSysIntr: Interrupt initialize failed./r/n")));
}
while (1)
{
WaitForSingleObject(gPwrButtonIntrEvent, INFINITE);
//在CPU接收到中断后,对中断的处理是在 OEMInterruptHandler()中,该函数的首先屏蔽该中断
//最后得到实际中断IRQ所对应的sysintr的值”
if (v_pINTRregs->INTMSK & (1<<IRQ_EINT2))
{
if (!KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL)) //得到逻辑地址
RETAILMSG(1, (TEXT("::: reset error /r/n")));
InterruptDone(g_RebootButtonSysIntr); //通知内核中断处理完毕
}
else if (v_pINTRregs->INTMSK & (1<<IRQ_EINT0)) //中断屏蔽
{
if (PBT_IsPushed())
{
Sleep(500); /* To Filter Noise*/
RETAILMSG(1, (TEXT("has a keys in downout /r/n")));
if (PBT_IsPushed())
{
RETAILMSG(1, (TEXT("::: Back Light On/Off /r/n")));
}
else
{
RETAILMSG(1, (TEXT("::: power off /r/n")));
if(gpfnSetSystemPowerState != NULL)
{
gpfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
}
//GwesPowerOffSystem的使用很简单:简单调用,系统就会挂起。
else
{
GwesPowerOffSystem();
}
GwesPowerOffSystem();
Sleep(0);
}
}
InterruptDone(g_PwrButtonSysIntr);
}
if(v_pINTRregs->INTMSK & (1<<IRQ_BAT_FLT))
{
if(gpfnSetSystemPowerState != NULL)
{
gpfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
}
else
{
GwesPowerOffSystem();
}
GwesPowerOffSystem();
Sleep(0);
InterruptDone(g_BattFLTSysIntr);
}
else
{
//should not happen
}
}
}
PUBLIC DWORD
DSK_Init(DWORD dwContext)
{
DWORD IDThread;
RETAILMSG(1, (TEXT("~~~~~~~DSK_Init~~~`` /r/n")));
gPwrButtonIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) PBT_IntrThread, 0, 0, &IDThread);
RETAILMSG(1, (TEXT("::: PBT_IntrThread ID = %x/r/n"), IDThread));
if (gPwrButtonIntrThread == 0)
{
RETAILMSG(1, (TEXT("::: CreateThread() Fail/r/n")));
return 0;
}
RETAILMSG(1, (TEXT("::: PBT_Init Out/r/n")));
return TRUE;
}
PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved) //动态链接库,函数的入口地址
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("PwrButton : DllEntry_DLL_PROCESS_ATTACH/r/n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
}
return (TRUE);
}
BOOL DSK_Close(
DWORD Handle
)
{
return TRUE;
}
BOOL DSK_Deinit(
DWORD dwContext // future: pointer to the per disk structure
)
{
return TRUE;
}
DWORD DSK_Open(
DWORD dwData,
DWORD dwAccess,
DWORD dwShareMode
)
{
return 0;
}
BOOL DSK_IOControl(
DWORD Handle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
return FALSE;
} // DSK_IOControl
DWORD DSK_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
return 0;
}
DWORD DSK_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
return 0;
}
DWORD DSK_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
}
void DSK_PowerUp(void)
{
PBT_EnableInterrupt();
return;
}
void
DSK_PowerDown(void)
{
return;
}