⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 realtimeclock.c

📁 CIRRUS 公司EP93XX系列CPU的WINCE下的BSP
💻 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 + -