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

📄 timer_vartick.c

📁 S3C2443 WINCE6.0 BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
			{
				DVS_ON();				
				ChangeVoltage(MIDVOLTAGE);
				g_oalIoCtlClockSpeed = S3C2443_HCLK;
				CurrentState = SlowActive;
				RETAILMSG(1, (TEXT("-S-")));
			}
			else if ( CurrentState == SlowActive && SlowCount++ >= 2)
			{
				HCLK_DOWNTO_PCLK();
				g_oalIoCtlClockSpeed = S3C2443_PCLK;
				if (GetCurrentVoltage() == MIDVOLTAGE ){
					ChangeVoltage(LOWVOLTAGE);
					RETAILMSG(1, (TEXT("L")));
				}
				
				CurrentState = LazyActive;
				RETAILMSG(1, (TEXT("-L-")));
			}
		}
	}
}
#endif	// DVS_METHOD
#endif	// DVS_EN
//------------------------------------------------------------------------------
//
//  Function: OALTimerIntrHandler
//
//  This function implement timer interrupt handler. It is called from common
//  ARM interrupt handler.
//
UINT32 OALTimerIntrHandler()
{
    UINT32 sysIntr = SYSINTR_NOP;

    // Update high resolution counter
    g_oalTimer.curCounts += g_oalTimer.countsPerSysTick*g_idleMSec;
                             
    // Update the millisecond counter
    CurMSec += g_idleMSec;

	OALTimerUpdate(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin);
	g_idleMSec = g_oalTimer.msecPerSysTick;

    // Reschedule?
    if ((int)(CurMSec - dwReschedTime) >= 0) sysIntr = SYSINTR_RESCHED;

#ifdef OAL_ILTIMING
    if (g_oalILT.active) {
        if (--g_oalILT.counter == 0) {
            sysIntr = SYSINTR_TIMING;
            g_oalILT.counter = g_oalILT.counterSet;
            g_oalILT.isrTime2 = OALTimerCountsSinceSysTick();
        }
    }        
#endif

#ifdef DVS_EN
#if (DVS_METHOD == 4 || DVS_METHOD == 5)
	ChangeSystemStateDVS();
#endif
#endif
    return sysIntr;
}


//------------------------------------------------------------------------------
//
//  Function: OALTimerCountsSinceSysTick
//
//  This function return count of hi res ticks since system tick.
//
//  Timer 4 counts down, so we should substract actual value from 
//  system tick period.
//

INT32 OALTimerCountsSinceSysTick()
{
	return (INREG32(&g_pPWMRegs->TCNTB4) - INREG32(&g_pPWMRegs->TCNTO4));
}

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
//  Function: OALTimerUpdate
//
//  This function is called to change length of actual system timer period.
//  If end of actual period is closer than margin period isn't changed (so
//  original period elapse). Function returns time which already expires
//  in new period length units. If end of new period is closer to actual time
//  than margin period end is shifted by margin (but next period should fix
//  this shift - this is reason why OALTimerRecharge doesn't read back 
//  compare register and it uses saved value instead).
//
UINT32 OALTimerUpdate(UINT32 period, UINT32 margin)
{
	UINT32 tcon, ret;
	
	ret = OALTimerCountsSinceSysTick();

	OUTREG32(&g_pPWMRegs->TCNTB4, period);
    tcon = INREG32(&g_pPWMRegs->TCON) & ~(0x0F << 20);
    OUTREG32(&g_pPWMRegs->TCON, tcon | (0x2 << 20) );
    OUTREG32(&g_pPWMRegs->TCON, tcon | (0x1 << 20) );

	return (ret);
}

//------------------------------------------------------------------------------
//
//  Function:     OEMIdle
//
//  This function is called by the kernel when there are no threads ready to 
//  run. The CPU should be put into a reduced power mode if possible and halted. 
//  It is important to be able to resume execution quickly upon receiving an 
//  interrupt.
//
//  Interrupts are disabled when OEMIdle is called and when it returns.
//
//  Note that system timer must be running when CPU/SoC is moved to reduced
//  power mode.
//
void OEMIdle(DWORD idleParam)
{
    UINT32 baseMSec, idleMSec, idleSysTicks;
    INT32 usedCounts, idleCounts;
    ULARGE_INTEGER idle;
    // Get current system timer counter
    baseMSec = CurMSec;

    // Compute the remaining idle time
    idleMSec = dwReschedTime - baseMSec;
//	RETAILMSG(1,(TEXT("(%d)"), idleMSec));
    
    // Idle time has expired - we need to return
    if ((INT32)idleMSec <= 0) return;

	// Limit the maximum idle time to what is supported.  
	// Counter size is the limiting parameter.  When kernel 
	// profiler or interrupt latency timing is active it is set
	// to one system tick.
	if (idleMSec > g_oalTimer.maxPeriodMSec) {
		idleMSec = g_oalTimer.maxPeriodMSec;
	}

	// We can wait only full systick
	idleSysTicks = idleMSec/g_oalTimer.msecPerSysTick;

	// This is idle time in hi-res ticks
	idleCounts = idleSysTicks * g_oalTimer.countsPerSysTick;

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

	if (usedCounts == g_oalTimer.countsPerSysTick)
	{
		return;
	}

    // Prolong beat period to idle time -- don't do it idle time isn't
    // longer than one system tick. Even if OALTimerExtendSysTick function
    // should accept this value it can cause problems if kernel profiler
    // or interrupt latency timing is active.
    if (idleSysTicks > 1) {
        // Extend timer period
        OALTimerUpdate(idleCounts-usedCounts, g_oalTimer.countsMargin);
        // Update value for timer interrupt which wakeup from idle
        g_oalTimer.actualMSecPerSysTick = idleMSec;
        g_oalTimer.actualCountsPerSysTick = idleCounts;
    }

	g_idleMSec = idleMSec;

    // Move SoC/CPU to idle mode
    OALCPUIdle();

    // Return system tick period back to original. Don't call when idle
    // time was one system tick. See comment above.
    if (idleSysTicks > 1) {
        // If there wasn't timer interrupt we have to update CurMSec&curCounts
        if (CurMSec == baseMSec) {
			// Return system tick period back to original
			idleCounts = OALTimerUpdate(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin)+usedCounts;

			g_idleMSec = g_oalTimer.msecPerSysTick;
//			RETAILMSG(1,(TEXT("(%x)"), idleSysTicks));

            // Restore original values
			g_oalTimer.actualMSecPerSysTick = g_oalTimer.msecPerSysTick;
			g_oalTimer.actualCountsPerSysTick = g_oalTimer.countsPerSysTick;

            // Fix system tick counters & idle counter
			CurMSec += idleCounts/g_oalTimer.countsPerMSec;
			//idleCounts = idleSysTicks * g_oalTimer.actualCountsPerSysTick;
			g_oalTimer.curCounts += idleCounts;
			idleCounts += OALTimerCountsSinceSysTick();
			usedCounts = 0;
        }
    } else {
        if (CurMSec == baseMSec) {
			// Update actual idle counts, if there wasn't timer interrupt
			idleCounts = OALTimerCountsSinceSysTick();
			usedCounts = 0;
        }
    }

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

    if (idleCounts < 0) idleCounts = 0;

//	RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, (CurMSec - baseMSec)*g_oalTimer.countsPerSysTick));

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

#ifdef DVS_EN
	dwCurrentidle = (DWORD)(idle.QuadPart/idleconv);
#endif
}


//------------------------------------------------------------------------------
//
//  Function:   OALCPUIdle
//
//  This Idle function implements a busy idle. It is intend to be used only
//  in development (when CPU doesn't support idle mode it is better to stub
//  OEMIdle function instead use this busy loop). The busy wait is cleared by
//  an interrupt from interrupt handler setting the g_oalLastSysIntr.
//

VOID OALCPUIdle()
{
    volatile S3C2443_CLKPWR_REG *s2443CLKPWR = (S3C2443_CLKPWR_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_CLOCK_POWER, FALSE);
    volatile S3C2443_IOPORT_REG *s2443IOPORT = (S3C2443_IOPORT_REG *)OALPAtoVA(S3C2443_BASE_REG_PA_IOPORT, FALSE);
    
#if (DVS_METHOD == 2)
// #define METHOD2_EXT

#ifdef DVS_EN
/**
 *	DVS_ON : Sync FCLK to HCLK
 *	Change voltage to lower
 *	set system mode to idle
 *	Wait for interrupt
 *	Change voltage to high
 *	Wait for recovering voltage to high
 *	DVS_OFF : restore FCLK
 */
//	RETAILMSG(1, (TEXT("I")));
#ifdef METHOD2_EXT
	HCLK_DOWNTO_PCLK();
	DVS_ON();		// FCLK to PCLK		
	g_oalIoCtlClockSpeed = S3C2443_PCLK;	
	ChangeVoltage(LOWVOLTAGE);		
// For 400Mhz Test
//	Max1718_Set(ARMVDD, 95);		// ARM Voltage 
//	Max1718_Set(INTVDD, 95);		// Int Voltage 
#else
	DVS_ON();		// FCLK to HCLK
	g_oalIoCtlClockSpeed = S3C2443_HCLK;
	ChangeVoltage(MIDVOLTAGE);	
#endif	// METHOD2_EXT

  b_oalInterruptFlag = FALSE;

	#if IDLELED_ACTIVATE==TRUE
	s2443IOPORT->GPFDAT |= ( 1<< 5);    // GPF5 output data, turn LED on
	#endif

	INTERRUPTS_ON();
	s2443CLKPWR->PWRMODE |=  (1 << 17);
	while (!b_oalInterruptFlag) {}		/* Wait until S3C2443 enters IDLE mode         */
	INTERRUPTS_OFF();
	s2443CLKPWR->PWRMODE &=  ~(1 << 17);	

	#if IDLELED_ACTIVATE==TRUE
	s2443IOPORT->GPFDAT &= ~(1 << 5);    // GPF5 output data, turn LED off		
	#endif

// For 400Mhz Test
//	Max1718_Set(0, 125);		// Int Voltage 1.25V
//	{	
//	 	volatile int i;
//		for(i=0;i<VOLTAGEDELAY;i++);
//	}
//	Max1718_Set(1, 125);		// Arm Volate 1.25V
#define UNDERSHOOT_WORKAROUND
#ifdef UNDERSHOOT_WORKAROUND
	{	
	 	volatile int i;
		for(i=0;i<VOLTAGEDELAY;i++);
	}
#endif
	ChangeVoltage(HIGHVOLTAGE);
	{	
		// Voltage Difference : 0.55V needs 100usec --> in 133MHZ, 13300 cycles
	 	volatile int i;
		for(i=0;i<VOLTAGEDELAY;i++);
	}
	DVS_OFF();
	g_oalIoCtlClockSpeed = S3C2443_FCLK;
	
#ifdef METHOD2_EXT
	HCLK_RECOVERYUP();
	{	
	 	volatile int i;
		for(i=0;i<VOLTAGEDELAY;i++);
	}	
#endif	// METHOD2_EXT
#endif	// DVS_EN
#else		// DVS_METHOD != 2 ==> (DVS OFF or DVS_METHOD == 4 or DVS_METHOD == 5)
	// Clear last SYSINTR global value
	//g_oalLastSysIntr = SYSINTR_NOP;
	b_oalInterruptFlag = FALSE;

	s2443IOPORT->GPFDAT |= ( 1<< 5);    // GPF5 output data, turn LED on
	INTERRUPTS_ON();		
	s2443CLKPWR->PWRMODE |=  (1 << 17);
	
	while (!b_oalInterruptFlag)	{}
	INTERRUPTS_OFF();
//	s2443CLKPWR->PWRMODE &=  ~(1 << 17);

	s2443IOPORT->GPFDAT &= ~(1 << 5);    // GPF5 output data, turn LED off
	
#endif // #IF(DVS_METHOD == 2)	
}

⌨️ 快捷键说明

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