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

📄 vartick.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 2 页
字号:
    }


    // update the counter register with the new counter
	// NOTE that nDiffTick can be negative.
    SHxIncrCounterRegister (nDiffTick);

    // OEMMinTickDistance is too small for variable-tick scheduler if the debugchk failed
    DEBUGCHK (LastINTMSec == dwPrev);

}

//
// TimerISR for SHx
//
DWORD SHxTimerISR (void)
{
    int nDiffMSec = dwReschedTime - NextINTMSec;
    int nDiffTick = 0;
    DWORD dwCounterElapsed = SHxMaxTicks - pTmuTimer0->tcnt;
    DWORD dwRetVal = SYSINTR_RESCHED;
/*
#ifdef	DEBUG
    char string[8];
    static	int		ii = 0;
	void PrintLED(char *);

		// Output to LED
		string[0] = 'T';
		string[1] = 'I';
		string[2] = 'M';
		string[3] = '0';
		string[4] = '0' + (UCHAR)ii / 100;
		string[5] = '0' + (UCHAR)(ii %100) / 10;
		string[6] = '0' + (UCHAR)(ii % 10);
		string[7] = '\0';
		PrintLED(string);
		if( ++ii > 1000 )	ii = 0;
#endif
*/
    wNumInterrupts ++;

    // Take care of the case if we're interrupted way late
    // Perf isn't an issue here since this should only occure when debugger disabling the interrupts.
    if (dwCounterElapsed >= (DWORD) SHxCount1MS) {

        SHxSetCounterRegister (SHxMaxTicks);

        // we can either try to catch up with the time lost, or simply forget about the lost ticks.
        // the following code will try to catch up with the time, but the problem is that it'll 
        // result in "time jump" from drivers' point of view. 
        // CurTicks.QuadPart += dwCounterElapsed;
        // NextINTMSec += dwCounterElapsed / SHxCount1MS;
        // nDiffMSec = dwReschedTime - NextINTMSec;
    }

    // auto reload of max
    CurTicks.QuadPart += dwCounterBase;
    dwCounterBase = SHxMaxTicks;

    //
    // clear underflow flag
    //
	do {
	    pTmuTimer0->tcr &= ~TMU_TCR_UNF;
	} while (pTmuTimer0->tcr & TMU_TCR_UNF);


    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, or iltiming/profiler running)
        if (nDiffMSec > nMaxSchedMSec) {
            nDiffMSec = nMaxSchedMSec;
        }
        dwRetVal = SYSINTR_NOP;
    }
    
    // update LastINTMSec and NextINTMSec
    LastINTMSec = NextINTMSec;
    NextINTMSec += nDiffMSec;

    // counter had already been reloaded with nMaxSchedMSec * SHxCount1MS. 
    // change it if we need to (tick shifted, or need to wake up earlier)
    if ((nDiffMSec -= nMaxSchedMSec) != 0) {
        nDiffTick = nDiffMSec * SHxCount1MS;
    }
    if (nDiffTick || shifted_tick) {
        // actully decrementing the counter here as nDiffMSec is always < nMaxSchedMSec
        SHxIncrCounterRegister (nDiffTick - shifted_tick);
        dwCounterBase += nDiffTick;
        shifted_tick = 0;
    }

    if (pOEMUpdateTimerLED) {
        pOEMUpdateTimerLED (LastINTMSec);
    }

    return dwRetVal;

}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL SHxInitClock(void)
{

    // derive constants from OEMTimerFreq;
    SHxCount1MS = OEMTimerFreq / 1000;                  // 1 MS
    nMaxSchedMSec = (0x7FFFFFFF / SHxCount1MS) - 1;     // Max MS representable by 32 integer - 1 (so we don't overflow)
    NextINTMSec = LastINTMSec + nMaxSchedMSec;
    SHxMaxTicks = (DWORD) nMaxSchedMSec * SHxCount1MS;
    idleconv = SHxCount1MS;
    dwCounterBase = SHxMaxTicks;

    // derive timer from OEMTimerBaseAddr
    pTmuComReg = (PTMU_COMREG) (OEMTimerBaseAddr + TMU_TSTR0_OFFSET);
    pTmuTimer0 = (PTMU_CLOCK_REG) (OEMTimerBaseAddr + TMU_TCOR0_OFFSET);
    pTmuTimer1 = pTmuTimer0 + 1;
    pTmuTimer2 = pTmuTimer0 + 2;

    // Use the count/compare timer as our system tick.
    pQueryPerformanceCounter = OEMQueryPerformanceCounter;
    pQueryPerformanceFrequency = OEMQueryPerformanceFrequency;

    pOEMUpdateRescheduleTime = SHxUpdateReschedTime;

    DEBUGMSG (1, (L"OEMTimerFreq = %8.8lx, SHxCount1MS = %8.8lx, nMaxSchedMSec = %8.8lx, SHxMaxTicks = %8.8lx\r\n",
        OEMTimerFreq, SHxCount1MS, nMaxSchedMSec, SHxMaxTicks));

    SHxInitTimer (SHxMaxTicks);

    return(TRUE);
}

//------------------------------------------------------------------------------
//
//  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
    )
{

	DWORD dwTick = pTmuTimer0->tcnt, dwTickLeft;
    ULARGE_INTEGER currIdle = {
        curridlelow,
        curridlehigh
    };

	pCPUEnterIdle (dwIdleParam);

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

	dwTickLeft = pTmuTimer0->tcnt;
	if (dwTick > dwTickLeft)
		dwTick -= dwTickLeft;
	currIdle.QuadPart += dwTick;
    curridlelow = currIdle.LowPart;
    curridlehigh = currIdle.HighPart;
}

//------------------------------------------------------------------------------
//  This routine is called by the kernel to get the 'real' tick count.
//------------------------------------------------------------------------------
DWORD SC_GetTickCount(void)
{
    volatile DWORD dwNext, dwShift, dwPrev; // volatile for comipler issue workaround.
    int nTicks;

    do {
        dwPrev = LastINTMSec;
        dwNext = NextINTMSec; 
        dwShift = shifted_tick;
        nTicks = pTmuTimer0->tcnt - dwShift;
        if (pTmuTimer0->tcr & TMU_TCR_UNF) {
            return dwNext;
        }
	    // return LastINTMSec if interrupted or within 1MS of last interrupt (avoid calling "divide" in Scheduler since this
		// will usually occurs while handling Timer interrupt.)
        if ((dwPrev != LastINTMSec) || ((int) (SHxMaxTicks - nTicks) < SHxCount1MS))
            return LastINTMSec;

    } while ((dwNext != NextINTMSec) || (dwShift != shifted_tick));

    return dwNext - ((nTicks + SHxCount1MS - 1) / SHxCount1MS);

}

//------------------------------------------------------------------------------
//  This routine returns the perf count since the last timer interrupt.
//------------------------------------------------------------------------------
DWORD PerfCountSinceTick (void)
{
    volatile DWORD dwShift, dwPrev, dwPrevCnt; // volatile for comipler issue workaround.
    int nTicks;

    do {
        dwPrev = LastINTMSec;
        dwShift = shifted_tick;
        dwPrevCnt = dwCounterBase;
        nTicks = pTmuTimer0->tcnt - dwShift;
        if ((pTmuTimer0->tcr & TMU_TCR_UNF) || (dwPrev != LastINTMSec))
            return dwPrevCnt;
    } while ((dwPrevCnt != dwCounterBase) || (dwShift != shifted_tick));

    return dwPrevCnt - nTicks;
}

//------------------------------------------------------------------------------
//
// Timer2 - handle profiler and iltiming
//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Start timer 2 (parameter - interrupt interval in micro-seconds)
//------------------------------------------------------------------------------
void SHxStartTimer2 (DWORD dwUSec)
{
#if (SH7770_REVISION == SH7770_1STCUT)
	UCHAR	*tstr;
#endif

    DWORD dwCount;

    if (!dwUSec) {
        //
        // Use default rate (1 MS)
        //
        dwUSec = 1000;

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

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

    DEBUGMSG(1, (TEXT("TMU_TSTR0 0x%02X \r\n"), pTmuComReg->tstr0 ));
    DEBUGMSG(1, (TEXT("TMU_TCR2  0x%08X \r\n"), pTmuTimer2->tcr  ));
    DEBUGMSG(1, (TEXT("TMU_TCOR2 0x%08X \r\n"), pTmuTimer2->tcor ));
    DEBUGMSG(1, (TEXT("TMU_TCNT2 0x%08X \r\n"), pTmuTimer2->tcnt ));

    // make sure timer2 is topped
#if (SH7770_REVISION == SH7770_1STCUT)
	tstr = (UCHAR *)DRV_GLOBAL_BASE + TSTR0_GLOBAL_OFFSET;
	*tstr &= ~TMU2_ENABLE;
    pTmuComReg->tstr0 = *tstr;
#else
    pTmuComReg->tstr0 &= ~TMU2_ENABLE;
#endif

    // initialize timer constant and count register
    pTmuTimer2->tcor = dwCount;
    pTmuTimer2->tcnt = dwCount;

    // start timer2
#if (SH7770_REVISION == SH7770_1STCUT)
	tstr = (UCHAR *)DRV_GLOBAL_BASE + TSTR0_GLOBAL_OFFSET;
	*tstr |= TMU2_ENABLE;
    pTmuComReg->tstr0 = *tstr;
#else
    pTmuComReg->tstr0 |= TMU2_ENABLE;
#endif

    // enable timer2 interrupts
    pTmuTimer2->tcr = TMU_TCR_UNIE | TMU_TCR_TPSC_D16;

    DEBUGMSG(1, (TEXT("->TMU_TSTR0 0x%02X \r\n"), pTmuComReg->tstr0 ));
    DEBUGMSG(1, (TEXT("->TMU_TCR0  0x%08X \r\n"), pTmuTimer0->tcr  ));
    DEBUGMSG(1, (TEXT("->TMU_TCOR0 0x%08X \r\n"), pTmuTimer0->tcor ));
    DEBUGMSG(1, (TEXT("->TMU_TCNT0 0x%08X \r\n"), pTmuTimer0->tcnt ));
    DEBUGMSG(1, (TEXT("->TMU_TCR1  0x%08X \r\n"), pTmuTimer1->tcr  ));
    DEBUGMSG(1, (TEXT("->TMU_TCOR1 0x%08X \r\n"), pTmuTimer1->tcor ));
    DEBUGMSG(1, (TEXT("->TMU_TCNT1 0x%08X \r\n"), pTmuTimer1->tcnt ));
    DEBUGMSG(1, (TEXT("->TMU_TCR2  0x%08X \r\n"), pTmuTimer2->tcr  ));
    DEBUGMSG(1, (TEXT("->TMU_TCOR2 0x%08X \r\n"), pTmuTimer2->tcor ));
    DEBUGMSG(1, (TEXT("->TMU_TCNT2 0x%08X \r\n"), pTmuTimer2->tcnt ));
}

//------------------------------------------------------------------------------
// Stop Timer 2
//------------------------------------------------------------------------------
void SHxStopTimer2 (void)
{
    DEBUGMSG(1, (TEXT("TMU_TCR2  0x%08X \r\n"), pTmuTimer2->tcr  ));

    //
    // Diable timer2 interrupt
    //
    pTmuTimer2->tcr = TMU_TCR_TPSC_D16;

    DEBUGMSG(1, (TEXT("->TMU_TCR2  0x%08X \r\n"), pTmuTimer2->tcr  ));
}

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

//------------------------------------------------------------------------------
// ISR for Timer2
//------------------------------------------------------------------------------
DWORD SHxTimer2ISRWrapped (DWORD ra)
{
    extern void ProfilerHit (DWORD ra);

/*
#ifdef	DEBUG
    char string[8];
    static	int		ii = 0;
	void PrintLED(char *);

		// Output to LED
		string[0] = 'T';
		string[1] = 'I';
		string[2] = 'M';
		string[3] = '2';
		string[4] = '0' + (UCHAR)ii / 100;
		string[5] = '0' + (UCHAR)(ii %100) / 10;
		string[6] = '0' + (UCHAR)(ii % 10);
		string[7] = '\0';
		PrintLED(string);
		if( ++ii > 1000 )	ii = 0;
#endif
*/

    if (fIntrTime) {
        dwIsrTime1 = SHxTimer2CountSinceTick ();
        dwSPC = ra;
        wNumInterrupts ++;
    }

    //
    // clear underflow flag
    //
	do {
	    pTmuTimer2->tcr &= ~TMU_TCR_UNF;
	} while (pTmuTimer2->tcr & TMU_TCR_UNF);

    if (pOEMUpdateProfLED)
        pOEMUpdateProfLED (ra);

    if (fIntrTime) {
        wNumInterrupts = 0;
        dwIsrTime2 = SHxTimer2CountSinceTick ();
		if( dwIsrTime1 > dwIsrTime2 ){	
			dwIsrTime2 += pTmuTimer2->tcor;	
		}
        return SYSINTR_TIMING;
    }

    if (fProfilerRunning) {
        ProfilerHit (ra);
    } 
    return SYSINTR_NOP;
}



//------------------------------------------------------------------------------
// disable profiler interrupts
//------------------------------------------------------------------------------
void OEMProfileTimerDisable(void)
{
    //
    // Stop Timer 2
    //
    if (fProfilerRunning) {
        SHxStopTimer2 ();
        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;
        SHxStartTimer2 (dwUSec);
    }
}
#pragma optimize("", on)

⌨️ 快捷键说明

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