📄 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>
#include <debugtimer.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)
//#define TICKS_TO_NANO_CHUNKS( time ) (time)*=10*17/100;
#define TICKS_TO_NANO_CHUNKS( time ) (time)*=1302; (time)=(time)>>7
//#define TICKS_TO_NANO_CHUNKS( time ) (time)*=10*11; (time)=(time)>>6
//
// 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
#define EE_DELAY_USEC 5
#define EE_READ_TIMEOUT 500
#define WRITE_ADDRESS 0xA2
#define READ_ADDRESS 0xA3
#define YEAR_REGISTER 8
#define MONTH_REGISTER 7
#define DAY_REGISTER 5
#define HOUR_REGISTER 4
#define MINUTE_REGISTER 3
#define SECOND_REGISTER 2
#define START_YEAR_VALUE 1950
#define YEAR_ADJUST_VALUE 30
#define NUMBER 1
UINT BcdToHex(UINT uiData);
UINT HexToBcd(UINT uiData);
static INT WriteI2CReg(UCHAR ucRegAddr, UCHAR *ucRegValue, INT nbytes);
static INT ReadI2CReg(UCHAR ucRegAddr, UCHAR *buffer, INT nbytes);
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;
UCHAR uiTemp;
UINT i,wC;
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 ) );
for(i=0;i<300;i++)
{
DelayInuSec(10);
ReadI2CReg(SECOND_REGISTER,&uiTemp,NUMBER);
uiTemp &= 0x7f;
curSysTime.wSecond = BcdToHex((UINT)(uiTemp));
DelayInuSec(10);
ReadI2CReg(MINUTE_REGISTER,&uiTemp,NUMBER);
uiTemp &= 0x7f;
curSysTime.wMinute = BcdToHex((UINT)(uiTemp));
DelayInuSec(10);
ReadI2CReg(HOUR_REGISTER,&uiTemp,NUMBER);
uiTemp &= 0x3f;
curSysTime.wHour = BcdToHex((UINT)(uiTemp));
DelayInuSec(10);
ReadI2CReg(DAY_REGISTER,&uiTemp,NUMBER);
uiTemp &= 0x3f;
curSysTime.wDay = BcdToHex((UINT)(uiTemp));
DelayInuSec(10);
ReadI2CReg(MONTH_REGISTER,&uiTemp,NUMBER);
if(uiTemp & 0x80)
wC = 1900;
else
wC = 2000;
uiTemp &= 0x1f;
curSysTime.wMonth = BcdToHex((UINT)(uiTemp));
DelayInuSec(10);
ReadI2CReg(YEAR_REGISTER,&uiTemp,NUMBER);
curSysTime.wYear = BcdToHex((UINT)(uiTemp)) + wC;
if(curSysTime.wYear > 1900)
break;
}
// 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;
//UCHAR uiTemp;
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;
UCHAR uiTemp;
static volatile BOOL noHAL_INIT_RTC = TRUE;
if (noHAL_INIT_RTC)
{
noHAL_INIT_RTC = FALSE ;
return TRUE ;
}
if (gfInitRTC)
{
// Setup the software RTC...
initRTC();
}
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)lpst->wMonth);
if(lpst->wYear < 2000)
uiTemp |= 0x80;
WriteI2CReg(MONTH_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)lpst->wDay);
WriteI2CReg(DAY_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)(lpst->wYear%100));
WriteI2CReg(YEAR_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)lpst->wHour);
WriteI2CReg(HOUR_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)lpst->wMinute);
WriteI2CReg(MINUTE_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
uiTemp = (UCHAR)HexToBcd((UINT)lpst->wSecond);
WriteI2CReg(SECOND_REGISTER,&uiTemp,NUMBER);
DelayInuSec(80);
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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -