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

📄 rtc.c

📁 老外的一个开源项目
💻 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 + -