2440 按键中断

很开心,按键中断终于基本搞定了,下面将自己的心得分享下:

 

中断驱动书写流程:
   1.编写本驱动库的入口函数。DllEntry()。
   2.设置物理地址到虚拟地址映射。原因wince启动后是对虚拟地址操作。EINT_InitializeAddresses。
   3.配置中断引脚EINT_ConfigInterruptPin()。
   4.创建一个线程,指定线程函数,并获得句柄。gEINTIntread=CreateThread().
   5.根据ISR获得一个SYSINTR(逻辑中断),所用函数为:KernelIoControl().WINCE提供IO请求命令
     IOCTL_HAL_REQUSST_SYSINTR,用于请求该中断的中断逻辑号。
   6.创建一个Event,并初始化为:自给动触发,未标识,并获得该句柄gReadKeyEvent[0]=CreateEvent(NULL,FALSE,FALSE,NULL).
   7.将SYSINTR与一个Event内核时间关联起来,当中断发生时,引发该事件。InterruptInitialize().
   8.等待时间的出发WaitForSingleObject().
   9.处理中断过程。
   10.通知内核中断处理完毕InterruptDone().
   11.释放中断资源。KernelIoControl().WINCE提供IO请求命令IOCTL_HAL_RELEASE_SYSINTR,用于请求该中断的中断逻辑号。
注意:凡是程序中开发者主动申请的内存,句柄,事件等一定要记得释放。


中断之间的关系在分析:
    外部设备通过CPU的中断引脚向CPU发送中断信号(IRQ),然后通过ISR映射,把IRQ转化成逻辑中断并返回给
内核,IST处理则负责中断的逻辑处理。
    IRQ(Interrupt ReQuest ):物理中断请求。检测是否有中断产生。当中断发生的时候,ISR就会触发事件生效。
    ISR(Interrupt Service Routine):中断服务例程,运行在内核中的一段代码,通常由OEM实现,ISR一般会给
返回一个SYSINTR(逻辑中断号)。也就是说,ISR必须把IRQ转换成逻辑中断号。
    IST(Interrupt Service Thread):中断服务线程。IST也就是一个普通的用户态线程,处理大部分中断操作,
一般空闲,只有操作系统通知IST有中断发生时,IST才操作。
    IST中常用的函数介绍:
InterruptInitialize()函数负责把某个逻辑中断号与一个Event内核对象关联起来。
WaitForSingleObject()阻塞当前线程,等待事件触发生效。
InterruptDone().告诉操作系统中断已经结束。
    IST第一件事情就是使用CreateEnent()函数创建一个Event内核对象,并且使用InterruptInitialize()函数
把这个Event与一个逻辑中断相关联,这样中断发生的时候,操作系统就可以引发这一事件。

 

   下面这个函数是我修改YC里面的,它里面的那个比较乱,很多函数没用,我也不知道上面意思,我把没用的删除掉了,测试后这个程序可以正常使用,我感觉YC里面的驱动很不负责,至少在初学者来说,写的很迷糊,理解起来有点困难,因此将精简的代码写出来,如果哪里错了,还忘各位给提醒下:

 

#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 "BSP.h"
#include "pwrbtn2440.h"

#define PRIVATE   static
#define PUBLIC

//以下为一个函数指针
typedef DWORD (*PFN_SetSystemPowerState)(LPCWSTR, DWORD, DWORD);
PFN_SetSystemPowerState   gpfnSetSystemPowerState;

PRIVATE HANDLE gPwrButtonIntrEvent;
PRIVATE HANDLE gPwrButtonIntrThread;


UINT32 g_PwrButtonIrq = IRQ_EINT0;
UINT32 g_PwrButtonSysIntr = SYSINTR_UNDEFINED;
UINT32 g_RebootButtonIrq = IRQ_EINT2;
UINT32 g_RebootButtonSysIntr = SYSINTR_UNDEFINED;
UINT32 g_BattFLTIrq = IRQ_BAT_FLT;
UINT32 g_BattFLTSysIntr = SYSINTR_UNDEFINED;


PRIVATE volatile   S3C2440A_IOPORT_REG   * v_pIOPregs;
volatile           S3C2440A_PWM_REG      * v_pPWMregs;
volatile           S3C2440A_INTR_REG     * v_pINTRregs;

PRIVATE VOID
PBT_EnableInterrupt(VOID)
{

 //Pwr button
 v_pIOPregs->GPFCON  &= ~(0x3 << 0);  /* Set EINT0(GPF0) as EINT0 */
 v_pIOPregs->GPFCON  |=  (0x2 << 0);

 v_pIOPregs->EXTINT0 &= ~(0x7 << 0);  /* Configure EINT0 as Falling Edge Mode */
 v_pIOPregs->EXTINT0 |=  (0x2 << 0);


 //SW_RESET button
 v_pIOPregs->GPFCON  &= ~(0x3 << 4);  /* Set EINT2(GPF2) as EINT2 */
 v_pIOPregs->GPFCON  |=  (0x2 << 4);

 v_pIOPregs->EXTINT0 &= ~(0x7 << 8);  /* Configure EINT2 as Falling Edge Mode */
 v_pIOPregs->EXTINT0 |=  (0x2 << 8);

}


PRIVATE BOOL PBT_IsPushed(VOID)   //判断案件是否按下
{
 
 return  (( v_pIOPregs->GPFDAT & (1 << 0))?  FALSE : TRUE);
}


PRIVATE BOOL PBT_InitializeAddresses(VOID)    //该函数是分配对应的虚拟的GPIO.
{
 BOOL RetValue = TRUE;
    RETAILMSG(1, (TEXT(">>> PBT_initalization address..set../r/n")));
    /* IO Register Allocation */
 v_pIOPregs = (volatile S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
 if (v_pIOPregs == NULL)
 {
  ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!/r/n")));
  RetValue = FALSE;
 }
 else
 {
  if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
  {
   ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!/r/n")));
   RetValue = FALSE;
  }
 }
 
 if (!RetValue)
 {
  RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!/r/n") ));

  if (v_pIOPregs)
  {
   VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
  }

  v_pIOPregs = NULL;
 }

 /* INTR Register Allocation */
 v_pINTRregs = (volatile S3C2440A_INTR_REG *)VirtualAlloc(0, sizeof(S3C2440A_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
 if (v_pINTRregs == NULL)
 {
  ERRORMSG(1,(TEXT("For INTRregs : VirtualAlloc failed!/r/n")));
  RetValue = FALSE;
 }
 else
 {
  if (!VirtualCopy((PVOID)v_pINTRregs, (PVOID)(S3C2440A_BASE_REG_PA_INTR >> 8), sizeof(S3C2440A_INTR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
  {
   ERRORMSG(1,(TEXT("For INTRregs: VirtualCopy failed!/r/n")));
   RetValue = FALSE;
  }
 }
 
 if (!RetValue)
 {
  RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!/r/n") ));

  if (v_pINTRregs)
  {
   VirtualFree((PVOID) v_pINTRregs, 0, MEM_RELEASE);
  }

  v_pINTRregs = NULL;
 }
 /* PWM Register Allocation */

 

 return(RetValue);
}
DWORD
PBT_IntrThread(PVOID pArg)    //线程
{
    PBT_InitializeAddresses();  //分得虚拟的IO
    RETAILMSG(1, (TEXT("::: ~~~~~INto~~~PBT_IntrThread~~~~~/r/n")));
    PBT_EnableInterrupt();    //设置中断方式
    gPwrButtonIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  //创建事件
     // Request a SYSINTR value from the OAL.
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
    {
        RETAILMSG(1, (TEXT("ERROR: PwrButton: Failed to request sysintr value for sw_reset button interrupt./r/n")));
        return(0);
    }
    RETAILMSG(1,(TEXT("INFO: PwrButton: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_PwrButtonIrq, g_PwrButtonSysIntr));
   if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_RebootButtonIrq, sizeof(UINT32), &g_RebootButtonSysIntr, sizeof(UINT32), NULL))
    {
        RETAILMSG(1, (TEXT("ERROR: RebootButton: Failed to request sysintr value for sw_reset button interrupt./r/n")));
        return(0);
    }
    RETAILMSG(1,(TEXT("INFO: RebootButton: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_RebootButtonIrq, g_RebootButtonSysIntr));

  if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_BattFLTIrq, sizeof(UINT32), &g_BattFLTSysIntr, sizeof(UINT32), NULL))
    {
        RETAILMSG(1, (TEXT("ERROR: BattFLT: Failed to request sysintr value for BattFLT interrupt./r/n")));
        return(0);
    }
    RETAILMSG(1,(TEXT("INFO: BattFLT: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_BattFLTIrq, g_BattFLTSysIntr));

  if (!(InterruptInitialize(g_PwrButtonSysIntr, gPwrButtonIntrEvent, 0, 0)))
  {
   RETAILMSG(1, (TEXT("ERROR: PwrButton: Interrupt initialize failed./r/n")));
  }
 if (!(InterruptInitialize(g_RebootButtonSysIntr, gPwrButtonIntrEvent, 0, 0)))
  {
   RETAILMSG(1, (TEXT("ERROR: RebootButton: Interrupt initialize failed./r/n")));
  }

 if (!(InterruptInitialize(g_BattFLTSysIntr, gPwrButtonIntrEvent, 0, 0)))
  {
   RETAILMSG(1, (TEXT("ERROR: g_BattFLTSysIntr: Interrupt initialize failed./r/n")));
  }
 while (1)
 {
  WaitForSingleObject(gPwrButtonIntrEvent, INFINITE);
  //在CPU接收到中断后,对中断的处理是在 OEMInterruptHandler()中,该函数的首先屏蔽该中断
  //最后得到实际中断IRQ所对应的sysintr的值”
  if (v_pINTRregs->INTMSK & (1<<IRQ_EINT2))
  {
   
   if (!KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL))  //得到逻辑地址
    RETAILMSG(1, (TEXT("::: reset error /r/n")));
                InterruptDone(g_RebootButtonSysIntr);   //通知内核中断处理完毕
  }
  else if (v_pINTRregs->INTMSK & (1<<IRQ_EINT0))   //中断屏蔽
  {
              if (PBT_IsPushed())  
    { 
      Sleep(500);            /* To Filter Noise*/
                     RETAILMSG(1, (TEXT("has a keys in  downout /r/n")));
     if (PBT_IsPushed())
     { 
      RETAILMSG(1, (TEXT("::: Back Light On/Off /r/n")));
      
     }
     else
     {
      RETAILMSG(1, (TEXT("::: power off /r/n")));
       if(gpfnSetSystemPowerState != NULL)
       {
        gpfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
       }
       //GwesPowerOffSystem的使用很简单:简单调用,系统就会挂起。
       else
       {
        GwesPowerOffSystem();
       }
                 GwesPowerOffSystem();
           Sleep(0);
     }
    }

    InterruptDone(g_PwrButtonSysIntr);
  }
   
      if(v_pINTRregs->INTMSK & (1<<IRQ_BAT_FLT))
  {
   if(gpfnSetSystemPowerState != NULL)
    {
     gpfnSetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);
    }
    else
    {
     GwesPowerOffSystem();
    }
        GwesPowerOffSystem();
     Sleep(0);
             InterruptDone(g_BattFLTSysIntr);
   }
     else
     {
      //should not happen 
     }
    }         
}


PUBLIC DWORD
DSK_Init(DWORD dwContext)
{
 DWORD      IDThread;
    RETAILMSG(1, (TEXT("~~~~~~~DSK_Init~~~`` /r/n")));
    gPwrButtonIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) PBT_IntrThread, 0, 0, &IDThread);
     RETAILMSG(1, (TEXT("::: PBT_IntrThread ID = %x/r/n"), IDThread));
       if (gPwrButtonIntrThread == 0)
  {
   RETAILMSG(1, (TEXT("::: CreateThread() Fail/r/n")));
      return 0;
  }
           RETAILMSG(1, (TEXT("::: PBT_Init Out/r/n")));
         return TRUE;
}


PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)     //动态链接库,函数的入口地址
{
    switch ( dwReason )
 {
    case DLL_PROCESS_ATTACH:
        RETAILMSG(1, (TEXT("PwrButton : DllEntry_DLL_PROCESS_ATTACH/r/n")));
  DisableThreadLibraryCalls((HMODULE) hInstDll);
        break;
 }
    return (TRUE);
}

BOOL DSK_Close(
    DWORD Handle
    )
{
    return TRUE;

BOOL DSK_Deinit(
    DWORD dwContext     // future: pointer to the per disk structure
    )
{
    return TRUE;
}  

DWORD DSK_Open(
    DWORD dwData,
    DWORD dwAccess,
    DWORD dwShareMode
    )
{
    return 0;


BOOL DSK_IOControl(
    DWORD Handle,
    DWORD dwIoControlCode,
    PBYTE pInBuf,
    DWORD nInBufSize,
    PBYTE pOutBuf,
    DWORD nOutBufSize,
    PDWORD pBytesReturned
    )
{
    return FALSE;
}   // DSK_IOControl


DWORD DSK_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
 return 0;
}
DWORD DSK_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
 return 0;
}
DWORD DSK_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
 return 0;
}

void DSK_PowerUp(void)
{
 PBT_EnableInterrupt();
 return;
}

void
DSK_PowerDown(void)
{
 return;
}

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值