Windows CE6.0中斷實驗過程
Windows CE6.0中斷實驗過程
----利用鍵盤控制LED的驅動程序
1.實驗目的:通過本次試驗學習Windows CE6.0的中斷處理的過程以及熟悉在驅動程序中運行中斷的編程。
2.我對Windows CE6.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(DWORD idInt, // SYSINTR中斷號
HANDLE hEvent , // 與該中斷相關聯的事件句柄
LPVOID pvData, // 傳給OEMInterruptEnable緩沖指針
DWORD cbData, // 緩沖區的大小
)
然后通過 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
typedef struct {
volatile S3C6410_GPIO_REG *pGPIOregs;
BOOL FlagExitThrd;
} 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"
#define Led1Mask 0x01
#define Led2Mask 0x02
#define Led3Mask 0x04
#define Led4Mask 0x08
#define LedAllMask 0x0F
#define Butt1Mask 0x01
#define Butt2Mask 0x02
#define Butt3Mask 0x04
#define Butt4Mask 0x08
#define Butt5Mask 0x10
#define Butt6Mask 0x20
static KEY_PUBLIC_CONTEXT *pPublicKey = NULL;
static volatile UINT32 dwLedFlag = 1;
UINT32 g_SysIntr1 = 0;
UINT32 g_SysIntr2 = 0;
HANDLE g_hEvent1 = NULL;
HANDLE g_hThread1 = NULL;
HANDLE g_hEvent2 = NULL;
HANDLE g_hThread2 = NULL;
/******************************************************************************
*
* MyKey button event thread
*
*******************************************************************************/
INT WINAPI Button1Thread(void)
{
RETAILMSG(1, (TEXT("Button1 Thread Entered ! /r/n")));
while(!pPublicKey->FlagExitThrd)
{
UINT16 ch;
RETAILMSG(1, (TEXT("Button1 KEY_Read: KEY Device Read Successfully./r/n")));
ch = (UINT16)pPublicKey->pGPIOregs->GPNDAT;
RETAILMSG(1,(TEXT("Button1 ReadValue: 0x%x /n"), ch));
RETAILMSG(1, (TEXT("Button1 Thread ! /r/n")));
WaitForSingleObject(g_hEvent1, INFINITE);
if(pPublicKey->FlagExitThrd)
break;
RETAILMSG(1, (TEXT("Button1 Thread Start Running ! /r/n")));
if( dwLedFlag == 1 )
{
dwLedFlag = 0;
pPublicKey->pGPIOregs->GPMDAT |= LedAllMask;
RETAILMSG(1, (TEXT("Button1 pressed---Led ALL On:/r/n")));
}
else
{
dwLedFlag = 1;
pPublicKey->pGPIOregs->GPMDAT &= ~LedAllMask;
RETAILMSG(1, (TEXT("Button1 pressed---Led ALL Off:/r/n")));
}
InterruptDone(g_SysIntr1);
}
RETAILMSG(1, (TEXT("KEY: KEY Button1Thread Exiting/r/n")));
return 0;
} // Key_Button1Thread()
INT WINAPI Button2Thread(void)
{
DWORD LedNum = 1;
RETAILMSG(1, (TEXT("Button2 Thread Entered ! /r/n")));
while(!pPublicKey->FlagExitThrd)
{
UINT16 ch;
RETAILMSG(1, (TEXT("Button2 KEY_Read: KEY Device Read Successfully./r/n")));
ch = (UINT16)pPublicKey->pGPIOregs->GPNDAT;
RETAILMSG(1,(TEXT("Button2 ReadValue: 0x%x /n"), ch));
RETAILMSG(1, (TEXT("Button2 Thread ! /r/n")));
WaitForSingleObject(g_hEvent2, INFINITE);
if(pPublicKey->FlagExitThrd)
break;
RETAILMSG(1, (TEXT("Button2 Thread Start Running ! /r/n")));
if( LedNum == 1 )
{
LedNum = 2;
pPublicKey->pGPIOregs->GPMDAT |= Led1Mask;
RETAILMSG(1, (TEXT("Button2 pressed---Led 1 on:/r/n")));
}
else if ( LedNum == 2 )
{
LedNum = 3;
pPublicKey->pGPIOregs->GPMDAT |= Led2Mask;;
RETAILMSG(1, (TEXT("Button2 pressed---Led 2 On:/r/n")));
}
else if ( LedNum == 3 )
{
LedNum = 4;
pPublicKey->pGPIOregs->GPMDAT |= Led3Mask;;
RETAILMSG(1, (TEXT("Button2 pressed---Led 3 On:/r/n")));
}
else if ( LedNum == 4 )
{
LedNum = 0;
pPublicKey->pGPIOregs->GPMDAT |= Led4Mask;;
RETAILMSG(1, (TEXT("Button2 pressed---Led 4 On:/r/n")));
}
else
{
LedNum = 1;
pPublicKey->pGPIOregs->GPMDAT &= ~LedAllMask;;
RETAILMSG(1, (TEXT("Button2 pressed---Led ALL off:/r/n")));
}
InterruptDone(g_SysIntr2);
}
RETAILMSG(1, (TEXT("KEY: KEY Button2Thread Exiting/r/n")));
return 0;
} // Key_Button2Thread()
BOOL KEY_Deinit(DWORD dwContext)
{
RETAILMSG(1, (TEXT("KEY_DeInit: dwContext = 0x%x/r/n/n"), dwContext));
// inform IST exit status
pPublicKey->FlagExitThrd = TRUE;
// free virtual memory
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);
}
// Wait for threads to finish
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_CONTEXT KEY_Init(DWORD dwContext)
{
LPTSTR ActivePath = (LPTSTR) dwContext; // HKLM/Drivers/Active/xx
BOOL bResult = TRUE;
DWORD dwHwIntr = 0;
RETAILMSG(1, (TEXT("KEY_Init:dwContext = 0x%x/r/n"), dwContext));
RETAILMSG(1,(TEXT("[KEY] Active Path : %s/n"), ActivePath));
if ( !(pPublicKey = (PKEY_PUBLIC_CONTEXT)LocalAlloc( LPTR, sizeof(KEY_PUBLIC_CONTEXT) )) )
{
RETAILMSG(1,(TEXT("[KEY] Can't not allocate for KEY Context/n")));
return NULL;
}
// GPIO Virtual alloc
pPublicKey->pGPIOregs = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
if (pPublicKey->pGPIOregs == NULL)
{
RETAILMSG(1,(TEXT("[KEY] For pGPIOregs: DrvLib_MapIoSpace failed!/r/n")));
bResult = FALSE;
goto CleanUp;
}
//禁止上下拉
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
{
//Button1 Thread
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] Failed to request the KEY sysintr./n")));
g_SysIntr1 = SYSINTR_UNDEFINED;
bResult = FALSE;
break;
}
if (!InterruptInitialize(g_SysIntr1, g_hEvent1, NULL, 0))
{
RETAILMSG(1,(TEXT("[KEY] KEY Interrupt Initialization failed!!!/n")));
bResult = FALSE;
break;
}
g_hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Button1Thread, NULL, 0, NULL);
if (g_hThread1 == NULL)
{
RETAILMSG(1,(TEXT("[KEY] Key Button Thread creation error!!!/n")));
bResult = FALSE;
break;
}
//Button2 Thread
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] Failed to request the KEY sysintr./n")));
g_SysIntr2 = SYSINTR_UNDEFINED;
bResult = FALSE;
break;
}
if (!InterruptInitialize(g_SysIntr2, g_hEvent2, NULL, 0))
{
RETAILMSG(1,(TEXT("[KEY] KEY Interrupt Initialization failed!!!/n")));
bResult = FALSE;
break;
}
g_hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Button2Thread, NULL, 0, NULL);
if (g_hThread2 == NULL)
{
RETAILMSG(1,(TEXT("[KEY] Key Button2 Thread creation error!!!/n")));
bResult = FALSE;
break;
}
} while (0);
RETAILMSG(1,(TEXT("--[KEY] KEY_Init Function/r/n")));
if(bResult)
{
return pPublicKey;
}
else
{
return NULL;
}
CleanUp:
if (!bResult)
{
if (pPublicKey->pGPIOregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicKey->pGPIOregs);
pPublicKey->pGPIOregs = NULL;
}
return NULL;
}
}
DWORD KEY_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
RETAILMSG(1, (TEXT("KEY_Open: KEY Device Open Successfully./r/n")));
return(dwData);
}
BOOL KEY_Close(DWORD Handle)
{
RETAILMSG(1, (TEXT("KEY_Close: KEY Device Close Successfully./r/n")));
return (TRUE);
}
DWORD KEY_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
UINT16 ch;
DWORD result;
RETAILMSG(1, (TEXT("KEY_Read: KEY Device Read Successfully./r/n")));
ch = (UINT16)pPublicKey->pGPIOregs->GPNDAT;
if( (ch & Butt1Mask) != 0)
{
result = 1;
RETAILMSG(1, (TEXT("Button 1 pressed:/r/n")));
}
else if( (ch & Butt2Mask) != 0)
{
result = 2;
RETAILMSG(1, (TEXT("Button 2 pressed:/r/n")));
}
else
{
result = -1;
RETAILMSG(1, (TEXT("No Button pressed:/r/n")));
}
dwNumBytes = result;
return (dwNumBytes);
}
DWORD KEY_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
RETAILMSG(1, (TEXT("BTN_Write:KEY Device Write Successfully./r/n")));
return(TRUE);
}
DWORD KEY_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return (DWORD)-1;
}
void KEY_PowerDown(void)
{
return;
}
void KEY_PowerUp(void)
{
return;
}
BOOL KEY_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
RETAILMSG(1, (TEXT("BTN_IOControl:/r/n")));
return(TRUE);
}
/*******************************************************************************
*DLL入口函數
*******************************************************************************/
BOOL
DllEntry(
HINSTANCE hinstDll,
DWORD dwReason,
LPVOID lpReserved
)
{
if ( dwReason == DLL_PROCESS_ATTACH )
{
DEBUGMSG (1, (TEXT("[MyKey] Process Attach/r/n")));
}
if ( dwReason == DLL_PROCESS_DETACH )
{
DEBUGMSG (1, (TEXT("[MyKey] Process Detach/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:
LIBRARY MyKey
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.dll NK SHK
(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.編譯建立此驅動。注意:這里只需要編譯驅動目錄就可以了,不需要重新編譯整個系統。
:
浙公網安備 33010602011771號