📄 dmtod.c
字号:
/* $id:dmTod.c V1.0 2001/09/5 */
/******************************************************************************
* This source code has been made available to you by CORETEK on
* AS-IS.Anyone receiving this source is licensed under
* CORETEK copyrights to use it in any way he or she deems fit,including
* copying it,modifying it,compiling it,and redistributing it either with
* or without modifictions.
*
*
* Any person who transfers this source code or any derivative work must
* include the CORETEK copyright notice, this paragraph,and the preceding
* two paragraphs in the transferred software.
*
*
* COPYRIGHT CORETEK CORPORATION 2001
* LICENSED MATERIAL - PROGRAM PROPERTY OF CORETEK
*****************************************************************************/
/******************************************************************************
*
* FILE: dmTod.c
*
* MODULE: DM
*
* PURPOSE: Define many function which is used to manager system time.
*
* AUTHOR(S):Zhang Yumin
*
* GROUP:TOOL_GROUP
*
* DATE CREATED:2001/09/05
*
* REFERENCE DOCUMENT ID:
*
* MODIFICATIONS:
* Date user Name Description
* 2001/09/05 Zhang Yumin Create this file
*
*********************************************************************************/
#include <sysTypes.h>
#include "dmlibio.h"
#include "dmTod.h"
#include "dmIntr.h"
#include "dmSem.h"
#include "dmClock.h"
T_EXTERN T_VOID printk(T_BYTE *fmt, ...);
T_MODULE T_VUWORD uwDM_TOD_Is_set = 0;
T_VOLATILE T_MODULE T_DM_TOD_Control utDM_TOD_Current = {0,1,1,0,0,0,0};
T_MODULE T_VUWORD uwDM_TOD_Seconds_since_epoch = 0;
T_MODULE T_UWORD uwDM_TOD_Microseconds_per_tick = 0;
T_MODULE T_UWORD uwDM_TOD_Ticks_per_second = 0;
T_MODULE T_VUWORD uwDM_TOD_Remainder_ticks = 0;
T_MODULE T_VUWORD uwDM_TOD_Seconds_since_boot = 0;
T_MODULE T_VUDWORD uwDM_TOD_Ticks_since_boot = 0; /* 64bit variable */
T_EXTERN T_VOID ( *fnDM_ClockRtcSet)(T_DM_TimeOfDay tod);
T_EXTERN T_VOID ( *fnDM_ClockRtcGet)(T_DM_TimeOfDay *tod);
T_EXTERN T_DM_StatusCode( *fnDM_OsSecondInterrupt)(T_VOID);
const T_UWORD uwaDM_TOD_Days_per_month[ 2 ][ 13 ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
const T_UWORD uwaDM_TOD_Days_to_date[2][13] = {
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
const T_UWORD uwaDM_TOD_Days_since_last_leap_year[4] = { 0, 366, 731, 1096 };
/********************************************************************
* FUNCTION: TodInsertTicks
*
* PURPOSE: This routine updating the delta interval counters.
* PARAMETERS:
*
* Input: remainder_ticks -remainder ticks in current second.
* Output: None
* InOut: None
*
* Return value: None
* Reentrant: No
********************************************************************/
T_MODULE T_VOID TodInsertTicks(T_UWORD remainder_ticks)
{
uwDM_TOD_Remainder_ticks = remainder_ticks;
}
/********************************************************************
* FUNCTION: fnDM_TodHandlerInit
*
* PURPOSE: This routine initializes the time of day handler.
* PARAMETERS:
*
* Input: microseconds_per_tick - microseconds between clock ticks.
* Output: None
* InOut: None
*
* Return value: None
* Reentrant: No
********************************************************************/
T_VOID fnDM_TodHandlerInit(
T_UWORD microseconds_per_tick
)
{
uwDM_TOD_Microseconds_per_tick = microseconds_per_tick;
uwDM_TOD_Seconds_since_epoch = 0;
utDM_TOD_Current.year = DM_TOD_BASE_YEAR;
utDM_TOD_Current.month = 1;
utDM_TOD_Current.day = 1;
utDM_TOD_Current.hour = 0;
utDM_TOD_Current.minute = 0;
utDM_TOD_Current.second = 0;
utDM_TOD_Current.ticks = 0;
if ( microseconds_per_tick == 0 )
uwDM_TOD_Ticks_per_second = 0;
else
uwDM_TOD_Ticks_per_second =
DM_TOD_MICROSECONDS_PER_SECOND / microseconds_per_tick;
uwDM_TOD_Is_set = FALSE;
TodInsertTicks( uwDM_TOD_Ticks_per_second );
}
/********************************************************************
* FUNCTION: fnDM_TodSet
*
* PURPOSE: This rountine sets the current date and time with the
* specified new date and time structure.
* PARAMETERS:
*
* Input: the_tod - pointer to the time and date structure
* seconds_since_epoch - seconds since system epoch
* Output: None
* InOut: None
*
* Return value: DM_SUCCESSFUL - if successful
* DM_INVALID_CLOCK - if invalid arguments!
* Reentrant: No
********************************************************************/
T_DM_StatusCode fnDM_TodSet(
T_DM_TOD_Control *the_tod
)
{
if(fnDM_TodValidate(the_tod))
{
T_UWORD level,Seconds_since_epoch,ticks_until_next_second;
Seconds_since_epoch = fnDM_TodToSeconds(the_tod);
fnDM_InterruptDisable(level);
uwDM_TOD_Seconds_since_epoch = Seconds_since_epoch;
ticks_until_next_second = uwDM_TOD_Ticks_per_second;
if ( ticks_until_next_second > utDM_TOD_Current.ticks )
ticks_until_next_second -= utDM_TOD_Current.ticks;
utDM_TOD_Current = *the_tod;
uwDM_TOD_Is_set = TRUE;
TodInsertTicks( ticks_until_next_second );
fnDM_InterruptEnable(level);
return DM_SUCCESSFUL;
}
return DM_INVALID_CLOCK;
}
/********************************************************************
* FUNCTION: fnDM_TodGet
*
* PURPOSE: This directive returns the current date and time. If
* the time hasnot been set by a fnDM_InterClockSet then
* an error is returned.(Internal function)
* PARAMETERS:
*
* Input: option -which value to return
* time_buffer -pointer to output buffer (a time and date
* structure or an interval)
* Output: time_buffer - output filled in
* InOut: None
*
* Return value: DM_SUCCESSFUL - if successful
* error code - if unsuccessful
*
* Reentrant: No
********************************************************************/
T_DM_StatusCode fnDM_TodGet(
T_DM_ClockGetOptions option,
T_VOID *time_buffer
)
{
T_WORD level;
T_UWORD tmp;
switch ( option )
{
case DM_CLOCK_GET_TOD:
if ( !uwDM_TOD_Is_set )
return DM_NOT_DEFINED;
*(T_DM_TimeOfDay *)time_buffer = utDM_TOD_Current;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_SECONDS_SINCE_EPOCH:
if ( !uwDM_TOD_Is_set )
return DM_NOT_DEFINED;
*(T_UWORD *)time_buffer = uwDM_TOD_Seconds_since_epoch;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_SECONDS_SINCE_BOOT:
*(T_UWORD *)time_buffer = uwDM_TOD_Seconds_since_boot;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_TICKS_SINCE_BOOT:
*(T_UWORD *)time_buffer = (T_UWORD)uwDM_TOD_Ticks_since_boot;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_TICKS64_SINCE_BOOT:
*(T_UDWORD *)time_buffer = uwDM_TOD_Ticks_since_boot;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_TICKS_PER_SECOND:
*(T_UWORD *)time_buffer = uwDM_TOD_Ticks_per_second;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_MICROSEC_PER_TICK:
*(T_UWORD *)time_buffer = uwDM_TOD_Microseconds_per_tick;
return DM_SUCCESSFUL;
case DM_CLOCK_GET_TIME_VALUE:
if ( !uwDM_TOD_Is_set )
return DM_NOT_DEFINED;
fnDM_InterruptDisable( level );
((T_DM_ClockTimeValue *)time_buffer)->seconds =
uwDM_TOD_Seconds_since_epoch;
tmp = utDM_TOD_Current.ticks;
fnDM_InterruptEnable( level );
tmp *= uwDM_TOD_Microseconds_per_tick;
((T_DM_ClockTimeValue *)time_buffer)->microseconds = tmp;
return DM_SUCCESSFUL;
}
return DM_INVALID_NUMBER; /* should never get here */
}
/********************************************************************
* FUNCTION: fnDM_TodValidate
*
* PURPOSE: This kernel routine checks the validity of a date and
* time structure.This routine only works for leap-years
* through 2099.
* PARAMETERS:
*
* Input: the_tod - pointer to a time and date structure
* Output: TRUE - if the date, time, and tick are valid
* FALSE - if the the_tod is invalid
* InOut: None
*
* Return value: TRUE -valid
* FALSE -invalid
* Reentrant: No
********************************************************************/
T_WORD fnDM_TodValidate(
T_DM_TOD_Control *the_tod
)
{
T_UWORD days_in_month;
if ((the_tod->ticks >= uwDM_TOD_Ticks_per_second) ||
(the_tod->second >= DM_TOD_SECONDS_PER_MINUTE) ||
(the_tod->minute >= DM_TOD_MINUTES_PER_HOUR) ||
(the_tod->hour >= DM_TOD_HOURS_PER_DAY) ||
(the_tod->month == 0) ||
(the_tod->month > DM_TOD_MONTHS_PER_YEAR) ||
(the_tod->year < DM_TOD_BASE_YEAR) ||
(the_tod->day == 0) )
return FALSE;
if (DM_isLeapYear(the_tod->year))
days_in_month = uwaDM_TOD_Days_per_month[ 1 ][ the_tod->month ];
else
days_in_month = uwaDM_TOD_Days_per_month[ 0 ][ the_tod->month ];
if ( the_tod->day > days_in_month )
return FALSE;
return TRUE;
}
/********************************************************************
* FUNCTION: fnDM_TodToSeconds
*
* PURPOSE: This routine returns the seconds from the epoch until the
* current date and time.
* PARAMETERS:
*
* Input: the_tod - pointer to the time and date structure
* Output: None
* InOut: None
*
* Return value: seconds since epoch until the_tod.
* Reentrant: No
********************************************************************/
T_UWORD fnDM_TodToSeconds(
T_DM_TOD_Control *the_tod
)
{
T_UWORD time;
T_UWORD year_mod_4;
T_UWORD nearCent,nearEra;
year_mod_4 = the_tod->year & 3;
nearEra = DM_TOD_BASE_YEAR / 100;
nearEra = (nearEra + 3)&~3;
nearEra *= 100;
nearCent = (DM_TOD_BASE_YEAR + 99) /100;
nearCent *=100;
if(the_tod->year > nearEra)
time = (((the_tod->year - DM_TOD_BASE_YEAR) / 4) *1461) -
(((the_tod->year - nearCent) / 100) + 1) +
(((the_tod->year - nearEra) / 400) +1);
else if(the_tod->year > nearCent)
time = (((the_tod->year - DM_TOD_BASE_YEAR) / 4) *1461) -
(((the_tod->year - nearCent) / 100) + 1);
else
time = (((the_tod->year - DM_TOD_BASE_YEAR) / 4) *1461);
time += uwaDM_TOD_Days_since_last_leap_year[year_mod_4];
if(DM_isLeapYear(the_tod->year))
time += uwaDM_TOD_Days_to_date[ 1 ][ the_tod->month ];
else
time += uwaDM_TOD_Days_to_date[ 0 ][ the_tod->month ];
time += the_tod->day - 1;
time *= DM_TOD_SECONDS_PER_DAY;
time += ((the_tod->hour * DM_TOD_MINUTES_PER_HOUR) + the_tod->minute)
* DM_TOD_SECONDS_PER_MINUTE;
time += the_tod->second;
return( time );
}
/********************************************************************
* FUNCTION: fnDM_TodTickle
*
* PURPOSE: This routine updates the calendar time .
* PARAMETERS:
*
* Input: None
* Output: None
* InOut: None
*
* Return value: None
* Reentrant: No
********************************************************************/
T_VOID fnDM_TodTickle()
{
T_UWORD leap;
uwDM_TOD_Remainder_ticks--;
if ( uwDM_TOD_Remainder_ticks != 0 )
return;
//printk("There has been %d seconds since epoch!\n",uwDM_TOD_Seconds_since_epoch);
utDM_TOD_Current.ticks = 0;
++uwDM_TOD_Seconds_since_epoch;
uwDM_TOD_Seconds_since_boot++;
if ( ++utDM_TOD_Current.second >= DM_TOD_SECONDS_PER_MINUTE ) {
utDM_TOD_Current.second = 0;
if ( ++utDM_TOD_Current.minute >= DM_TOD_MINUTES_PER_HOUR ) {
utDM_TOD_Current.minute = 0;
if ( ++utDM_TOD_Current.hour >= DM_TOD_HOURS_PER_DAY ) {
utDM_TOD_Current.hour = 0;
if (DM_isLeapYear(utDM_TOD_Current.year)) leap = 1;
else leap = 0;
if ( ++utDM_TOD_Current.day >
uwaDM_TOD_Days_per_month[ leap ][ utDM_TOD_Current.month ]) {
utDM_TOD_Current.day = 1;
if ( ++utDM_TOD_Current.month > DM_TOD_MONTHS_PER_YEAR ) {
utDM_TOD_Current.month = 1;
utDM_TOD_Current.year++;
}
}
}
}
}
if(fnDM_ClockAnnounce)
(*fnDM_ClockAnnounce)(DM_ANNOUNCE_SECOND);
TodInsertTicks( uwDM_TOD_Ticks_per_second );
}
/********************************************************************
* FUNCTION: fnDM_TodCurTicks
*
* PURPOSE: This routine return the current ticks.
* PARAMETERS:
*
* Input: None
* Output: None
* InOut: None
*
* Return value: current ticks
* Reentrant: No
********************************************************************/
T_UWORD fnDM_TodCurTicks()
{
return utDM_TOD_Current.ticks;
}
/*
* fnDM_TodTickleTicks
*
* DESCRIPTION:
*
* This routine increments the ticks field of the current time of
* day at each clock tick.
*/
inline T_VOID inlDM_TodTickleTicks( T_VOID )
{
utDM_TOD_Current.ticks++;
uwDM_TOD_Ticks_since_boot++;
}
/*
* fnDM_TodSecondInterrupt
*
* DESCRIPTION:
*
* This directive notifies the executve that a second has
* occurred.
*/
inline T_VOID inlDM_TodSecondInterrupt( T_VOID )
{
T_UWORD leap;
//printk("Current ticks = %d\n",utDM_TOD_Current.ticks);
utDM_TOD_Current.ticks = 0;
uwDM_TOD_Seconds_since_boot++;
if(((T_UWORD)fnDM_ClockRtcSet) == ((T_UWORD)0x1))
{
++uwDM_TOD_Seconds_since_epoch;
if ( ++utDM_TOD_Current.second >= DM_TOD_SECONDS_PER_MINUTE ) {
utDM_TOD_Current.second = 0;
if ( ++utDM_TOD_Current.minute >= DM_TOD_MINUTES_PER_HOUR ) {
utDM_TOD_Current.minute = 0;
if ( ++utDM_TOD_Current.hour >= DM_TOD_HOURS_PER_DAY ) {
utDM_TOD_Current.hour = 0;
if (DM_isLeapYear(utDM_TOD_Current.year)) leap = 1;
else leap = 0;
if ( ++utDM_TOD_Current.day >
uwaDM_TOD_Days_per_month[ leap ][ utDM_TOD_Current.month ]) {
utDM_TOD_Current.day = 1;
if ( ++utDM_TOD_Current.month > DM_TOD_MONTHS_PER_YEAR ) {
utDM_TOD_Current.month = 1;
utDM_TOD_Current.year++;
}
}
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -