📄 realtimeclock.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.
//
/* -*-C-*-
*
* $Revision: 1.5 $
* $Author: xinxing $
* $Date: 2005/04/29 02:45:54 $
*
* Copyright (c) 1999 ARM Limited
* All Rights Reserved
*
* timex20t.c - ARMX20T (X = 7, 9, 10) platform timer routines
*/
#include <windows.h>
#include <nkintr.h>
extern BOOL (*KLocalFileTimeToFileTime)(const FILETIME *, LPFILETIME);
#include <hwdefs.h>
DWORD dwReschedIncrement;
extern volatile LARGE_INTEGER CurTicks;
// The following control the debug output of the alarm & set functions
#define DEBUG_ALARM 0
#define DEBUG_SET 0
static volatile BOOL gfInitRTC = TRUE;
static FILETIME gftLastFileTime;
static LARGE_INTEGER gliLastCurTicks; // in ms
//
// The following are located in hal\interrupt.c
// They are used to control the alarm setting.
//
extern volatile BOOL gfRTCAlarm; // Is the RTC alarm enabled?
extern volatile LARGE_INTEGER gliRTCAlarmTicks; // Date & time of the alarm.
//
// Multipling by 161111 and then right shifting by 13 is the same as 10000000 / TIMER_508KHZ_FREQ
//
// This gives you the number of 100 nano second chunks...(nano chunks)
//
#define TICKS_TO_NANO_CHUNKS( time ) (time) *= 161111; (time) = ((time) >> 13)
//
// Multiply by 33 and then right shift by 24 is the same as TIMER_508KHZ_FREQ / 10000000
// This will give us TICKS
//
#define NANO_CHUNKS_TO_TICKS( time ) (time) = ((time) << 13); (time) = (time) / 161111
static void add64_64_64(
const LPFILETIME lpNum1,
const LPFILETIME lpNum2,
LPFILETIME lpResult
)
{
__int64 num1, num2;
num1 = (((__int64)lpNum1->dwHighDateTime)<<32);
num1 += (__int64)lpNum1->dwLowDateTime;
num2 = (((__int64)lpNum2->dwHighDateTime)<<32);
num2 += (__int64)lpNum2->dwLowDateTime;
num1 += num2;
lpResult->dwHighDateTime = (DWORD)(num1 >> 32);
lpResult->dwLowDateTime = (DWORD)(num1 & 0xffffffff);
}
// The following function initializes the RT area in an attempt to
// eliminate the run time dependency of the OS on the CMOS. The X86
// CMOS is very slow and can take up to 1ms to get the full CMOS clock.
// This function get the start time from the CMOS and initializes the
// local variables that the RT functions need.
//
static void initRTC( void )
{
SYSTEMTIME curSysTime;
FILETIME curFTime;
RETAILMSG(FALSE,(TEXT("\r\n\n******Called initRTC\r\n\n")));
// This is changed here so that we don't try to
// initialize the RTC at the same time that it
// is already being done.
//
gfInitRTC = FALSE;
//
// Provide a default time...
memset( &curSysTime, 0, sizeof( curSysTime ) );
curSysTime.wMonth = 6;
curSysTime.wDay = 1;
curSysTime.wYear = 1999;
curSysTime.wHour = 12;
curSysTime.wMinute = 0;
curSysTime.wSecond = 0;
// Convert the file time structure
//
if( !KSystemTimeToFileTime( &curSysTime, &curFTime ) )
{
memset( &curSysTime, 0, sizeof( curSysTime ) );
memset( &curFTime, 0, sizeof( curFTime ) );
}
// Update current versions of the RTC support
//
gliLastCurTicks.QuadPart = CurTicks.QuadPart;
gftLastFileTime.dwLowDateTime = curFTime.dwLowDateTime;
gftLastFileTime.dwHighDateTime = curFTime.dwHighDateTime;
}
BOOL OEMGetRealTime(LPSYSTEMTIME lpst)
{
//
// NOTE: this function is assumed to return a LOCAL time rather than a UTC time!
//
unsigned __int64 ui64Delta;
BOOL bResult = FALSE;
LARGE_INTEGER liTimeDelta;
FILETIME ftDelta;
FILETIME ftCurFTime;
LARGE_INTEGER tmpCurTicks;
if (gfInitRTC)
{
// Setup the software RTC...
// gliLastCurTicks & gftLastFileTime is set in
// the following call.
initRTC();
}
// get a snapshot of the current tick count...
tmpCurTicks.QuadPart = CurTicks.QuadPart;
// Calculate the current diference
//
if( tmpCurTicks.QuadPart >= gliLastCurTicks.QuadPart )
{
liTimeDelta.QuadPart =
tmpCurTicks.QuadPart - gliLastCurTicks.QuadPart;
}
else
{
// The counter wrapped...
LARGE_INTEGER liMaxLargeInt;
liMaxLargeInt.HighPart = 0xFFFFFFFF;
liMaxLargeInt.LowPart = 0xFFFFFFFF;
liTimeDelta.QuadPart =
tmpCurTicks.QuadPart +
(liMaxLargeInt.QuadPart - gliLastCurTicks.QuadPart);
}
ui64Delta = (unsigned __int64) liTimeDelta.QuadPart;
TICKS_TO_NANO_CHUNKS( ui64Delta ); // convert to nano chunks
// setup to add in the nano chunk time difference
ftDelta.dwLowDateTime = (DWORD) ui64Delta;
ftDelta.dwHighDateTime = (DWORD) (ui64Delta >> 32);
// Add the delta to the last known time...
//
add64_64_64( &gftLastFileTime , &ftDelta, &ftCurFTime );
// convert the answer to a system time format
//
if(KFileTimeToSystemTime( &ftCurFTime, lpst ) )
{
//
// update the RTC variables...
//
gftLastFileTime.dwLowDateTime = ftCurFTime.dwLowDateTime;
gftLastFileTime.dwHighDateTime = ftCurFTime.dwHighDateTime;
gliLastCurTicks.QuadPart = tmpCurTicks.QuadPart;
bResult = TRUE;
}
else
{
// Failed, don't change anything!!!!
//
bResult = FALSE;
}
return( bResult );
}
BOOL OEMSetRealTime(LPSYSTEMTIME lpst)
{
//
// NOTE: this function is passed a LOCAL time rather than a UTC time!
//
BOOL bResult;
SYSTEMTIME curTime;
if (gfInitRTC)
{
// Setup the software RTC...
initRTC();
}
KFileTimeToSystemTime( &gftLastFileTime, &curTime );
// if the last file time is updated, then update
// the last current tick value...
if( KSystemTimeToFileTime( lpst, &gftLastFileTime ) )
{
SYSTEMTIME newTime;
// remember when we last updated the time...
gliLastCurTicks.QuadPart = CurTicks.QuadPart;
KFileTimeToSystemTime( &gftLastFileTime, &newTime );
DEBUGMSG(DEBUG_SET, (_T("OEMSetRealTime: gliLastCurTicks: %d\r\n"),
gliLastCurTicks.QuadPart ));
DEBUGMSG(DEBUG_SET, (_T("OEMSetRealTime: cur: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
curTime.wMonth, curTime.wDay, curTime.wYear,
curTime.wHour, curTime.wMinute, curTime.wSecond ));
DEBUGMSG(DEBUG_SET, (_T("OEMSetRealTime: In: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
lpst->wMonth, lpst->wDay, lpst->wYear,
lpst->wHour, lpst->wMinute, lpst->wSecond ));
DEBUGMSG(DEBUG_SET, (_T("OEMSetRealTime: ft: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
newTime.wMonth, newTime.wDay, newTime.wYear,
newTime.wHour, newTime.wMinute, newTime.wSecond ));
bResult = TRUE;
}
return( bResult );
}
BOOL OEMSetAlarmTime(LPSYSTEMTIME lpst)
{
BOOL bResult = TRUE;
SYSTEMTIME stCurTime;
FILETIME ftAlarmTime;
ULARGE_INTEGER uliCurFTime;
ULARGE_INTEGER uliAlarmFTime;
// The following call will make sure that
// the RTC is properly initialized...
// This will return the LOCAL time.
// A side-effect that is used here is that
// gftLastFileTime is set to the current time...
// gliLastCurTicks is also modified...
OEMGetRealTime( &stCurTime );
DEBUGMSG(DEBUG_ALARM, (_T("OEMSetAlarmTime: CurTime: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
stCurTime.wMonth, stCurTime.wDay, stCurTime.wYear,
stCurTime.wHour, stCurTime.wMinute, stCurTime.wSecond ));
DEBUGMSG(DEBUG_ALARM, (_T("OEMSetAlarmTime: Alarm: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
lpst->wMonth, lpst->wDay, lpst->wYear,
lpst->wHour, lpst->wMinute, lpst->wSecond ));
DEBUGMSG(DEBUG_ALARM, (_T("OEMSetAlarmTime: gliLastCurTicks(0x%08X:0x%08X)\r\n"),
gliLastCurTicks.HighPart, gliLastCurTicks.LowPart ));
uliCurFTime.LowPart = gftLastFileTime.dwLowDateTime;
uliCurFTime.HighPart = gftLastFileTime.dwHighDateTime;
// Convert the SYSTEMTIME alarmTime to FILETIME
KSystemTimeToFileTime( lpst, &ftAlarmTime );
// now to ULARGE_INTEGER
uliAlarmFTime.LowPart = ftAlarmTime.dwLowDateTime;
uliAlarmFTime.HighPart = ftAlarmTime.dwHighDateTime;
DEBUGMSG(DEBUG_ALARM, (_T("OEMSetAlarmTime: uliCurFTime(0x%08X:0x%08X) uliAlarmFTime(0x%08X:0x%08X)\r\n"),
uliCurFTime.HighPart, uliCurFTime.LowPart,
uliAlarmFTime.HighPart, uliAlarmFTime.LowPart ));
// Compare the current time with the alarm time
// to make sure that the alarm is in the future.
if (uliAlarmFTime.QuadPart > uliCurFTime.QuadPart)
{
#if (1 == DEBUG_ALARM)
unsigned __int64 ui64RealTime;
// The alarm time is in the future, so
// we now need to figure out the TICK count
// to look for.
// Find the difference in NANO chunks...
uliAlarmFTime.QuadPart -= uliCurFTime.QuadPart;
// now we need to convert NANO chunks to TICKS
ui64RealTime = (unsigned __int64) uliAlarmFTime.HighPart << 32;
ui64RealTime += uliAlarmFTime.LowPart;
NANO_CHUNKS_TO_TICKS( ui64RealTime );
// Add the current ticks back to get desired the alarm ticks...
ui64RealTime += (unsigned __int64) gliLastCurTicks.QuadPart;
// Save it back into uliAlarmFTime (now in TICKS)
uliAlarmFTime.HighPart = (DWORD) (ui64RealTime >> 32);
uliAlarmFTime.LowPart = (DWORD) ui64RealTime;
DEBUGMSG(TRUE, (_T("OEMSetAlarmTime: uliAlarmFTime(0x%08X:0x%08X)\r\n"),
uliAlarmFTime.HighPart, uliAlarmFTime.LowPart ));
#endif // ( DEBUG_ALARM )
gliRTCAlarmTicks.QuadPart = uliAlarmFTime.QuadPart;
#if (1 == DEBUG_ALARM )
// Test the alarm date & time to see if it is close to what
// was wanted...
{
LARGE_INTEGER tmpCurTicks = gliRTCAlarmTicks;
LARGE_INTEGER liTimeDelta;
FILETIME ftDelta;
FILETIME ftCurFTime;
SYSTEMTIME stTime;
unsigned __int64 ui64Delta;
// Calculate the current diference
//
liTimeDelta.QuadPart =
tmpCurTicks.QuadPart - gliLastCurTicks.QuadPart;
ui64Delta = (unsigned __int64) liTimeDelta.QuadPart;
TICKS_TO_NANO_CHUNKS( ui64Delta ); // convert to nano chunks
// setup to add in the nano chunk time difference
ftDelta.dwLowDateTime = (DWORD) ui64Delta;
ftDelta.dwHighDateTime = (DWORD) (ui64Delta >> 32);
// Add the delta to the last known time...
//
add64_64_64( &gftLastFileTime , &ftDelta, &ftCurFTime );
// convert the answer to a system time format
//
KFileTimeToSystemTime( &ftCurFTime, &stTime );
DEBUGMSG( DEBUG_ALARM, (_T("OEMSetAlarmTime: Converted alarmTime: ST(%02d/%02d/%04d %02d:%02d:%02d)\r\n"),
stTime.wMonth, stTime.wDay, stTime.wYear,
stTime.wHour, stTime.wMinute, stTime.wSecond ) );
// Write out to the debug serial port that we
// are enabling the alarm...
//OEMWriteDebugByte('S');
}
#endif // ( DEBUG_ALARM )
gfRTCAlarm = TRUE;
// clear interrupts, write the comparator, and enable interrupts
OEMInterruptEnable( SYSINTR_RTC_ALARM, NULL, 0 );
bResult = TRUE;
}
else
{
DEBUGMSG( TRUE,
(_T("OEMSetAlarmTime: alarm occurs before current time!\r\n") ) );
bResult = FALSE;
}
return( bResult );
}
/* EOF timex20t.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -