//------------------------------------------------------------------------------ // // Function: OALTimerInit // // This function is typically called from the OEMInit to initialize // Windows CE system timer. The tickMSec parameter determine timer // period in milliseconds. On most platform timer period will be // 1 ms, but it can be usefull to use higher value for some // specific (low-power) devices. // // Implementation for s3c2450 is using timer 4 as system timer. // BOOL OALTimerInit( UINT32 msecPerSysTick, UINT32 countsPerMSec, UINT32 countsMargin ) { BOOL rc = FALSE; UINT32 countsPerSysTick; UINT32 sysIntr, irq; UINT32 tcon; /*#undef OAL_TIMER #undef OAL_FUNC #define OAL_TIMER 1 #define OAL_FUNC 1*/ OALMSG(OAL_TIMER&&OAL_FUNC, ( L"+OALTimerInit( %d, %d, %d )\r\n", msecPerSysTick, countsPerMSec, countsMargin )); // Validate Input parameters countsPerSysTick = countsPerMSec * msecPerSysTick; if ( msecPerSysTick < 1 || msecPerSysTick > 1000 || countsPerSysTick < 1 || countsPerSysTick > 65535 ) { OALMSG(OAL_ERROR, ( L"ERROR: OALTimerInit: System tick period out of range..." )); goto cleanUp; } // Initialize timer state global variable g_oalTimer.msecPerSysTick = msecPerSysTick; g_oalTimer.countsPerMSec = countsPerMSec; g_oalTimer.countsMargin = countsMargin; g_oalTimer.countsPerSysTick = countsPerSysTick; g_oalTimer.curCounts = 0; g_oalTimer.maxPeriodMSec = 0xFFFF/g_oalTimer.countsPerMSec; g_oalTimer.actualMSecPerSysTick = msecPerSysTick; g_oalTimer.actualCountsPerSysTick = countsPerSysTick; // Set kernel exported globals to initial values idleconv = countsPerMSec; curridlehigh = 0; curridlelow = 0; // Initialize high resolution timer function pointers pQueryPerformanceFrequency = OALTimerQueryPerformanceFrequency; pQueryPerformanceCounter = OALTimerQueryPerformanceCounter; // Create SYSINTR for timer irq = IRQFORTIMER; sysIntr = OALIntrRequestSysIntr(1, &irq, OAL_INTR_FORCE_STATIC); // Hardware Setup #if (BSP_TYPE == BSP_SMDK2443) g_pPWMRegs = (S3C2450_PWM_REG*)OALPAtoUA(S3C2450_BASE_REG_PA_PWM); #elif (BSP_TYPE == BSP_SMDK2450) g_pPWMRegs = (volatile S3C2450_PWM_REG*)OALPAtoUA(S3C2450_BASE_REG_PA_PWM); g_pClkpwrRegs = (volatile S3C2450_CLKPWR_REG *)OALPAtoUA(S3C2450_BASE_REG_PA_CLOCK_POWER); g_pIntrRegs = (volatile S3C2450_INTR_REG *)OALPAtoUA(S3C2450_BASE_REG_PA_INTR); g_pPortRegs = (volatile S3C2450_IOPORT_REG *)OALPAtoUA(S3C2450_BASE_REG_PA_IOPORT); #endif // Set prescaler 1 to 1 OUTREG32(&g_pPWMRegs->TCFG0, INREG32(&g_pPWMRegs->TCFG0) & ~0x0000FF00); OUTREG32(&g_pPWMRegs->TCFG0, INREG32(&g_pPWMRegs->TCFG0) | (PRESCALER<<8)); // Select MUX input 1/2 OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) & ~(0xF << 16)); #if( SYS_TIMER_DIVIDER == DV2 ) OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_2 << 16)); #elif ( SYS_TIMER_DIVIDER == DV4 ) OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_4 << 16)); #elif ( SYS_TIMER_DIVIDER == DV8 ) OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_8 << 16)); #elif ( SYS_TIMER_DIVIDER == DV16 ) OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_16 << 16)); #endif // Set timer register OUTREG32(&g_pPWMRegs->TCNTB4, g_oalTimer.countsPerSysTick); // Start timer in auto reload mode tcon = INREG32(&g_pPWMRegs->TCON) & ~(0x0F << 20); OUTREG32(&g_pPWMRegs->TCON, tcon | (0x2 << 20) ); OUTREG32(&g_pPWMRegs->TCON, tcon | (0x5 << 20) ); // Enable System Tick interrupt if (!OEMInterruptEnable(sysIntr, NULL, 0)) { OALMSG(OAL_ERROR, ( L"ERROR: OALTimerInit: Interrupt enable for system timer failed" )); goto cleanUp; } // // Define ENABLE_WATCH_DOG to enable watchdog timer support. // NOTE: When watchdog is enabled, the device will reset itself if watchdog timer is not refreshed within ~4.5 second. // Therefore it should not be enabled when kernel debugger is connected, as the watchdog timer will not be refreshed. // #ifdef ENABLE_WATCH_DOG { extern void SMDKInitWatchDogTimer (void); SMDKInitWatchDogTimer (); } #endif // Done rc = TRUE; cleanUp: OALMSG(OAL_TIMER && OAL_FUNC, (L"-OALTimerInit(rc = %d)\r\n", rc)); return rc; }
//------------------------------------------------------------------------------ // // Function: OALTimerInit // // General purpose timer 1 is used for system tick. It supports // count/compare mode on 32kHz clock // BOOL OALTimerInit( UINT32 sysTickMSec, UINT32 countsPerMSec, UINT32 countsMargin ) { BOOL rc = FALSE; UINT srcClock; UINT32 sysIntr; UNREFERENCED_PARAMETER(sysTickMSec); UNREFERENCED_PARAMETER(countsPerMSec); UNREFERENCED_PARAMETER(countsMargin); OALMSG(1&&OAL_FUNC, (L"+OALTimerInit(%d, %d, %d)\r\n", sysTickMSec, countsPerMSec, countsMargin )); // Initialize timer state information g_oalTimerContext.maxPeriodMSec = dwOEMMaxIdlePeriod; // Maximum period the timer will interrupt on, in mSec g_oalTimerContext.margin = DELTA_TIME; // Time needed to reprogram the timer interrupt g_oalTimerContext.curCounts = 0; g_oalTimerContext.base = 0; g_oalTimerContext.match = 0xFFFFFFFF; g_oalTimerContext.Posted = 0; // Set idle conversion constant and counters idleconv = MSEC_TO_TICK(1); curridlehigh = 0; curridlelow = 0; // Use variable system tick pOEMUpdateRescheduleTime = OALTimerUpdateRescheduleTime; // Get virtual addresses for hardware g_TimerDevice = BSPGetSysTimerDevice(); // OMAP_DEVICE_GPTIMER1 g_pTimerRegs = OALPAtoUA(GetAddressByDevice(g_TimerDevice)); OALMSG(1 && OAL_FUNC, (L" TimerPA: 0x%x\r\n", GetAddressByDevice(g_TimerDevice))); OALMSG(1 && OAL_FUNC, (L" TimerUA: 0x%x\r\n", g_pTimerRegs)); // Select 32K frequency source clock srcClock = BSPGetSysTimer32KClock(); // k32K_FCLK //PrcmDeviceSetSourceClocks(g_TimerDevice,1,&srcClock); // enable gptimer EnableDeviceClocks(g_TimerDevice, TRUE); // stop timer OALTimerSetReg(&g_pTimerRegs->TCLR, 0); // Soft reset GPTIMER OALTimerSetReg(&g_pTimerRegs->TIOCP, SYSCONFIG_SOFTRESET); // While until done while ((OALTimerGetReg(&g_pTimerRegs->TISTAT) & GPTIMER_TISTAT_RESETDONE) == 0); // Set smart idle OALTimerSetReg( &g_pTimerRegs->TIOCP, SYSCONFIG_SMARTIDLE|SYSCONFIG_ENAWAKEUP| SYSCONFIG_AUTOIDLE ); // Enable posted mode OALTimerSetReg(&g_pTimerRegs->TSICR, GPTIMER_TSICR_POSTED); g_oalTimerContext.Posted = 1; // Set match register to avoid unwanted interrupt OALTimerSetReg(&g_pTimerRegs->TMAR, 0xFFFFFFFF); // Enable match interrupt OALTimerSetReg(&g_pTimerRegs->TIER, GPTIMER_TIER_MATCH); // Enable match wakeup OALTimerSetReg(&g_pTimerRegs->TWER, GPTIMER_TWER_MATCH); // Enable timer in auto-reload and compare mode OALTimerSetReg(&g_pTimerRegs->TCLR, GPTIMER_TCLR_CE|GPTIMER_TCLR_AR|GPTIMER_TCLR_ST); // Wait until write is done //while ((INREG32(&g_pTimerRegs->TWPS) & GPTIMER_TWPS_TCLR) != 0); // Set global variable to tell interrupt module about timer used g_oalTimerIrq = GetIrqByDevice(g_TimerDevice,NULL); // 37 // Request SYSINTR for timer IRQ, it is done to reserve it... sysIntr = OALIntrRequestSysIntr(1, &g_oalTimerIrq, OAL_INTR_FORCE_STATIC); // 17 // Enable System Tick interrupt if (!OEMInterruptEnable(sysIntr, NULL, 0)) { OALMSG(OAL_ERROR, ( L"ERROR: OALTimerInit: Interrupt enable for system timer failed" )); goto cleanUp; } // Initialize timer to maximum period UpdatePeriod(g_oalTimerContext.maxPeriodMSec); // Done rc = TRUE; cleanUp: OALMSG(1 && OAL_FUNC, (L"-OALTimerInit(rc = %d)\r\n", rc)); return rc; }