📄 timer_vartick.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Module: timer.c
//
// Interface to OAL timer services.
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <oal.h>
#include <s3c2450.h>
#include <bsp_cfg.h>
#define IRQFORTIMER IRQ_TIMER4
extern void MMU_WaitForInterrupt();
//------------------------------------------------------------------------------
// Local Variables
static S3C2450_PWM_REG *g_pPWMRegs = NULL;
#if (BSP_TYPE == BSP_SMDK2443)
extern volatile S3C2450_INTR_REG *g_pIntrRegs;
#elif (BSP_TYPE == BSP_SMDK2450)
static S3C2450_INTR_REG *g_pIntrRegs;
#endif
UINT32 g_idleMSec;
#ifdef DVS_EN
volatile BOOL IDLEflag = FALSE;
extern BOOL VSYNCINTR;
extern BOOL CurrStateIdle;
extern void DVS_ON(void);
extern void DVS_OFF(void);
extern void ChangeVoltage(int, int*);
extern int GetCurrentVoltage(int);
//extern void Max1718_Set(int, int);
volatile int CurrentState;
extern void HCLK_DOWNTO_PCLK();
extern void HCLK_RECOVERYUP();
extern volatile int CurrentState;
DWORD dwCurrentidle;
DWORD dwPrevTotalTick1000 = 0;
DWORD dwPrevTotalTick100 = 0;
DWORD dwPrevIdleTick1000 = 0;
DWORD dwPrevIdleTick100 = 0;
DWORD dwPercentIdle1000 = 0;
DWORD dwPercentIdle100 = 0;
#endif
#if (BSP_TYPE == BSP_SMDK2443)
#elif (BSP_TYPE == BSP_SMDK2450)
static S3C2450_PWM_REG *g_pPWMRegs;
static S3C2450_IOPORT_REG *g_pPortRegs;
static S3C2450_CLKPWR_REG *g_pClkpwrRegs;
static S3C2450_INTR_REG *g_pIntrRegs;
UINT32 g_idleMSec;
volatile UINT32 g_oalLastSysIntr;
#endif
//------------------------------------------------------------------------------
//
// 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;
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
g_pPWMRegs = (S3C2450_PWM_REG*)OALPAtoUA(S3C2450_BASE_REG_PA_PWM);
#if (BSP_TYPE == BSP_SMDK2443)
#elif (BSP_TYPE == BSP_SMDK2450)
g_pClkpwrRegs = (S3C2450_CLKPWR_REG *)OALPAtoUA(S3C2450_BASE_REG_PA_CLOCK_POWER);
g_pIntrRegs = (S3C2450_INTR_REG *)OALPAtoUA(S3C2450_BASE_REG_PA_INTR);
g_pPortRegs = (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));
//OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (2 << 16)); // charlie, Timer4 Division
OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) & ~(0xF << 16));
#if( SYS_TIMER_DIVIDER == D2 )
OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_2 << 16));
#elif ( SYS_TIMER_DIVIDER == D4 )
OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_4 << 16));
#elif ( SYS_TIMER_DIVIDER == D8 )
OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (D1_8 << 16));
#elif ( SYS_TIMER_DIVIDER == D16 )
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 | (0x1 << 20) ); // (0<<22) : one-shot, (1<<22) : auto reload
// 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;
}
#ifdef DVS_EN
VOID ChangeSystemStateDVS()
{
unsigned int dwCurrentMSec, dwCurrentIdleSec;
//unsigned int PercentIdle;
volatile unsigned int i;
static unsigned int SlowCount = 0;
dwCurrentMSec = CurMSec;
dwCurrentIdleSec = dwCurrentidle;
if ( dwCurrentMSec - dwPrevTotalTick100 > 100 )
{
dwPercentIdle100 = ((100*(dwCurrentIdleSec - dwPrevIdleTick100)) / (dwCurrentMSec - dwPrevTotalTick100));
dwPrevTotalTick100 = dwCurrentMSec;
dwPrevIdleTick100 = dwCurrentIdleSec;
if ( dwPercentIdle100 < 20 )
{
if ( CurrentState == SlowActive)
{
if ( GetCurrentVoltage(ARM_VDD) == 0 ){
RETAILMSG(1,(TEXT("Cannot get current voltage. State Freezing\n")));
return;
}
if ( GetCurrentVoltage(ARM_VDD) != HIGHVOLTAGE )
{
// DVS OFF...
int voltage_set[2] = HIGH_V_SET;
ChangeVoltage(ARM_INT_VDD, voltage_set);
// RETAILMSG(1, (TEXT("H")));
}
DVS_OFF();
g_oalIoCtlClockSpeed = S3C2450_FCLK;
CurrentState = Active;
SlowCount = 0;
// RETAILMSG(1, (TEXT("-A-")));
}
if( CurrentState == LazyActive) // Change state from SlowActive to Active...
{
if ( GetCurrentVoltage(ARM_VDD) == 0 ){
RETAILMSG(1,(TEXT("Cannot get current voltage. State Freezing\n")));
return;
}
if ( GetCurrentVoltage(ARM_VDD) != HIGHVOLTAGE )
{
// DVS OFF...
int voltage_set[2] = HIGH_V_SET;
ChangeVoltage(ARM_INT_VDD, voltage_set);
// RETAILMSG(1, (TEXT("H")));
}
DVS_OFF();
g_oalIoCtlClockSpeed = S3C2450_FCLK;
HCLK_RECOVERYUP();
CurrentState = Active;
SlowCount = 0;
// RETAILMSG(1, (TEXT("-A-")));
}
}
}
if ( dwCurrentMSec - dwPrevTotalTick1000 > 1000 )
{
dwPercentIdle1000 = ((100*(dwCurrentIdleSec - dwPrevIdleTick1000)) / (dwCurrentMSec - dwPrevTotalTick1000));
dwPrevTotalTick1000 = dwCurrentMSec;
dwPrevIdleTick1000 = dwCurrentIdleSec;
// RETAILMSG(1, (TEXT("%d,%d "), dwPercentIdle100, CurrentState));
if ( dwPercentIdle1000 > 70 )
{
if ( CurrentState == Active)
{
int voltage_set[2] = MID_V_SET;
DVS_ON();
ChangeVoltage(ARM_INT_VDD, voltage_set);
g_oalIoCtlClockSpeed = S3C2450_HCLK;
CurrentState = SlowActive;
// RETAILMSG(1, (TEXT("-S-")));
}
else if ( CurrentState == SlowActive && ++SlowCount >= 1)
{
HCLK_DOWNTO_PCLK();
g_oalIoCtlClockSpeed = S3C2450_PCLK;
if ( GetCurrentVoltage(ARM_VDD) == 0 ){
RETAILMSG(1,(TEXT("Cannot get current voltage. State Freezing\n")));
return;
}
if ( GetCurrentVoltage(ARM_VDD) == MIDVOLTAGE ){
int voltage_set[2] = LOW_V_SET;
ChangeVoltage(ARM_INT_VDD, voltage_set);
// RETAILMSG(1, (TEXT("L")));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -