⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idle.c

📁 此压缩包为杰得开发得z228的BSP的源代码,可以实现很多功能,尤其是视频解码有很好的效果.
💻 C
字号:
/*
*   The content of this file or document is CONFIDENTIAL and PROPRIETARY
*   to Jade Technologies Co., Ltd.  It is subjected to the terms of a
*   License Agreement between Licensee and Jade Technologies Co., Ltd.
*   restricting among other things, the use, reproduction, distribution
*   and transfer.  Each of the embodiments, including this information 
*   and any derivative work shall retain this copyright notice.
* 
*   Copyright (c) 2004 - 2005 Jade Technologies Co., Ltd. 
*   All rights reserved.
 * ----------------------------------------------------------------
 * File:     idle.c,v
 * Revision: 1.0
 * ----------------------------------------------------------------
 * $ 
 */

#include <windows.h>
#include <nkintr.h>
#include <oalintr.h>
#include <platform.h>
#include <oalfuncs.h>
#include <board.h>

// Define this to override the VFP enabled instruction set value and so
//  allow the WCETK to connect to WinCE 
#define VFP_ID_FIX

#ifdef VFP_ID_FIX
extern DWORD CEInstructionSet;
#endif

/*
    @doc    EXTERNAL KERNEL HAL

    @module cfwp2.c - P2 HW Support | 
        OEM support Functions for the Windows CE P2 Platform.
    
    @xref <f OEMInit> <f OEMInterruptEnable> <f OEMInterruptDisable> 
          <f OEMInterruptDone> <l HAL Overview.Windows CE Kernel OEM Interface>
          
    @topic Windows CE Kernel OEM Interface |
          This defines the HAL layer - OEM and platform dependent pieces of
          code which we expect the OEM to deliver to us. There are three pieces
          of OEM deliverable code  - the bootstrap loader & monitor (for 
          debugging), the HAL portions which are interfaces between the kernel
          and the firmware, and the driver interface. This topic covers just 
          the HAL portion.

          The philosophy is to keep the HAL layer as simple as possible.  The 
          HAL should not be confused with the machine or CPU independence. HAL 
          is specific for a particular CPU and platform. It includes interfaces 
          for the following devices:<nl>
          Real Time Clock<nl>
          Interval Timer (used for the scheduler operation) <nl>
          Interrupt handlers and support <nl>

          Note that it does not include abstractions for devices like the DMA 
          controller etc. since the kernel does not use one. Also note that the
          list could change for different CPU's and platforms - for instance, 
          some chips might include a lot of peripheral devices (like the 
          interval timer) on the CPU chip itself, removing the need for a 
          separate interface for them.

          The interfaces for the real time clock and interval timer are still 
          being developed. But they should in general be extremely simple and
          straightforward. For details on the interrupt support model in the 
          kernel look at <l Interrupt Support Overview.Kernel Interrupt Support>

    @xref <l Interrupt Support Overview.Kernel Interrupt Support>
          <f OEMInit> <f OEMInterruptEnable> <f OEMInterruptDisable> 
          <f OEMInterruptDone> <f HookInterrupt>
             
 */

//
// Kernel global variables used by GetIdleTime( ) to determine CPU utilization
//
extern DWORD curridlehigh, curridlelow; // 64-bit idle time in ms

extern DWORD dwReschedTime;
extern BOOL fIntrTime;
extern BOOL bProfileTimerRunning;
extern DWORD dwReschedIncrement;

// The kernel exports...
#ifdef AddrCurMSec
// Some kernels export a pointer to the CurMSec variable.
static volatile DWORD * pCurMSec  = (volatile DWORD *) AddrCurMSec;
#else
extern volatile DWORD CurMSec;
static volatile DWORD * pCurMSec = &CurMSec;
#endif

volatile ULARGE_INTEGER CurTicks = { 0, 0 };
volatile ULARGE_INTEGER * pCurTicks = &CurTicks;



//------------------------------------------------------------------------------
//
//  OEMQueryPerformanceCounter
//  
//      The OEMQueryPerformanceCounter function retrieves the current value of 
//      the high-resolution performance counter, if one exists. 
//  
//  BOOL QueryPerformanceCounter(
//  
//      LARGE_INTEGER  *lpliPerformanceCount    // address of current counter value
//     );   
//  
//  Parameters
//  
//  lpliPerformanceCount
//  
//      Points to a variable that the function sets, in counts, to the current 
//      performance-counter value. If the installed hardware does not support 
//      a high-resolution performance counter, this parameter can be to zero. 
//  
//  Return Value
//  
//      If the installed hardware supports a high-resolution performance 
//      counter, the return value is TRUE.
//      If the installed hardware does not support a high-resolution 
//      performance counter, the return value is FALSE.   
//  
//  If this function is implemented by the OEM, the pointer pQueryPerformanceCounter
//  should be initialized as follows:
//  
//  BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
//
//------------------------------------------------------------------------------
BOOL 
OEMQueryPerformanceCounter(LARGE_INTEGER *lpliPerformanceCount)
{
    ULARGE_INTEGER liBase;
    DWORD dwCurCount;

    // Make sure CurTicks is the same before and after read of counter to account for
    // possible rollover
    do {
        liBase = CurTicks;
        dwCurCount = PerfCountSinceTick();
    } while  (liBase.LowPart != CurTicks.LowPart) ;  

    lpliPerformanceCount->QuadPart = liBase.QuadPart + dwCurCount;
    
    return TRUE;
}



//------------------------------------------------------------------------------
//
//  OEMQueryPerformanceFrequency
//  
//      The OEMQueryPerformanceFrequency function retrieves the frequency of 
//      the high-resolution performance counter, if one exists. 
//  
//  BOOL OEMQueryPerformanceFrequency(
//  
//      LARGE_INTEGER  *lpliPerformanceFreq     // address of current frequency
//     );   
//  
//  Parameters
//  
//  lpliPerformanceFreq
//  
//      Points to a variable that the function sets, in counts per second, to 
//      the current performance-counter frequency. If the installed hardware 
//      does not support a high-resolution performance counter, this parameter
//      can be to zero. 
//  
//  Return Value
//  
//      If the installed hardware supports a high-resolution performance 
//      counter, the return value is TRUE.
//      If the installed hardware does not support a high-resolution 
//      performance counter, the return value is FALSE.
//  
//  If this function is implemented by the OEM, the pointer pQueryPerformanceFrequency
//  should be initialized as follows:
//  
//  BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpPerformanceFrequency)=OEMQueryPerformanceFrequency;
//
//------------------------------------------------------------------------------
BOOL 
OEMQueryPerformanceFrequency( LARGE_INTEGER *lpliPerformanceFreq ) 
{
    extern DWORD PerfCountFreq();
    
    lpliPerformanceFreq->HighPart = 0;
    lpliPerformanceFreq->LowPart  = PerfCountFreq();
    return TRUE;
}

// set pointers to OEM functions
BOOL (*pQueryPerformanceCounter)(LARGE_INTEGER *lpliPerformanceCount)=OEMQueryPerformanceCounter;
BOOL (*pQueryPerformanceFrequency)(LARGE_INTEGER *lpliPerformanceFreq)=OEMQueryPerformanceFrequency;


//------------------------------------------------------------------------------
//
//  This routine is called by the kernel when there are no threads ready to
//  run. The CPU should be put into a reduced power mode and halted. It is 
//  important to be able to resume execution quickly upon receiving an interrupt.
//  Note: It is assumed that interrupts are off when OEMIdle is called.  Interrrupts
//  are turned off when OEMIdle returns.
//
//------------------------------------------------------------------------------
static DWORD dwPartialCurMSec = 0;           // Keep CPU-specific sub-millisecond leftover.
void 
OEMIdle( DWORD dwIdleParam )
{
    DWORD dwIdleMSec;
    DWORD dwPrevMSec = *pCurMSec;

    // Use for 64-bit math
    ULARGE_INTEGER currIdle = {
        curridlelow,
        curridlehigh
    };

    if ((int) (dwIdleMSec = dwReschedTime - dwPrevMSec) <= 0) 
    {
        // already time to wakeup
        return;
    }

    // just idle till tick if profiling or running iltiming
    if (bProfileTimerRunning || fIntrTime) 
    {
        // idle till end of 'tick'
        CPUEnterIdle(dwIdleParam);

        // Update global idle time and return
        currIdle.QuadPart += RESCHED_PERIOD;
        curridlelow = currIdle.LowPart;
        curridlehigh = currIdle.HighPart;
        
        return;
    }

#ifdef VFP_ID_FIX
    CEInstructionSet = PROCESSOR_ARM_V4I_INSTRUCTION;
#endif

    //
    // Since OEMIdle( ) is being called in the middle of a normal reschedule
    // period, CurMSec, dwPartialCurMSec, and CurTicks need
    // to be updated accordingly.
    // Once we reach this point, we must re-program the timer (if we ever did) 
    // because dwPartialCurMSec will be modified in the next function call.
    //
    CPUGetSysTimerCountElapsed(RESCHED_PERIOD, pCurMSec, &dwPartialCurMSec, pCurTicks);

    if ((int) (dwIdleMSec -= *pCurMSec - dwPrevMSec) > 0) 
    {
        dwPrevMSec = *pCurMSec;

        //
        // The system timer may not be capable of arbitrary timeouts. Get the
        // CPU-specific highest possible timeout available.
        //
        dwIdleMSec = CPUGetSysTimerCountMax(dwIdleMSec);
    
        //
        // Set the timer to wake up much later than usual, if needed.
        //
        CPUSetSysTimerCount(dwIdleMSec);
        CPUClearSysTimerIRQ( );
        
        //
        // Enable wakeup on any interrupt, then go to sleep.
        //
        CPUEnterIdle(dwIdleParam);
      
        // Pulse the interrupts on and then off to make sure the wake-up ISR,
        // or any other, runs before the next code sequence.
        INTERRUPTS_ON();
        INTERRUPTS_OFF();
        
        //
        // We're awake as either the timer or another interrupt has occurred.
        // Establish which and adjust the timer data as appropriate.
        //
        if (dwPrevMSec != *pCurMSec) 
        {
            //
            // We completed the full period we asked to sleep.  Update the counters.
            //
            *pCurMSec  += (dwIdleMSec - RESCHED_PERIOD); // Subtract resched period, because ISR also incremented.
            CurTicks.QuadPart += (dwIdleMSec - RESCHED_PERIOD) * dwReschedIncrement;

            currIdle.QuadPart += dwIdleMSec;
        } 
        else 
        {
            //
            // Some other interrupt woke us up before the full idle period was
            // complete.  Determine how much time has elapsed.
            //
            currIdle.QuadPart += CPUGetSysTimerCountElapsed(dwIdleMSec, pCurMSec, &dwPartialCurMSec, pCurTicks);
        }
    }

    // Re-arm counters
    CPUSetSysTimerCount(RESCHED_PERIOD);
    CPUClearSysTimerIRQ( );

    // Update global idle time
    curridlelow = currIdle.LowPart;
    curridlehigh = currIdle.HighPart;

    return;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// SC_GetTickCount must take into account the partials to reflect where we really
// are in time AND IT SHOULD NOT MODIFY ANY OF THE GLOBALS.
//
DWORD SC_GetTickCount(void) 
{
    DWORD dwInc = 0, dwPartial = dwPartialCurMSec, dwPrev = *pCurMSec;
    ULARGE_INTEGER cdummy = {0, 0};
    CPUGetSysTimerCountElapsed(RESCHED_PERIOD, &dwInc, &dwPartial, &cdummy);
    return (dwPrev == *pCurMSec)? dwPrev + dwInc : *pCurMSec;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -