timer.c
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:17k
源码类别:
Windows CE
开发平台:
Windows_Unix
- /*++
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
- Module Name:
- Abstract:
- Platform dependent PCMCIA initialization functions
- rev:
- 2002.4.11 : RTC function work (Hyojoon KIM, zzartto@samsung.com)
- 2002.4.3 : first S3C2410 version (SOC)
- 2002.2.5 : timer related bug fixups (kwangyoon LEE, kwangyoon@samsung.com)
- prevent timer round-up
- - CPUSetSysTimerCount()
- - CPUClearSysTimerIRQ()
- - CPUGetSysTimerCountElapsed()
- 2002.1.29 : bug fixups (kwangyoon LEE, kwangyoon@samsung.com)
- - PerfCountFreq()
- - PerfCountSinceTick()
- - CPUSetSysTimerCount()
- - CPUClearSysTimerIRQ()
- - CPUGetSysTimerCountElapsed()
- - CPUGetSysTimerCountMax()
- 2002.1.28 : CE.NET initial port (kwangyoon LEE, kwangyoon@samsung.com)
- Notes:
- --*/
- #include <windows.h>
- #include <nkintr.h>
- #include <S2440.h>
- extern DWORD CurMSec;
- extern DWORD DiffMSec;
- DWORD dwReschedIncrement;
- DWORD OEMCount1ms;
- static volatile DWORD dwCurReschedIncr;
- void EnterSlowMode();
- void ExitSlowMode();
- extern void MMU_WaitForInterrupt(void);
- unsigned __int64 RealTimeBias = 0; // Number of 100-nanosecond intervals since
- // January 1, 1601.
- DWORD AlarmTime = 0; // Alarm Off at startup
- volatile BOOL fInterruptFlag;
- volatile BOOL fSlowInterruptFlag;
- unsigned int saveREFRESH;
- //------------------------------------------------------------------------------
- //
- // When this is called we will set up GPIO<1> to be a falling edge interrupt
- // InitClock sets up the OS timer to int via match reg 0 on the IRQ level
- // an int is requested in 1ms from now.
- //
- // Interrupts are disable when this is called. check with Thomas.
- //
- //------------------------------------------------------------------------------
- void
- InitClock(void)
- {
- volatile PWMreg *s2440PWM =(PWMreg *)PWM_BASE;
- volatile INTreg *s2440INT = (INTreg *)INT_BASE;
- DWORD ttmp;
- // Timer4 as OS tick and disable it first.
- s2440INT->rINTMSK |= BIT_TIMER4; // Mask timer4 interrupt.
- s2440INT->rSRCPND = BIT_TIMER4; // Clear pending bit
- s2440INT->rINTPND = BIT_TIMER4;
- // Operating clock : PCLK=101500000 (101.5 Mhz)
- // IMPORTANT : MUST CHECK S2440.H DEFINITIONS !!!!
- s2440PWM->rTCFG1 = 0x8080; //;;; SHL
- s2440PWM->rTCFG0 &= ~(0xff << 8); /* Prescaler 1's Value */
- s2440PWM->rTCFG0 |= (PRESCALER << 8); // prescaler value=15
- /* Timer4 Divider field clear */
- s2440PWM->rTCFG1 = 0x11111; // ;;; SHL
- s2440PWM->rTCFG1 &= ~(0xf << 16);
- #if( SYS_TIMER_DIVIDER == D2 )
- s2440PWM->rTCFG1 |= (D1_2 << 16); /* 1/2 */
- #elif ( SYS_TIMER_DIVIDER == D4 )
- s2440PWM->rTCFG1 |= (D1_4 << 16); /* 1/4 */
- #elif ( SYS_TIMER_DIVIDER == D8 )
- s2440PWM->rTCFG1 |= (D1_8 << 16); /* 1/8 */
- #elif ( SYS_TIMER_DIVIDER == D16 )
- s2440PWM->rTCFG1 |= (D1_16 << 16); /* 1/16 */
- #endif
- s2440PWM->rTCNTB4 = RESCHED_INCREMENT; //((RESCHED_PERIOD * OEM_CLOCK_FREQ) / 1000)
- ttmp = s2440PWM->rTCON & (~(0xf << 20));
- s2440PWM->rTCON = ttmp | (2 << 20); /* update TCVNTB4, stop */
- s2440PWM->rTCON = ttmp | (1 << 20); /* one-shot mode, start */
- // Number of timer counts for reschedule interval
- dwReschedIncrement = RESCHED_INCREMENT;
- // Set OEM timer count for 1 ms
- OEMCount1ms = OEM_COUNT_1MS;
- // Set OEM clock frequency
- OEMClockFreq = OEM_CLOCK_FREQ;
- s2440INT->rINTMSK &= ~BIT_TIMER4;
- return;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- DWORD
- GetTimerPeriod(void)
- {
- return RESCHED_PERIOD;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- #define FROM_BCD(n) ((((n) >> 4) * 10) + ((n) & 0xf))
- // NOTE: The RTC on the SMDK2440 isn't battery-backed so RTC settings will be lost
- // when power is removed.
- //
- BOOL
- OEMGetRealTime(LPSYSTEMTIME lpst)
- {
- #if 0
- volatile RTCreg *s2440RTC = (RTCreg *)RTC_BASE;
- do
- {
- lpst->wYear = FROM_BCD(s2440RTC->rBCDYEAR) + 2000 ;
- lpst->wMonth = FROM_BCD(s2440RTC->rBCDMON & 0x1f);
- lpst->wDay = FROM_BCD(s2440RTC->rBCDDAY & 0x3f);
- lpst->wDayOfWeek = (s2440RTC->rBCDDATE - 1);
- lpst->wHour = FROM_BCD(s2440RTC->rBCDHOUR & 0x3f);
- lpst->wMinute = FROM_BCD(s2440RTC->rBCDMIN & 0x7f);
- lpst->wSecond = FROM_BCD(s2440RTC->rBCDSEC & 0x7f);
- lpst->wMilliseconds = 0;
- }
- while(!(lpst->wSecond));
- return(TRUE);
- #else
- volatile RTCreg *s2440RTC;
- s2440RTC = (RTCreg *)RTC_BASE;
- //RETAILMSG(1, (_T("OEMGetRealTimern")));
- // enable RTC control
- // s2440RTC->rRTCCON = 0x1;
- lpst->wMilliseconds = 0;
- lpst->wSecond = FROM_BCD(s2440RTC->rBCDSEC & 0x7f);
- lpst->wMinute = FROM_BCD(s2440RTC->rBCDMIN & 0x7f);
- lpst->wHour = FROM_BCD(s2440RTC->rBCDHOUR& 0x3f);
- lpst->wDayOfWeek = (s2440RTC->rBCDDATE - 1);
- lpst->wDay = FROM_BCD(s2440RTC->rBCDDAY & 0x3f);
- lpst->wMonth = FROM_BCD(s2440RTC->rBCDMON & 0x1f);
- // lpst->wYear = (2000 + s2440RTC->rBCDYEAR) ;
- lpst->wYear = FROM_BCD(s2440RTC->rBCDYEAR) + 2000 ;
- if ( lpst->wSecond == 0 )
- {
- lpst->wSecond = FROM_BCD(s2440RTC->rBCDSEC & 0x7f);
- lpst->wMinute = FROM_BCD(s2440RTC->rBCDMIN & 0x7f);
- lpst->wHour = FROM_BCD(s2440RTC->rBCDHOUR& 0x3f);
- lpst->wDayOfWeek = (s2440RTC->rBCDDATE - 1);
- lpst->wDay = FROM_BCD(s2440RTC->rBCDDAY & 0x3f);
- lpst->wMonth = FROM_BCD(s2440RTC->rBCDMON & 0x1f);
- lpst->wYear = (2000 + s2440RTC->rBCDYEAR) ;
- }
- // disable RTC control
- // s2440RTC->rRTCCON = 0;
- return TRUE;
- #endif
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- #define TO_BCD(n) ((((n) / 10) << 4) | ((n) % 10))
- // NOTE: The RTC on the SMDK2440 isn't battery-backed so RTC settings will be lost
- // when power is removed.
- //
- BOOL
- OEMSetRealTime(LPSYSTEMTIME lpst)
- {
- #if 0
- volatile RTCreg *s2440RTC = (RTCreg *)RTC_BASE;
- // Enable RTC control.
- //
- s2440RTC->rRTCCON |= 1;
- s2440RTC->rBCDSEC = (unsigned char)TO_BCD(lpst->wSecond );
- s2440RTC->rBCDMIN = (unsigned char)TO_BCD(lpst->wMinute );
- s2440RTC->rBCDHOUR = (unsigned char)TO_BCD(lpst->wHour );
- s2440RTC->rBCDDATE = (unsigned char)(lpst->wDayOfWeek + 1);
- s2440RTC->rBCDDAY = (unsigned char)TO_BCD(lpst->wDay );
- s2440RTC->rBCDMON = (unsigned char)TO_BCD(lpst->wMonth );
- s2440RTC->rBCDYEAR = (unsigned char)TO_BCD((lpst->wYear % 100));
- RETAILMSG(1,(TEXT("OEMSetRealTime: Year: %x, Month: %x, Day: %x, Hour: %x, Minute: %x, second: %x rcnr=%Xhn"),
- s2440RTC->rBCDYEAR, s2440RTC->rBCDMON,s2440RTC->rBCDDAY, s2440RTC->rBCDHOUR, s2440RTC->rBCDMIN,s2440RTC->rBCDSEC,s2440RTC->rRTCCON));
- // Disable RTC control.
- //
- s2440RTC->rRTCCON &= ~1;
- return(TRUE);
- #else
- volatile RTCreg *s2440RTC = (RTCreg *)RTC_BASE;
- static int firsttime = 0;
- // enable RTC control
- s2440RTC->rRTCCON = 0x1;
- s2440RTC->rBCDSEC = (unsigned char)TO_BCD(lpst->wSecond );
- s2440RTC->rBCDMIN = (unsigned char)TO_BCD(lpst->wMinute );
- s2440RTC->rBCDHOUR = (unsigned char)TO_BCD(lpst->wHour );
- s2440RTC->rBCDDATE = (unsigned char)(lpst->wDayOfWeek + 1);
- if ( firsttime == 0 )
- {
- lpst->wYear = 2003; lpst->wMonth = 1; lpst->wDay = 1;
- firsttime = 1;
- }
- s2440RTC->rBCDDAY = (unsigned char)TO_BCD(lpst->wDay );
- s2440RTC->rBCDMON = (unsigned char)TO_BCD(lpst->wMonth );
- s2440RTC->rBCDYEAR = (unsigned char)TO_BCD((lpst->wYear % 100));
- RETAILMSG(1,(TEXT("OEMSetRealTime: Year: %u, Month: %u, Day: %u, Hour: %u, Minute: %u, second: %u rcnr=%Xhn"), lpst->wYear, lpst->wMonth,lpst->wDay, lpst->wHour, lpst->wMinute,lpst->wSecond,s2440RTC->rRTCCON));
- RETAILMSG(1,(TEXT("OEMSetRealTime(register): Year: %x, Month: %x, Day: %x, Hour: %x, Minute: %x, second: %x rcnr=%Xhn"),
- s2440RTC->rBCDYEAR, s2440RTC->rBCDMON,s2440RTC->rBCDDAY, s2440RTC->rBCDHOUR, s2440RTC->rBCDMIN,s2440RTC->rBCDSEC,s2440RTC->rRTCCON));
- // disable RTC control
- s2440RTC->rRTCCON = 0; //&= ~0x1;
- // Just certify heart bit
- // timer_cnt = 0;
- return TRUE;
- #endif
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- BOOL
- OEMSetAlarmTime(LPSYSTEMTIME lpst)
- {
- volatile INTreg *s2440INT = (INTreg *)INT_BASE; // for alarm 030818
- volatile RTCreg *s2440RTC = (RTCreg *)RTC_BASE;
- RETAILMSG(1,(TEXT("OEMSetAlarmTime: Year: %u, Month: %u, Day: %u, Hour: %u, Minute: %u, second: %u rcnr=%Xhn"),
- lpst->wYear, lpst->wMonth,lpst->wDay, lpst->wHour, lpst->wMinute,lpst->wSecond,s2440RTC->rRTCCON));
- if ( !lpst || // for alarm 030818
- (lpst->wSecond > 59) || // 0 - 59
- (lpst->wMinute > 59) || // 0 - 59
- (lpst->wHour > 23) || // 0 - 23
- (lpst->wDayOfWeek > 6) || // 0 - 6, Sun:0, Mon:1, ...
- (lpst->wDay > 31) || // 0 - 31
- (lpst->wMonth > 12) || // 1 - 12, Jan:1, Feb:2, ...
- (lpst->wMonth == 0) ||
- (lpst->wYear < 2000) || // We have a 100 year calander (2 BDC digits) with
- (lpst->wYear > 2099) // a leap year generator hard-wired to year 2000.
- )
- return FALSE;
- s2440RTC->rRTCCON = (1 << 0); /* RTC Control Enable */
- s2440RTC->rALMSEC = (unsigned char)TO_BCD(lpst->wSecond );
- s2440RTC->rALMMIN = (unsigned char)TO_BCD(lpst->wMinute );
- s2440RTC->rALMHOUR = (unsigned char)TO_BCD(lpst->wHour );
- s2440RTC->rALMDAY = (unsigned char)TO_BCD(lpst->wDay );
- s2440RTC->rALMMON = (unsigned char)TO_BCD(lpst->wMonth );
- s2440RTC->rALMYEAR = (unsigned char)TO_BCD((lpst->wYear % 100));
- s2440RTC->rRTCALM = 0x7f; // for alarm 030818
- s2440RTC->rRTCCON = (0 << 0); /* RTC Control Disable */
- // for alarm 030818
- s2440INT->rSRCPND = BIT_RTC; /* RTC Alarm Interrupt Clear */
- s2440INT->rINTPND = BIT_RTC;
- s2440INT->rINTMSK &= ~BIT_RTC; /* RTC Alarm Enable */
- return TRUE;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- DWORD
- PerfCountFreq()
- {
- return (OEMClockFreq);
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- DWORD
- PerfCountSinceTick()
- {
- volatile PWMreg *s2440PWM;
- DWORD dwCount;
- s2440PWM = (PWMreg *)PWM_BASE;
- dwCount= ((DWORD)s2440PWM->rTCNTO4);
- // Note: if dwCount is negative, the counter went past the match point. The math
- // still works since it accounts for the dwReschedIncr time plus the time past
- // the match.
- return dwCurReschedIncr - dwCount;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- void
- CPUSetSysTimerCount(
- DWORD dwCountdownMSec
- )
- {
- DWORD dwMatch, ttmp;
- volatile PWMreg *s2440PWM;
- s2440PWM = (PWMreg *)PWM_BASE;
- dwCurReschedIncr = dwCountdownMSec * OEMCount1ms;
- dwMatch = dwCurReschedIncr;
- s2440PWM->rTCNTB4 = dwMatch;
- ttmp = s2440PWM->rTCON & (~(0xf << 20));
- s2440PWM->rTCON = ttmp | (2 << 20); /* update TCVNTB4, stop */
- s2440PWM->rTCON = ttmp | (1 << 20); /* one-shot mode, start */
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- BOOL
- CPUClearSysTimerIRQ(
- void
- )
- {
- volatile INTreg *s2440INT;
- BOOL fPending;
- DWORD intstatus;
- s2440INT = (INTreg *)INT_BASE;
- intstatus = s2440INT->rSRCPND;
- if ((intstatus & (BIT_TIMER4)) != 0) {
- s2440INT->rSRCPND = BIT_TIMER4;
- s2440INT->rINTPND = BIT_TIMER4;
- fPending = TRUE;
- } else {
- fPending = FALSE;
- }
- return fPending;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- DWORD
- CPUGetSysTimerCountElapsed(
- DWORD dwTimerCountdownMSec,
- volatile DWORD *pCurMSec,
- DWORD *pPartialCurMSec,
- volatile ULARGE_INTEGER *pCurTicks
- )
- {
- volatile PWMreg *s2440PWM;
- DWORD dwTick, dwCount;
- s2440PWM = (PWMreg *)PWM_BASE;
- dwTick = dwTimerCountdownMSec * OEMCount1ms;
- // If timer IRQ pending, a full resched period elapsed
- if (CPUClearSysTimerIRQ( )) {
- *pCurMSec += dwTimerCountdownMSec;
- pCurTicks->QuadPart += dwTick;
- return dwTimerCountdownMSec;
- }
- // No timer IRQ pending, calculate how much time has elapsed
- dwCount= ((DWORD)s2440PWM->rTCNTO4);
- if (dwCount > dwTick) {
- // This is an error case. Recover gracefully.
- dwCount = dwTick;
- } else {
- dwCount = dwTick - dwCount;
- }
- pCurTicks->QuadPart += dwCount;
- dwCount += *pPartialCurMSec;
- *pPartialCurMSec = dwCount % OEMCount1ms;
- *pCurMSec += (dwCount /= OEMCount1ms);
- return dwCount;
- }
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- extern void CPUEnterIdleMode(void);
- extern void OEMWriteDebugLED(WORD wIndex, DWORD dwPattern);
- void
- CPUEnterIdle()
- {
- static volatile CLKPWRreg * s2440CLKPW = (CLKPWRreg *)CLKPWR_BASE;
- static volatile IOPreg * s2440IOP = (IOPreg *)IOP_BASE;
- fInterruptFlag = FALSE;
- INTERRUPTS_ON();
- s2440IOP->rGPFDAT &= ~(1 << 5);
- s2440CLKPW->rCLKCON |= (1 << 2); /* Enter IDLE Mode */
- while (!fInterruptFlag) {} /* Wait until S3C2440X enters IDLE mode */
- s2440CLKPW->rCLKCON &= ~(1 << 2); /* turn-off IDLE bit. */
- /* Any interrupt will wake up from IDLE mode */
- s2440IOP->rGPFDAT |= (1 << 5);
- }
- // Maximum idle is fixed a 1 ms because the PIT has to count down to 0 before reloading
- // the new countdown value.
- #define IDLE_MAX_MS 100
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- DWORD
- CPUGetSysTimerCountMax(
- DWORD dwIdleMSecRequested
- )
- {
- if (dwIdleMSecRequested > IDLE_MAX_MS) {
- return IDLE_MAX_MS;
- }
- return dwIdleMSecRequested;
- }
- void EnterSlowMode()
- {
- static volatile CLKPWRreg * s2440CLKPW = (CLKPWRreg *)CLKPWR_BASE;
- static volatile IOPreg * s2440IOP = (IOPreg *)IOP_BASE;
- static volatile MEMreg * s2440MemReg = (MEMreg *)MEMCTRL_BASE;
- //RETAILMSG(1,(TEXT("EnterSlowMode rn")));
- fSlowInterruptFlag = TRUE;
- s2440IOP->rGPFDAT &= ~(1 << 7);
- //FCLK=FIN/1, SLOW mode, MPLL=off, UPLL=off
- s2440CLKPW->rCLKSLOW |= (1<<4)|(1<<5)|(1<<7);
- saveREFRESH = s2440MemReg->rREFRESH;
- s2440MemReg->rREFRESH=(1<<23)|(unsigned int)(2048+1-12*15.6);
- //Trp=2clk, Trc=4clk
- }
- void ExitSlowMode()
- {
- static volatile CLKPWRreg * s2440CLKPW = (CLKPWRreg *)CLKPWR_BASE;
- static volatile IOPreg * s2440IOP = (IOPreg *)IOP_BASE;
- static volatile MEMreg * s2440MemReg = (MEMreg *)MEMCTRL_BASE;
- // int i;
- //RETAILMSG(1,(TEXT("ExitSlowMode rn")));
- fSlowInterruptFlag = FALSE;
- s2440CLKPW->rCLKSLOW = 0|(1<<4)|(0<<5);// PLL on, MPLL=on
- //for ( i = 0; i < 2048; i++); //S/W MPLL lock-time
- s2440CLKPW->rCLKSLOW = 0|(0<<4)|(0<<5);// NORMAL mode, PLL=on, MPLL=on
- s2440MemReg->rREFRESH = saveREFRESH;
- s2440IOP->rGPFDAT |= (1 << 7);
- }
- void SetSysTimerInterval(DWORD dwTicks)
- {
- volatile PWMreg *s2440PWM = (PWMreg *)PWM_BASE;
- volatile INTreg *s2440INT = (INTreg *)INT_BASE;
- DWORD dwTimerTemp;
- // Mask and clear timer interrupt.
- //
- s2440INT->rINTMSK |= BIT_TIMER4;
- s2440INT->rSRCPND = BIT_TIMER4;
- s2440INT->rINTPND = BIT_TIMER4;
- // Change number of timer ticks in the period.
- //
- s2440PWM->rTCNTB4 = dwTicks;
- dwTimerTemp = s2440PWM->rTCON & (~(0xf << 20));
- s2440PWM->rTCON = dwTimerTemp | (2 << 20); // Update TCVNTB4 and stop.
- s2440PWM->rTCON = dwTimerTemp | (1 << 20); // One-shot mode and start.
- // Unmask the timer interrupt.
- //
- s2440INT->rINTMSK &= ~BIT_TIMER4;
- }