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

📄 rtc.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 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.
//
//------------------------------------------------------------------------------
//
//  File:  rtc.c
//
//  This file contains real time clock implementation base on TOY timer. 
//  The TOY timer is 32-bit timer so RTC time will roll over after cca 49 days.
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <oal.h>
#include <au1.h>

//------------------------------------------------------------------------------
//
//  Global:  g_rtcBase
//
static struct {
    UINT64 timeBase;
    UINT32 toyBase;
} g_rtc = {
    126858960000000000,
    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_TOYMATCH2);

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

//------------------------------------------------------------------------------
//
//  Function:  OEMSetRealTime
//
//  This function is called by the kernel to set the real-time clock.
//
BOOL OEMSetRealTime(SYSTEMTIME *pTime)
{
    BOOL rc = FALSE;
    AU1_SYS_REGS *pSysRegs = OALPAtoUA(AU1_SYS_REGS_PA);
    ULARGE_INTEGER time;
    FILETIME fileTime;

    // First check for possible invalid argument
    if (pTime == NULL) 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;

            g_rtc.timeBase = time.QuadPart; 
            g_rtc.toyBase = INREG32(&pSysRegs->TOYREAD);
        }
    }
    
cleanUp:    
    OALMSG(OAL_RTC&&OAL_FUNC, (L"-OEMSetRealTime(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. Implementation for Au1 assumes 32.768 kHz crystal
//  and it uses TOY timer as RTC. It is assumed that TOY timer has prescaler
//  set to 33.
//
BOOL OEMGetRealTime(SYSTEMTIME *pTime)
{
    BOOL rc = FALSE;
    AU1_SYS_REGS *pSysRegs = OALPAtoUA(AU1_SYS_REGS_PA);
    UINT32 toyValue, toyDelta;
    ULARGE_INTEGER time;
    FILETIME fileTime;

    OALMSG(OAL_RTC&&OAL_FUNC, (L"+OEMGetRealTime(0x%08x)\r\n", pTime));

    // First check for possible invalid argument
    if (pTime == NULL) goto cleanUp;

    // Calculate how much time passed since last update
    toyValue = INREG32(&pSysRegs->TOYREAD);
    toyDelta = toyValue - g_rtc.toyBase;

    // Calculate new time
    time.QuadPart = ((LONGLONG)toyDelta*10000*33000)/32768 + g_rtc.timeBase;

    // Update base values if delta is large enough
    if (toyDelta > 0x10000000) {
        g_rtc.timeBase = time.QuadPart;
        g_rtc.toyBase = toyValue;
    }        

    // Convert time to SYSTEMTIME format    
    fileTime.dwLowDateTime = time.LowPart;
    fileTime.dwHighDateTime = time.HighPart;
    if(KFileTimeToSystemTime)
    {
        if((rc = KFileTimeToSystemTime(&fileTime, pTime)))
        {
            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:  OEMSetAlarmTime
//
//  This function is called by the kernel to set the real-time clock alarm.
//  Implementation for Au1 uses TOYMATCH2 register for alarm. 
//
BOOL OEMSetAlarmTime(SYSTEMTIME *pTime)
{
    BOOL rc = FALSE;
    AU1_SYS_REGS *pSysRegs = OALPAtoUA(AU1_SYS_REGS_PA);
    ULARGE_INTEGER time;
    FILETIME fileTime;
    UINT32 toyMatch, toyValue, toyDelta;
    UINT32 irq;

    // First check for possible invalid argument
    if (pTime == NULL) 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
    ));

    // Calculate how much time passed since last update
    toyValue = INREG32(&pSysRegs->TOYREAD);
    toyDelta = toyValue - g_rtc.toyBase;

    // Calculate new time
    time.QuadPart = ((LONGLONG)toyDelta*10000*33000)/32768 + g_rtc.timeBase;

    // Update base values
    g_rtc.timeBase = time.QuadPart;
    g_rtc.toyBase = toyValue;

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

            // Calculate delta
            time.QuadPart -= g_rtc.timeBase;
            time.QuadPart = (time.QuadPart * 32768)/(33000*10000);

            if (time.HighPart > 0) time.LowPart = 0xFFFF;
            toyMatch = g_rtc.toyBase + time.LowPart;

            // Set it to hardware
            OUTREG32(&pSysRegs->TOYMATCH2, toyMatch);

            // Enable interrupt
            irq = IRQ_TOYMATCH2;
            OALIntrEnableIrqs(1, &irq);
        }
    }

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

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

⌨️ 快捷键说明

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