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

📄 rtc.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//------------------------------------------------------------------------------
//
//  Module: rtc.c
//
//  Real-time clock (RTC) routines for the Intel Bulverde processor.
//
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <bulverde.h>
#include <pcf50606.h>
#include <power_i2c.h>

//------------------------------------------------------------------------------
// Unions to make it easier to extract bit fields from the 32 bit registers
//
typedef union DAY_REGISTER 
{
    UINT32 value;
    struct
    {
        unsigned seconds    : 6;
        unsigned minutes    : 6;
        unsigned hours      : 5;
        unsigned dayOfWeek  : 3;
        unsigned weekOfMonth: 3;
        unsigned reserved   : 9;
    };
} DayRegister;

typedef union YEAR_REGISTER
{
    UINT32 value;
    struct 
    {
        unsigned dayOfMonth : 5;
        unsigned month      : 4;
        unsigned year       : 12;
        unsigned reserved   : 11;
    };
} YearRegister;

BOOL g_fPI2CInitialized = FALSE;

//------------------------------------------------------------------------------
//
//  Function:  OEMGetRealTime
//
//  Reads the current RTC value and returns a system time.
//
BOOL OEMGetRealTime(LPSYSTEMTIME pTime)
{
    volatile BULVERDE_RTC_REG *pRTCRegs = (volatile BULVERDE_RTC_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_RTC, FALSE);
    DayRegister  dayReg;
    YearRegister yearReg;
    BOOL     retVal  = FALSE;
    WORD     seconds = 0;

    OALMSG(OAL_RTC&&OAL_FUNC, (L"+OEMGetRealTime(pTime = 0x%x)\r\n", pTime));
    if (!pTime) goto Done;

    do
    {
        // Get register values
        dayReg.value  = (UINT32)pRTCRegs->rdcr;
        seconds = dayReg.seconds;
        yearReg.value = (UINT32)pRTCRegs->rycr; 
    } while (seconds != (pRTCRegs->rdcr & 0x3F));

    // Fill in the SYSTEMTIME structure with the appropriate values
    pTime->wYear      = yearReg.year;
    pTime->wMonth     = yearReg.month;
    pTime->wDay       = yearReg.dayOfMonth;
    pTime->wDayOfWeek = dayReg.dayOfWeek - 1;   // Hardware is [1,7] Structure is [0,6]
    pTime->wHour      = dayReg.hours;
    pTime->wMinute    = dayReg.minutes;
    pTime->wSecond    = dayReg.seconds;
    pTime->wMilliseconds = 0;
    retVal = TRUE;

Done:
    OALMSG(OAL_RTC&&OAL_FUNC, (L"-OEMGetRealTime(retVal = %d)\r\n", retVal));
    return(retVal);
}

//------------------------------------------------------------------------------
//
//  Function:  OEMSetRealTime
//
//  Updates the RTC with the specified system time.
//
BOOL OEMSetRealTime(LPSYSTEMTIME pTime) 
{
    volatile BULVERDE_RTC_REG *pRTCRegs = (volatile BULVERDE_RTC_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_RTC, FALSE);
    BOOL         retVal = FALSE;
    DayRegister  dayReg;
    YearRegister yearReg;
    BOOL enabled;


    if (!pTime) goto Done;

    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
    ));

    dayReg.value = 0;
    yearReg.value = 0;
    #define RDCRBITSSET 0x000fffff  //RDCR register bits set by the code
    #define RYCRBITSSET 0x001fffff  //RYCR register bits set
    
    // Set up the format of the register variables
    yearReg.year        = pTime->wYear;
    yearReg.month       = pTime->wMonth;
    yearReg.dayOfMonth  = pTime->wDay;
    dayReg.dayOfWeek    = pTime->wDayOfWeek + 1;    // Hardware is [1,7] Structure is [0,6]
    dayReg.hours        = pTime->wHour;
    dayReg.minutes      = pTime->wMinute;
    dayReg.seconds      = pTime->wSecond;

    enabled = INTERRUPTS_ENABLE(FALSE);
    
    // Set the value in the RTC and be sure to write to the day register 
    // after the year...this will set the year register up properly.
    pRTCRegs->rycr = yearReg.value;
    pRTCRegs->rdcr = dayReg.value;
    // Wait for RDCR & RYCR update
    while(((pRTCRegs->rdcr & RDCRBITSSET) != dayReg.value) || ((pRTCRegs->rycr & RYCRBITSSET) != yearReg.value)) {
        pRTCRegs->rycr = yearReg.value;
        pRTCRegs->rdcr = dayReg.value;
    }

    INTERRUPTS_ENABLE(enabled);
    
    retVal         = TRUE;

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


//------------------------------------------------------------------------------
//
//  Function:  OEMSetAlarmTime
//
//  Set the RTC alarm time.
//
BOOL OEMSetAlarmTime(LPSYSTEMTIME pTime)
{
    volatile BULVERDE_RTC_REG *pRTCRegs = (volatile BULVERDE_RTC_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_RTC, FALSE);
    BOOL         retVal = FALSE;
    UINT32       irq;
    DayRegister  dayReg;
    YearRegister yearReg;
    BOOL enabled;


    if (!pTime) goto Done;

    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
    ));

    // Set up the format of the register variables
    yearReg.year        = pTime->wYear;
    yearReg.month       = pTime->wMonth;
    yearReg.dayOfMonth  = pTime->wDay;
    dayReg.dayOfWeek    = pTime->wDayOfWeek + 1;    // Hardware is [1,7] Structure is [0,6]
    dayReg.hours        = pTime->wHour;
    dayReg.minutes      = pTime->wMinute;
    dayReg.seconds      = pTime->wSecond;

    enabled = INTERRUPTS_ENABLE(FALSE);

    // Set the value in the RTC and be sure to write to the day register 
    // after the year...this will set the year register up properly.
    pRTCRegs->ryar1 = yearReg.value;
    pRTCRegs->rdar1 = dayReg.value;

    INTERRUPTS_ENABLE(enabled);

    retVal          = TRUE;


    // Enable the RTC wristwatch1 alarm
    // (this will also clear the RDAL1 bit if it is set)
    pRTCRegs->rtsr  |= XLLP_RTSR_RDALE1;

    // Enable the RTC alarm interrupt
    irq = IRQ_RTCALARM;
    OALIntrDoneIrqs(1, &irq);
    retVal = TRUE;

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


//------------------------------------------------------------------------------
//
//  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;
    UCHAR RTCRegs = {0};

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

    if(pOutSize) {
        *pOutSize = 0;
    }

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

    // Initialize Power I2C registers;
    //
    if (!g_fPI2CInitialized && !PI2CInit())
    {
        OALMSGS(1, (TEXT("OALIoCtlHalInitRTC: Failed to initialize Pi2c communication. Returning.\r\n")));
        goto cleanUp;
    }

    // Read the PMIC RTC to see if has a persisted value
    // A zero from the year register would mean that 
    // no value is not persisted
    RTCRegs = ReadPI2CRegister(RTCYR);
    if (RTCRegs == 0)
    {
        // No persisted RTC time, let's follow what kernel tells us
        rc = OEMSetRealTime(pTime);
    }
    else
    {
        rc = TRUE;
    }

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

⌨️ 快捷键说明

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