📄 rtc.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
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include <omap730.h>
//------------------------------------------------------------------------------
// Defines
#define BCD2BIN(b) (((b) >> 4)*10 + ((b)&0xF))
#define BIN2BCD(b) ((((UINT8)(b)/10) << 4)|((UINT8)(b)%10))
//------------------------------------------------------------------------------
//
// External: g_oalRtcResetTime
//
// RTC init time after a RTC reset has occured. It should
// be defined in platform code.
extern SYSTEMTIME g_oalRtcResetTime;
//------------------------------------------------------------------------------
// Local Variables
static OMAP730_RTC_REGS *g_pRTCRegs = NULL;
//------------------------------------------------------------------------------
//
// 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;
UINT8 stat;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalInitRTC(...)\r\n"));
// Initialize virtual address pointer
if (g_pRTCRegs == NULL) g_pRTCRegs = OALPAtoUA(OMAP730_RTC_REGS_PA);
// Initialize the control register.
OUTREG8(&g_pRTCRegs->CTRL, 0);
// Wait until RUN is active
while ((INREG8(&g_pRTCRegs->STAT) & RTC_STAT_RUN) != 0);
// Initialize interrupt register
OUTREG8(&g_pRTCRegs->INTR, 0);
// Save reset status
stat = INREG8(&g_pRTCRegs->STAT);
// Clear power up status and alarm interrupt
OUTREG8(&g_pRTCRegs->STAT, RTC_STAT_ALARM|RTC_STAT_RESET);
// Start the RTC
SETREG8(&g_pRTCRegs->CTRL, RTC_CTRL_RUN);
rc = TRUE;
// Set time defined in platform only once after powerup
if ((stat & RTC_STAT_RESET) == RTC_STAT_RESET)
rc = OEMSetRealTime(&g_oalRtcResetTime);
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;
BOOL enabled;
UINT8 year, month, dweek, day, hour, min, sec;
OALMSG(OAL_RTC&&OAL_FUNC, (L"+OEMGetRealTime\r\n"));
if (!pTime) goto cleanUp;
// Initialize virtual address pointer
if (g_pRTCRegs == NULL) g_pRTCRegs = OALPAtoUA(OMAP730_RTC_REGS_PA);
// Disable interrupts when registers are read
enabled = INTERRUPTS_ENABLE(FALSE);
// Wait for BUSY low. Anytime BUSY is low, there is
// at least 15us to carry out the R/W.
while ((INREG8(&g_pRTCRegs->STAT) & RTC_STAT_BUSY) != 0);
// Read RTC time registers
year = INREG8(&g_pRTCRegs->YEAR);
month = INREG8(&g_pRTCRegs->MONTH);
dweek = INREG8(&g_pRTCRegs->WEEKDAY);
day = INREG8(&g_pRTCRegs->DAY);
hour = INREG8(&g_pRTCRegs->HOURS);
min = INREG8(&g_pRTCRegs->MINS);
sec = INREG8(&g_pRTCRegs->SECS);
// Enable interrupts
INTERRUPTS_ENABLE(enabled);
// Convert from RTC Binary Coded Decimal to SYSTEMTIME and store.
pTime->wYear = BCD2BIN(year);
pTime->wYear += (pTime->wYear < 80 ? 2000 : 1900);
pTime->wMonth = BCD2BIN(month);
pTime->wDayOfWeek = BCD2BIN(dweek);
pTime->wDay = BCD2BIN(day);
pTime->wHour = BCD2BIN(hour);
pTime->wMinute = BCD2BIN(min);
pTime->wSecond = BCD2BIN(sec);
pTime->wMilliseconds = 0;
rc = TRUE;
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)
{
BOOL rc = FALSE;
BOOL enabled;
UINT8 year, month, dweek, day, hour, min, sec;
WORD wYear;
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
));
// Initialize virtual address pointer
if (g_pRTCRegs == NULL) g_pRTCRegs = OALPAtoUA(OMAP730_RTC_REGS_PA);
// Limit and convert from SYSTEMTIME structure to BCD
wYear = pTime->wYear;
if (wYear < 1980)
wYear = 80;
else if (wYear < 2000)
wYear -= 1900;
else if (wYear < 2080)
wYear -= 2000;
else
wYear = 79;
year = BIN2BCD(wYear);
month = BIN2BCD(pTime->wMonth);
dweek = BIN2BCD(pTime->wDayOfWeek);
day = BIN2BCD(pTime->wDay);
hour = BIN2BCD(pTime->wHour);
min = BIN2BCD(pTime->wMinute);
sec = BIN2BCD(pTime->wSecond);
// Disable interrupts when registers are written
enabled = INTERRUPTS_ENABLE(FALSE);
// Wait for BUSY low. Anytime BUSY is low, there is
// at least 15us to carry out the R/W.
while ((INREG8(&g_pRTCRegs->STAT) & RTC_STAT_BUSY) != 0);
// Write RTC time registers.
OUTREG8(&g_pRTCRegs->YEAR, year);
OUTREG8(&g_pRTCRegs->MONTH, month);
OUTREG8(&g_pRTCRegs->WEEKDAY, dweek);
OUTREG8(&g_pRTCRegs->DAY, day);
OUTREG8(&g_pRTCRegs->HOURS, hour);
OUTREG8(&g_pRTCRegs->MINS, min);
OUTREG8(&g_pRTCRegs->SECS, sec);
// Enable interrupts
INTERRUPTS_ENABLE(enabled);
rc = TRUE;
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;
BOOL enabled;
UINT8 year, month, day, hour, min, sec;
OMAP730_RTC_REGS *pRTCRegs = g_pRTCRegs;
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
));
// Get virtual address
if (g_pRTCRegs == NULL)
g_pRTCRegs = OALPAtoUA(OMAP730_RTC_REGS_PA);
// Limit and convert from SYSTEMTIME structure to BCD
if (pTime->wYear < 1980)
pTime->wYear = 80;
else if (pTime->wYear < 2000)
pTime->wYear -= 1900;
else if (pTime->wYear < 2080)
pTime->wYear -= 2000;
else
pTime->wYear = 79;
year = BIN2BCD(pTime->wYear);
month = BIN2BCD(pTime->wMonth);
day = BIN2BCD(pTime->wDay);
hour = BIN2BCD(pTime->wHour);
min = BIN2BCD(pTime->wMinute);
sec = BIN2BCD(pTime->wSecond);
// Reset interrupt
OUTREG8(&g_pRTCRegs->STAT, RTC_STAT_ALARM);
// Disable alarm interrupt for while
CLRREG8(&g_pRTCRegs->INTR, RTC_INTR_ALARM);
// Disable interrupts when registers are written
enabled = INTERRUPTS_ENABLE(FALSE);
// Wait for BUSY low. Anytime BUSY is low, there is
// at least 15us to carry out the R/W.
while ((INREG8(&g_pRTCRegs->STAT) & RTC_STAT_BUSY) != 0);
// Write RTC time registers.
OUTREG8(&g_pRTCRegs->ALARM_YEAR, year);
OUTREG8(&g_pRTCRegs->ALARM_MONTH, month);
OUTREG8(&g_pRTCRegs->ALARM_DAY, day);
OUTREG8(&g_pRTCRegs->ALARM_HOURS, hour);
OUTREG8(&g_pRTCRegs->ALARM_MINS, min);
OUTREG8(&g_pRTCRegs->ALARM_SECS, sec);
// Re-enable alarm interrupt
SETREG8(&g_pRTCRegs->INTR, RTC_INTR_ALARM);
// Enable interrupts
INTERRUPTS_ENABLE(enabled);
// Re-enable interrupt (it is disabled since last alarm occurs)
OEMInterruptDone(SYSINTR_RTC_ALARM);
rc = TRUE;
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 + -