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

📄 timer.c

📁 该2440 BSP是由三星公司提供的wince5.0的BSP移植到到wince6.0下的
💻 C
📖 第 1 页 / 共 2 页
字号:
//  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 rc, count, offset, edge;

    count = OALTimerGetCount();
    edge = count + margin;

    if (period == 0) {
        // Period is zero, let interrupt occurs asap
        rc = 0;
        g_timer.compare = g_timer.base;
        OALTimerSetCompare(edge);
    } 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;
    INT32 usedCounts, idleCounts;
    ULARGE_INTEGER idle;

    // Get current system timer counter
    baseMSec = CurMSec;
    
    // Find how many hi-res ticks was already used
    usedCounts = OALTimerCountsSinceSysTick();

    // We should wait this time
    idleCounts = g_oalTimer.actualCountsPerSysTick;
    
    // Move SoC/CPU to idle mode
    OALCPUIdle();

    // When there wasn't timer interrupt modify idle time
    if (CurMSec == baseMSec) {
        idleCounts = OALTimerCountsSinceSysTick();
    }

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

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

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

//------------------------------------------------------------------------------
//
//  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 S3C2440A_CLKPWR_REG *p2440CLKPWR = (S3C2440A_CLKPWR_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_CLOCK_POWER, FALSE);
    volatile S3C2440A_INTR_REG *p2440INTR = (S3C2440A_INTR_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_INTR, FALSE);
    volatile S3C2440A_IOPORT_REG *p2440IOP = (S3C2440A_IOPORT_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
	volatile S3C2440A_LCD_REG *p2440LCD = (S3C2440A_LCD_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_LCD, FALSE);
#ifdef DVS_EN
#if(DVS_METHOD == 1)
	if  ( p2440LCD->LCDSRCPND & 2 ) p2440LCD->LCDSRCPND = 2;
	if  ( p2440LCD->LCDINTPND & 2 ) p2440LCD->LCDINTPND = 2;
	if  ( p2440INTR->SRCPND & (1 << IRQ_LCD )) p2440INTR->SRCPND = 1 << IRQ_LCD;
	if  ( p2440INTR->INTPND & (1 << IRQ_LCD )) p2440INTR->INTPND = 1 << IRQ_LCD;
	p2440INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt
	if ( CurrStateIdle == TRUE )
		p2440INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt

	b_oalInterruptFlag = FALSE;
	IDLEflag = TRUE;

	INTERRUPTS_ON();

	p2440CLKPWR->CLKCON |=  (1 << 2);		/* Enter IDLE Mode                                */
	while (!b_oalInterruptFlag)	{}
	p2440CLKPWR->CLKCON &= ~(1 << 2);		/* turn-off IDLE bit.	*/

    INTERRUPTS_OFF();

	IDLEflag = FALSE;

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

#elif (DVS_METHOD == 2)
	// 2.3 DVS_ON = 1 (3:3:6)
	DVS_ON();

	// 2.4 Drop Voltage
	ChangeVoltage(LOWVOLTAGE);

	b_oalInterruptFlag = FALSE;
	INTERRUPTS_ON();

	p2440CLKPWR->CLKCON |=  (1 << 2);		/* Enter IDLE Mode                                */
	while (!b_oalInterruptFlag)	{}
	p2440CLKPWR->CLKCON &= ~(1 << 2);		/* turn-off IDLE bit.	*/

    INTERRUPTS_OFF();

#elif (DVS_METHOD == 3)
	if ( CurrentState == LazyActive ) // Lazy Active -> Deep Idle
	{
		b_oalInterruptFlag = FALSE;
		IDLEflag = TRUE;
		INTERRUPTS_ON();

		p2440CLKPWR->CLKCON |=  (1 << 2);		/* Enter IDLE Mode                              */
		while (!b_oalInterruptFlag)	{}
		p2440CLKPWR->CLKCON &= ~(1 << 2);

	    INTERRUPTS_OFF();

		IDLEflag = FALSE;

	}
	else if ( CurrentState == SlowActive )	// Slow Active -> Deep Idle
	{
		if( p2440LCD->LCDSRCPND & 2 ) p2440LCD->LCDSRCPND = 2;
		if( p2440LCD->LCDINTPND & 2 ) p2440LCD->LCDINTPND = 2;
		if( p2440INTR->SRCPND & (1 << IRQ_LCD) ) p2440INTR->SRCPND = ( 1 << IRQ_LCD );
		if( p2440INTR->INTPND & (1 << IRQ_LCD) ) p2440INTR->INTPND = ( 1 << IRQ_LCD );
		p2440INTR->INTMSK &= ~(1 << IRQ_LCD);		// enable LCD interrupt
		if ( CurrStateIdle == TRUE )
			p2440INTR->INTMSK |= (1 << IRQ_LCD);		// disable LCD interrupt

		NextState = DeepIdle;
		b_oalInterruptFlag = FALSE;
		IDLEflag = TRUE;

		INTERRUPTS_ON();

		p2440CLKPWR->CLKCON |=  (1 << 2);		/* Enter IDLE Mode                              */
		while (!b_oalInterruptFlag)	{}
		p2440CLKPWR->CLKCON &= ~(1 << 2);
	    INTERRUPTS_OFF();

		IDLEflag = FALSE;

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

		NextState = SlowActive;
	}
	else if ( CurrentState == Active )	// Active -> Idle
	{
		DVS_ON();
		ChangeVoltage(LOWVOLTAGE);

		b_oalInterruptFlag = FALSE;
		IDLEflag = TRUE;

		INTERRUPTS_ON();

		p2440CLKPWR->CLKCON |=  (1 << 2);		/* Enter IDLE Mode                              */
		while (!b_oalInterruptFlag)	{}
		p2440CLKPWR->CLKCON &= ~(1 << 2);

	    INTERRUPTS_OFF();
		
		IDLEflag = FALSE;
	}

#endif //DVS_METHOD

#else	
	b_oalInterruptFlag = FALSE;

    INTERRUPTS_ON();

	p2440CLKPWR->CLKCON |=  (1 << 2);
    // Wait until interrupt handler set interrupt flag
    while (!b_oalInterruptFlag)	{}
	p2440CLKPWR->CLKCON &= ~(1 << 2);
    INTERRUPTS_OFF();
#endif
}

⌨️ 快捷键说明

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