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

📄 rtc.c

📁 NXP LPC3000系列 wince BSP包
💻 C
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only  
//* which provides customers with programming information regarding the  
//* products. This software is supplied "AS IS" without any warranties.  
//* NXP Semiconductors assumes no responsibility or liability for the 
//* use of the software, conveys no license or title under any patent, 
//* copyright, or mask work right to the product. NXP Semiconductors 
//* reserves the right to make changes in the software without 
//* notification. NXP Semiconductors also make no representation or 
//* warranty that such application will be suitable for the specified 
//* use without further testing or modification. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// rtc.c
//
// The RTC is implemented with 2 peripherals. The RTC peripheral block stores
// a 1-second count of persistent system time (across power cycles). The RTC
// alarm function is also implemented with the RTC with a 1-second granularity.
// The high resolution system time functions are implemented with a standard
// timer which is setup from the RTC when WinCE is cold or warm booted. The
// standard timer is not connected to an interrupt, but is configured to be
// queried by clock functions. The IOCTL_HAL_INIT_RTC IOCTL isn't needed with
// this method, but the OEMSetupRTC() function needs to be called as part of
// OEMInit().
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <oal.h>

#include "bsp.h"
#include "lpc32xx_rtc.h"
#include "lpc32xx_timer.h"
#include "clkpwr_support.h"

// Pointer to timer block (used for RTC control)
static TIMER_CNTR_REGS_T *pTMR;
static RTC_REGS_T *pRTC;

// Time base used for high reolution conversion
static UINT32 tickspersec;

// Estimated base year used for clock/calaneder offset, trying to set
// a time less than this date will fail.
#define BASEDATE 2000

// FILETIME base offset used for local time conversion (in mS) for 1970
static ULARGE_INTEGER btime;

//------------------------------------------------------------------------------
//
// OEMSetupRTC
//
// This function is called from the OEMInit to initialize the WinCE RTC and
// system time functions. It must be called prior to any system time or RTC
// based functions being called.
//
BOOL OEMSetupRTC(VOID)
{
	SYSTEMTIME systime;
	FILETIME ftime;
	BOOL rc = FALSE;

    OALMSG(OAL_FUNC, (L"+OEMSetupRTC\r\n"));

	// Enable clock for this block
	clkpwr_clk_en_dis(CLKPWR_TIMER1_CLK, TRUE);

	// Get pointer to RTC and timer register blocks
	pTMR = (TIMER_CNTR_REGS_T *) OALPAtoVA((UINT32) TIMER_CNTR1, FALSE);
	pRTC = (RTC_REGS_T *) OALPAtoVA((UINT32) RTC, FALSE);

	// Setup timer
	pTMR->tcr = 0;
	pTMR->ir = TIMER_CNTR_MTCH_BIT(0);
	pTMR->mr [0] = 0;
	pTMR->mcr = 0;
	pTMR->pc = 0;

	// Get base clock for the timer
	tickspersec = clkpwr_get_base_clock_rate(CLKPWR_PERIPH_CLK);

	// A 1 second tick rate with a high reolution count
	pTMR->pr = tickspersec;

	// Examine the RTC ONSW load value. If it is incorrect, reset the RTC
	// to it's base time and disable any alarms
	if (pRTC->key != RTC_KEY_ONSW_LOADVAL)
	{
		pRTC->ctrl = RTC_CNTR_DIS;
		pRTC->ucount = 0;
		pRTC->dcount = 0xFFFFFFFF;
		pRTC->intstat = (RTC_MATCH0_INT_STS | RTC_MATCH1_INT_STS |
			RTC_ONSW_INT_STS);
		pRTC->match0 = 0xFFFFFFFF;
		pRTC->ctrl = RTC_MATCH0_EN;
		pRTC->key = RTC_KEY_ONSW_LOADVAL;
	}

	// Transfer current RTC count to timer count
	pTMR->tc = pRTC->ucount;

	// Enable timer
	pTMR->tcr = TIMER_CNTR_TCR_EN;

	// Get base time for clock
	systime.wYear = 2000;
	systime.wMonth = 1;
	systime.wDayOfWeek = 1;
	systime.wDay = 1;
	systime.wHour = 1;
	systime.wMinute = 0;
	systime.wSecond = 0;
	systime.wMilliseconds = 0;
	rc = NKSystemTimeToFileTime(&systime, &ftime);
	btime.LowPart = ftime.dwLowDateTime;
	btime.HighPart = ftime.dwHighDateTime;

	OALMSG(OAL_FUNC, (L"-OEMSetupRTC (rx = %d))\r\n", rc));
	return rc;
}

//------------------------------------------------------------------------------
//
// OEMGetRealTime
//
// Retrieve the system time
//
BOOL OEMGetRealTime(LPSYSTEMTIME lpst)
{
    BOOL rc = FALSE;
    ULARGE_INTEGER time;
    FILETIME fileTime;
	UINT32 psc1, psc2, tc;

    OALMSG(OAL_FUNC, (L"-OEMGetRealTime\r\n"));

	// If the prescaler overflowed during the timer count read, read it again
	psc1 = 1;
	psc2 = 0;
	while (psc2 < psc1)
	{
		// Handle timer overflow
		psc1 = pTMR->pc;
		tc = pTMR->tc;
		psc2 = pTMR->pc;
	}

	// The tc and psc1 contain the time offset from FTOFFS
	// Computet Millisecond offset
	time.LowPart = (DWORD) psc1;
	time.HighPart = 0;
	time.QuadPart = (time.QuadPart * 1000) / (UINT64) tickspersec;

	// Add in second offset
	time.QuadPart = time.QuadPart + (((UINT64) tc) * 1000);

	// Adjust for 100nS base
	time.QuadPart = time.QuadPart * 10000;

	// Adjust for local date offset
	time.QuadPart = time.QuadPart + btime.QuadPart;

	// Convert to system time
	fileTime.dwLowDateTime = time.LowPart;
	fileTime.dwHighDateTime = time.HighPart;
	rc = NKFileTimeToSystemTime(&fileTime, lpst);
    if(rc == TRUE)
    {
        OALMSG(OAL_FUNC, (
            L"-OEMGetRealTime(rc = %d %d/%d/%d %d:%d:%d.%03d)\r\n", rc, 
            lpst->wYear, lpst->wMonth, lpst->wDay, lpst->wHour, lpst->wMinute,
            lpst->wSecond, lpst->wMilliseconds));
    }

	return rc;
}

//------------------------------------------------------------------------------
//
// OEMSetRealTime
//
// Set the system time (Real time clock)
//
BOOL OEMSetRealTime(LPSYSTEMTIME lpst)
{
    BOOL rc = FALSE;
    ULARGE_INTEGER time, lsecs, lnsecs;
    FILETIME fileTime;
	UINT32 secs, nsecs;

    if(lpst != NULL)
	{
	    OALMSG(OAL_FUNC, (
		    L"+OEMSetRealTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
			lpst->wYear, lpst->wMonth, lpst->wDay, lpst->wHour, lpst->wMinute,
	        lpst->wSecond, lpst->wMilliseconds));
    
		if (lpst->wYear >= BASEDATE)
		{
			rc = NKSystemTimeToFileTime(lpst, &fileTime);
		}
	    if (rc != FALSE)
	    {
			// Get number of nS since Jan 1, 1601
	        time.LowPart = fileTime.dwLowDateTime;
		    time.HighPart = fileTime.dwHighDateTime;

			// Bias milliseconds to get in 32-bit range
			time.QuadPart = time.QuadPart - btime.QuadPart;

			// Break time in nS and Second parts
			lsecs.QuadPart = time.QuadPart / 10000000;
			lnsecs.QuadPart = time.QuadPart - (lsecs.QuadPart * 10000000);

			// Computed offsets
			secs = (UINT32) lsecs.QuadPart;
			time.QuadPart = (lnsecs.QuadPart * (UINT64) tickspersec) / 10000000;
			nsecs = (UINT32) time.QuadPart;

			// Get computed offset times for timer
			pTMR->tcr = 0;
			pTMR->tc = (UINT32) secs;
			pTMR->pc = nsecs;
			pTMR->tcr = TIMER_CNTR_TCR_EN;

			// Set RTC to new time
			pRTC->ctrl = RTC_CNTR_DIS;
			pRTC->ucount = (UINT32) secs;
			pRTC->dcount = (0xFFFFFFFF - (UINT32) secs);
			pRTC->ctrl = RTC_MATCH0_EN;
	    }
	}

    OALMSG(OAL_RTC&&OAL_FUNC, (L"-OEMSetRealTime(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
// OEMSetAlarmTime
//
// Set the alarm time
//
BOOL OEMSetAlarmTime(LPSYSTEMTIME lpst)
{
    BOOL rc = FALSE;
    ULARGE_INTEGER time;
    FILETIME fileTime;

	// Convert to seconds
    if(lpst != NULL)
	{
	    OALMSG(OAL_FUNC, (
		    L"+OEMSetAlarmTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
			lpst->wYear, lpst->wMonth, lpst->wDay, lpst->wHour, lpst->wMinute,
	        lpst->wSecond, lpst->wMilliseconds));
    
		rc = NKSystemTimeToFileTime(lpst, &fileTime);
	    if (rc != FALSE)
	    {
			// Get number of nS since Jan 1, 1601
	        time.LowPart = fileTime.dwLowDateTime;
		    time.HighPart = fileTime.dwHighDateTime;

			// Bias milliseconds to get in 32-bit range
			time.QuadPart = time.QuadPart - btime.QuadPart;

			// Get seconds
			time.QuadPart = time.QuadPart / 10000000;

			// Set RTC alarm time
			pRTC->match0 = (UINT32) time.QuadPart;
		}
	}

    OALMSG(OAL_FUNC, (L"-OEMSetAlarmTime(rc = %d)\r\n", rc));
	return rc;
}

//------------------------------------------------------------------------------
//
// 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.
//
BOOL OALIoCtlHalInitRTC(
    UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer, 
    UINT32 outSize, UINT32 *pOutSize
) {
    BOOL rc = FALSE;
    SYSTEMTIME *pTime = (SYSTEMTIME *) pInpBuffer;
	pRTC = (RTC_REGS_T *) OALPAtoVA((UINT32) RTC, FALSE);

    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalInitRTC(...)\r\n"));

    if (pOutSize) {
        *pOutSize = 0;
    }

	// Validate inputs
    if (pInpBuffer == NULL || inpSize < sizeof(SYSTEMTIME)) {
        NKSetLastError(ERROR_INVALID_PARAMETER);
        OALMSG(OAL_ERROR, (
            L"ERROR: OALIoCtlHalInitRTC: Invalid parameter\r\n"
        ));
        goto cleanUp;
    }

	if (pRTC->key != RTC_KEY_ONSW_LOADVAL)
	{
	    rc = OEMSetupRTC();
	    rc &= OEMSetRealTime(pTime);
	}
    
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 + -