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

📄 idle.c

📁 ebd9307开发板wince bsp源码,包括cs8900,lcd,nand,serial,touch,usb,gpio,wd等驱动
💻 C
字号:
//**********************************************************************
//                                                                      
// Filename: idle.c
//                                                                      
// Description: 
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved                       
//                                                                      
//**********************************************************************
#include <windows.h>
#include <bldver.h>
#include <nkintr.h>
#include <oalintr.h>
#include <clocks.h>
#include <hwdefs.h>

//
// Kernel global variables used by GetIdleTime( ) to determine CPU utilization
//
extern DWORD idleconv;                  // translation constant in 1 ms units
extern DWORD curridlehigh, curridlelow; // 64-bit idle time in ms
extern void EnterStandbyMode();

// dougfir or later
//
extern volatile DWORD CurMSec;

extern DWORD dwReschedTime;


extern BOOL fIntrTime;
extern BOOL bProfileTimerRunning;

volatile ULARGE_INTEGER CurTicks = { 0, 0 };


extern DWORD dwReschedIncrement;
//extern DWORD OEMCount1ms;
extern ULONG gulCS8950KitlUsed;
extern volatile DWORD gdwInterruptMask1, gdwInterruptMask2;
extern volatile DWORD gdwInterruptWakeMask1, gdwInterruptWakeMask2;
extern volatile BYTE  gfSysIntrWakeupMask[SYSINTR_MAXIMUM];
extern volatile DWORD gdwLastWakeupSource;
extern volatile BOOL  gfResumeFlag;

extern volatile DWORD dwTimeValueWhenSuspend;

//
// CPU-specific functions for OEMIdle
//
extern void  CPUEnterIdle(DWORD dwIdleParam);
extern DWORD PerfCountSinceTick();

extern BOOL SysIntrNumToInterruptMask
(
    DWORD dwSysIntr, 
    PULONG pulInterruptMask1,
    PULONG pulInterruptMask2
);




//------------------------------------------------------------------------------
//
//  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.
//
//------------------------------------------------------------------------------




VOID OEMIdle(DWORD idleParam)
{
    UINT32 baseMSec ;
    ULARGE_INTEGER idle;
	UINT32 idleMSec;

    INT32 usedCounts, idleCounts;

    // Get current system timer counter
    baseMSec = CurMSec;
    
    idleMSec = dwReschedTime - baseMSec;
    
    // Idle time has expired - we need to return
    if ((INT32)idleMSec <= 0) return;

    // Find how many hi-res ticks was already used
    usedCounts = PerfCountSinceTick();

/*	usedMSec=usedCounts/OEM_COUNT_1MS;
    if ( idleMSec + usedMSec  > IDLE_MAX_MS)
    {
         idleMSec=IDLE_MAX_MS-usedMSec;
    }*/

    // We should wait this time
    idleCounts = OEM_COUNT_1MS * idleMSec;

    // Move SoC/CPU to idle mode
    CPUEnterIdle( 0 );

    if ((int)(CurMSec - dwReschedTime) < 0 ) {

        idleCounts = PerfCountSinceTick();
    }

    // Get real idle value. If result is negative we didn't idle at all.
    idleCounts -= usedCounts;
    if (idleCounts < 0) idleCounts = 0;

    // Update idle counters
    idle.LowPart = curridlelow;
    idle.HighPart = curridlehigh;
    idle.QuadPart += idleCounts/OEM_COUNT_1MS;
    curridlelow  = idle.LowPart;
    curridlehigh = idle.HighPart;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// 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 dwCount;
	dwCount=(DWORD)(CurTicks.QuadPart/983);

	CurMSec=dwCount;

	return dwCount;

/*
 #if (RESCHED_PERIOD==1)

//	RETAILMSG(1,(L"SC_COUNT %d\r\n",CurMSec));
	return  CurMSec;
 #else
    UINT32 count;
    INT32 offset;

        // System timer tick period exceeds 1 ms. 
        //
        // This code adjusts the accuracy of the returned value to the nearest
        // MSec when the system tick exceeds 1 ms. The following code checks if 
        // a system timer interrupt occurred between reading the CurMSec value 
        // and the call to fetch the HiResTicksSinceSysTick. If so, the value of
        // CurMSec and Offset is re-read, with the certainty that a system timer
        // interrupt will not occur again.
    do {
        count = CurMSec;
        offset = PerfCountSinceTick();
    } 
    while (count != CurMSec);

    // Adjust the MSec value with the contribution from HiRes counter.
    count += offset/OEM_COUNT_1MS;

    return count;
#endif
	*/
}

//****************************************************************************
// OEMPowerOff
//****************************************************************************
// Power management stuff.
// 
//
VOID OEMPowerOff(void)
{
//    volatile ULONG      ulTemp;
    ULONG               ulCscPwrCnt, ulCscDevCfg;

    //
    // Print out the current clock rates to the debug port.
    //
    NKDbgPrintfW( L"OEMPowerOff\r\n" );
    
    INTERRUPTS_OFF();

    //
    // Replace the interrupt mask with the wake event interrupt mask.  These
    // will be the only interrupts that can wake us from suspend.
    //
    *VIC1_INTCLEAR  = 0xFFFFFFFF;
    *VIC2_INTCLEAR  = 0xFFFFFFFF;

    *VIC1_INTENABLE = gdwInterruptWakeMask1 | INT1_TIMER1;
    *VIC2_INTENABLE = gdwInterruptWakeMask2;

    //
    // Check to see if there is a kitl connection.  If so then 
    // keep the clocks on.
    //
    if(!gulCS8950KitlUsed)
    {
        //
        // Power down the system clocks here.
        //
        ulCscPwrCnt                     = *CSC_PWRCNT;
        ulCscDevCfg                     = *CSC_DEVCFG;

        //
        // Power down the clocks as much as possible.
        //
        *CSC_SYSLOCK                    = 0xAA;
        *CSC_PWRCNT                     = 0;

        *CSC_SYSLOCK                    = 0xAA;
        *CSC_DEVCFG                     = (ulCscDevCfg & 
                                          ~(DEVCFG_KEYS | DEVCFG_ADCPD | DEVCFG_RAS  |
                                            DEVCFG_TIN  | DEVCFG_U1EN  | DEVCFG_U2EN |
                                            DEVCFG_U3EN)) | DEVCFG_SHENA;

        *CSC_SYSLOCK                    = 0xAA;
        *CSC_CLKSET2                    = CLKSET2_VALUE & ~( CLKSET2_PLL2_EN | CLKSET2_PLL2_NBYP);

        *SDRAM_REFRESH                  = SDRAM_14MHZ_REFRESH_VALUE;


        *CSC_SYSLOCK                    = 0xAA;
        *CSC_CLKSET1                    = CLKSET1_VALUE & ~CLKSET1_PLL1_NBYP;

        //
        // Flush the pipeline.
        //    
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
    }


    gfResumeFlag = FALSE;

    INTERRUPTS_ON();

	dwTimeValueWhenSuspend= *RTC_DR;// *TIM_DEBUGVALUELOW;

    while(!gfResumeFlag)
    {

        if(gulCS8950KitlUsed)
        {
            CPUEnterIdle(0);
        }
        else
        {
			EnterStandbyMode( );
            //ulTemp = *CSC_STBY;
        }
    }

    INTERRUPTS_OFF();

    //
    // Check to see if there is a kitl connection.  If so then 
    // keep the clocks on.
    //
    if(!gulCS8950KitlUsed)
    {
        //
        // Power down the system clocks here.
        //
        *CSC_SYSLOCK                    = 0xAA;
        *CSC_CLKSET1                    = CLKSET1_VALUE;

        //
        // Flush the pipeline.
        //    
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);
        __emit(0xe1a00000);

        *SDRAM_REFRESH                  = SDRAM_REFRESH_VALUE;


        *CSC_SYSLOCK                    = 0xAA;
        *CSC_CLKSET2                    = CLKSET2_VALUE;
                                          
        *CSC_SYSLOCK                    = 0xAA;
        *CSC_DEVCFG                     = ulCscDevCfg;

        *CSC_SYSLOCK                    = 0xAA;
        *CSC_PWRCNT                     = ulCscPwrCnt;
    }

    //
    // Restore the original interupt mask.
    //
    *VIC1_INTCLEAR  = 0xFFFFFFFF;
    *VIC2_INTCLEAR  = 0xFFFFFFFF;
    *VIC1_INTENABLE = gdwInterruptMask1 | INT1_TIMER1;
    *VIC2_INTENABLE = gdwInterruptMask2;

    INTERRUPTS_ON();
}



//****************************************************************************
// OEMPowerManagerInit
//****************************************************************************
// Power Managment Initialization routine.
// 
//
DWORD OEMPowerManagerInit(void)
{
    int ulInt;
    for(ulInt = 0; ulInt < SYSINTR_MAXIMUM ; ulInt++)
    {
        gfSysIntrWakeupMask[ ulInt ]  = 0;
    }

    //
    // Clear the interrupt wake mask
    //
    gdwInterruptWakeMask1   = 0 ; 
    gdwInterruptWakeMask2   = 0 ;

    return 1;
}

//****************************************************************************
// OEMSetWakeupSource
//****************************************************************************
// This sets the source for the wakeup interrupt.
// 
//
DWORD OEMSetWakeupSource( DWORD dwSources)
{
    DWORD   dwIntMask1, dwIntMask2;
  
    NKDbgPrintfW( L"OEMSetWakeupSource dwSource = 0x%x\r\n",dwSources );
    if(dwSources <SYSINTR_MAXIMUM)
    {
        //
        // OEMTranslateSysIntr currently returns the passed value.
        //
        // DWORD dwPhysInt = OEMTranslateSysIntr(dwSources);

        gfSysIntrWakeupMask[dwSources] = 1;

        SysIntrNumToInterruptMask(dwSources, &dwIntMask1, &dwIntMask2);
        gdwInterruptWakeMask1 |= dwIntMask1;
        gdwInterruptWakeMask2 |= dwIntMask2;
        return 1;
    }
    return 0;
}

//****************************************************************************
// OEMResetWakeupSource
//****************************************************************************
// This clears the specified wakeup interrupt.
// 
//
DWORD OEMResetWakeupSource( DWORD dwSources)
{
    DWORD   dwIntMask1, dwIntMask2;

    NKDbgPrintfW( L"OEMResetWakeupSource dwSource = 0x%x\r\n",dwSources );
    if(dwSources < SYSINTR_MAXIMUM)
    {
        //
        // OEMTranslateSysIntr just returns the passed value.
        //
        //DWORD physInt = OEMTranslateSysIntr(dwSources);

        gfSysIntrWakeupMask[dwSources] = 0;

        SysIntrNumToInterruptMask(dwSources, &dwIntMask1, &dwIntMask2);
        gdwInterruptWakeMask1 &= ~dwIntMask1;
        gdwInterruptWakeMask2 &= ~dwIntMask2;
        return 1;
    }
    return 0;
}

//****************************************************************************
// OEMClearIntSources
//****************************************************************************
// I am going to assume there is only one interrupt in the queue
// when the system wakes up from an interrupt.
// 
//
void OEMClearIntSources( )
{
    NKDbgPrintfW( L"OEMClearIntSources.\r\n");
    gfResumeFlag = FALSE;
}

//****************************************************************************
// OEMGetWakeupSource
//****************************************************************************
// Gets the last interrupt that woke up the system.
// 
//
DWORD OEMGetWakeupSource(void)
{
    NKDbgPrintfW( L"OEMGetWakeupSource.\r\n");
    return gdwLastWakeupSource;
}

⌨️ 快捷键说明

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