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

📄 rtc.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 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 + -