rtc.c

来自「Windows CE 6.0 BSP for VOIPAC Board (PXA」· C语言 代码 · 共 264 行

C
264
字号
//
// 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.
//
//------------------------------------------------------------------------------
//
//  File:  rtc.c
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include <vr4131.h>


//------------------------------------------------------------------------------
//
//  Type:  VR4131_RTC
//
//  Structure is used to simplify conversion from hardware to OS time format.
//
#include <packon.h>

typedef union {
    struct {
        UINT16 l;
        UINT16 m;
        UINT16 h;
        UINT16 x;
    };
    UINT64 v;
} VR4131_RTC;

#include <packoff.h>

//------------------------------------------------------------------------------
//
//  Local:  g_rtcBase
//
static UINT64 g_rtcBase = 0;


//------------------------------------------------------------------------------
//
//  Function:  OALIoCtlHalInitRTC
//
//  This function is called by WinCE OS to initialize the time after boot.
//  Input buffer contains SYSTEMTIME structure with default time value.
//  If hardware has persistent real time clock it will ignore this value
//  (or all call).
//
BOOL OALIoCtlHalInitRTC(
    UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer, 
    UINT32 outSize, UINT32 *pOutSize
) {
    BOOL rc = FALSE;
    SYSTEMTIME *pTime = (SYSTEMTIME*)pInpBuffer;

    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalInitRTC(...)\r\n"));

    // Validate inputs
    if (pInpBuffer == NULL || inpSize < sizeof(SYSTEMTIME)) {
        OALMSG(OAL_ERROR, (L"ERROR:OALIoCtlHalInitRTC: INVALID PARAMETER\r\n"));
        goto cleanUp;
    }

    // Add static mapping for RTC alarm
    OALIntrStaticTranslate(SYSINTR_RTC_ALARM, IRQ_ETIMER);

    // And enable it (it will not occur until it is set in OEMSetAlarmTime)
    OEMInterruptEnable(SYSINTR_RTC_ALARM, NULL, 0);

    rc = OEMSetRealTime(pTime);
    
cleanUp:
    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OALIoCtlHalInitRTC(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OEMGetRealTime
//
//  This function is called by the kernel to retrieve the time from
//  the real-time clock.
//
BOOL OEMGetRealTime(SYSTEMTIME *pTime) 
{
    BOOL rc = FALSE;
    VR4131_RTCU_REGS *pRTCRegs;
    VR4131_RTC t;
    ULARGE_INTEGER time;
    FILETIME fileTime;

    OALMSG(OAL_RTC&&OAL_FUNC, (L"+OEMGetRealTime\r\n"));

    if(!pTime) goto cleanUp;

    // Get virtual address
    pRTCRegs = OALPAtoUA(VR4131_REG_PA_RTCU);

    t.v = 0;

    do {
        t.l = INREG16(&pRTCRegs->ETIMEL);
        t.m = INREG16(&pRTCRegs->ETIMEM); 
        t.h = INREG16(&pRTCRegs->ETIMEH);
    } while (t.l !=INREG16(&pRTCRegs->ETIMEL));

    time.QuadPart = (t.v * 10000000)/32768 + g_rtcBase;
    fileTime.dwLowDateTime = time.LowPart;
    fileTime.dwHighDateTime = time.HighPart;
    if(KFileTimeToSystemTime)
    {
        if((rc = KFileTimeToSystemTime(&fileTime, pTime)))
        {
            #if 0
            OALLog(
                L"OEMGetRealTime: %04x:%04x:%04x base: %08x:%08x time: %08x:%08x\r\n",
                t.h, t.m, t.l, (UINT32)(g_rtcBase >> 16), (UINT16)g_rtcBase,
                time.HighPart, time.LowPart
            );
            #endif

            OALMSG(OAL_RTC&&OAL_FUNC, (
                L"-OEMGetRealTime(rc = %d, %d/%d/%d %d:%d:%d.%03d)\r\n", rc, 
                pTime->wYear, pTime->wMonth, pTime->wDay, pTime->wHour, pTime->wMinute,
                pTime->wSecond, pTime->wMilliseconds
            ));
        }
    }


cleanUp:
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:     OEMSetRealTime
//
//  This function is called by the kernel to set the real-time clock.
//

BOOL OEMSetRealTime(SYSTEMTIME *pTime) 
{
    VR4131_RTCU_REGS *pRTCRegs;
    VR4131_RTC t;
    ULARGE_INTEGER time;
    FILETIME fileTime;
    BOOL rc = FALSE;

    if(!pTime) goto cleanUp;

    OALMSG(OAL_RTC&&OAL_FUNC, (
        L"+OEMSetRealTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
        pTime->wYear, pTime->wMonth, pTime->wDay, pTime->wHour, pTime->wMinute,
        pTime->wSecond, pTime->wMilliseconds
    ));

    if(KSystemTimeToFileTime)
    {
        if((rc = KSystemTimeToFileTime(pTime, &fileTime)))
        {
            time.LowPart = fileTime.dwLowDateTime;
            time.HighPart = fileTime.dwHighDateTime;

           // Get virtual address
            pRTCRegs = OALPAtoUA(VR4131_REG_PA_RTCU);

            t.v = 0;
            do {
                t.h = INREG16(&pRTCRegs->ETIMEH);
                t.m = INREG16(&pRTCRegs->ETIMEM);
                t.l = INREG16(&pRTCRegs->ETIMEL);
            } while (
                t.m != INREG16(&pRTCRegs->ETIMEM) || t.h != INREG16(&pRTCRegs->ETIMEH)
            );

            time.QuadPart -= (t.v * 10000000)/32768;
            g_rtcBase = time.QuadPart; 

        #if 0
           OALLog(
                L"OEMGetRealTime: %04x:%04x:%04x base: %08x:%08x time: %08x:%08x\r\n",
                t.h, t.m, t.l, (UINT32)(g_rtcBase >> 16), (UINT16)g_rtcBase,
                time.HighPart, time.LowPart
            );
        #endif
        }
    }

cleanUp:
    OALMSG(OAL_RTC&&OAL_FUNC, (L"-OEMSetRealTime(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OEMSetAlarmTime
//
//  This function is called by the kernel to set the real-time clock alarm.
//
BOOL OEMSetAlarmTime(SYSTEMTIME *pTime) 
{
    BOOL rc = FALSE;
    VR4131_RTCU_REGS *pRTCRegs;
    VR4131_RTC t;
    ULARGE_INTEGER time;
    FILETIME fileTime;

    if(!pTime) goto cleanUp;

    OALMSG(OAL_RTC&&OAL_FUNC, (
        L"+OEMSetAlarmTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
        pTime->wYear, pTime->wMonth, pTime->wDay, pTime->wHour, pTime->wMinute,
        pTime->wSecond, pTime->wMilliseconds
    ));
    
    if(KSystemTimeToFileTime)
    {
        if((rc = KSystemTimeToFileTime(pTime, &fileTime)))
        {
            time.LowPart = fileTime.dwLowDateTime;
            time.HighPart = fileTime.dwHighDateTime;
            time.QuadPart -= g_rtcBase;

            t.v = (time.QuadPart * 32768)/10000000;

            // Get virtual address
            pRTCRegs = OALPAtoUA(VR4131_REG_PA_RTCU);

            OALMSG(FALSE, (
                L" %04x:%04x:%04x -- %04x:%04x:%04x\r\n", INREG16(&pRTCRegs->ETIMEH),
                INREG16(&pRTCRegs->ETIMEM), INREG16(&pRTCRegs->ETIMEL), t.h, t.m, t.l
            ));
    
            // Set hardware    
            OUTREG16(&pRTCRegs->ECMPH, t.h);
            OUTREG16(&pRTCRegs->ECMPM, t.m);
            OUTREG16(&pRTCRegs->ECMPL, t.l);

            // Re-enable interrupt (it is disabled since last alarm occurs)
            OEMInterruptDone(SYSINTR_RTC_ALARM);
        }
    }

cleanUp:
    OALMSG(OAL_RTC&&OAL_FUNC, (L"-OEMSetAlarmTime(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?