Windows CE6.0中断实验过程

Windows CE6.0中断实验过程

                        ----利用键盘控制LED的驱动程序

1.实验目的:通过本次试验学习Windows CE6.0的中断处理的过程以及熟悉在驱动程序中运行中断的编程。

2.我对Windows CE6.0中断的理解:

Windows® CE将中断处理分成两个步骤:中断服务程序ISR和中断服务线程IST。如果中断被使能,则当中断产生时,内核将调用该中断注册的ISRISR执行完后将返回系统中断号,内核检查系统中断号并且设置相关的事件,内核设置相关事件后,相应的IST将开始执行。

3.Windows® CE的处理流程:

(1)如果一个驱动程序要处理一个中断,那么驱动程序首先要建立一个事件(CreateEvent),然后调用InterruptInitialize将该事件与中断号绑定,这一步会使能该中断,OAL中的OEMInerrupteEnable会被调用,如果该函数不返回true的话,InterruptInitialize就会失败。然后驱动程序中的IST就可以使用WaitForSingleObject函数来等待中断的发生。

(2)当一个硬件中断发生之后,操作系统陷入异常,中断向量指示进入CE的异常处理程序,该异常处理程序然后调用OALOEMInterruptHandler函数,该函数检测硬件之后,将硬件中断转换为软件的中断号,返回给系统。该中断号就是上面提到的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.cMyKey.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中断

//禁止GPN0GPN1上下拉

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.编写配置文件,包括如下文件sourcesMyKey.defmakefile如下:

技巧:可以到其他驱动程序目录下拷贝在加以修改

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.编译建立此驱动。注意:这里只需要编译驱动目录就可以了,不需要重新编译整个系统。

 

posted @ 2010-02-05 17:58  蔷薇理想人生  阅读(598)  评论(0编辑  收藏  举报