diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2017-10-16 09:31:32 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2017-10-16 09:31:32 +0000 |
commit | 6bbfd2126f0cd20c733b78682d322250d8223d93 (patch) | |
tree | 9f9856ad4e17aeee3dba156e5211eb0579061844 /os/rt/include | |
parent | 97442e7faaed76d0da347c96df3da2122e033bd1 (diff) | |
parent | 5596d3e69e0d1c7c9a7b07f9bf83416d2c25cd8b (diff) | |
download | ChibiOS-6bbfd2126f0cd20c733b78682d322250d8223d93.tar.gz ChibiOS-6bbfd2126f0cd20c733b78682d322250d8223d93.tar.bz2 ChibiOS-6bbfd2126f0cd20c733b78682d322250d8223d93.zip |
Reintegrated RT5 point1 branch.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10833 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/rt/include')
-rw-r--r-- | os/rt/include/ch.h | 19 | ||||
-rw-r--r-- | os/rt/include/chcond.h | 4 | ||||
-rw-r--r-- | os/rt/include/chevents.h | 6 | ||||
-rw-r--r-- | os/rt/include/chschd.h | 6 | ||||
-rw-r--r-- | os/rt/include/chsem.h | 4 | ||||
-rw-r--r-- | os/rt/include/chsystypes.h | 11 | ||||
-rw-r--r-- | os/rt/include/chthreads.h | 22 | ||||
-rw-r--r-- | os/rt/include/chtime.h | 519 | ||||
-rw-r--r-- | os/rt/include/chvt.h | 418 |
9 files changed, 621 insertions, 388 deletions
diff --git a/os/rt/include/ch.h b/os/rt/include/ch.h index e11a049ac..d3bd8217b 100644 --- a/os/rt/include/ch.h +++ b/os/rt/include/ch.h @@ -66,7 +66,7 @@ #define CH_KERNEL_PATCH 0
/** @} */
-/* Core headers.*/
+/* Configuration headers and checks.*/
#include "chtypes.h"
#include "chconf.h"
@@ -78,12 +78,23 @@ #error "obsolete or unknown configuration file"
#endif
+/* Early function prototypes required by the following headers.*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSysHalt(const char *reason);
+#ifdef __cplusplus
+}
+#endif
+
+/* Including everything else.*/
#include "chlicense.h"
#include "chchecks.h"
#include "chsystypes.h"
+#include "chdebug.h"
+#include "chtime.h"
#include "chalign.h"
#include "chcore.h"
-#include "chdebug.h"
#include "chtrace.h"
#include "chtm.h"
#include "chstats.h"
@@ -108,10 +119,6 @@ #include "chfactory.h"
#include "chdynamic.h"
-#if !defined(_CHIBIOS_RT_CONF_)
-#error "missing or wrong configuration file"
-#endif
-
#endif /* CH_H */
/** @} */
diff --git a/os/rt/include/chcond.h b/os/rt/include/chcond.h index bf1e02cd5..9b753f274 100644 --- a/os/rt/include/chcond.h +++ b/os/rt/include/chcond.h @@ -98,8 +98,8 @@ extern "C" { msg_t chCondWait(condition_variable_t *cp);
msg_t chCondWaitS(condition_variable_t *cp);
#if CH_CFG_USE_CONDVARS_TIMEOUT == TRUE
- msg_t chCondWaitTimeout(condition_variable_t *cp, systime_t time);
- msg_t chCondWaitTimeoutS(condition_variable_t *cp, systime_t time);
+ msg_t chCondWaitTimeout(condition_variable_t *cp, sysinterval_t timeout);
+ msg_t chCondWaitTimeoutS(condition_variable_t *cp, sysinterval_t timeout);
#endif
#ifdef __cplusplus
}
diff --git a/os/rt/include/chevents.h b/os/rt/include/chevents.h index 8b14ed112..d155e0e6d 100644 --- a/os/rt/include/chevents.h +++ b/os/rt/include/chevents.h @@ -141,9 +141,9 @@ extern "C" { eventmask_t chEvtWaitAll(eventmask_t events);
#endif
#if CH_CFG_USE_EVENTS_TIMEOUT == TRUE
- eventmask_t chEvtWaitOneTimeout(eventmask_t events, systime_t time);
- eventmask_t chEvtWaitAnyTimeout(eventmask_t events, systime_t time);
- eventmask_t chEvtWaitAllTimeout(eventmask_t events, systime_t time);
+ eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAllTimeout(eventmask_t events, sysinterval_t timeout);
#endif
#ifdef __cplusplus
}
diff --git a/os/rt/include/chschd.h b/os/rt/include/chschd.h index 79ff437a1..9d3b5dd4e 100644 --- a/os/rt/include/chschd.h +++ b/os/rt/include/chschd.h @@ -325,7 +325,7 @@ struct ch_thread { struct ch_virtual_timer {
virtual_timer_t *next; /**< @brief Next timer in the list. */
virtual_timer_t *prev; /**< @brief Previous timer in the list. */
- systime_t delta; /**< @brief Time delta before timeout. */
+ sysinterval_t delta; /**< @brief Time delta before timeout. */
vtfunc_t func; /**< @brief Timer callback function
pointer. */
void *par; /**< @brief Timer callback function
@@ -343,7 +343,7 @@ struct ch_virtual_timers_list { list. */
virtual_timer_t *prev; /**< @brief Last timer in the delta
list. */
- systime_t delta; /**< @brief Must be initialized to -1. */
+ sysinterval_t delta; /**< @brief Must be initialized to -1. */
#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
volatile systime_t systime; /**< @brief System Time counter. */
#endif
@@ -476,7 +476,7 @@ extern "C" { thread_t *chSchReadyI(thread_t *tp);
thread_t *chSchReadyAheadI(thread_t *tp);
void chSchGoSleepS(tstate_t newstate);
- msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time);
+ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout);
void chSchWakeupS(thread_t *ntp, msg_t msg);
void chSchRescheduleS(void);
bool chSchIsPreemptionRequired(void);
diff --git a/os/rt/include/chsem.h b/os/rt/include/chsem.h index ef2848b16..d8958eeeb 100644 --- a/os/rt/include/chsem.h +++ b/os/rt/include/chsem.h @@ -93,8 +93,8 @@ extern "C" { void chSemResetI(semaphore_t *sp, cnt_t n);
msg_t chSemWait(semaphore_t *sp);
msg_t chSemWaitS(semaphore_t *sp);
- msg_t chSemWaitTimeout(semaphore_t *sp, systime_t time);
- msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t time);
+ msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout);
+ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout);
void chSemSignal(semaphore_t *sp);
void chSemSignalI(semaphore_t *sp);
void chSemAddCounterI(semaphore_t *sp, cnt_t n);
diff --git a/os/rt/include/chsystypes.h b/os/rt/include/chsystypes.h index 527ff2e8b..dac7d297b 100644 --- a/os/rt/include/chsystypes.h +++ b/os/rt/include/chsystypes.h @@ -45,17 +45,6 @@ /*===========================================================================*/
/**
- * @brief Type of system time.
- */
-#if (CH_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__)
-typedef uint32_t systime_t;
-#elif CH_CFG_ST_RESOLUTION == 16
-typedef uint16_t systime_t;
-#else
-#error "invalid CH_CFG_ST_RESOLUTION setting"
-#endif
-
-/**
* @extends threads_queue_t
*
* @brief Type of a thread structure.
diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h index 6ac40d3b8..ade7dc30b 100644 --- a/os/rt/include/chthreads.h +++ b/os/rt/include/chthreads.h @@ -190,7 +190,7 @@ typedef struct { *
* @api
*/
-#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec))
+#define chThdSleepSeconds(sec) chThdSleep(TIME_S2I(sec))
/**
* @brief Delays the invoking thread for the specified number of
@@ -206,7 +206,7 @@ typedef struct { *
* @api
*/
-#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec))
+#define chThdSleepMilliseconds(msec) chThdSleep(TIME_MS2I(msec))
/**
* @brief Delays the invoking thread for the specified number of
@@ -222,7 +222,7 @@ typedef struct { *
* @api
*/
-#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec))
+#define chThdSleepMicroseconds(usec) chThdSleep(TIME_US2I(usec))
/** @} */
/*===========================================================================*/
@@ -255,14 +255,14 @@ extern "C" { tprio_t chThdSetPriority(tprio_t newprio);
void chThdTerminate(thread_t *tp);
msg_t chThdSuspendS(thread_reference_t *trp);
- msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout);
+ msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
void chThdResumeI(thread_reference_t *trp, msg_t msg);
void chThdResumeS(thread_reference_t *trp, msg_t msg);
void chThdResume(thread_reference_t *trp, msg_t msg);
- msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout);
+ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
- void chThdSleep(systime_t time);
+ void chThdSleep(sysinterval_t time);
void chThdSleepUntil(systime_t time);
systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next);
void chThdYield(void);
@@ -376,9 +376,9 @@ static inline thread_t *chThdStartI(thread_t *tp) { }
/**
- * @brief Suspends the invoking thread for the specified time.
+ * @brief Suspends the invoking thread for the specified number of ticks.
*
- * @param[in] time the delay in system ticks, the special values are
+ * @param[in] ticks the delay in system ticks, the special values are
* handled as follow:
* - @a TIME_INFINITE the thread enters an infinite sleep
* state.
@@ -387,11 +387,11 @@ static inline thread_t *chThdStartI(thread_t *tp) { *
* @sclass
*/
-static inline void chThdSleepS(systime_t time) {
+static inline void chThdSleepS(sysinterval_t ticks) {
- chDbgCheck(time != TIME_IMMEDIATE);
+ chDbgCheck(ticks != TIME_IMMEDIATE);
- (void) chSchGoSleepTimeoutS(CH_STATE_SLEEPING, time);
+ (void) chSchGoSleepTimeoutS(CH_STATE_SLEEPING, ticks);
}
/**
diff --git a/os/rt/include/chtime.h b/os/rt/include/chtime.h new file mode 100644 index 000000000..701dfb4d5 --- /dev/null +++ b/os/rt/include/chtime.h @@ -0,0 +1,519 @@ +/*
+ ChibiOS - Copyright (C) 2006..2016 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
+ * @{
+ */
+
+#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. */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16, 32 or 64 bits.
+ */
+#if !defined(CH_CFG_ST_RESOLUTION) || defined(__DOXYGEN__)
+#define CH_CFG_ST_RESOLUTION 32
+#endif
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#if !defined(CH_CFG_ST_FREQUENCY) || defined(__DOXYGEN__)
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Time intervals data size.
+ * @note Allowed values are 16, 32 or 64 bits.
+ */
+#if !defined(CH_CFG_INTERVALS_SIZE) || defined(__DOXYGEN__)
+#define CH_CFG_INTERVALS_SIZE 32
+#endif
+
+/**
+ * @brief Time types data size.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_TIME_TYPES_SIZE) || defined(__DOXYGEN__)
+#define CH_CFG_TIME_TYPES_SIZE 32
+#endif
+
+/*===========================================================================*/
+/* 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
+ */
+#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))
+
+/**
+ * @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
+ */
+#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))
+
+/**
+ * @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
+ */
+#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)
+
+/**
+ * @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
+ */
+#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)
+/** @} */
+
+/*===========================================================================*/
+/* 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] sec 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;
+
+ ticks = (((time_conv_t)msec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
+ (time_conv_t)999) / (time_conv_t)1000;
+
+ 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;
+
+ ticks = (((time_conv_t)usec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
+ (time_conv_t)999999) / (time_conv_t)1000000;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
+ "conversion overflow");
+
+ return (time_usecs_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) {
+
+ chDbgCheck(interval <= (sysinterval_t)((systime_t)-1));
+
+ 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) {
+
+ return (sysinterval_t)((systime_t)(end - start));
+}
+
+
+/**
+ * @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 */
+
+/** @} */
diff --git a/os/rt/include/chvt.h b/os/rt/include/chvt.h index dc08dbe07..e115bec63 100644 --- a/os/rt/include/chvt.h +++ b/os/rt/include/chvt.h @@ -32,37 +32,6 @@ /* Module constants. */
/*===========================================================================*/
-/**
- * @name Special time constants
- * @{
- */
-/**
- * @brief Zero time 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 ((systime_t)0)
-
-/**
- * @brief Infinite time 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 ((systime_t)-1)
-
-/**
- * @brief Maximum time constant.
- */
-#define TIME_MAXIMUM ((systime_t)-2)
-/** @} */
-
-/**
- * @brief Maximum unsigned integer.
- */
-#define __UINT_MAX ((unsigned int)-1)
-
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
@@ -71,14 +40,6 @@ /* Derived constants and error checks. */
/*===========================================================================*/
-#if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32)
-#error "invalid CH_CFG_ST_RESOLUTION specified, must be 16 or 32"
-#endif
-
-#if CH_CFG_ST_FREQUENCY <= 0
-#error "invalid CH_CFG_ST_FREQUENCY specified, must be greater than zero"
-#endif
-
#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
#error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
"be zero or greater than one"
@@ -100,108 +61,6 @@ /* Module macros. */
/*===========================================================================*/
-/**
- * @name Fast time conversion utilities
- * @{
- */
-/**
- * @brief Seconds to system ticks.
- * @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] sec number of seconds
- * @return The number of ticks.
- *
- * @api
- */
-#define S2ST(sec) \
- ((systime_t)((uint32_t)(sec) * (uint32_t)CH_CFG_ST_FREQUENCY))
-
-/**
- * @brief Milliseconds to system ticks.
- * @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] msec number of milliseconds
- * @return The number of ticks.
- *
- * @api
- */
-#define MS2ST(msec) \
- ((systime_t)(((((uint32_t)(msec)) * \
- ((uint32_t)CH_CFG_ST_FREQUENCY)) + 999UL) / 1000UL))
-
-/**
- * @brief Microseconds to system ticks.
- * @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] usec number of microseconds
- * @return The number of ticks.
- *
- * @api
- */
-#define US2ST(usec) \
- ((systime_t)(((((uint32_t)(usec)) * \
- ((uint32_t)CH_CFG_ST_FREQUENCY)) + 999999UL) / 1000000UL))
-
-/**
- * @brief System ticks 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] n number of system ticks
- * @return The number of seconds.
- *
- * @api
- */
-#define ST2S(n) (((n) + CH_CFG_ST_FREQUENCY - 1UL) / CH_CFG_ST_FREQUENCY)
-
-/**
- * @brief System ticks 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] n number of system ticks
- * @return The number of milliseconds.
- *
- * @api
- */
-#define ST2MS(n) (((n) * 1000UL + CH_CFG_ST_FREQUENCY - 1UL) / \
- CH_CFG_ST_FREQUENCY)
-
-/**
- * @brief System ticks 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] n number of system ticks
- * @return The number of microseconds.
- *
- * @api
- */
-#define ST2US(n) (((n) * 1000000UL + CH_CFG_ST_FREQUENCY - 1UL) / \
- CH_CFG_ST_FREQUENCY)
-/** @} */
-
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@@ -213,7 +72,7 @@ extern "C" {
#endif
void _vt_init(void);
- void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
+ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
vtfunc_t vtfunc, void *par);
void chVTDoResetI(virtual_timer_t *vtp);
#ifdef __cplusplus
@@ -225,142 +84,6 @@ extern "C" { /*===========================================================================*/
/**
- * @name Secure time conversion utilities
- * @{
- */
-/**
- * @brief Seconds to system ticks.
- * @details Converts from seconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] sec number of seconds
- * @return The number of ticks.
- *
- * @api
- */
-static inline systime_t LL_S2ST(unsigned int sec) {
- uint64_t ticks = (uint64_t)sec * (uint64_t)CH_CFG_ST_FREQUENCY;
-
- chDbgAssert(ticks <= (uint64_t)TIME_MAXIMUM, "conversion overflow");
-
- return (systime_t)ticks;
-}
-
-/**
- * @brief Milliseconds to system ticks.
- * @details Converts from milliseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] msec number of milliseconds
- * @return The number of ticks.
- *
- * @api
- */
-static inline systime_t LL_MS2ST(unsigned int msec) {
- uint64_t ticks = (((uint64_t)msec * (uint64_t)CH_CFG_ST_FREQUENCY) + 999ULL)
- / 1000ULL;
-
- chDbgAssert(ticks <= (uint64_t)TIME_MAXIMUM, "conversion overflow");
-
- return (systime_t)ticks;
-}
-
-/**
- * @brief Microseconds to system ticks.
- * @details Converts from microseconds to system ticks number.
- * @note The result is rounded upward to the next tick boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] usec number of microseconds
- * @return The number of ticks.
- *
- * @api
- */
-static inline systime_t LL_US2ST(unsigned int usec) {
- uint64_t ticks = (((uint64_t)usec * (uint64_t)CH_CFG_ST_FREQUENCY) + 999999ULL)
- / 1000000ULL;
-
- chDbgAssert(ticks <= (uint64_t)TIME_MAXIMUM, "conversion overflow");
-
- return (systime_t)ticks;
-}
-
-/**
- * @brief System ticks to seconds.
- * @details Converts from system ticks number to seconds.
- * @note The result is rounded up to the next second boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] n number of system ticks
- * @return The number of seconds.
- *
- * @api
- */
-static inline unsigned int LL_ST2S(systime_t n) {
- uint64_t sec = ((uint64_t)n + (uint64_t)CH_CFG_ST_FREQUENCY - 1ULL)
- / (uint64_t)CH_CFG_ST_FREQUENCY;
-
- chDbgAssert(sec < (uint64_t)__UINT_MAX, "conversion overflow");
-
- return (unsigned int)sec;
-}
-
-/**
- * @brief System ticks to milliseconds.
- * @details Converts from system ticks number to milliseconds.
- * @note The result is rounded up to the next millisecond boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] n number of system ticks
- * @return The number of milliseconds.
- *
- * @api
- */
-static inline unsigned int LL_ST2MS(systime_t n) {
- uint64_t msec = (((uint64_t)n * 1000ULL) + (uint64_t)CH_CFG_ST_FREQUENCY - 1ULL)
- / (uint64_t)CH_CFG_ST_FREQUENCY;
-
- chDbgAssert(msec < (uint64_t)__UINT_MAX, "conversion overflow");
-
- return (unsigned int)msec;
-}
-
-/**
- * @brief System ticks to microseconds.
- * @details Converts from system ticks number to microseconds.
- * @note The result is rounded up to the next microsecond boundary.
- * @note This function uses a 64 bits internal representation,
- * use with non-constant parameters can lead to inefficient
- * code because 64 bits arithmetic would be used at runtime.
- *
- * @param[in] n number of system ticks
- * @return The number of microseconds.
- *
- * @api
- */
-static inline unsigned int LL_ST2US(systime_t n) {
- uint64_t usec = (((uint64_t)n * 1000000ULL) + (uint64_t)CH_CFG_ST_FREQUENCY - 1ULL)
- / (uint64_t)CH_CFG_ST_FREQUENCY;
-
- chDbgAssert(usec < (uint64_t)__UINT_MAX, "conversion overflow");
-
- return (unsigned int)usec;
-}
-/** @} */
-
-/**
* @brief Initializes a @p virtual_timer_t object.
* @note Initializing a timer object is not strictly required because
* the function @p chVTSetI() initializes the object too. This
@@ -426,30 +149,9 @@ static inline systime_t chVTGetSystemTime(void) { *
* @xclass
*/
-static inline systime_t chVTTimeElapsedSinceX(systime_t start) {
+static inline sysinterval_t chVTTimeElapsedSinceX(systime_t start) {
- return chVTGetSystemTimeX() - start;
-}
-
-/**
- * @brief Checks if the specified time is within the specified time window.
- * @note When start==end then the function returns always true because the
- * whole time range is specified.
- * @note This function can be called from any context.
- *
- * @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 chVTIsTimeWithinX(systime_t time,
- systime_t start,
- systime_t end) {
-
- return (bool)((systime_t)(time - start) < (systime_t)(end - start));
+ return chTimeDiffX(chVTGetSystemTimeX(), start);
}
/**
@@ -467,7 +169,7 @@ static inline bool chVTIsTimeWithinX(systime_t time, */
static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) {
- return chVTIsTimeWithinX(chVTGetSystemTimeX(), start, end);
+ return chTimeIsInRangeX(chVTGetSystemTimeX(), start, end);
}
/**
@@ -485,7 +187,7 @@ static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) { */
static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
- return chVTIsTimeWithinX(chVTGetSystemTime(), start, end);
+ return chTimeIsInRangeX(chVTGetSystemTime(), start, end);
}
/**
@@ -504,7 +206,7 @@ static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) { *
* @iclass
*/
-static inline bool chVTGetTimersStateI(systime_t *timep) {
+static inline bool chVTGetTimersStateI(sysinterval_t *timep) {
chDbgCheckClassI();
@@ -516,8 +218,10 @@ static inline bool chVTGetTimersStateI(systime_t *timep) { #if CH_CFG_ST_TIMEDELTA == 0
*timep = ch.vtlist.next->delta;
#else
- *timep = ch.vtlist.lasttime + ch.vtlist.next->delta +
- CH_CFG_ST_TIMEDELTA - chVTGetSystemTimeX();
+ *timep = chTimeDiffX(chVTGetSystemTimeX(),
+ chTimeAddX(ch.vtlist.lasttime,
+ ch.vtlist.next->delta +
+ (sysinterval_t)CH_CFG_ST_TIMEDELTA));
#endif
}
@@ -617,7 +321,7 @@ static inline void chVTReset(virtual_timer_t *vtp) { *
* @iclass
*/
-static inline void chVTSetI(virtual_timer_t *vtp, systime_t delay,
+static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay,
vtfunc_t vtfunc, void *par) {
chVTResetI(vtp);
@@ -646,7 +350,7 @@ static inline void chVTSetI(virtual_timer_t *vtp, systime_t delay, *
* @api
*/
-static inline void chVTSet(virtual_timer_t *vtp, systime_t delay,
+static inline void chVTSet(virtual_timer_t *vtp, sysinterval_t delay,
vtfunc_t vtfunc, void *par) {
chSysLock();
@@ -672,7 +376,7 @@ static inline void chVTDoTickI(void) { if (&ch.vtlist != (virtual_timers_list_t *)ch.vtlist.next) {
/* The list is not empty, processing elements on top.*/
--ch.vtlist.next->delta;
- while (ch.vtlist.next->delta == (systime_t)0) {
+ while (ch.vtlist.next->delta == (sysinterval_t)0) {
virtual_timer_t *vtp;
vtfunc_t fn;
@@ -688,48 +392,51 @@ static inline void chVTDoTickI(void) { }
#else /* CH_CFG_ST_TIMEDELTA > 0 */
virtual_timer_t *vtp;
- systime_t now, delta;
+ systime_t now;
+ sysinterval_t delta, nowdelta;
- /* First timer to be processed.*/
+ /* Looping through timers.*/
vtp = ch.vtlist.next;
- now = chVTGetSystemTimeX();
-
- /* All timers within the time window are triggered and removed,
- note that the loop is stopped by the timers header having
- "ch.vtlist.vt_delta == (systime_t)-1" which is greater than
- all deltas.*/
- while (vtp->delta <= (systime_t)(now - ch.vtlist.lasttime)) {
- vtfunc_t fn;
-
- /* The "last time" becomes this timer's expiration time.*/
- ch.vtlist.lasttime += vtp->delta;
-
- vtp->next->prev = (virtual_timer_t *)&ch.vtlist;
- ch.vtlist.next = vtp->next;
- fn = vtp->func;
- vtp->func = NULL;
-
- /* if the list becomes empty then the timer is stopped.*/
- if (ch.vtlist.next == (virtual_timer_t *)&ch.vtlist) {
- port_timer_stop_alarm();
+ while (true) {
+
+ /* Getting the system time as reference.*/
+ now = chVTGetSystemTimeX();
+ nowdelta = chTimeDiffX(ch.vtlist.lasttime, now);
+
+ /* The list scan is limited by the timers header having
+ "ch.vtlist.vt_delta == (sysinterval_t)-1" which is
+ greater than all deltas.*/
+ if (nowdelta < vtp->delta) {
+ break;
}
- /* Leaving the system critical zone in order to execute the callback
- and in order to give a preemption chance to higher priority
- interrupts.*/
- chSysUnlockFromISR();
+ /* Consuming all timers between "vtp->lasttime" and now.*/
+ do {
+ vtfunc_t fn;
- /* The callback is invoked outside the kernel critical zone.*/
- fn(vtp->par);
+ /* The "last time" becomes this timer's expiration time.*/
+ ch.vtlist.lasttime += vtp->delta;
+ nowdelta -= vtp->delta;
- /* Re-entering the critical zone in order to continue the exploration
- of the list.*/
- chSysLockFromISR();
+ vtp->next->prev = (virtual_timer_t *)&ch.vtlist;
+ ch.vtlist.next = vtp->next;
+ fn = vtp->func;
+ vtp->func = NULL;
- /* Next element in the list, the current time could have advanced so
- recalculating the time window.*/
- vtp = ch.vtlist.next;
- now = chVTGetSystemTimeX();
+ /* if the list becomes empty then the timer is stopped.*/
+ if (ch.vtlist.next == (virtual_timer_t *)&ch.vtlist) {
+ port_timer_stop_alarm();
+ }
+
+ /* The callback is invoked outside the kernel critical zone.*/
+ chSysUnlockFromISR();
+ fn(vtp->par);
+ chSysLockFromISR();
+
+ /* Next element in the list.*/
+ vtp = ch.vtlist.next;
+ }
+ while (vtp->delta <= nowdelta);
}
/* if the list is empty, nothing else to do.*/
@@ -737,15 +444,26 @@ static inline void chVTDoTickI(void) { return;
}
+ /* The "unprocessed nowdelta" time slice is added to "last time"
+ and subtracted to next timer's delta.*/
+ ch.vtlist.lasttime += nowdelta;
+ ch.vtlist.next->delta -= nowdelta;
+
/* Recalculating the next alarm time.*/
- delta = ch.vtlist.lasttime + vtp->delta - now;
- if (delta < (systime_t)CH_CFG_ST_TIMEDELTA) {
- delta = (systime_t)CH_CFG_ST_TIMEDELTA;
+ delta = chTimeDiffX(now, chTimeAddX(ch.vtlist.lasttime, vtp->delta));
+ if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
+ delta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
}
- port_timer_set_alarm(now + delta);
+#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
+ /* The delta could be too large for the physical timer to handle.*/
+ else if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
+ delta = (sysinterval_t)TIME_MAX_SYSTIME;
+ }
+#endif
+ port_timer_set_alarm(chTimeAddX(now, delta));
- chDbgAssert((chVTGetSystemTimeX() - ch.vtlist.lasttime) <=
- (now + delta - ch.vtlist.lasttime),
+ chDbgAssert(chTimeDiffX(ch.vtlist.lasttime, chVTGetSystemTimeX()) <=
+ chTimeDiffX(ch.vtlist.lasttime, chTimeAddX(now, delta)),
"exceeding delta");
#endif /* CH_CFG_ST_TIMEDELTA > 0 */
}
|