Files
hpw421/component/osal/osal/common/OSAL_Clock.c
T
2026-07-03 18:08:25 +08:00

369 lines
9.3 KiB
C

/*!
* \file OSAL_Clock.c
*
* \brief Target xc6xxx hal spi implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*********************************************************************
* INCLUDES
*/
#include "comdef.h"
#include "hal_board.h"
#include "OnBoard.h"
#include "OSAL.h"
#include "OSAL_Clock.h"
/*********************************************************************
* MACROS
*/
#define YearLength(yr) ((uint16)(IsLeapYear(yr) ? 366 : 365))
/*********************************************************************
* CONSTANTS
*/
// (MAXCALCTICKS * 5) + (max remainder) must be <= (uint16 max),
// so: (13105 * 5) + 7 <= 65535
#define MAXCALCTICKS ((uint16)(13105))
#define BEGYEAR 2000 // UTC started at 00:00:00 January 1, 2000
#define DAY 86400UL // 24 hours * 60 minutes * 60 seconds
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
extern uint32 getMcuPrecisionCount(void);
#define CONVERT_MS_TO_S_ELAPSED_REMAINDER( x, y, z ) st( \
y += x / 1000; \
z = x % 1000; \
)
/*********************************************************************
* LOCAL VARIABLES
*/
#ifndef USE_ICALL
static uint32 previousMacTimerTick = 0;
static uint16 remUsTicks = 0;
#endif /* !USE_ICALL */
static uint32 timeMSec = 0;
// number of seconds since 0 hrs, 0 minutes, 0 seconds, on the
// 1st of January 2000 UTC
UTCTime OSAL_timeSeconds = 0;
/*********************************************************************
* LOCAL FUNCTION PROTOTYPES
*/
static uint8 monthLength( uint8 lpyr, uint8 mon );
static void osalClockUpdate( uint32 elapsedMSec );
/*********************************************************************
* FUNCTIONS
*********************************************************************/
/*********************************************************************
* @fn osalTimeUpdate
*
* @brief Uses the free running rollover count of the MAC backoff timer;
* this timer runs freely with a constant 320 usec interval. The
* count of 320-usec ticks is converted to msecs and used to update
* the OSAL clock and Timers by invoking osalClockUpdate() and
* osalTimerUpdate(). This function is intended to be invoked
* from the background, not interrupt level.
*
* @param None.
*
* @return None.
*/
void osalTimeUpdate( void )
{
#ifndef USE_ICALL
/* Note that when ICall is in use the OSAL tick is not updated
* in this fashion but rather through real OS timer tick. */
//halIntState_t intState;
uint32 tmp;
uint16 ticks625us;
uint16 elapsedMSec = 0;
HAL_ENTER_CRITICAL_SECTION();
// Get the free-running count of 320us timer ticks
tmp = getMcuPrecisionCount();
HAL_EXIT_CRITICAL_SECTION();
if ( tmp != previousMacTimerTick )
{
// Calculate the elapsed ticks of the free-running timer.
ticks625us = tmp > previousMacTimerTick ? (tmp - previousMacTimerTick):(0xffffffffu)&(0x100000000 - previousMacTimerTick + tmp);
// Store the LL Timer tick count for the next time through this function.
previousMacTimerTick = tmp;
/* It is necessary to loop to convert the usecs to msecs in increments so as
* not to overflow the 16-bit variables.
*/
while ( ticks625us > MAXCALCTICKS )
{
ticks625us -= MAXCALCTICKS;
elapsedMSec += MAXCALCTICKS * 5 / 8;
remUsTicks += MAXCALCTICKS * 5 % 8;
}
// update converted number with remaining ticks from loop and the
// accumulated remainder from loop
tmp = (ticks625us * 5) + remUsTicks;
// Convert the 625 us ticks into milliseconds and a remainder
elapsedMSec += tmp / 8;
remUsTicks = tmp % 8;
// Update OSAL Clock and Timers
if ( elapsedMSec )
{
osalClockUpdate( elapsedMSec );
osalTimerUpdate( elapsedMSec );
}
}
#endif /* USE_ICALL */
}
/*********************************************************************
* @fn osalClockUpdate
*
* @brief Updates the OSAL Clock time with elapsed milliseconds.
*
* @param elapsedMSec - elapsed milliseconds
*
* @return none
*/
static void osalClockUpdate( uint32 elapsedMSec )
{
uint32 tmp;
//halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION();
// Add elapsed milliseconds to the saved millisecond portion of time
timeMSec += elapsedMSec;
// Roll up milliseconds to the number of seconds
if ( timeMSec >= 1000 )
{
tmp = timeMSec;
CONVERT_MS_TO_S_ELAPSED_REMAINDER(tmp, OSAL_timeSeconds, timeMSec);
}
HAL_EXIT_CRITICAL_SECTION();
}
#if defined HAL_BOARD_CC2538 || defined USE_ICALL
/*********************************************************************
* @fn osalAdjustTimer
*
* @brief Updates the OSAL Clock and Timer with elapsed milliseconds.
*
* @param MSec - elapsed milliseconds
*
* @return none
*/
void osalAdjustTimer(uint32 Msec )
{
/* Disable SysTick interrupts */
SysTickIntDisable();
osalClockUpdate(Msec);
osalTimerUpdate(Msec);
/* Enable SysTick interrupts */
SysTickIntEnable();
}
#endif /* HAL_BOARD_CC2538 || USE_ICALL */
/*********************************************************************
* @fn osal_setClock
*
* @brief Set the new time. This will only set the seconds portion
* of time and doesn't change the factional second counter.
*
* @param newTime - number of seconds since 0 hrs, 0 minutes,
* 0 seconds, on the 1st of January 2000 UTC
*
* @return none
*/
void osal_setClock( UTCTime newTime )
{
HAL_CRITICAL_STATEMENT(OSAL_timeSeconds = newTime);
}
/*********************************************************************
* @fn osal_getClock
*
* @brief Gets the current time. This will only return the seconds
* portion of time and doesn't include the factional second
* counter.
*
* @param none
*
* @return number of seconds since 0 hrs, 0 minutes, 0 seconds,
* on the 1st of January 2000 UTC
*/
UTCTime osal_getClock( void )
{
return ( OSAL_timeSeconds );
}
/*********************************************************************
* @fn osal_ConvertUTCTime
*
* @brief Converts UTCTime to UTCTimeStruct
*
* @param tm - pointer to breakdown struct
*
* @param secTime - number of seconds since 0 hrs, 0 minutes,
* 0 seconds, on the 1st of January 2000 UTC
*
* @return none
*/
void osal_ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime )
{
// calculate the time less than a day - hours, minutes, seconds
{
uint32 day = secTime % DAY;
tm->seconds = day % 60UL;
tm->minutes = (day % 3600UL) / 60UL;
tm->hour = day / 3600UL;
}
// Fill in the calendar - day, month, year
{
uint16 numDays = secTime / DAY;
tm->year = BEGYEAR;
while ( numDays >= YearLength( tm->year ) )
{
numDays -= YearLength( tm->year );
tm->year++;
}
tm->month = 0;
while ( numDays >= monthLength( IsLeapYear( tm->year ), tm->month ) )
{
numDays -= monthLength( IsLeapYear( tm->year ), tm->month );
tm->month++;
}
tm->day = numDays;
}
}
/*********************************************************************
* @fn monthLength
*
* @param lpyr - 1 for leap year, 0 if not
*
* @param mon - 0 - 11 (jan - dec)
*
* @return number of days in specified month
*/
static uint8 monthLength( uint8 lpyr, uint8 mon )
{
uint8 days = 31;
if ( mon == 1 ) // feb
{
days = ( 28 + lpyr );
}
else
{
if ( mon > 6 ) // aug-dec
{
mon--;
}
if ( mon & 1 )
{
days = 30;
}
}
return ( days );
}
/*********************************************************************
* @fn osal_ConvertUTCSecs
*
* @brief Converts a UTCTimeStruct to UTCTime
*
* @param tm - pointer to provided struct
*
* @return number of seconds since 00:00:00 on 01/01/2000 (UTC)
*/
UTCTime osal_ConvertUTCSecs( UTCTimeStruct *tm )
{
uint32 seconds;
/* Seconds for the partial day */
seconds = (((tm->hour * 60UL) + tm->minutes) * 60UL) + tm->seconds;
/* Account for previous complete days */
{
/* Start with complete days in current month */
uint16 days = tm->day;
/* Next, complete months in current year */
{
int8 month = tm->month;
while ( --month >= 0 )
{
days += monthLength( IsLeapYear( tm->year ), month );
}
}
/* Next, complete years before current year */
{
uint16 year = tm->year;
while ( --year >= BEGYEAR )
{
days += YearLength( year );
}
}
/* Add total seconds before partial day */
seconds += (days * DAY);
}
return ( seconds );
}