/* 程序开始定义包含的头文件及定义需要的全局变量*/
#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 "bulverde.h" //定义了PXA270的寄存器地址等
#define PRIVATE static
#define PUBLIC
/* 读按键事件*/
PRIVATE HANDLE gReadKeyEvent[2];
/*定义了一个读按键事件数组,当按下按键时,中断服务线程IST通过事件gReadKeyEvent[0]通知本驱动的读函数KEY_Read():按键按下;当本驱动退出或卸载时,通过事件gReadKeyEvent[1]通知读函数KEY_Read():驱动已经关闭或卸载。*/
/* 按键按下中断事件*/
PRIVATE HANDLE gWaitEvent;
/* 是否退出中断服务线程*/
PRIVATE UINT32 g_bKillIST = FALSE;
/*此处定义了一个全局变量g_bKillIST,它用于当驱动卸载时通知中断服务线程退出,这样才能完全卸载驱动*/
/* 中断处理线程*/
PRIVATE HANDLE gEINTIntrThread;
/* 驱动打开计数器*/
PRIVATE UINT32 gOpenCount = 0;
/* EINT的物理中断号及逻辑中断号*/
PRIVATE UINT32 g_EINTIrq = XLLP_INTC_GPIOXX_2;
PRIVATE UINT32 g_EINTSysIntr = SYSINTR_UNDEFINED;
/* GPIO寄存器对应的虚拟地址,定义了一个处理器GPIO相关寄存器的结构体变量,该结构体的定义在xllp_gpio.h头文件中。其他全局变量在使用时说明*/
PRIVATE volatile XLLP_GPIO_T * v_pGPIOReg;
/* 中断寄存器对应的虚拟地址,定义了一个处理器的中断寄存器的结构体变量,该结构体的定义在xllp_intc.h头文件中。其他全局变量在使用时说明*/
PRIVATE volatile XLLP_INTC_T * v_pICReg;
/* 驱动动态库入口函数*/
BOOL WINAPI DllEntry (HANDLE hInstDll,DWORD dwReason,LPVOID lpvReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1,(TEXT("Key:DLL_PROCESS_ATTACH./r/n")));
DisableThreadLibraryCalls((HMODULE)hInstDll);
break;//挂载成功
case DLL_PROCESS_DETACH:
RETAILMSG(1,(TEXT("Key:DLL_PROCESS_DETACH./r/n")));
break;//卸载成功
}
return (TRUE);
}
/* 申请GPIO寄存器地址对应的虚拟空间,在WinCE中,程序访问的地址都是虚地址,因此,要访问硬件物理地址,必须将物理地址空间映射到虚拟地址空间*/
PRIVATE BOOL EINT_InitializeAddresses(VOID)
{
BOOL RetValue = TRUE;
RETAILMSG(1,(TEXT(">>>EINT_initalization address..set../r/n")));
/* IO Register Allocation,VirtualAlloc()函数的功能是申请一块虚拟内存空间,该空间的大小为sizeof(PXA270寄存器结构体的大小),*/
v_pGPIOReg = (volatile XLLP_GPIO_T *)VirtualAlloc(0,sizeof(XLLP_GPIO_T),MEM_RESERVE,PAGE_NOACCESS);
if (v_pGPIOReg ==NULL)
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed! /r/n")));
RetValue = FALSE;
}
else
{
/*VirtualCopy()函数的功能是将VirtualAlloc()函数申请的虚拟空间(起始地址为v_pGPIOReg)映射到GPIO寄存器的物理地址,经过映射后,通过全局变量指针v_pGPIOReg就可以访问GPIO寄存器了*/
if(! VirtualCopy((PVOID)v_pGPIOReg,(PVOID)(0x40E00000>>8),
sizeof(XLLP_GPIO_T),PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualCopy failed! /r/n")));
RetValue = FALSE;
}
}
if(! RetValue)
{
RETAILMSG(1,(TEXT(":::EINT_InitializeAddresses - Fail!!/r/n")));
if (v_pGPIOReg)
{
VirtualFree((PVOID)v_pGPIOReg,0,MEM_RELEASE);
}
v_pGPIOReg = NULL;
}
else
RETAILMSG(1,(TEXT(":::EINT_InitializeAddresses - Success/r/n")));
return (RetValue);
}
/* 编写配置EINT(GPIO100)引脚为外部中断引脚,这里示例了如何操作硬件寄存器:*/
PRIVATE VOID EINT_ConfigInterruptPin(VOID)
{
v_pGPIOReg->GPDR2 &=~( 0x1<<30 );//XLLP_GPIO_BIT_KP_MKIN1,设置方向寄存器
v_pGPIOReg->GRER2 |=( 0x1<<30 );//使能上升沿中断
v_pGPIOReg->GFER2 &=~( 0x1<<30 );//禁止下降沿中断
v_pGPIOReg->GAFR2_U &=~( 0x3<<28);//设置为通用的IO口
v_pICReg->icmr |=( 0x1<<10 );//开屏蔽中断位
v_pICReg->iclr &=~( 0x1<<10 );//中断被传递到IRQ中断输入
v_pICReg->iccr |=0x01; //没有被屏蔽的中断才能将处理器从空闲状态中唤醒
v_pICReg->ipr[10] =0x8000000a;
;
}
PRIVATE BOOL Key_IsPushed(VOID)
{
return ((v_pGPIOReg->GEDR2&(1<<30)?TRUE:FALSE));//??????
}
PRIVATE VOID EINT_ConfigPinDefault(VOID)
{
v_pGPIOReg->GEDR2|=(1<<30);
}
DWORD EINTKey_IntrThread(PVOID pArg)
{
DWORD ret;
/*创建外部中断事件,用于ISR通知ISR外部中断触发,然后调用内核函数InterruptInitialize()
将逻辑中断号g_EINTSysIntr与事件gWaitEvent关联起来,并使能该中断,当该中断触发时,ISR就
触发事件gWaitEvent生效,完成以上工作,该线程就进行无限循环,等待事件生效;*/
gWaitEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
//初始化外部按键中断:注册外部中断事件,允许外部中断
if ( !( InterruptInitialize(g_EINTSysIntr,gWaitEvent,0,0)))
{
RETAILMSG(1,(TEXT("ERROR:EINTKey:InterruptInitialize failed./r/n")));
CloseHandle(gWaitEvent);
return 0;
}
while (1)
{
ret = WaitForSingleObject(gWaitEvent,INFINITE);
if ( (ret == WAIT_OBJECT_0)&&(g_bKillIST == FALSE))
{
if(Key_IsPushed())
{
Sleep(20); //延时20ms用于滤去噪声
if (Key_IsPushed()) //外部中断按键确实已经按下
{
SetEvent(gReadKeyEvent[0]); //通知读函数,外部中断按键按下
RETAILMSG(1,(TEXT(":::The Key1 Pushed./r/n")));
//EINT_ConfigPinDefault();
}
}
}
else
{
CloseHandle(gWaitEvent);
RETAILMSG(1,(TEXT(":::EINTKey_IntrThread Exit./r/n")));
return 0;
}//if (ret != WAIT_OBJECT_0) or Error occurs
InterruptDone(g_EINTSysIntr);//通知内核,中断处理结束
}
return 1;
}
/*流驱动接口函数的初始化函数,该函数的主要工作是进行外部中断引脚的初始化,申请的逻辑中断号并保存到全局变量*/
DWORD KEY_Init(DWORD dwContext)
{
DWORD IDThread;
//取得GPIO相关寄存器的虚拟地址空间
if ( EINT_InitializeAddresses() == FALSE )
return 0;
//使能EINT引脚为中断引脚,并为上升沿触发
EINT_ConfigInterruptPin();
//从OAL请求一个SYSINTR值
if( ! KernelIoControl( IOCTL_HAL_REQUEST_SYSINTR,&g_EINTIrq,sizeof(UINT32),
&g_EINTSysIntr,sizeof(UINT32),NULL))
{
RETAILMSG(1,(TEXT("ERROR:EINTKey:Failed to request sysintr value for EINT interrupt./r/n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO:EINTKey:Mapped Irq 0x%x to SysIntr 0x%x./r/n"),g_EINTIrq,g_EINTSysIntr));
//创建一个外部中断处理线程IST
gEINTIntrThread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)EINTKey_IntrThread,0,0,&IDThread);
if ( gEINTIntrThread == NULL )
{
RETAILMSG(1,(TEXT(":::KEY_Init:CreateThread()Fail./r/n")));
KernelIoControl( IOCTL_HAL_RELEASE_SYSINTR,&g_EINTIrq,sizeof(UINT32),
NULL,0,NULL);
return 0;
}
gReadKeyEvent[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
gReadKeyEvent[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
RETAILMSG(1,(TEXT(":::KEY_Init Sucessfully!/r/n")));
//返回不为0的数
return (DWORD)gEINTIntrThread;
}
DWORD KEY_Open(DWORD hDeviceContext,DWORD AccessCode,DWORD ShareMode)
{
if ( gOpenCount > 0 )//本驱动只允许单一访问
return 0;
gOpenCount++;
return gOpenCount; //返回一个不为零的数
}
DWORD KEY_Read(DWORD Handle,LPVOID pBuffer,DWORD dwNumBytes)
{
DWORD ret;
uchar * pReadBuffer;
if (( pBuffer == NULL ) || (dwNumBytes <= 0 ))
return 0;
pReadBuffer = MapPtrToProcess(pBuffer,GetCallerProcess());
* pReadBuffer = 0;
/*挂起当前线程,直到KEY1按键按下或驱动关闭*/
ret = WaitForMultipleObjects(2,gReadKeyEvent,FALSE,INFINITE);
if ( ret == WAIT_OBJECT_0)
{
ResetEvent(gReadKeyEvent[0]);
* pReadBuffer = 1;
return 1;
}
else if( ret == ( WAIT_OBJECT_0 + 1 ) )
{
ResetEvent(gReadKeyEvent[1]);
* pReadBuffer = 0;
return 1;
}
return 0;
}
BOOL KEY_Close(DWORD Handle)
{
if ( gOpenCount > 0 )
SetEvent(gReadKeyEvent[1]);//通知读函数线程驱动已经关闭
gOpenCount = 0;
return TRUE;
}//KEY_Close
BOOL KEY_Deinit(DWORD dwContext)
{
SetEvent(gWaitEvent);//通知中断服务线程退出
g_bKillIST = TRUE;
Sleep(200); //等待中断服务线程退出
SetEvent(gReadKeyEvent[1]);//通知读函数线程驱动已经关闭
//释放中断资源
InterruptDone(g_EINTSysIntr);
InterruptDisable(g_EINTSysIntr);
KernelIoControl( IOCTL_HAL_RELEASE_SYSINTR,&g_EINTSysIntr,sizeof(UINT32),
NULL,0,NULL);
//恢复外部中断引脚为输入GPIO
//EINT_ConfigPinDefault();
//释放申请的虚拟空间
if (v_pGPIOReg)
VirtualFree((PVOID)v_pGPIOReg,0,MEM_RELEASE);
gOpenCount = 0;
CloseHandle(gReadKeyEvent[0]);
CloseHandle(gReadKeyEvent[1]);
return TRUE;
}
DWORD KEY_Write(DWORD hOpenContext,LPCVOID pBuffer,DWORD Count)
{
return 0;
}
DWORD KEY_Seek(DWORD hOpenContext,long Amount ,DWORD Type)
{
return 0;
}
BOOL KEY_IOControl(DWORD hOpenContext,
DWORD dwCode ,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
return FALSE;
}
void KEY_PowerUp(void)
{
;
}
void KEY_PowerDown(void)
{
;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liqiong154/archive/2009/04/06/4051710.aspx