123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- /*
- ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
- This file is part of ChibiOS.
- ChibiOS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- ChibiOS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /**
- * @file chtime.h
- * @brief Time and intervals macros and structures.
- *
- * @addtogroup time_intervals
- * @details This module is responsible for handling of system time and time
- * intervals.
- * @{
- */
- #ifndef CHTIME_H
- #define CHTIME_H
- /*===========================================================================*/
- /* Module constants. */
- /*===========================================================================*/
- /**
- * @name Special time constants
- * @{
- */
- /**
- * @brief Zero interval specification for some functions with a timeout
- * specification.
- * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
- * see the specific function documentation.
- */
- #define TIME_IMMEDIATE ((sysinterval_t)0)
- /**
- * @brief Infinite interval specification for all functions with a timeout
- * specification.
- * @note Not all functions accept @p TIME_INFINITE as timeout parameter,
- * see the specific function documentation.
- */
- #define TIME_INFINITE ((sysinterval_t)-1)
- /**
- * @brief Maximum interval constant usable as timeout.
- */
- #define TIME_MAX_INTERVAL ((sysinterval_t)-2)
- /**
- * @brief Maximum system of system time before it wraps.
- */
- #define TIME_MAX_SYSTIME ((systime_t)-1)
- /** @} */
- /*===========================================================================*/
- /* Module pre-compile time settings. */
- /*===========================================================================*/
- /*===========================================================================*/
- /* Derived constants and error checks. */
- /*===========================================================================*/
- #if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32) && \
- (CH_CFG_ST_RESOLUTION != 64)
- #error "invalid CH_CFG_ST_RESOLUTION specified, must be 16, 32 or 64"
- #endif
- #if CH_CFG_ST_FREQUENCY < 10
- #error "invalid CH_CFG_ST_FREQUENCY specified, must be >= 10"
- #endif
- #if (CH_CFG_INTERVALS_SIZE != 16) && (CH_CFG_INTERVALS_SIZE != 32) && \
- (CH_CFG_INTERVALS_SIZE != 64)
- #error "invalid CH_CFG_INTERVALS_SIZE specified, must be 16, 32 or 64"
- #endif
- #if (CH_CFG_TIME_TYPES_SIZE != 16) && (CH_CFG_TIME_TYPES_SIZE != 32)
- #error "invalid CH_CFG_TIME_TYPES_SIZE specified, must be 16 or 32"
- #endif
- #if CH_CFG_INTERVALS_SIZE < CH_CFG_ST_RESOLUTION
- #error "CH_CFG_INTERVALS_SIZE must be >= CH_CFG_ST_RESOLUTION"
- #endif
- /*===========================================================================*/
- /* Module data structures and types. */
- /*===========================================================================*/
- /**
- * @brief Type of system time.
- * @note It is selectable in configuration between 16, 32 or 64 bits.
- */
- #if (CH_CFG_ST_RESOLUTION == 64) || defined(__DOXYGEN__)
- typedef uint64_t systime_t;
- #elif CH_CFG_ST_RESOLUTION == 32
- typedef uint32_t systime_t;
- #elif CH_CFG_ST_RESOLUTION == 16
- typedef uint16_t systime_t;
- #endif
- /**
- * @brief Type of time interval.
- * @note It is selectable in configuration between 16, 32 or 64 bits.
- */
- #if (CH_CFG_INTERVALS_SIZE == 64) || defined(__DOXYGEN__)
- typedef uint64_t sysinterval_t;
- #elif CH_CFG_INTERVALS_SIZE == 32
- typedef uint32_t sysinterval_t;
- #elif CH_CFG_INTERVALS_SIZE == 16
- typedef uint16_t sysinterval_t;
- #endif
- #if (CH_CFG_TIME_TYPES_SIZE == 32) || defined(__DOXYGEN__)
- /**
- * @brief Type of seconds.
- * @note It is selectable in configuration between 16 or 32 bits.
- */
- typedef uint32_t time_secs_t;
- /**
- * @brief Type of milliseconds.
- * @note It is selectable in configuration between 16 or 32 bits.
- */
- typedef uint32_t time_msecs_t;
- /**
- * @brief Type of microseconds.
- * @note It is selectable in configuration between 16 or 32 bits.
- */
- typedef uint32_t time_usecs_t;
- /**
- * @brief Type of time conversion variable.
- * @note This type must have double width than other time types, it is
- * only used internally for conversions.
- */
- typedef uint64_t time_conv_t;
- #else
- typedef uint16_t time_secs_t;
- typedef uint16_t time_msecs_t;
- typedef uint16_t time_usecs_t;
- typedef uint32_t time_conv_t;
- #endif
- /*===========================================================================*/
- /* Module macros. */
- /*===========================================================================*/
- /**
- * @name Fast time conversion utilities
- * @{
- */
- /**
- * @brief Seconds to time interval.
- * @details Converts from seconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] secs number of seconds
- * @return The number of ticks.
- *
- * @api
- */
- #define TIME_S2I(secs) \
- ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
- /**
- * @brief Milliseconds to time interval.
- * @details Converts from milliseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] msecs number of milliseconds
- * @return The number of ticks.
- *
- * @api
- */
- #if CH_CFG_ST_FREQUENCY == 1000000
- #define TIME_MS2I(msecs) ((sysinterval_t)((time_conv_t)(msecs))*(time_conv_t)1000)
- #else
- #define TIME_MS2I(msecs) \
- ((sysinterval_t)((((time_conv_t)(msecs) * \
- (time_conv_t)CH_CFG_ST_FREQUENCY) + \
- (time_conv_t)999) / (time_conv_t)1000))
- #endif
- /**
- * @brief Microseconds to time interval.
- * @details Converts from microseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] usecs number of microseconds
- * @return The number of ticks.
- *
- * @api
- */
- #if CH_CFG_ST_FREQUENCY == 1000000
- #define TIME_US2I(usecs) ((sysinterval_t)(usecs))
- #else
- #define TIME_US2I(usecs) \
- ((sysinterval_t)((((time_conv_t)(usecs) * \
- (time_conv_t)CH_CFG_ST_FREQUENCY) + \
- (time_conv_t)999999) / (time_conv_t)1000000))
- #endif
- /**
- * @brief Time interval to seconds.
- * @details Converts from system ticks number to seconds.
- * @note The result is rounded up to the next second boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] interval interval in ticks
- * @return The number of seconds.
- *
- * @api
- */
- #define TIME_I2S(interval) \
- (time_secs_t)(((time_conv_t)(interval) + \
- (time_conv_t)CH_CFG_ST_FREQUENCY - \
- (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
- /**
- * @brief Time interval to milliseconds.
- * @details Converts from system ticks number to milliseconds.
- * @note The result is rounded up to the next millisecond boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] interval interval in ticks
- * @return The number of milliseconds.
- *
- * @api
- */
- #if CH_CFG_ST_FREQUENCY == 1000000
- #define TIME_I2MS(interval) \
- (time_msecs_t)(((time_conv_t)(interval)+999)/(time_conv_t)1000)
- #else
- #define TIME_I2MS(interval) \
- (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
- (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
- (time_conv_t)CH_CFG_ST_FREQUENCY)
- #endif
- /**
- * @brief Time interval to microseconds.
- * @details Converts from system ticks number to microseconds.
- * @note The result is rounded up to the next microsecond boundary.
- * @note Use of this macro for large values is not secure because
- * integer overflows, make sure your value can be correctly
- * converted.
- *
- * @param[in] interval interval in ticks
- * @return The number of microseconds.
- *
- * @api
- */
- #if CH_CFG_ST_FREQUENCY == 1000000
- #define TIME_I2US(interval) ((time_usecs_t)(interval))
- #else
- #define TIME_I2US(interval) \
- (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
- (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
- (time_conv_t)CH_CFG_ST_FREQUENCY)
- #endif
- /** @} */
- /*===========================================================================*/
- /* External declarations. */
- /*===========================================================================*/
- /*
- * Virtual Timers APIs.
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifdef __cplusplus
- }
- #endif
- /*===========================================================================*/
- /* Module inline functions. */
- /*===========================================================================*/
- /**
- * @name Secure time conversion utilities
- * @{
- */
- /**
- * @brief Seconds to time interval.
- * @details Converts from seconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- *
- * @param[in] secs number of seconds
- * @return The number of ticks.
- *
- * @special
- */
- static inline sysinterval_t chTimeS2I(time_secs_t secs) {
- time_conv_t ticks;
- ticks = (time_conv_t)secs * (time_conv_t)CH_CFG_ST_FREQUENCY;
- chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
- "conversion overflow");
- return (sysinterval_t)ticks;
- }
- /**
- * @brief Milliseconds to time interval.
- * @details Converts from milliseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- *
- * @param[in] msec number of milliseconds
- * @return The number of ticks.
- *
- * @special
- */
- static inline sysinterval_t chTimeMS2I(time_msecs_t msec) {
- time_conv_t ticks;
- #if CH_CFG_ST_FREQUENCY == 1000000
- ticks = msec*(time_conv_t)1000;
- #else
- ticks = (((time_conv_t)msec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
- (time_conv_t)999) / (time_conv_t)1000;
- #endif
- chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
- "conversion overflow");
- return (sysinterval_t)ticks;
- }
- /**
- * @brief Microseconds to time interval.
- * @details Converts from microseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- *
- * @param[in] usec number of microseconds
- * @return The number of ticks.
- *
- * @special
- */
- static inline sysinterval_t chTimeUS2I(time_usecs_t usec) {
- time_conv_t ticks;
- #if CH_CFG_ST_FREQUENCY == 1000000
- ticks = usec;
- #else
- ticks = (((time_conv_t)usec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
- (time_conv_t)999999) / (time_conv_t)1000000;
- #endif
- chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
- "conversion overflow");
- return (sysinterval_t)ticks;
- }
- /**
- * @brief Time interval to seconds.
- * @details Converts from system interval to seconds.
- * @note The result is rounded up to the next second boundary.
- *
- * @param[in] interval interval in ticks
- * @return The number of seconds.
- *
- * @special
- */
- static inline time_secs_t chTimeI2S(sysinterval_t interval) {
- time_conv_t secs;
- secs = ((time_conv_t)interval +
- (time_conv_t)CH_CFG_ST_FREQUENCY -
- (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY;
- chDbgAssert(secs < (time_conv_t)((time_secs_t)-1),
- "conversion overflow");
- return (time_secs_t)secs;
- }
- /**
- * @brief Time interval to milliseconds.
- * @details Converts from system interval to milliseconds.
- * @note The result is rounded up to the next millisecond boundary.
- *
- * @param[in] interval interval in ticks
- * @return The number of milliseconds.
- *
- * @special
- */
- static inline time_msecs_t chTimeI2MS(sysinterval_t interval) {
- time_conv_t msecs;
- #if CH_CFG_ST_FREQUENCY == 1000000
- msecs = ((interval + (time_conv_t)999)/(time_conv_t)1000);
- #else
- msecs = (((time_conv_t)interval * (time_conv_t)1000) +
- (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
- (time_conv_t)CH_CFG_ST_FREQUENCY;
- #endif
- chDbgAssert(msecs < (time_conv_t)((time_msecs_t)-1),
- "conversion overflow");
- return (time_msecs_t)msecs;
- }
- /**
- * @brief Time interval to microseconds.
- * @details Converts from system interval to microseconds.
- * @note The result is rounded up to the next microsecond boundary.
- *
- * @param[in] interval interval in ticks
- * @return The number of microseconds.
- *
- * @special
- */
- static inline time_usecs_t chTimeI2US(sysinterval_t interval) {
- time_conv_t usecs;
- #if CH_CFG_ST_FREQUENCY == 1000000
- usecs = (time_conv_t)interval;
- #else
- usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
- (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
- (time_conv_t)CH_CFG_ST_FREQUENCY;
- #endif
- chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
- "conversion overflow");
- return (time_usecs_t)usecs;
- }
- /**
- * @brief Time interval to microseconds 64 bit if supported.
- * @details Converts from system interval to microseconds.
- * @note The result is rounded up to the next microsecond boundary.
- *
- * @param[in] interval interval in ticks
- * @return The number of microseconds.
- *
- * @special
- */
- static inline time_usecs_t chTimeI2US64(sysinterval_t interval) {
- time_conv_t usecs;
- #if CH_CFG_ST_FREQUENCY == 1000000
- usecs = (time_conv_t)interval;
- #else
- usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
- (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
- (time_conv_t)CH_CFG_ST_FREQUENCY;
- #endif
- chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
- "conversion overflow");
- return (time_conv_t)usecs;
- }
- /**
- * @brief Adds an interval to a system time returning a system time.
- *
- * @param[in] systime base system time
- * @param[in] interval interval to be added
- * @return The new system time.
- *
- * @xclass
- */
- static inline systime_t chTimeAddX(systime_t systime,
- sysinterval_t interval) {
- #if CH_CFG_ST_RESOLUTION != CH_CFG_INTERVALS_SIZE
- chDbgCheck(interval <= (sysinterval_t)((systime_t)-1));
- #endif
- return systime + (systime_t)interval;
- }
- /**
- * @brief Subtracts two system times returning an interval.
- *
- * @param[in] start first system time
- * @param[in] end second system time
- * @return The interval representing the time difference.
- *
- * @xclass
- */
- static inline sysinterval_t chTimeDiffX(systime_t start, systime_t end) {
- /*lint -save -e9033 [10.8] This cast is required by the operation, it is
- known that the destination type can be wider.*/
- return (sysinterval_t)((systime_t)(end - start));
- /*lint -restore*/
- }
- /**
- * @brief Checks if the specified time is within the specified time range.
- * @note When start==end then the function returns always true because the
- * whole time range is specified.
- *
- * @param[in] time the time to be verified
- * @param[in] start the start of the time window (inclusive)
- * @param[in] end the end of the time window (non inclusive)
- * @retval true current time within the specified time window.
- * @retval false current time not within the specified time window.
- *
- * @xclass
- */
- static inline bool chTimeIsInRangeX(systime_t time,
- systime_t start,
- systime_t end) {
- return (bool)((time - start) < (end - start));
- }
- /** @} */
- #endif /* CHTIME_H */
- /** @} */
|