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

📄 timer.c

📁 CIRRUS 公司EP93XX系列CPU的WINCE下的BSP
💻 C
字号:
//**********************************************************************
//                                                                      
// Filename: timer.c
//                                                                      
// Description: Routines dealing with the timer.
//
// 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 2003, All Rights Reserved                       
//                                                                      
//**********************************************************************
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft 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 LICENSE.RTF on your
// install media.
//
/* -*-C-*-
 *
 *
 * board.c - Integrator-specific C code
 *
 * Copyright (c) ARM Limited 1998-2000
 * All Rights Reserved.
 */

#include <windows.h>
#include <nkintr.h>
#include <hwdefs.h>
#include <clocks.h>
#include <debugtimer.h>

//
// ISRs set this flag to indicate an interrupt has occurred 
//
volatile BOOL fInterruptFlag;

//
// counts per reschedule 
//
extern DWORD dwReschedIncrement;



//****************************************************************************
// CPUEnterIdle
//****************************************************************************
// Put the cpu into a low-power state.  If none is available, loop on a 
// flag that gets set by ISRs.
//
//
void  CPUEnterIdle(DWORD dwIdleParam)
{
    volatile ULONG ulTemp;

    fInterruptFlag = FALSE;
    ulTemp = *CSC_HALT;


    // INTERRUPTS_ON();
    // while (!fInterruptFlag) 
    //{
        // Just sit here. Any interrupt will bump us out.
        //
        // Execute halt command here.
        //
    //}
}

//****************************************************************************
// CPUGetSysTimerCountMax
//****************************************************************************
// Determine the maximum delay for a given request within the limits of the 
// hardware
//
DWORD CPUGetSysTimerCountMax(DWORD dwIdleMSecRequested)
{
    if (dwIdleMSecRequested > IDLE_MAX_MS) 
    {
        //
        // Our timer isn't capable of idling more than IDLE_MAX_MS milliseconds. 
        // We'll have to break the sleep time into reasonable chunks.
        //
        return IDLE_MAX_MS;
    }
    
    return dwIdleMSecRequested;
}

//****************************************************************************
// SetSysTimerInterval
//****************************************************************************
// Set a timer to a specific tick count instead of the time in milliseconds.
// 
//
void SetSysTimerInterval(DWORD dwTicks)
{
    // NKDbgPrintfW
    // (
    //     L"Interval = 0x%0x\r\n", 
    //     dwTicks
    // );

    //
    // Program the new timer value
    //
    *TIM_TIMER1CONTROL  = TIMERCONTROL_CLKSEL | TIMERCONTROL_MODE ;
    *TIM_TIMER1LOAD     = dwTicks;
    *TIM_TIMER1CONTROL  = TIMERCONTROL_CLKSEL | TIMERCONTROL_MODE | 
                          TIMERCONTROL_ENABLE;
}

//****************************************************************************
// CPUSetSysTimerCount
//****************************************************************************
// Set the new period for the timer in milliseconds.
// 
//    
void  CPUSetSysTimerCount(DWORD dwIdleMSec)
{
    DWORD dwTicks;

    //   
    // Determine the number of ticks required for the number of milliseconds 
    // requested 
    //
    dwTicks = dwIdleMSec * RESCHED_INCREMENT;
    
    //
    // Program the new timer value
    //
    *TIM_TIMER1CONTROL  = TIMERCONTROL_CLKSEL | TIMERCONTROL_MODE ;
    *TIM_TIMER1LOAD    = dwTicks;
    *TIM_TIMER1CONTROL  = TIMERCONTROL_CLKSEL | TIMERCONTROL_MODE | 
                          TIMERCONTROL_ENABLE;
}

 
//****************************************************************************
// CPUClearSysTimerIRQ
//****************************************************************************
// Return TRUE if a timer IRQ was pending, false otherwise.  
// Clear the interrupt if pending.
//

BOOL CPUClearSysTimerIRQ(void)
{
    BOOL    bReturnValue;

    bReturnValue = (*VIC1_RAWINTR & INT1_TIMER1);
    if(bReturnValue)
    {
        *TIM_TIMER1CLEAR = 0;
    }

    //
    // Return if an interrupt was pending.
    //
    return(bReturnValue);
}

#if (CE_MAJOR_VER == 0x0003)
//
// cedar
//
DWORD
CPUGetSysTimerCountElapsed(
                           DWORD dwTimerCountdownMSec,
                           volatile DWORD *pCurMSec,
                           volatile DWORD *pDiffMSec,
                           DWORD *pPartialCurMSec,
                           DWORD *pPartialDiffMSec,
                           volatile ULARGE_INTEGER *pCurTicks
                           )
{
    TimerStruct_t  *pTimer = gSysTimers[OS_TIMER].pt;
    DWORD dwTick = dwTimerCountdownMSec * OEMCount1ms;
    DWORD dwCount, dwTemp;
    
    // If timer IRQ pending, a full resched period elapsed
    if (CPUClearSysTimerIRQ( )) 
    {
        *pCurMSec += dwTimerCountdownMSec;
        *pDiffMSec += dwTimerCountdownMSec;
        pCurTicks->QuadPart += dwTick;
        return dwTimerCountdownMSec;
    }
    
    // No timer IRQ pending, calculate how much time has elapsed
    dwCount = pTimer->TimerValue;
    if (dwCount > dwTick) {
        // This is an error case.  Recover gracefully.
        DEBUGMSG(1, (L"CPUGetSysTimerCountElapsed( ): Correcting periodic timer read error\r\n"));
        dwCount = dwTick;
    } else {
        dwCount = dwTick - dwCount;
    }
    
    pCurTicks->QuadPart += dwCount;
    
    dwTemp = dwCount;
    dwTemp += *pPartialDiffMSec;
    *pPartialDiffMSec = dwTemp % OEMCount1ms;
    *pDiffMSec += dwTemp / OEMCount1ms;
    
    dwTemp = dwCount;
    dwTemp += *pPartialCurMSec;
    *pPartialCurMSec = dwTemp % OEMCount1ms;
    dwTemp = dwTemp / OEMCount1ms;
    *pCurMSec += dwTemp;
    
    return dwTemp;
}

#else   // (CE_MAJOR_VER == 0x0003)
//
// dougfir or later
//
DWORD CPUGetSysTimerCountElapsed
(
    DWORD                   dwTimerCountdownMSec,
    volatile DWORD          *pCurMSec,
    DWORD                   *pPartialCurMSec,
    volatile ULARGE_INTEGER *pCurTicks
)
{

    DWORD dwTick = dwTimerCountdownMSec * RESCHED_INCREMENT;
    DWORD dwCount;
    
    //
    // If timer IRQ pending, a full resched period elapsed
    //
    if (CPUClearSysTimerIRQ( )) 
    {
        *pCurMSec += dwTimerCountdownMSec;
        pCurTicks->QuadPart += dwTick;
        return dwTimerCountdownMSec;
    }

    //    
    // No timer IRQ pending, calculate how much time has elapsed
    //
    dwCount = *TIM_TIMER1VALUE;
    if (dwCount > dwTick) 
    {
        //
        // This is an error case.  Recover gracefully.
        //
        DEBUGMSG
        (
            1, 
            (
                L"ERROR: CPUGetSysTimerCountElapsed "
                L"Count = 0x%x, Tick =0x%x Load =0x%x, Value = 0x%x, control=0x%x\r\n",
                dwCount,
                dwTick,
                *TIM_TIMER1LOAD,
                *TIM_TIMER1VALUE,
                *TIM_TIMER1CONTROL 
            )
        );
        dwCount = dwTick;
    } 
    else 
    {
        dwCount = dwTick - dwCount;
    }
    
    pCurTicks->QuadPart += dwCount;
    
    dwCount += *pPartialCurMSec;
    *pPartialCurMSec = dwCount % RESCHED_INCREMENT;
    *pCurMSec += (dwCount /= RESCHED_INCREMENT);
    
    return dwCount;
}
#endif  // (CE_MAJOR_VER == 0x0003)

//****************************************************************************
// PerfCountFreq
//****************************************************************************
// This function returns the frequency of the timer used by PerfCountSinceTick 
// and PerfCountFreq.
//

DWORD PerfCountFreq()
{
    //
    // Need to change this to the 1 us debug timer.
    //
    return OEM_CLOCK_FREQ;
}

//****************************************************************************
// PerfCountSinceTick
//****************************************************************************
// Counter value based on the current high-performance counter 
// for the system.
//
DWORD PerfCountSinceTick()
{
    DWORD intstatus = (*VIC1_RAWINTR | INT1_TIMER1);
    DWORD dwCount;
    
    // if an interrupt is pending we have gone past the count limit
    if(intstatus ) 
    {
        //
        // We don't really know how long we are overdue, so just return one 
        // tick's worth of counts
        //
        dwCount = dwReschedIncrement;
    } 
    else 
    {
        //
        // Timer counts down, so calculate the number of ticks elapsed.
        //
        dwCount = dwReschedIncrement - *TIM_TIMER1VALUE;
    }
    
    return dwCount;
}

//****************************************************************************
// InitTimer
//****************************************************************************
// Initialize the scheduling timer.
// 
//
void InitClock(void)
{
    //
    // Initialize and start scheduler timer. Initialize the clock to
    // 508Khz, Perodic mode.
    //
    dwReschedIncrement = RESCHED_INCREMENT;
    *TIM_TIMER1LOAD    = dwReschedIncrement;
    *TIM_TIMER1CONTROL = TIMERCONTROL_CLKSEL | TIMERCONTROL_MODE | 
                         TIMERCONTROL_ENABLE;
}


/* EOF board.c */

⌨️ 快捷键说明

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