Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreTOD
0007  * @ingroup RTEMSScoreTODHooks
0008  *
0009  * @brief This header file provides the interfaces of the
0010  *   @ref RTEMSScoreTOD and the @ref RTEMSScoreTODHooks.
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 1989-2009.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifndef _RTEMS_SCORE_TODIMPL_H
0040 #define _RTEMS_SCORE_TODIMPL_H
0041 
0042 #include <rtems/score/status.h>
0043 #include <rtems/score/timestamp.h>
0044 #include <rtems/score/timecounterimpl.h>
0045 #include <rtems/score/watchdog.h>
0046 #include <rtems/score/watchdogticks.h>
0047 
0048 #include <sys/time.h>
0049 #include <time.h>
0050 
0051 #ifdef __cplusplus
0052 extern "C" {
0053 #endif
0054 
0055 /**
0056  * @defgroup RTEMSScoreTOD Time of Day Handler
0057  *
0058  * @ingroup RTEMSScore
0059  *
0060  * @brief This group contains the Time of Day Handler implementation.
0061  *
0062  * The following constants are related to the time of day and are
0063  * independent of RTEMS.
0064  *
0065  * @{
0066  */
0067 
0068 /**
0069  *  This constant represents the number of seconds in a minute.
0070  */
0071 #define TOD_SECONDS_PER_MINUTE (uint32_t)60
0072 
0073 /**
0074  *  This constant represents the number of minutes per hour.
0075  */
0076 #define TOD_MINUTES_PER_HOUR   (uint32_t)60
0077 
0078 /**
0079  *  This constant represents the number of months in a year.
0080  */
0081 #define TOD_MONTHS_PER_YEAR    (uint32_t)12
0082 
0083 /**
0084  *  This constant represents the number of days in a non-leap year.
0085  */
0086 #define TOD_DAYS_PER_YEAR      (uint32_t)365
0087 
0088 /**
0089  *  This constant represents the number of hours per day.
0090  */
0091 #define TOD_HOURS_PER_DAY      (uint32_t)24
0092 
0093 /**
0094  *  This constant represents the number of seconds in a day which does
0095  *  not include a leap second.
0096  */
0097 #define TOD_SECONDS_PER_DAY    (uint32_t) (TOD_SECONDS_PER_MINUTE * \
0098                                 TOD_MINUTES_PER_HOUR   * \
0099                                 TOD_HOURS_PER_DAY)
0100 
0101 /**
0102  *  This constant represents the number of seconds in a non-leap year.
0103  */
0104 #define TOD_SECONDS_PER_NON_LEAP_YEAR (365 * TOD_SECONDS_PER_DAY)
0105 
0106 /**
0107  *  This constant represents the number of millisecond in a second.
0108  */
0109 #define TOD_MILLISECONDS_PER_SECOND     (uint32_t)1000
0110 
0111 /**
0112  *  This constant represents the number of microseconds in a second.
0113  */
0114 #define TOD_MICROSECONDS_PER_SECOND     (uint32_t)1000000
0115 
0116 /**
0117  *  This constant represents the number of nanoseconds in a second.
0118  */
0119 #define TOD_NANOSECONDS_PER_SECOND      (uint32_t)1000000000
0120 
0121 /**
0122  *  This constant represents the number of nanoseconds in a mircosecond.
0123  */
0124 #define TOD_NANOSECONDS_PER_MICROSECOND (uint32_t)1000
0125 
0126 /**@}*/
0127 
0128 /**
0129  *  Seconds from January 1, 1970 to January 1, 1988.  Used to account for
0130  *  differences between POSIX API and RTEMS core. The timespec format time
0131  *  is kept in POSIX compliant form.
0132  */
0133 #define TOD_SECONDS_1970_THROUGH_1988 \
0134   (((1987 - 1970 + 1)  * TOD_SECONDS_PER_NON_LEAP_YEAR) + \
0135   (4 * TOD_SECONDS_PER_DAY))
0136 
0137 /**
0138  * @brief Seconds from 1970-01-01T00:00:00Z to 2400-01-01T00:00:00Z.
0139  *
0140  * This is the latest time of day which should be set by _TOD_Set().  The year
0141  * 2400 was chosen to guarantee a defined CLOCK_REALTIME within the range of a
0142  * system uptime of about 114 years.
0143  */
0144 #define TOD_SECONDS_1970_THROUGH_2400 13569465600
0145 
0146 /**
0147  *  @brief Earliest year to which an time of day can be initialized.
0148  *
0149  *  The following constant define the earliest year to which an
0150  *  time of day can be initialized.  This is considered the
0151  *  epoch.
0152  */
0153 #define TOD_BASE_YEAR 1988
0154 
0155 /**
0156  *  @brief Latest year to which a time of day can be initialized.
0157  *
0158  *  The following constant defines the latest year to which an
0159  *  RTEMS time of day can be set using rtems_clock_set().
0160  *
0161  *  32 bits can accept as latest point in time 2106-Feb-7 6:28:15
0162  *  but to simplify the implementation, is was decided to only
0163  *  check that the year is not greater than the year of this constant.
0164  *  The year 2099 was chosen because all years evenly divisible by 4 from 1988
0165  *  to 2099 are leap years.  In this time frame, years evenly divisible by 100
0166  *  are no leap years unless they are evenly divisible by 400.  Thus the year
0167  *  2000 is a leap year.
0168  *
0169  *  The internal CLOCK_REALTIME can run centuries longer but in
0170  *  contrast to the POSIX API, the RTEMS Classic API does not
0171  *  support this for efficiency reasons.
0172  */
0173 #define TOD_LATEST_YEAR 2099
0174 
0175 /**
0176  * @addtogroup RTEMSScoreTOD
0177  *
0178  * This handler encapsulates functionality used to manage time of day.
0179  *
0180  * @{
0181  */
0182 
0183 /**
0184  *  @brief TOD control.
0185  */
0186 typedef struct {
0187   /**
0188    *  @brief Indicates if the time of day is set.
0189    *
0190    *  This is true if the application has set the current
0191    *  time of day, and false otherwise.
0192    */
0193   bool is_set;
0194 } TOD_Control;
0195 
0196 /**
0197  * @brief TOD Management information
0198  */
0199 extern TOD_Control _TOD;
0200 
0201 /**
0202  * @brief This array contains the number of days in all months up to the month
0203  *   indicated by the index of the second dimension.
0204  *
0205  * The first dimension should be 0 for leap years, and 1 otherwise.
0206  */
0207 extern const uint16_t _TOD_Days_to_date[ 2 ][ 13 ];
0208 
0209 /**
0210  * @brief Locks the time of day mutex.
0211  */
0212 void _TOD_Lock( void );
0213 
0214 /**
0215  * @brief Unlocks the time of day mutex.
0216  */
0217 void _TOD_Unlock( void );
0218 
0219 /**
0220  * @brief Checks if api mutex is owner of the time of day mutex.
0221  *
0222  * @retval true It is owner of the time of day mutex.
0223  * @retval false It is not owner of the time of day mutex.
0224  */
0225 #if defined(RTEMS_DEBUG)
0226 bool _TOD_Is_owner( void );
0227 #endif
0228 
0229 /**
0230  * @brief Acquires the lock context for the timecounter.
0231  *
0232  * @param lock_context The lock to acquire.
0233  */
0234 static inline void _TOD_Acquire( ISR_lock_Context *lock_context )
0235 {
0236   _Timecounter_Acquire( lock_context );
0237 }
0238 
0239 /**
0240  * @brief Releases the lock context for the timecounter.
0241  *
0242  * @param lock_context The lock to release.
0243  */
0244 static inline void _TOD_Release( ISR_lock_Context *lock_context )
0245 {
0246   _Timecounter_Release( lock_context );
0247 }
0248 
0249 /**
0250  * @brief Maps the year to the leap year index.
0251  *
0252  * @param year is the year to map.
0253  *
0254  * @retval 0 The year is a leap year.
0255  *
0256  * @retval 1 The year is not a leap year.
0257  */
0258 static inline size_t _TOD_Get_leap_year_index( uint32_t year )
0259 {
0260   _Assert( year % 4 != 0 || year % 100 != 0 || year % 400 == 0 );
0261   return ( ( year % 4 ) + 3 ) / 4;
0262 }
0263 
0264 /**
0265  * @brief Checks the time point is a valid new time of day for _TOD_Set().
0266  *
0267  * @param tod the time of day to check.
0268  *
0269  * @retval STATUS_SUCCESSFUL The time of day is valid.
0270  *
0271  * @retval STATUS_INVALID_NUMBER The time of day is invalid.
0272  */
0273 Status_Control _TOD_Is_valid_new_time_of_day( const struct timespec *tod );
0274 
0275 /**
0276  * @brief Sets the time of day.
0277  *
0278  * The caller must be the owner of the TOD lock.
0279  *
0280  * @param tod The new time of day in timespec format representing
0281  *   the time since UNIX Epoch.  The new time of day shall be valid according
0282  *   to _TOD_Is_valid_new_time_of_day().
0283  * @param lock_context The ISR lock context used for the corresponding
0284  *   _TOD_Acquire().  The caller must be the owner of the TOD lock.  This
0285  *   function will release the TOD lock.
0286  *
0287  * @retval STATUS_SUCCESSFUL Successful operation.
0288  * @retval other Some error occurred.
0289  */
0290 Status_Control _TOD_Set(
0291   const struct timespec *tod,
0292   ISR_lock_Context      *lock_context
0293 );
0294 
0295 /**
0296  * @brief Gets the current time in the timespec format.
0297  *
0298  * @param[out] time The value gathered by the request.
0299  */
0300 static inline void _TOD_Get(
0301   struct timespec *tod
0302 )
0303 {
0304   _Timecounter_Nanotime( tod );
0305 }
0306 
0307 /**
0308  * @brief Gets the system uptime with potential accuracy to the nanosecond.
0309  *
0310  * This routine returns the system uptime with potential accuracy
0311  * to the nanosecond.
0312  *
0313  * The initial uptime value is undefined.
0314  *
0315  * @param[out] time Is a pointer to the uptime after the method call.
0316  */
0317 static inline void _TOD_Get_uptime(
0318   Timestamp_Control *time
0319 )
0320 {
0321   *time = _Timecounter_Sbinuptime();
0322 }
0323 
0324 /**
0325  * @brief Gets the system uptime with potential accuracy to the nanosecond.
0326  *
0327  * The initial uptime value is zero.
0328  *
0329  * @param[out] time Is a pointer to the uptime after the method call.
0330  */
0331 static inline void _TOD_Get_zero_based_uptime(
0332   Timestamp_Control *time
0333 )
0334 {
0335   *time = _Timecounter_Sbinuptime() - SBT_1S;
0336 }
0337 
0338 /**
0339  * @brief Gets the system uptime with potential accuracy to the nanosecond.
0340  *
0341  * The initial uptime value is zero.
0342  *
0343  * @param[out] time Is a pointer to the uptime after the method call.
0344  */
0345 static inline void _TOD_Get_zero_based_uptime_as_timespec(
0346   struct timespec *time
0347 )
0348 {
0349   _Timecounter_Nanouptime( time );
0350   --time->tv_sec;
0351 }
0352 
0353 /**
0354  * @brief Returns Number of seconds Since RTEMS epoch.
0355  *
0356  * The following contains the number of seconds from 00:00:00
0357  * January 1, TOD_BASE_YEAR until the current time of day.
0358  *
0359  * @return The number of seconds since RTEMS epoch.
0360  */
0361 static inline uint32_t _TOD_Seconds_since_epoch( void )
0362 {
0363   return (uint32_t) _Timecounter_Time_second;
0364 }
0365 
0366 /**
0367  *  @brief Gets number of ticks in a second.
0368  */
0369 #define TOD_TICKS_PER_SECOND _Watchdog_Ticks_per_second
0370 
0371 /**
0372  * @brief This routine returns a timeval based upon the internal timespec
0373  *      format TOD.
0374  *
0375  * @param[out] time The timeval to be filled in by the method.
0376  */
0377 static inline void _TOD_Get_timeval(
0378   struct timeval *time
0379 )
0380 {
0381   _Timecounter_Microtime( time );
0382 }
0383 
0384 /**
0385  * @brief Check if the TOD is Set
0386  *
0387  * @retval true The time is set.
0388  * @retval false The time is not set.
0389  */
0390 static inline bool _TOD_Is_set( void )
0391 {
0392   return _TOD.is_set;
0393 }
0394 
0395 /** @} */
0396 
0397 /**
0398  * @defgroup RTEMSScoreTODHooks Time of Day Handler Action Hooks
0399  *
0400  * @ingroup RTEMSScoreTOD
0401  *
0402  * @brief This group contains the implementation to support Time of Day Handler
0403  *   action hooks.
0404  *
0405  * The following support registering a hook which is invoked
0406  * when the TOD is set. These can be used by a paravirtualized
0407  * BSP to mirror time changes to the hosting environment or a
0408  * regular BSP to program a real-time clock when the RTEMS TOD
0409  * is set.
0410  *
0411  * @{
0412  */
0413 
0414 /**
0415  *  @brief Possible actions where a registered hook could be invoked
0416  */
0417 typedef enum {
0418   /**
0419    *  @brief Constant to indicate the TOD is being set.
0420    */
0421   TOD_ACTION_SET_CLOCK
0422 } TOD_Action;
0423 
0424 /**
0425  * @brief Structure to manage each TOD action hook
0426  */
0427 typedef struct TOD_Hook {
0428   /** This is the chain node portion of an object. */
0429   Chain_Node Node;
0430 
0431   /** This is the TOD action hook that is invoked. */
0432   Status_Control ( *handler )( TOD_Action, const struct timespec * );
0433 } TOD_Hook;
0434 
0435 /**
0436  * @brief Set of registered methods for TOD Actions
0437  */
0438 extern Chain_Control _TOD_Hooks;
0439 
0440 /**
0441  * @brief Add a TOD Action Hook
0442  *
0443  * This method is used to add a hook to the TOD action set.
0444  *
0445  * @brief hook is the action hook to register.
0446  */
0447 void _TOD_Hook_Register(
0448   TOD_Hook *hook
0449 );
0450 
0451 /**
0452  * @brief Remove a TOD Action Hook
0453  *
0454  * This method is used to remove a hook from the TOD action set.
0455  *
0456  * @brief hook is the action hook to unregister.
0457  */
0458 void _TOD_Hook_Unregister(
0459   TOD_Hook *hook
0460 );
0461 
0462 /**
0463  * @brief Run the TOD Action Hooks
0464  *
0465  * This method is used to invoke the set of TOD action hooks.
0466  *
0467  * @brief action The action which triggered this run.
0468  * @brief tod The current time of day.
0469  *
0470  * @retval STATUS_SUCCESSFUL Successful operation.
0471  * @retval other Some error occurred.
0472  */
0473 Status_Control _TOD_Hook_Run(
0474   TOD_Action             action,
0475   const struct timespec *tod
0476 );
0477 
0478 
0479 /** @} */
0480 
0481 #ifdef __cplusplus
0482 }
0483 #endif
0484 
0485 #endif
0486 /* end of include file */