轉自 http://flyswordfly.blog.163.com/blog/static/1436663620082116329336/
/* 程序開(kāi)始定義包含的頭文件及定義需要的全局變量*/
#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];
/*定義了一個(gè)讀按鍵事件數組,當按下按鍵時(shí),中斷服務(wù)線(xiàn)程IST通過(guò)事件 gReadKeyEvent[0]通知本驅動(dòng)的讀函數KEY_Read():按鍵按下;當本驅動(dòng)退出或卸載時(shí),通過(guò)事件gReadKeyEvent[1] 通知讀函數KEY_Read():驅動(dòng)已經(jīng)關(guān)閉或卸載。*/
/* 按鍵按下中斷事件*/
PRIVATE HANDLE gWaitEvent;
/* 是否退出中斷服務(wù)線(xiàn)程*/
PRIVATE UINT32 g_bKillIST = FALSE;
/*此處定義了一個(gè)全局變量g_bKillIST,它用于當驅動(dòng)卸載時(shí)通知中斷服務(wù)線(xiàn)程退出,這樣才能完全卸載驅動(dòng)*/
/* 中斷處理線(xiàn)程*/
PRIVATE HANDLE gEINTIntrThread;
/* 驅動(dòng)打開(kāi)計數器*/
PRIVATE UINT32 gOpenCount = 0;
/* EINT的物理中斷號及邏輯中斷號*/
PRIVATE UINT32 g_EINTIrq = XLLP_INTC_GPIOXX_2;
PRIVATE UINT32 g_EINTSysIntr = SYSINTR_UNDEFINED;
/* GPIO寄存器對應的虛擬地址,定義了一個(gè)處理器GPIO相關(guān)寄存器的結構體變量,該結構體的定義在xllp_gpio.h頭文件中。其他全局變量在使用時(shí)說(shuō)明*/
PRIVATE volatile XLLP_GPIO_T * v_pGPIOReg;
/* 中斷寄存器對應的虛擬地址,定義了一個(gè)處理器的中斷寄存器的結構體變量,該結構體的定義在xllp_intc.h頭文件中。其他全局變量在使用時(shí)說(shuō)明*/
PRIVATE volatile XLLP_INTC_T * v_pICReg;
/* 驅動(dòng)動(dòng)態(tài)庫入口函數*/
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中,程序訪(fǎng)問(wèn)的地址都是虛地址,因此,要訪(fǎng)問(wèn)硬件物理地址,必須將物理地址空間映射到虛擬地址空間*/
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寄存器的物理地址,經(jīng)過(guò)映射后,通過(guò)全局變量指針v_pGPIOReg就可以訪(fǎng)問(wèn)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);
}
/* 編寫(xiě)配置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 );//開(kāi)屏蔽中斷位
v_pICReg->iclr &=~( 0x1<<10 );//中斷被傳遞到IRQ中斷輸入
v_pICReg->iccr |=0x01; //沒(méi)有被屏蔽的中斷才能將處理器從空閑狀態(tài)中喚醒
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;
/*創(chuàng )建外部中斷事件,用于ISR通知ISR外部中斷觸發(fā),然后調用內核函數InterruptInitialize()
將邏輯中斷號g_EINTSysIntr與事件gWaitEvent關(guān)聯(lián)起來(lái),并使能該中斷,當該中斷觸發(fā)時(shí),ISR就
觸發(fā)事件gWaitEvent生效,完成以上工作,該線(xiàn)程就進(jìn)行無(wú)限循環(huán),等待事件生效;*/
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); //延時(shí)20ms用于濾去噪聲
if (Key_IsPushed()) //外部中斷按鍵確實(shí)已經(jīng)按下
{
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;
}
/*流驅動(dòng)接口函數的初始化函數,該函數的主要工作是進(jìn)行外部中斷引腳的初始化,申請的邏輯中斷號并保存到全局變量*/
DWORD KEY_Init(DWORD dwContext)
{
DWORD IDThread;
//取得GPIO相關(guān)寄存器的虛擬地址空間
if ( EINT_InitializeAddresses() == FALSE )
return 0;
//使能EINT引腳為中斷引腳,并為上升沿觸發(fā)
EINT_ConfigInterruptPin();
//從OAL請求一個(gè)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));
//創(chuàng )建一個(gè)外部中斷處理線(xiàn)程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 )//本驅動(dòng)只允許單一訪(fǎng)問(wèn)
return 0;
gOpenCount++;
return gOpenCount; //返回一個(gè)不為零的數
}
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;
/*掛起當前線(xiàn)程,直到KEY1按鍵按下或驅動(dòng)關(guān)閉*/
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]);//通知讀函數線(xiàn)程驅動(dòng)已經(jīng)關(guān)閉
gOpenCount = 0;
return TRUE;
}//KEY_Close
BOOL KEY_Deinit(DWORD dwContext)
{
SetEvent(gWaitEvent);//通知中斷服務(wù)線(xiàn)程退出
g_bKillIST = TRUE;
Sleep(200); //等待中斷服務(wù)線(xiàn)程退出
SetEvent(gReadKeyEvent[1]);//通知讀函數線(xiàn)程驅動(dòng)已經(jīng)關(guān)閉
//釋放中斷資源
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)
{
;
}
聯(lián)系客服