主题 : 初学wince。2通过Kn控制LEDn(中断) 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 69726
精华: 0
发帖: 4
金钱: 20 两
威望: 4 点
贡献值: 0 点
综合积分: 8 分
注册时间: 2012-05-10
最后登录: 2012-05-26
楼主  发表于: 2012-05-24 16:21

 初学wince。2通过Kn控制LEDn(中断)

功能描述:按下Kn的时候LEDn亮(n=1..4)

一、    驱动程序(KeyLed.cpp)

#include <windows.h>
//#include <ceddk.h>
#include <nkintr.h>
//#include <oalintr.h>
#include <pm.h>
#include "pmplatform.h"
#include "Pkfuncs.h"
#include "s2440.h"

volatile IOPreg     *s2440IOP = (IOPreg *)IOP_BASE;
volatile INTreg        *s2440INT = (INTreg *)INT_BASE;

HANDLE KeyThread;
HANDLE KeyEvent;
UINT32 g_KeySysIntr[4];

void Virtual_Alloc();                        // Virtual allocation
DWORD UserKeyProcessThread(void);

const TCHAR szevtUserInput[] = L"FriendlyARM/ButtonEvent";

DWORD UserKeyProcessThread(void)
{
    DWORD IRQ;
    // 创建一个事件
    KeyEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
    if (!KeyEvent)
    {
        RETAILMSG(1,(TEXT("ERROR:KEL:Failed to create event.\r\n")));
        return FALSE;
    }

    // 将物理中断号转换为逻辑中断号
    // IRQ 物理中断号;g_KeySysIntr逻辑中断号
    IRQ = 36;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&IRQ,sizeof(UINT32),&g_KeySysIntr[0],sizeof(UINT32),NULL))
    {
        RETAILMSG(1,(TEXT("ERROR:KEL: Failed to request sysintr value.\r\n")));
        return FALSE;
    }

    IRQ = 39;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&IRQ,sizeof(UINT32),&g_KeySysIntr[1],sizeof(UINT32),NULL))
    {
        RETAILMSG(1,(TEXT("ERROR:KEL: Failed to request sysintr value.\r\n")));
        return FALSE;
    }

    IRQ = 41;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&IRQ,sizeof(UINT32),&g_KeySysIntr[2],sizeof(UINT32),NULL))
    {
        RETAILMSG(1,(TEXT("ERROR:KEL: Failed to request sysintr value.\r\n")));
        return FALSE;
    }

    IRQ = 42;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&IRQ,sizeof(UINT32),&g_KeySysIntr[3],sizeof(UINT32),NULL))
    {
        RETAILMSG(1,(TEXT("ERROR:KEL: Failed to request sysintr value.\r\n")));
        return FALSE;
    }

    // 通知系统使能这个中断(g_KeySysIntr),并且当这个中断产生时产生一个事件、
    if (!InterruptInitialize(g_KeySysIntr[0],KeyEvent,NULL,0))
    {
        RETAILMSG(1,(TEXT("Fail to initialize key interrupt event\r\n")));
        return FALSE;
    }

    if (!InterruptInitialize(g_KeySysIntr[1],KeyEvent,NULL,0))
    {
        RETAILMSG(1,(TEXT("Fail to initialize key interrupt event\r\n")));
        return FALSE;
    }

    if (!InterruptInitialize(g_KeySysIntr[2],KeyEvent,NULL,0))
    {
        RETAILMSG(1,(TEXT("Fail to initialize key interrupt event\r\n")));
        return FALSE;
    }

    if (!InterruptInitialize(g_KeySysIntr[3],KeyEvent,NULL,0))
    {
        RETAILMSG(1,(TEXT("Fail to initialize key interrupt event\r\n")));
        return FALSE;
    }


    while(1)
    {
        // 等待中断发生
        WaitForSingleObject(KeyEvent,INFINITE);

        const char nIndex[] = { 0, 3, 5, 6};
        const char nIndex2[]= { 5, 6, 7, 8};
        
        // 扫描Kn(1..4)的状态并赋给LEDn(1..4)
        for (int i=0;i<4;i++)
        {
            if (s2440IOP->rGPGDAT & (0x01 << nIndex))
            {
                s2440IOP->rGPBDAT = s2440IOP->rGPBDAT | (0x01 << nIndex2);
            }
            else
            {
                s2440IOP->rGPBDAT = s2440IOP->rGPBDAT &~ (0x01 << nIndex2);
            }
        }

        // 已经完成中断的处理,重新开启该中断
        // K1
        if(s2440IOP->rEINTMASK & (DWORD)(0x1<<8))
        {
            InterruptDone(g_KeySysIntr[0]);
        }

        //EINT11 - K2
        if(s2440IOP->rEINTMASK & (DWORD)(0x1<<11))
        {
            InterruptDone(g_KeySysIntr[1]);    
        }

        //EINT13 - K3
        if(s2440IOP->rEINTMASK & (DWORD)(0x1<<13))
        {
            InterruptDone(g_KeySysIntr[2]);    
        }
                
        //EINT14 - K4
        if(s2440IOP->rEINTMASK & (DWORD)(0x1<<14))
        {
            InterruptDone(g_KeySysIntr[3]);    
        }
    }
}

void Virtual_Alloc()
{
    s2440IOP = (volatile IOPreg *) VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE, PAGE_NOACCESS);
    // 申请虚拟内存空间
    if(s2440IOP == NULL)
    {
        RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc failed!\r\n")));
    }
    else
    {
        // 将虚拟内存空间映射到物理内存空间
        if(!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE | PAGE_NOCACHE ))
        {
            RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy failed!\r\n")));
        }
    }
    
    // 申请虚拟内存空间
    s2440INT = (volatile INTreg *) VirtualAlloc(0,sizeof(INTreg),MEM_RESERVE, PAGE_NOACCESS);
    if(s2440INT == NULL)
    {
        RETAILMSG(1,(TEXT("For s2440INT: VirtualAlloc failed!\r\n")));
    }
    else
    {
        // 将虚拟内存空间映射到物理内存空间
        if(!VirtualCopy((PVOID)s2440INT,(PVOID)(INT_BASE),sizeof(INTreg),PAGE_READWRITE | PAGE_NOCACHE )) {
            RETAILMSG(1,(TEXT("For s2440INT: VirtualCopy failed!\r\n")));
        }
    }
}


BOOL WINAPI  
DllEntry(HANDLE    hinstDLL,
            DWORD dwReason,
            LPVOID  Reserved/* lpvReserved */)
{
    switch(dwReason)
    {
    case DLL_PROCESS_ATTACH:
        DEBUGREGISTER((HINSTANCE)hinstDLL);
        return TRUE;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
#ifdef UNDER_CE
    case DLL_PROCESS_EXITING:
        break;
    case DLL_SYSTEM_STARTED:
        break;
#endif
    }

    return TRUE;
}


BOOL KEL_Deinit(DWORD hDeviceContext)
{
    BOOL bRet = TRUE;
    
    RETAILMSG(1,(TEXT("USERKEY: KEY_Deinit\r\n")));
    
    // 关闭线程
    CloseHandle(KeyThread);
    // 释放内存空间
    VirtualFree((void*)s2440IOP, sizeof(IOPreg), MEM_RELEASE);
    VirtualFree((void*)s2440INT, sizeof(INTreg), MEM_RELEASE);
    return TRUE;
}


BOOL KeyGpioInit()
{
    RETAILMSG(1,(TEXT("Key_Gpio_Setting----\r\n")));
    //s2440IOP->rGPGUP   = 0xffff;
    // K1设置为输入,上升沿或者下降沿都触发
    s2440IOP->rGPGCON  = (s2440IOP->rGPGCON  & ~(0x3 << 0x0)) | (0x2 << 0x0);    // GPG0 == EINT8        
    s2440IOP->rEXTINT1 = (s2440IOP->rEXTINT1 & ~(0x7<< 0)) | (0x6 << 0);
    // K2设置为输入,上升沿或者下降沿都触发
    s2440IOP->rGPGCON  = (s2440IOP->rGPGCON  & ~(0x3 << 6)) | (0x2 << 6);    // GPG3 == EINT11    
    s2440IOP->rEXTINT1 = (s2440IOP->rEXTINT1 & ~(0x7<< 12)) | (0x6 << 12);
    // K3设置为输入,上升沿或者下降沿都触发
    s2440IOP->rGPGCON  = (s2440IOP->rGPGCON  & ~(0x3 << 10)) | (0x2 << 10);    // GPG5 == EINT13        
    s2440IOP->rEXTINT1 = (s2440IOP->rEXTINT1 & ~(0x7<< 20)) | (0x2 << 20);        
    // K4设置为输入,上升沿或者下降沿都触发
    s2440IOP->rGPGCON  = (s2440IOP->rGPGCON  & ~(0x3 << 12)) | (0x2 << 12);    // GPG6 == EINT14        
    s2440IOP->rEXTINT1 = (s2440IOP->rEXTINT1 & ~(0x7<< 24)) | (0x4 << 24);        
    // LED1设置为输出
    s2440IOP->rGPBCON  = (s2440IOP->rGPBCON  &~(3 << 10)) | (1<< 10);    // GPB5 == OUTPUT.
    // LED2设置为输出
    s2440IOP->rGPBCON  = (s2440IOP->rGPBCON  &~(3 << 12)) | (1<< 12);    // GPB6 == OUTPUT.
    // LED3设置为输出
    s2440IOP->rGPBCON  = (s2440IOP->rGPBCON  &~(3 << 14)) | (1<< 14);    // GPB7 == OUTPUT.
    // LED4设置为输出
    s2440IOP->rGPBCON  = (s2440IOP->rGPBCON  &~(3 << 16)) | (1<< 16);    // GPB8 == OUTPUT.
    return TRUE;
}

DWORD KEL_Init(DWORD dwContext)
{
    DWORD       threadID;                         // thread ID
    RETAILMSG(1,(TEXT("KEY_Init----\r\n")));

    // 申请内存
    Virtual_Alloc();
    
    // 初始化寄存器
    KeyGpioInit();

    // 创建线程
    KeyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)UserKeyProcessThread,  0,  0, &threadID);
    
    if (NULL == KeyThread )
    {
        RETAILMSG(1,(TEXT("ERROR: failed to Create Key Thread!\r\n")));
        return FALSE;
    }
    
    return TRUE;
}

//-----------------------------------------------------------------------------
DWORD KEL_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
    RETAILMSG(1,(TEXT("KEYLED: KEL_Open ret is\r\n")));
    return TRUE;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL KEL_Close(DWORD hOpenContext)
{
    RETAILMSG(1,(TEXT("KEYLED: KEL_Close ret is\r\n")));
    return TRUE;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void KEL_PowerDown(DWORD hDeviceContext)
{
    
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void KEL_PowerUp(DWORD hDeviceContext)
{
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD KEL_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
    RETAILMSG(1,(TEXT("KEYLED: KEL_Read ret is\r\n")));
    return 1;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD KEL_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
    RETAILMSG(1,(TEXT("KEYLED: KEL_Seek ret is\r\n")));
    return 0;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD KEL_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
    RETAILMSG(1,(TEXT("KEYLED: KEL_Write ret is\r\n")));
    return 0;
}


二、    把驱动程序添加到BSP中编译
1)    在mini2440\Src\Drivers下建立KeyLed目录,并在dirs文件中加入此目录,使系统编译bsp的时候可以编译这个文件
2)    为驱动创建Makefile文件
#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the components of Peg
#
!INCLUDE $(_MAKEENVROOT)\makefile.def
3)    为驱动创建source文件
!if 0
    File:   sources

    Author: fire

    Copyright (c) 1995-2002 Microsoft Corporation.  All rights reserved.
!endif

RELEASETYPE=PLATFORM
TARGETNAME=KEYLED
TARGETTYPE=DYNLINK
DLLENTRY=DllEntry

TARGETLIBS= \
    $(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib \

MSC_WARNING_LEVEL = $(MSC_WARNING_LEVEL) /W3 /WX

INCLUDES= \
    $(_TARGETPLATROOT)\inc; \
    $(_COMMONOAKROOT)\inc; \
    $(_PUBLICROOT)\common\oak\inc;$(_PUBLICROOT)\common\sdk\inc;$(_PUBLICROOT)\common\ddk\inc;    \
    ..\..\inc
      
SOURCES= \
    KeyLed.cpp \
    
4)    编写Keyled.def导出dll符号
;
; Windows CE Key Driver. Written by flyingfingers

LIBRARY KeyLed
EXPORTS
    KEL_Close
    KEL_Deinit
    KEL_Init
;    KEL_IOControl
    KEL_Open
    KEL_PowerDown
    KEL_PowerUp
    KEL_Read
    KEL_Seek
KEL_Write
5)    把驱动加入内核
在配置文件platform.bib中加入以下内容:(不是很明白为什么要加入IF BSP_NOKEL)
IF BSP_NOKEL !
    keyled.dll                $(_FLATRELEASEDIR)\keyled.dll    NK    SH    
ENDIF BSP_NOKEL !
6)    把驱动加入注册表
在注册表文件platform.reg中加入以下内容:
IF BSP_NOKEL !
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\keyled]
   "Prefix"="KEL"
   "Dll"="keyled.dll"
   "Order"="200"
ENDIF BSP_NOKEL !
三、    上机结果
友善之臂的Micro2440+WINCE5.0
按下Kn,LEDn亮;松开Kn,LEDn灭(n=1..4)
中断处理。

四、    中断线程我现在采用的方法
线程函数
{
    创建一个事件。
    设置优先级
    将物理中断号转换为逻辑中断号
    通知系统使能这个中断,并且当这个中断产生时产生一个事件
    等待中断发生
    中断处理
    中断完成
}


初学WINCE。欢迎交流。


描述:源文件
附件: Keyled.zip (14 K) 下载次数:34