调试成功的按键中断流驱动(转)
调试成功的按键中断流驱动
自己修改的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