调试成功的按键中断流驱动

 

自己修改的EINT11按键驱动成功的运行了,上次出现的USB鼠标,SD卡不能运行的问题也不知道是什么原因,后来新建了工程后解决了这个问题,估计是再改底层时动了什么其他的东西,现将按键中断驱动流程分析一下:

 

修改的文件:

1.    WINCE420\PLATFORM\SMDK2440\INC\oalintr.h

增加:

//周义加上的

#define SYSINTR_SW9                 (SYSINTR_FIRMWARE+23)//按键SW9中断

修改:

_inline

DWORD

MapIrq2SysIntr(DWORD _Irq)

{

    //if( _Irq<=22 )

    if( _Irq<=23 )//因为 SYSINTR_EINT1而改为23  周义改

        return ( SYSINTR_FIRMWARE + _Irq );

    else

        return (0xffffffff);

}

 

2.   WINCE420\PLATFORM\SMDK2440\KERNEL\HAL\ARM\armint.c

               if ( dwSubMask & (1 << 19))        // 0x200 EINT19 : SW9按键 周义加08-7-11

                   {

                            s2440IOP->rEINTMASK |=(1 << 19); 

                            s2440IOP->rEINTPEND = (1 << 19);

 

                            s2440INT->rSRCPND = BIT_EINT8_23;       

                            if (s2440INT->rINTPND & BIT_EINT8_23) s2440INT->rINTPND = BIT_EINT8_23;

 

                             RETAILMSG(1, (TEXT("INT:SYSINTR_ETHER INT s2440IOP->rEINTMASK = 0x%8x, s2440IOP->rEINTMASK\r\n")));

                             RETAILMSG(1, (TEXT("SW9 OEMInterruptHandler!by ZHOUYI")));

                            // RETAILMSG(1, (TEXT("INT:SYSINTR_ETHER INT s2440IOP->rEINTPEND = 0x%8x, s2440IOP->rEINTPEND\r\n")));

                            return SYSINTR_SW9;

                   }                                  //08-7-11改动结束

 

3.       WINCE420\PLATFORM\SMDK2440\KERNEL\HAL\ cfw.c

OEMInterruptEnable()中

增加:

    case SYSINTR_SW9:                       // SW9按键 on EINT19.08-07-11周义加

                   s2440IOP->rEINTPEND   = (1<<19);

                   s2440IOP->rEINTMASK  &= ~(1<<19);

                   //s2440INT->rSRCPND     = BIT_EINT8_23;     // by shim

                   // S3C2440X Developer Notice (page 4) warns against writing a 1 to a 0 bit in the INTPND register.

                   if (s2440INT->rINTPND & BIT_EINT8_23) s2440INT->rINTPND = BIT_EINT8_23;

                   s2440INT->rINTMSK    &= ~BIT_EINT8_23;

                   //RETAILMSG(1,(TEXT("::: SYSINTR_ETHER    OEMInterruptEnable\r\n")));

        break;                 // SW9按键 on EINT19.08-07-11周义加 结束

OEMInterruptDisable()中增加

    case SYSINTR_SW9:                    // SW9按键 on EINT19.08-07-11周义加

             s2440INT->rINTMSK   |= BIT_EINT8_23;

             s2440IOP->rEINTMASK |= (1 << 19);

             //RETAILMSG(1,(TEXT("::: SYSINTR_ETHER    OEMInterruptDisable\r\n")));

        break;                           // SW9按键 on EINT19.08-07-11周义加 结束!

OEMInterruptDone()中增加

   case SYSINTR_SW9: // SW9按键 on EINT19.08-07-11周义加

             s2440INT->rINTMSK   &= ~BIT_EINT8_23;

             s2440IOP->rEINTMASK &= ~(1 << 19);

             //RETAILMSG(1, (TEXT("::: SYSINTR_USBD      OEMInterruptDone\r\n")));

             break;        // SW9按键 on EINT19.08-07-11周义加 结束!


驱动的代码如下:

/****************************************Copyright (c)**************************************************

**--------------File Info-------------------------------------------------------------------------------

** File Name:     EINTKey.c

** Last modified Date:   2008-07-14

** Last Version:   V1.0 

** Description:    This driver uses EINT11 button(KEY1) On YC2440

** 修改说明:        1.将CPU寄存器定义换成S2440.H,修改了相关的寄存器

**                          2.将中断11作为按键中断

**                          3.将逻辑中断由KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_EINTIrq, sizeof(UINT32)

**                            函数动态申请改为OAL层静态定义,定义文件在oalintr.h

**                          4.改动WINCE OAL层三个有关中断的文件armint.c, cfw.c ,oalintr.h             

**------------------------------------------------------------------------------------------------------

**------------------------------------------------------------------------------------------------------

** Created By:     ZhouYi 周义

** Created date:    2008-07-14

** Version:     V1.0

** Descriptions:   The original version

**

**------------------------------------------------------------------------------------------------------

********************************************************************************************************/

#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 <Pkfuncs.h>

#include <oalintr.h>

#include <s2440.h>

#include "EINTKey.h"

#define PRIVATE   static

#define PUBLIC

/* 读按键事件*/

PRIVATE HANDLE gReadKeyEvent[2];      

/* 按键按下中断事件 */

PRIVATE HANDLE gWaitEvent;

/* 是否退出中断服务线程 */

PRIVATE UINT32 g_bKillIST = FALSE;

/* 中断处理线程 */

PRIVATE HANDLE gEINTIntrThread;

/* 驱动打开计数器 */

PRIVATE UINT32 gOpenCount = 0;

/* EINT11 的物理中断号及逻辑中断号 */

PRIVATE UINT32 g_EINTIrq = INTSRC_EINT8_23;

PRIVATE UINT32 g_EINTSysIntr = SYSINTR_SW9;

/* GPIO 寄存器对应的虚拟地址 */

PRIVATE volatile IOPreg * v_pIOPregs;

/*******************************************************************************************

函数名称: EINT_ConfigInterruptPin

描    述: 配置外部中断引脚并使能为 下降 沿触发

输入参数: 无

输出参数: 无

返    回: 无

********************************************************************************************/

PRIVATE VOID EINT_ConfigInterruptPin(VOID)

{

 //v_pIOPregs->GPFCON  &= ~(0x3 << 8);   /* Set EINT4(GPF4) as EINT4 */

 //v_pIOPregs->GPFCON  |=  (0x2 << 8);

 //v_pIOPregs->rGPFCON  &= ~(0x3 << 2);   /* Set EINT1(GPF1) as EINT1 */

 //v_pIOPregs->rGPFCON  |=  (0x2 << 2);

    v_pIOPregs->rGPGCON  &= ~(0x3 << 22);   /* Set EINT19(GPF11) as EINT19 */

 v_pIOPregs->rGPGCON  |=  (0x2 << 22);

    //v_pIOPregs->EXTINT0 &= ~(0x7 << 16);  /* Configure EINT4 as falling edge tiggered Mode */

    //v_pIOPregs->EXTINT0 |=  (0x2 << 16);

    //v_pIOPregs->rEXTINT0 &= ~(0x7 << 4);  /* Configure EINT1 as falling edge tiggered Mode */

    //v_pIOPregs->rEXTINT0 |=  (0x2 << 4);

    v_pIOPregs->rEXTINT2 &= ~(0x7 << 12);  /* Configure EINT19 as falling edge tiggered Mode */

    v_pIOPregs->rEXTINT2 |=  (0x2 << 12);

}

/*******************************************************************************************

函数名称: EINT_ConfigPinDefault

描    述: 配置外部中断引脚恢复为输入引脚

输入参数: 无

输出参数: 无

返    回: 无

********************************************************************************************/

PRIVATE VOID EINT_ConfigPinDefault(VOID)

{

 //v_pIOPregs->GPFCON  &= ~(0x3 << 8);   /* Set EINT4(GPF4) as GPIO(IN)  */

 //v_pIOPregs->rGPFCON  &= ~(0x3 << 2);   /* Set EINT1(GPF1) as GPIO(IN)  */

 v_pIOPregs->rGPGCON  &= ~(0x3 << 22);   /* Set EINT19(GPF11) as GPIO(IN)  */

}

/*******************************************************************************************

函数名称: Key_IsPushed

描    述: 查询按键是否已按下

输入参数: 无

输出参数: 无

返    回: FALSE: 按键未按下    TRUE: 按键已按下

*******************************************************************************************/

PRIVATE BOOL Key_IsPushed(VOID)

{

 //return ((v_pIOPregs->GPFDAT & (1 << 4)) ? FALSE : TRUE);

 //return ((v_pIOPregs->rGPFDAT & (1 << 1)) ? FALSE : TRUE);

 return ((v_pIOPregs->rGPGDAT & (1 << 11)) ? FALSE : TRUE);

}

/*******************************************************************************************

函数名称: EINT_InitializeAddresses

描    述: 取得相关寄存器的虚拟地址

输入参数: 无

输出参数: 无

返    回: > 0 分配得到的虚拟地址;  FALSE: 分配失败 

*******************************************************************************************/

PRIVATE BOOL EINT_InitializeAddresses(VOID)

{

 BOOL RetValue = TRUE;

 RETAILMSG(1, (TEXT(">>> EINT_initalization address..set..\r\n")));

 

 /* IO Register Allocation */

 v_pIOPregs = (volatile IOPreg *)VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);

 if (v_pIOPregs == NULL)

 {

  ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!\r\n")));

  RetValue = FALSE;

 }

 else

 {

  /*为了匹配S2440,H的寄存器,将S3C2410X_BASE_REG_PA_IOPORT改为IOP_BASE*/

  if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(IOP_BASE >> 8), sizeof(IOPreg), 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_pIOPregs)

  {

   VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);

  }

  v_pIOPregs = NULL;

 }

 else

  RETAILMSG (1, (TEXT("::: EINT_InitializeAddresses - Success\r\n") ));

 return(RetValue);

}

/*******************************************************************************************

函数名称: EINTKey_IntrThread

描    述: 外部中断按键服务线程

输入参数: PVOID pArg:   线程输入参数

输出参数: 无

返    回: 1 或 0

*******************************************************************************************/

DWORD EINTKey_IntrThread(PVOID pArg)

{

 DWORD ret;

 // 创建外部中断中断事件

 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")));

    }

   }

  }

  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;

}

/*******************************************************************************************

函数名称: KEY_Init

描    述: 驱动程序初始化函数

输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置 

输出参数: 无

返    回: 驱动程序句柄

*******************************************************************************************/

PUBLIC DWORD KEY_Init(DWORD dwContext)

{

 DWORD IDThread;

 // 取得 GPIO 相关寄存器的虚拟地址空间

 if (EINT_InitializeAddresses() == FALSE)

    return 0;  

 // 使能 EINT4 引脚为中断引脚, 并为下降沿触发

 EINT_ConfigInterruptPin();

    // 从 OAL 请求一个 SYSINTR 值

    //if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_EINTIrq, sizeof(UINT32), &g_EINTSysIntr, sizeof(UINT32), NULL))

    /*if (!KernelIoControl(IOCTL_HAL_TRANSLATE_IRQ, &g_EINTIrq, sizeof(UINT32), &g_EINTSysIntr, sizeof(UINT32), NULL))

    //周义IOCTL_HAL_REQUEST_SYSINTR在PUBLIC\COMMON\OAK\INC\nkintr.h中控制字不支持,所以将其改为IOCTL_HAL_TRANSLATE_IRQ

    {

        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_EINTSysIntr, 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;

}

/*******************************************************************************************

函数名称: DllEntry

描    述: 驱动程序动态库入口

输入参数: 

输出参数:

返    回:

*******************************************************************************************/

PUBLIC 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);

}

/*******************************************************************************************

函数名称: KEY_Close

描    述: 驱动程序关闭函数

输入参数: DWORD Handle:驱动程序句柄

输出参数: 无

返    回: FALSE: 失败    TRUE: 成功

*******************************************************************************************/

BOOL KEY_Close(DWORD Handle)

{

 if (gOpenCount > 0)

  SetEvent(gReadKeyEvent[1]);      /* 通知调用读函数的线程, 驱动已经关闭 */

 gOpenCount = 0;

 return TRUE;

}   // KEY_Close


/*******************************************************************************************

函数名称: KEY_Deinit

描    述: 驱动程序卸载函数

输入参数: DWORD dwContext: 驱动程序句柄

输出参数: 无

返    回: FALSE: 失败    TRUE: 成功

*******************************************************************************************/

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_pIOPregs)

  VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);  

    gOpenCount = 0;

   CloseHandle(gReadKeyEvent[0]);      /* 关闭相关事件 */

 CloseHandle(gReadKeyEvent[1]);

 return TRUE;

}   // KEY_Deinit

/*******************************************************************************************

函数名称: KEY_Open

描    述: 打开驱动程序

输入参数: DWORD dwData     : 驱动程序引用事例句柄

          DWORD dwAccess   : 访问请求代码,是读和写的组合

          DWORD dwShareMode: 共享模式 

输出参数:

返    回: 驱动程序引用事例句柄

*******************************************************************************************/

DWORD KEY_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)

{

    if (gOpenCount > 0)

        return 0;                // 本驱动只允许单一访问

    gOpenCount = 1; 

    return gOpenCount;

}   // KEY_Open

/*******************************************************************************************

函数名称: KEY_IOControl

描    述: 驱动程序 I/O 请求

输入参数:

输出参数:

返    回: 本驱动不支持该请求,返回 FALSE

*******************************************************************************************/

BOOL

KEY_IOControl(

    DWORD Handle,

    DWORD dwIoControlCode,

    PBYTE pInBuf,

    DWORD nInBufSize,

    PBYTE pOutBuf,

    DWORD nOutBufSize,

    PDWORD pBytesReturned

    )

{

    return FALSE;

}   // KEY_IOControl


/*******************************************************************************************

函数名称: KEY_Read

描    述: 读取按键状态

输入参数: DWORD Handle    : 驱动程序引用事例句柄

          LPVOID pBuffer  : 接收缓冲区

          DWORD dwNumBytes: 要读的字节数

输出参数: 无

返    回: 实际读到字节数

*******************************************************************************************/

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;

}   // KEY_Read

/*******************************************************************************************

函数名称: KEY_Write

描    述: 写函数,本驱动不支持

输入参数:

输出参数:

返    回:

*******************************************************************************************/

DWORD KEY_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)

{

 return 0;

}   // KEY_Write

/*******************************************************************************************

函数名称: KEY_Seek

描    述: 对设备的数据指针进行操作,本驱动不支持该函数

输入参数:

输出参数:

返    回:

*******************************************************************************************/

DWORD KEY_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)

{

 return 0;

}  // KEY_Seek

/*******************************************************************************************

函数名称: KEY_PowerUp

描    述: 电源上电驱动处理函数

输入参数:

输出参数:

返    回: 无

*******************************************************************************************/

void KEY_PowerUp(void)

{

 return;

}  // KEY_PowerUp

/*******************************************************************************************

函数名称: KEY_PowerDown

描    述: 电源下电驱动处理函数

输入参数:

输出参数:

返    回: 无

*******************************************************************************************/

void

KEY_PowerDown(void)

{

 return;

}  // KEY_PowerDown


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dengxin123/archive/2008/12/08/3477181.aspx

posted on 2010-08-16 15:19  jiege  阅读(599)  评论(0编辑  收藏  举报