转自 http://flyswordfly.blog.163.com/blog/static/1436663620082116329336/ /* 程序开始定义包含的头文件及定义需要的全局变量*/ #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) { ; } |
|