📄 rtc.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 + -