📄 rtc.c
字号:
// Copyright (c) David Vescovi. All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//
// File: rtc.c
//
// This module implements some RTC and time functions.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <pxa255.h>
//------------------------------------------------------------------------------
// Defines
//
#define ORIGINYEAR 1980
#define JAN1WEEK 2 /* Tuesday */
//------------------------------------------------------------------------------
// 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;
//------------------------------------------------------------------------------
// Externs
//
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
//
static unsigned int monthtable[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static unsigned int monthtable_leap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//------------------------------------------------------------------------------
// Local Functions
//
static UINT32 IsLeapYear(UINT32 Year)
{
UINT32 Leap;
Leap = 0;
if ((Year % 4) == 0)
{
Leap = 1;
if ((Year % 100) == 0)
{
Leap = (Year % 400) ? 0 : 1;
}
}
return(Leap);
}
static void FormatSystemTime(UINT32 CurrTime, LPSYSTEMTIME pSysTime)
{
UINT32 ms, sec, min, hour, day, month, year, leap;
UINT32 *mtbl;
ms = 0;
sec = CurrTime % 60;
min = (CurrTime / 60);
hour = (min / 60);
day = (hour / 24);
pSysTime->wMilliseconds = ms;
pSysTime->wSecond = sec;
pSysTime->wMinute = (min % 60);
pSysTime->wHour = (hour % 24);
pSysTime->wDayOfWeek = (day + JAN1WEEK) % 7;
year = ORIGINYEAR;
while (TRUE)
{
leap = IsLeapYear(year);
if (day < 365+leap)
break;
day -= 365+leap;
year++;
}
pSysTime->wYear = year;
mtbl = leap ? monthtable_leap : monthtable;
for (month=0; month<12; month++) {
if (day < mtbl[month])
break;
day -= mtbl[month];
}
pSysTime->wDay = day+1;
pSysTime->wMonth = month+1;
return;
}
static UINT32 ConvertSystemTime(LPSYSTEMTIME lpst)
{
UINT32 min, day, month, year;
UINT32 *mtbl;
day = 0;
for (year=ORIGINYEAR; year<lpst->wYear; year++) {
day += 365 + IsLeapYear(year);
}
mtbl = IsLeapYear(year) ? monthtable_leap : monthtable;
for (month=0; month<(unsigned int)(lpst->wMonth-1); month++) {
day += mtbl[month];
}
day += lpst->wDay - 1;
min = (day * 24 + lpst->wHour) * 60 + lpst->wMinute;
return(min * 60 + lpst->wSecond);
}
static BOOL IsSystemTimeStructValid(LPSYSTEMTIME pTime)
{
WORD dayCompare = 0;
if (!pTime)
{
return FALSE;
}
// Check the basic validity of the values that are passed in
if ((pTime->wYear > 4095))
{
return FALSE;
}
if ((pTime->wMonth > 12) || (pTime->wMonth == 0))
{
return FALSE;
}
if (!(pTime->wHour < 24))
{
return FALSE;
}
if (!(pTime->wMinute < 60))
{
return FALSE;
}
if (!(pTime->wSecond < 60))
{
return FALSE;
}
// SYSTEMTIME struct store the day of week starting
// at 0 while the hardware is expecting a 1.
if ((pTime->wDayOfWeek >= 7))
{
return FALSE;
}
// Calculate the day comparison value
if ((pTime->wMonth == 4) ||
(pTime->wMonth == 6) ||
(pTime->wMonth == 9) ||
(pTime->wMonth == 11))
{
dayCompare = 30;
}
else if (pTime->wMonth == 2)
{
dayCompare = (IsLeapYear(pTime->wYear)) ? 29:28;
}
else
{
dayCompare = 31;
}
// This should be checking for a wDay == 0 as an error
// but the documentation does not specify.
if ((pTime->wDay > dayCompare))
{
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: OEMGetRealTime
//
// Reads the current RTC value and returns a system time.
//
//------------------------------------------------------------------------------
BOOL OEMGetRealTime(LPSYSTEMTIME pSysTime)
{
volatile RTC_REG_T *pRTCRegs = (volatile RTC_REG_T *)OALPAtoVA(PXA255_BASE_REG_PA_RTC, FALSE);
UINT32 CurrTime = 0;
// Get the RTC value.
CurrTime = pRTCRegs->RCNR;
FormatSystemTime(CurrTime, pSysTime);
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: OEMSetRealTime
//
// Updates the RTC with the specified system time.
//
//------------------------------------------------------------------------------
BOOL OEMSetRealTime(LPSYSTEMTIME pTime)
{
BOOL retVal = FALSE;
volatile RTC_REG_T *pRTCRegs = (volatile RTC_REG_T *)OALPAtoVA(PXA255_BASE_REG_PA_RTC, FALSE);
if (!pTime) goto Done;
if (!IsSystemTimeStructValid(pTime)) goto Done;
// Set the RTC value.
pRTCRegs->RCNR = ConvertSystemTime(pTime);
retVal = TRUE;
Done:
return(retVal);
}
//------------------------------------------------------------------------------
//
// Function: OEMSetAlarmTime
//
// Sets the RTC alarm with the specified system time.
//
//------------------------------------------------------------------------------
BOOL OEMSetAlarmTime(LPSYSTEMTIME pTime)
{
BOOL retVal = FALSE;
volatile RTC_REG_T *pRTCRegs = (volatile RTC_REG_T *)OALPAtoVA(PXA255_BASE_REG_PA_RTC, FALSE);
volatile INTC_REG_T *pINTCRegs = (volatile INTC_REG_T *)OALPAtoVA(PXA255_BASE_REG_PA_INTC, FALSE);
if (!pTime) goto Done;
if (!IsSystemTimeStructValid(pTime)) goto Done;
// Set the Alarm value
pRTCRegs->RTAR = ConvertSystemTime(pTime);
// Clear any current RTC alarm interrupt
pRTCRegs->RTSR |= RTSR_AL;
// Enable the RTC alarm interrupt
pRTCRegs->RTSR |= RTSR_ALE;
// Enable the RTC alarm interrupt
pINTCRegs->ICMR |= INTC_RTCALARM;
retVal = TRUE;
Done:
return(retVal);
}
//------------------------------------------------------------------------------
//
// Function: OEMEthGetSecs
//
// Get number of seconds
//
//------------------------------------------------------------------------------
DWORD OEMEthGetSecs(void)
{
SYSTEMTIME st;
OEMGetRealTime( &st );
return((60UL * (60UL * (24UL * (31UL * st.wMonth + st.wDay) + st.wHour) + st.wMinute)) + st.wSecond);
}
//------------------------------------------------------------------------------
//
// Function: OALGetTickCount
//
// This function is called by some KITL libraries to obtain relative time
// since device boot. It is mostly used to implement timeout in network
// protocol.
//
//------------------------------------------------------------------------------
UINT32 OALGetTickCount()
{
return OEMEthGetSecs () * 1000;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -