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

📄 dmtod.c

📁 uCOS for S3C44x.rar,将usos2移植的源代码
💻 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 + -