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

📄 timer.c

📁 支持三星原产的S3C2413开发板
💻 C
📖 第 1 页 / 共 2 页
字号:

	if (period == 0) {
		// Period is zero, let interrupt occurs asap
		rc = 0;
		g_timer.compare = edge;
		OALTimerSetCount(g_timer.compare);
	} else if ((INT32)(g_timer.compare - edge) > 0) {
		// We are more than margin before actual compare, update period
		offset = count - g_timer.base;
		// Avoid divide/multiply for most cases
		if ((INT32)(offset - period) <= 0) {
			rc = 0;
		} else {			
			rc = offset/period;
			g_timer.base += rc * period;		 
		}
		// New compare value is base plus period
		g_timer.compare = g_timer.base + period;
		// Are we more than margin before new compare?
		if ((INT32)(g_timer.compare - edge) > 0) {
			// Yes, then use calculated value
			OALTimerSetCompare(g_timer.compare);
		} else {
			// No, shift real compare value
			OALTimerSetCompare(edge);
		}			
	} else {
		// No, stay with original period
		rc = (g_timer.compare - g_timer.base)/period - 1;
	}	
	return rc;
*/
}

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

	volatile S3C2413_IOPORT_REG *s2413IOP = (S3C2413_IOPORT_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_IOPORT, FALSE);

	while (s2413IOP->GSTATUS4 == 0x2bed);	// for avoiding collision with sleep mode
	s2413IOP->GSTATUS4 = 0x1d1e;
	
	// 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();

//	RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, usedCounts));
	if (idleCounts == usedCounts)
	{
		//RETAILMSG(1,(TEXT("(%x, %x)"), idleCounts, usedCounts));
		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
			idleSysTicks = OALTimerUpdate(g_oalTimer.countsPerSysTick, g_oalTimer.countsMargin);

			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 += idleSysTicks * g_oalTimer.actualMSecPerSysTick;
			idleCounts = idleSysTicks * g_oalTimer.actualCountsPerSysTick;
			g_oalTimer.curCounts += idleCounts;
			idleCounts += OALTimerCountsSinceSysTick();
		}
	} else {
		if (CurMSec == baseMSec) {
			// Update actual idle counts, if there wasn't timer interrupt
			idleCounts = OALTimerCountsSinceSysTick();
//			RETAILMSG(1,(TEXT("(%x)"), idleCounts));
		}
	}

	// 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;
	s2413IOP->GSTATUS4 = 0;

#ifdef DVS_EN
	dwCurrentidle = (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.
//

// LED status on/off for IDLE action.
#define IDLELED_ACTIVATE TRUE

extern void Nop(void);
extern void MMU_WaitForInterrupt();

VOID OALCPUIdle()
{
	S3C2413_IOPORT_REG *s2413IOPORT = (S3C2413_IOPORT_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_IOPORT, FALSE);
	S3C2413_CLKPWR_REG *s2413CLKPWR = (S3C2413_CLKPWR_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_CLOCK_POWER, FALSE);
	S3C2413_INTR_REG *s2413INTR= (S3C2413_INTR_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_INTR, FALSE);	
	int i=0;
	
#ifdef DVS_EN
	S3C2413_LCD_REG *pLCD = (S3C2413_LCD_REG*)OALPAtoVA(S3C2413_BASE_REG_PA_LCD, FALSE);
#if(DVS_METHOD == 1)
{
	if  ( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
	if  ( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
	if  ( s2413INTR->SRCPND & (1 << IRQ_LCD )) s2413INTR->SRCPND = 1 << IRQ_LCD;
	if  ( s2413INTR->INTPND & (1 << IRQ_LCD )) s2413INTR->INTPND = 1 << IRQ_LCD;

	s2413INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt

	if ( CurrStateIdle == TRUE )
		s2413INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt

	IDLEflag = TRUE;

	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
	#endif

	s2413CLKPWR->PWRCFG &=~(3<<6);	// clear bit for bit remained after sleep
	s2413CLKPWR->PWRCFG |=(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
	MMU_WaitForInterrupt();
	s2413CLKPWR->PWRCFG &= ~(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 

	if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
		OALTimerIntrHandler();

	//IDLEflag = FALSE;
	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
	#endif

	if  ( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
	if  ( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
	if  ( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
	if  ( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
	
	s2413INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt

	if ( CurrStateIdle == FALSE )
		s2413INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt
}
#elif (DVS_METHOD == 2)
{
	//RETAILMSG(1, (TEXT("-2-")));
#if 1
	DVS_ON();
	g_oalIoCtlClockSpeed = S3C2413_HCLK;

	ChangeVoltage(MIDVOLTAGE);

	//g_oalLastSysIntr = FALSE;

	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
	#endif
	
	s2413CLKPWR->PWRCFG &=~(3<<6);	// clear bit for bit remained after sleep
	s2413CLKPWR->PWRCFG |=(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
	MMU_WaitForInterrupt();
	s2413CLKPWR->PWRCFG &= ~(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 


	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
	#endif
	

	ChangeVoltage(HIGHVOLTAGE);
	for(i=0;i<VOLTAGEDELAY;i++)
	{
		INREG32(&s2413IOPORT->GPFDAT);  // for loop operation, just read.
	}

	DVS_OFF();

	if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
	  OALTimerIntrHandler();
	
	s2413IOPORT->GPFDAT |= (1 << 5);
	g_oalIoCtlClockSpeed = S3C2413_FCLK;
	
#endif	
	
}	
#elif (DVS_METHOD == 3)
	if ( CurrentState == Active )	// Active -> Idle
	{
		#if IDLELED_ACTIVATE==TRUE
		s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
		#endif	

//		DVS_ON();
//		g_oalIoCtlClockSpeed = S3C2413_HCLK;
//		ChangeVoltage(MIDVOLTAGE);

	
		IDLEflag = TRUE;


		s2413CLKPWR->PWRCFG &=~(3<<6);	// clear bit for bit remained after sleep
		s2413CLKPWR->PWRCFG |=(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
		MMU_WaitForInterrupt();
		s2413CLKPWR->PWRCFG &= ~(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
	

		if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
			OALTimerIntrHandler();
		//IDLEflag = FALSE;
		#if IDLELED_ACTIVATE==TRUE
		s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
		#endif
	}
	else if ( CurrentState == SlowActive )	// Slow Active -> Deep Idle
	{
		#if IDLELED_ACTIVATE==TRUE
		s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
		#endif	

		if( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
		if( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
		if( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
		if( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
		s2413INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt
		if ( CurrStateIdle == TRUE )	s2413INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt


		IDLEflag = TRUE;
//		RETAILMSG(1, (TEXT("-D-")));


		s2413CLKPWR->PWRCFG &=~(3<<6);	// clear bit for bit remained after sleep
		s2413CLKPWR->PWRCFG |=(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
		MMU_WaitForInterrupt();
		s2413CLKPWR->PWRCFG &= ~(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 

		if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
			OALTimerIntrHandler();
		//IDLEflag = FALSE;
		#if IDLELED_ACTIVATE==TRUE
		s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
		#endif
		
		if( pLCD->LCDSRCPND & 2 ) pLCD->LCDSRCPND = 2;
		if( pLCD->LCDINTPND & 2 ) pLCD->LCDINTPND = 2;
		if( s2413INTR->SRCPND & (1 << IRQ_LCD) ) s2413INTR->SRCPND = ( 1 << IRQ_LCD );
		if( s2413INTR->INTPND & (1 << IRQ_LCD) ) s2413INTR->INTPND = ( 1 << IRQ_LCD );
		s2413INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt
		if ( CurrStateIdle == FALSE )	s2413INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt
	}
	else
	{
	}
#endif //DVS_METHOD
#else

	//g_oalLastSysIntr = FALSE;

	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT | (1<<5)); // LED2 OFF
	#endif
	

	s2413CLKPWR->PWRCFG &=~(3<<6);	// clear bit for bit remained after sleep
	s2413CLKPWR->PWRCFG |=(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 
	MMU_WaitForInterrupt();
	s2413CLKPWR->PWRCFG &= ~(1<<6);	//STADNBYWFI : 00:ignore, 01:idle, 10:stop, 11:sleep mode 

	if(g_pIntrRegs->SRCPND & (1<<IRQ_TIMER4))
		OALTimerIntrHandler();

	#if IDLELED_ACTIVATE==TRUE
	s2413IOPORT->GPFDAT = (s2413IOPORT->GPFDAT & ~(1<<5)); // LED2 ON
	#endif
	
#endif //DVS_EN	

}
//------------------------------------------------------------------------------

⌨️ 快捷键说明

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