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

📄 vartick.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
📖 第 1 页 / 共 2 页
字号:

	// calculate the tick difference.
    nDiffTick = nDiffMSec * ARMCount1MS;

	// shift tick if we need to (too close to count register)
    nTicksFromCountReg = nDiffTick - (countReg - CurTicks.LowPart);
	if ((nShiftTick = OEMMinTickDistance - nTicksFromCountReg) > 0) {
        nDiffTick += nShiftTick;
	}

    // update NextINTMSec
    NextINTMSec = nDiffMSec + dwPrev;

    // update compare register
    pOSTreg->osmr0 = CurTicks.LowPart + nDiffTick;

	// Tick shift is not enough if the following debugchk failed. Increase OEMMinTickDistance if this happens.
	DEBUGCHK (dwPrev == LastINTMSec);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int ARMTimerISR (DWORD ra)
{
    int nDiffMSec;
    int nRetVal;
    int nTicks = pOSTreg->oscr - pOSTreg->osmr0;

    // fix the case if we're interrupted way too late (should only occur when we're in debugger).
    // We just need to line up CurTick with count register here. Yes, we'll 'lose' some time, but
    // we've already lost way more during interrupts off.
    if (nTicks >= ARMCount1MS) {
        CurTicks.QuadPart += nTicks; 
    }

    nDiffMSec = dwReschedTime - NextINTMSec;
    nRetVal = SYSINTR_RESCHED;

    if (nDiffMSec <= 0) {
        // time to reschedule, update next reschedule time to the max we can set
        nDiffMSec = nMaxSchedMSec;
        
    } else {
        // don't need to reschedule yet (most likely due to timer's limit of setting
        // interrupt tick too far away)
        if (nDiffMSec > nMaxSchedMSec) {
            nDiffMSec = nMaxSchedMSec;
        }
        nRetVal = SYSINTR_NOP;
    }

    // update ticks, compare register, and LastINTMSec/NextINTMSec
    CurTicks.QuadPart += (NextINTMSec - CurMSec) * ARMCount1MS;
    LastINTMSec = NextINTMSec;
    NextINTMSec += nDiffMSec;
    pOSTreg->osmr0 = CurTicks.LowPart + nDiffMSec * ARMCount1MS;

    // clear timer0 interrupts
    pOSTreg->ossr = OSSR_M0;
    
    // update LED if any
    if (pOEMUpdateTimerLED)
        pOEMUpdateTimerLED (LastINTMSec);

    return nRetVal;
}

//------------------------------------------------------------------------------
// Initialize system timer. We use match register for timer tick
//------------------------------------------------------------------------------
BOOL ARMInitClock(void)
{
    // initialize the timer address
    pOSTreg = (PVOST_REGS) OEMOSTBaseAddr;

    // derive constants from OEMTimerFreq;
	ARMCount1MS = OEMTimerFreq / 1000;				// 1 MS
	ARMMaxSchedMSec = nMaxSchedMSec = 0x7FFFFFFF / ARMCount1MS;	    // Max MS representable by 32 integer
	NextINTMSec = LastINTMSec + nMaxSchedMSec;
	CurTicks.LowPart = pOSTreg->oscr;
	pOSTreg->osmr0 = CurTicks.LowPart + nMaxSchedMSec * ARMCount1MS;
    idleconv = ARMCount1MS;

    pOSTreg->ossr = OSSR_M0; // clear any current interrupt
    pOSTreg->oier = OIER_E0; // turn on timer 0 the interrupt

	pQueryPerformanceCounter = OEMQueryPerformanceCounter;
	pQueryPerformanceFrequency = OEMQueryPerformanceFrequency;
	pOEMUpdateRescheduleTime = ARMUpdateReschedTime;

    return(TRUE);
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
FakedCPUEnterIdle(
    DWORD dwIdleParam
    )
{
    fInterruptFlag = FALSE;
    INTERRUPTS_ON();
    while (!fInterruptFlag) {
        // Just sit here. Any interrupt will bump us out.
    }
}



//------------------------------------------------------------------------------
//
//  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 dwIdleParam
    )
{
	ULARGE_INTEGER prevTicks = CurTicks;
    ULARGE_INTEGER currIdle = {
        curridlelow,
        curridlehigh
    };

	pCPUEnterIdle (dwIdleParam);

	// wake up from Idle, calculate idle time
	INTERRUPTS_OFF ();

	currIdle.QuadPart += CurTicks.QuadPart - prevTicks.QuadPart + PerfCountSinceTick ();
    curridlelow = currIdle.LowPart;
    curridlehigh = currIdle.HighPart;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD SC_GetTickCount(void) 
{
    DWORD dwPrev = LastINTMSec;
    DWORD dwMSec = dwPrev + PerfCountSinceTick () / ARMCount1MS;

    // return LastINTMSec if timer interrup occur in the middle of this function
    return (dwPrev == LastINTMSec)? dwMSec : LastINTMSec;
}


//------------------------------------------------------------------------------
// profiler/iltiming related funciton
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Start timer 2 (parameter - interrupt interval in micro-seconds)
//------------------------------------------------------------------------------
void ARMStartTimer2 (DWORD dwUSec)
{
    if (!dwUSec) {
        //
        // Use default rate (1 MS)
        //
        dwUSec = 1000;

    } else if (dwUSec < 20) {
        //
        // Rate specified: at least 20us
        //
        dwUSec = 20;
    }
    
    dwTimer2Ticks = (dwUSec * ARMCount1MS) / 1000;

    //
    // Init timer2 and enable timer2 interrupt
    //

    // clear and disable timer2 interrupts

    // initialize timer compare register
    pOSTreg->osmr2 = pOSTreg->oscr + dwTimer2Ticks;

    // enable timer2 interrupts
    pOSTreg->ossr = OSSR_M2;
    pOSTreg->oier |= OIER_E2;
}

//------------------------------------------------------------------------------
// Stop Timer 2
//------------------------------------------------------------------------------
void ARMStopTimer2 (void)
{
    //
    // Diable timer2 interrupt
    //
    pOSTreg->oier &= ~OIER_E2;
}

static volatile DWORD dwCompareReg;

//------------------------------------------------------------------------------
// Timer 2 perf count since tick. Since we don't have to worry about interrupt here
// it's a lot simplier.
//------------------------------------------------------------------------------
DWORD ARMTimer2CountSinceTick (void)
{
    return pOSTreg->oscr - dwCompareReg;
}

int ARMTimer2ISR (DWORD ra)
{
    extern void ProfilerHit (DWORD ra);

    dwCompareReg = pOSTreg->osmr2;

    // take care of ilTiming
    if (fIntrTime) {
        dwIsrTime1 = pOSTreg->oscr - dwCompareReg;
        dwSPC = ra;
    }

    // clear timer2 interrupts
    pOSTreg->ossr = OSSR_M2;

    // update compare register
    pOSTreg->osmr2 += dwTimer2Ticks;

    // take care of ilTiming
    if (fIntrTime) {
        dwIsrTime2 = pOSTreg->oscr - dwCompareReg;
        wNumInterrupts = 0;
        return SYSINTR_TIMING;
    }
    // take care of profiler 
    if (fProfilerRunning) {
        ProfilerHit (ra);
    } 

    return SYSINTR_NOP;
}


//------------------------------------------------------------------------------
// disable profiler interrupts
//------------------------------------------------------------------------------
void OEMProfileTimerDisable(void)
{
    //
    // Stop Timer 2
    //
    if (fProfilerRunning) {
        ARMStopTimer2 ();
        fProfilerRunning = FALSE;
        RETAILMSG(1, (TEXT("Profiler interrupt stopped\r\n")));
    }
}

//------------------------------------------------------------------------------
// start profiler interrupts
//------------------------------------------------------------------------------
void OEMProfileTimerEnable(DWORD dwUSec)
{
    if (fIntrTime) {
        RETAILMSG(1, (TEXT("Cannot starting Monte Carlo Profiler while iltiming is running\r\n")));

    } else if (!fProfilerRunning) {
        RETAILMSG(1, (TEXT("Starting profile timer at %d uS rate\r\n"), dwUSec));
        fProfilerRunning = TRUE;
        ARMStartTimer2 (dwUSec);
    }
}

⌨️ 快捷键说明

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