2416 睡眠唤醒的代码

本文详细解析了PowerButton.c文件中与电源按键交互的代码实现,包括寄存器配置、中断事件的动态分配与管理,以及与系统电源状态的交互逻辑。文章深入探讨了如何通过中断事件来实现电源管理功能,包括唤醒、休眠和恢复等功能的实现细节。

PowerButton.c

 

 

//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//

#include <windows.h>
#include <nkintr.h>
#include <windev.h>
#include <winbase.h>
#include "pwr.h"
#include <bsp.h>

#define SIZEOFARRAY(a)  (sizeof(a) / sizeof(a[0]))
#define ENABLE  TRUE
#define DISABLE FALSE

#define TICKTEST      0
#define SWRST_BTN  0
#define ww 1

// Make sure the driver builds OK in tinykern configuration
HMODULE g_hMod = NULL;
typedef void (*PFN_GwesPowerOffSystem)(void);
PFN_GwesPowerOffSystem g_pfnGwesPowerOffSystem = NULL;

//寄存器定义
volatile S3C2450_IOPORT_REG *v_pIOPregs;
volatile S3C2450_RTC_REG *v_pRTCregs;
volatile S3C2450_INTR_REG *v_pIntrRegs;
//睡眠和唤醒中断
UINT32 g_PwrButtonIrq = IRQ_EINT14; // #PWR_KEY
UINT32 g_PwrButtonSysIntr = SYSINTR_UNDEFINED;
//复位中断,这里没有用到
UINT32 g_ResetButtonIrq = IRQ_EINT15; //POWER_ON/OFF_RST
UINT32 g_ResetButtonSysIntr = SYSINTR_UNDEFINED;
HANDLE g_ResetThread;
HANDLE g_ResetEvent;
//中断线程
static DWORD PWR_IST(LPVOID Context);


/**********************************************************************************************
相关寄存器配置   
***********************************************************************************************/
DWORD
HW_InitRegisters(  PPWR_CONTEXT pPWR )
{
 DWORD retry = 0;

 RETAILMSG(ww, (TEXT("HW_InitRegisters start!!!1 /r/n")));

 //虚拟地址分配
 v_pIOPregs = (volatile S3C2450_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2450_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
 VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2450_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2450_IOPORT_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE ); 
 v_pIntrRegs = (volatile S3C2450_INTR_REG *)VirtualAlloc(0, sizeof(S3C2450_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
 VirtualCopy((PVOID)v_pIntrRegs, (PVOID)(S3C2450_BASE_REG_PA_INTR >> 8), sizeof(S3C2450_INTR_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE ); 

 //GPG bit6  #PWR_KEY
 v_pIOPregs->GPGDAT  &= ~(0x1 << 6);
 v_pIOPregs->GPGCON  &= ~(0x3 <<12);
 v_pIOPregs->GPGCON  |=  (0x2 << 12);
 // EINT14 下降沿触发
 v_pIOPregs->EXTINT1 = ((v_pIOPregs->EXTINT1) & ~(0xf<<24)) | (0x1 << 27)|(0x2 << 24);

 RETAILMSG(ww, (TEXT("HW_InitRegisters over!!!! /r/n")));
 
 return 0;
}

/*******************************************************************************************
// #PWR_KEY动态分配逻辑中断号,并进行与中断事件的关联
// 初始化的最后,创建PWR_IST 中断线程。
********************************************************************************************/
DWORD
HW_Init( PPWR_CONTEXT pPWR )
{
 DWORD dwErr = ERROR_SUCCESS;

 RETAILMSG(ww, (TEXT("HW_Init:  start  !!!! /r/n")));

 if ( !pPWR )
  return ERROR_INVALID_PARAMETER;
 pPWR->State = INITIALIZE;

 dwErr = HW_InitRegisters(pPWR);
 if ( dwErr ) {
  RETAILMSG(ww, (TEXT("HW_Init : HW_InitRegisters  Error (0x%x) /r/n"), dwErr));
  goto _error_exit;
 }

 RETAILMSG(ww, (TEXT("HW_Init : CreateEvent /r/n")));
 pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

 // #PWR_KEY ---申请逻辑中断号 -- 自动分配--中断关联
 RETAILMSG(ww, (TEXT("HW_Init : IOCTL_HAL_REQUEST_SYSINTR /r/n")));
 if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
 {
  RETAILMSG(ww, (TEXT("ERROR: PwrButton: Failed to request sysintr value for power button interrupt./r/n")));
  return(0);
 }
 RETAILMSG(ww,(TEXT("INFO: PwrButton: Mapped Irq 0x%x to SysIntr 0x%x./r/n"), g_PwrButtonIrq, g_PwrButtonSysIntr));
 if (!(InterruptInitialize(g_PwrButtonSysIntr, pPWR->ISTEvent, 0, 0)))
 {RETAILMSG(ww, (TEXT("ERROR: PwrButton: InterruptInitialize failed./r/n"))); }
 //启动线程
 RETAILMSG(ww, (TEXT("HW_Init : CreateThread /r/n"), dwErr));
 if ( (pPWR->IST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PWR_IST, pPWR, 0, NULL)) == NULL) {
  dwErr = GetLastError( );
  RETAILMSG(ww,(TEXT("PCF50606 ERROR: Unable to create IST: %u/r/n"), dwErr));
  goto _error_exit;
 }
 //设置线程优先级
 //RETAILMSG(ww, (TEXT("HW_Init : CeSetThreadPriority /r/n"), dwErr));
 // TODO: registry override
 if ( !CeSetThreadPriority(pPWR->IST, 250)) {
  dwErr = GetLastError( );
  RETAILMSG(ww, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d /r/n"), dwErr));
  goto _error_exit;
 }

 pPWR->State = RUN;
 RETAILMSG(ww, (TEXT("HW_Init : over !!!! /r/n"), dwErr));   

_error_exit:
 return dwErr;
}

/*******************************************************************************************
 释放资源
********************************************************************************************/
DWORD
HW_Deinit( PPWR_CONTEXT pPWR )
{
 RETAILMSG(ww,(TEXT("+PWR_Deinit /r/n")));

 if ( !pPWR )
 return ERROR_INVALID_PARAMETER;

 pPWR->State = UNINITIALIZED;
 if (pPWR->hADC && CloseHandle(pPWR->hADC))
  pPWR->hADC = NULL;
 if (pPWR->hTSCPRES && CloseHandle(pPWR->hTSCPRES))
  pPWR->hTSCPRES = NULL;
 if (pPWR->hI2C && pPWR->hI2C != INVALID_HANDLE_VALUE && CloseHandle(pPWR->hI2C))
  pPWR->hI2C = INVALID_HANDLE_VALUE;
 InterruptDisable(g_PwrButtonSysIntr);

 if (pPWR->ISTEvent && CloseHandle(pPWR->ISTEvent))
  pPWR->ISTEvent = NULL;
 if (pPWR->IST && CloseHandle(pPWR->IST))
  pPWR->IST = NULL; 

 //  Free the coredll instance if we have allocated one
 if(g_hMod) {
  FreeLibrary(g_hMod);
  g_hMod = NULL;
 }

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

 RETAILMSG(ww,(TEXT("-PWR_Deinit /r/n")));

 return ERROR_SUCCESS;
}

/*******************************************************************************************
其他函数
********************************************************************************************/
DWORD
HW_Open( PPWR_CONTEXT pPWR )
{
 RETAILMSG(ww, (TEXT("PCF: HW_Open /r/n")));
 return ERROR_SUCCESS;
}

DWORD
HW_Close( PPWR_CONTEXT pPWR )
{
 RETAILMSG(ww, (TEXT("PCF: HW_Close /r/n")));
 return ERROR_SUCCESS;
}

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

********************************************************************************************/
BOOL
HW_PowerUp( PPWR_CONTEXT pPWR )
{
 RETAILMSG(ww, (TEXT("PCF: HW_PowerUp /r/n")));
 pPWR->State = RESUME;
 // pPWR->State = RUN;
 // SetInterruptEvent(g_PwrButtonSysIntr);
 return TRUE;
}


BOOL
HW_PowerDown( PPWR_CONTEXT pPWR )
{
 RETAILMSG(ww, (TEXT("PCF: HW_PowerDown /r/n")));
 pPWR->State = SUSPEND;
 return TRUE;
}

/*******************************************************************************************
电源相关操作
********************************************************************************************/
BOOL
HW_PowerCapabilities( PPWR_CONTEXT pPWR, PPOWER_CAPABILITIES ppc )
{
 return TRUE;
}

BOOL
HW_PowerSet( PPWR_CONTEXT pPWR,PCEDEVICE_POWER_STATE pDx  )
{  
 CEDEVICE_POWER_STATE NewDx = *pDx;

 if ( VALID_DX(NewDx) )
 {
  // We only support D0, so do nothing. Just return current state.
  pPWR->Dx = *pDx = D0;
  RETAILMSG(ww, (TEXT("PCF: IOCTL_POWER_SET: D%u => D%u /r/n"), NewDx, pPWR->Dx));
  return TRUE;
 }
 return FALSE;
}

BOOL
HW_PowerGet(PPWR_CONTEXT pPWR, PCEDEVICE_POWER_STATE pDx )
{  
 // return our Current Dx value
 *pDx = pPWR->Dx;
 RETAILMSG(ww, (TEXT("PCF: IOCTL_POWER_GET: D%u /r/n"), pPWR->Dx));

 return TRUE;
}

/*******************************************************************************************
关键函数
********************************************************************************************/
int OEM_SEU_PWRKEYSleep( )
{
 HKEY hKey;
 LONG lRes;
 DWORD dwDelay, dwSize, dwType;
 TCHAR WindowName[ ] = TEXT("DelayTime");
 DWORD dwTime = 0, dwCount;
 unsigned int status;

 RETAILMSG(ww, (TEXT("OEM_SEU_PWRKEYSleep/r/n")));

 //lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("//Drivers//PowerManager//PWRKEYDelay"), 0, 0, &hKey );   
 //if(ERROR_SUCCESS != lRes) 
 //{
  //RETAILMSG(ww, (TEXT("RegOpenKeyEx( ) failed! error is %d /r/n"), GetLastError()));
  //RegCloseKey(hKey);
  //return -1;
 //}

 //dwSize = sizeof(DWORD);
 //if(ERROR_SUCCESS == RegQueryValueEx( hKey, WindowName, NULL, &dwType, (PBYTE)&dwDelay, &dwSize))
 //{
  //dwCount = dwDelay / 50;

  dwCount = 400 / 50;

  while(1)
  {
   Sleep(50);
   dwTime++;

   status = v_pIOPregs->GPGDAT & (0x1<<6);
   
   //按键2秒内弹起,保持唤醒
   if( status == 1 )
   {
    RETAILMSG(ww, (TEXT("Inside OEM_SEU_PWRKEYSleep  <2s   return -2 !!!!!/r/n")));
    //RegCloseKey(hKey);
    return -2;
   }
   //按键长按2秒后才弹起,则进入睡眠状态
   else if( dwTime >= dwCount )
   {
    RETAILMSG(ww, (TEXT("Inside OEM_SEU_PWRKEYSleep  >2s return 0 !!!!!/r/n")));
    //RegCloseKey(hKey);
    return 0;
   }
  }
 //}
 
 // never hear
 RETAILMSG(ww, (TEXT("OEM_SEU_PWRKEYSleep return -1  !!!!!/r/n")));
 //return -1;
}

/*******************************************************************************************
重要线程
********************************************************************************************/
static DWORD
PWR_IST(  PPWR_CONTEXT pPWR  )
{
 DWORD we;
 WCHAR  state[1024] = {0};
 LPWSTR pState = &state[0];
 DWORD dwBufChars = (sizeof(state) / sizeof(state[0]));
 DWORD  dwStateFlags = 0;
 DWORD dwTimeout = 1000;
 int Ret = 0;
 DWORD dwPwrFlags;
 TCHAR szPowerState[MAX_PATH];

 RETAILMSG(ww,(TEXT("/r/nPWR_IST: enter PWR_IST:pPWR->State = 0x%x /r/n"), pPWR->State));

 if (!pPWR)
  return  ERROR_INVALID_PARAMETER;

 while (1) {
  __try {
   we = WaitForSingleObject(pPWR->ISTEvent, INFINITE);
   RETAILMSG(ww,(TEXT("/r/nPWR_IST: pPWR->State = 0x%x /r/n"), pPWR->State));
           
   if ((pPWR->State == RUN))
   { 
    RETAILMSG(ww, (TEXT("pPWR->State == RUN!!! /r/n")));
    Ret = OEM_SEU_PWRKEYSleep( );
    switch(Ret)
    {
     case -1:
      RETAILMSG(ww, (TEXT("Sleep /r/n")));
      Sleep(100);      //加入延时,防止睡眠按钮抖动
      break;
     case 0:
      RETAILMSG(ww,(TEXT("/r/nPWR_IST: Call SetSystemPowerState Enter Suspend.... /r/n")));
      SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE);
      break;
     default:
      RETAILMSG(ww,(TEXT("/r/nPWR_IST: Press for long time to enter sleep mode!/r/n")));
      // Back to "on" state if we are in "unattaneded" mode or "screenoff" mode.
      GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
      if((wcscmp(szPowerState,L"unattended")==0) || (wcscmp(szPowerState,L"screenoff")==0))
      {
       // We are in"unattended" or "screenoff" mode. Go back to "on" state.
       SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);
       // Block until the system is back to the "on" state.
       do
       {
        Sleep(10);
        GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
       } while(!(POWER_STATE(dwPwrFlags) & POWER_STATE_ON));
      }   
    }
    RETAILMSG(ww,(TEXT("pPWR->State == RUN    over.. /r/n")));
    //SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE );
   }
   else///APR if ( pPWR->State == 0x2 )
   {  
    RETAILMSG(ww,(TEXT("pPWR->State  is not RUN !!!!/r/n")));
    SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
    pPWR->State = RUN;
   }
   InterruptDone(g_PwrButtonSysIntr);
  }
  _except(EXCEPTION_EXECUTE_HANDLER)
  {
   RETAILMSG(ww,(TEXT("!!! PWR_IST EXCEPTION: 0x%X !!!/r/n"), GetExceptionCode( ) ));
  }
 }
}

/*******************************************************************************************
RealTime
********************************************************************************************/
BOOL
PWR_GetRealTime(  PPWR_CONTEXT pPWR, LPSYSTEMTIME lpst)
{ return TRUE; }

BOOL
PWR_SetRealTime( PPWR_CONTEXT pPWR, LPSYSTEMTIME lpst )
{ return TRUE; }

/*******************************************************************************************
RealTime
********************************************************************************************/
BOOL
HW_IOControl(
    PPWR_CONTEXT pPWR,
    DWORD dwCode,
    PBYTE pBufIn,
    DWORD dwLenIn,
    PBYTE pBufOut,
    DWORD dwLenOut,
    PDWORD pdwActualOut
   )
{ return FALSE; }

待机与休眠的区别 1、待机”电源管理模式 待机模式主要用于节电,该功能使你可不需重新启动计算机就可返回工作状态。待机模式可关闭监视器和硬盘、风扇之类设备,使整个系统处于低能耗状态。在你重新使用计算机时,它会迅速退出待机模式,而且桌面(包括打开的文档和程序)精确恢复到进入等待时的状态。 如要解除等待状态并重新使用计算机,可移动一下鼠标或按键盘上的任意键,或快速按一下计算机上的电源按钮即可。 请注意!与下面所述的“休眠模式”不同,待机模式不在硬盘上存储未保存的信息,这些信息仅仅只存储在计算机内存中。如果期间突然断电,这些信息将丢失。因此,在将计算机置于待机模式前应该保存文件。如果你希望在离开计算机时自动保存所做的工作,可使用休眠模式而非待机模式。但是,休眠模式将关闭计算机。 2.“休眠” 电源管理模式 在使用休眠模式时,你可以关掉计算机,并确信在回来时所有工作(包括没来得及保存或关闭的程序和文档)都会完全精确地还原到离开时的状态。内存中的内容会保存在磁盘上,监视器和硬盘会关闭,同时也节省了电能,降低了计算机的损耗。一般来说,使计算机解除休眠状态所需的时间要比解除等待状态所需的时间要长,但休眠状态消耗的电能更少。 如果你工作时经常被打断,如某些秘书职业,往往一边要进行计算机处理一边还得接听电话等等,你就可以考虑将计算机设置为经过指定多少分钟后进入自动休眠模式。休眠模式会将内存中的所有内容保存到硬盘,关闭监视器和硬盘,然后关闭计算机。 应用网络切换
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneOnce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值