diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2013-07-28 12:15:57 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2013-07-28 12:15:57 +0000 |
commit | 0cb6bc9b9d260beb05fcc9e2ec4d72f0ba621b71 (patch) | |
tree | 5c939b5cdc9ec039dd36e93bd7fbf416674e40e3 | |
parent | cea523fdb0cad1ec6422a9b4ea13ba08da0932a1 (diff) | |
download | ChibiOS-0cb6bc9b9d260beb05fcc9e2ec4d72f0ba621b71.tar.gz ChibiOS-0cb6bc9b9d260beb05fcc9e2ec4d72f0ba621b71.tar.bz2 ChibiOS-0cb6bc9b9d260beb05fcc9e2ec4d72f0ba621b71.zip |
RT measurements unit added.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6036 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r-- | os/kernel/include/ch.h | 4 | ||||
-rw-r--r-- | os/kernel/include/chrt.h | 98 | ||||
-rw-r--r-- | os/kernel/include/chvt.h | 17 | ||||
-rw-r--r-- | os/kernel/kernel.mk | 1 | ||||
-rw-r--r-- | os/kernel/src/chrt.c | 206 | ||||
-rw-r--r-- | os/kernel/src/chsys.c | 3 | ||||
-rw-r--r-- | os/kernel/src/chthreads.c | 2 | ||||
-rw-r--r-- | os/ports/GCC/ARMCMx/chtypes.h | 7 |
8 files changed, 257 insertions, 81 deletions
diff --git a/os/kernel/include/ch.h b/os/kernel/include/ch.h index c7e3ec80d..1d1e053ce 100644 --- a/os/kernel/include/ch.h +++ b/os/kernel/include/ch.h @@ -109,11 +109,11 @@ typedef struct thread thread_t; #include "chtypes.h"
#include "chdebug.h"
#include "chcore.h"
+#include "chsys.h"
+#include "chvt.h"
#include "chrt.h"
#include "chthreads.h"
#include "chlists.h"
-#include "chsys.h"
-#include "chvt.h"
#include "chschd.h"
#include "chregistry.h"
#include "chsem.h"
diff --git a/os/kernel/include/chrt.h b/os/kernel/include/chrt.h index bac5635dc..dfb2a4277 100644 --- a/os/kernel/include/chrt.h +++ b/os/kernel/include/chrt.h @@ -22,7 +22,7 @@ * @file chrt.h
* @brief Real Time Counter and Measurement module macros and structures.
*
- * @addtogroup rt_measurement
+ * @addtogroup realtime_counter
* @{
*/
@@ -45,17 +45,29 @@ /* Derived constants and error checks. */
/*===========================================================================*/
-#if !CH_PORT_SUPPORTS_RT
-#error "the port layer does not support the realtime counter functionality"
-#endif
-
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
+/**
+ * @brief Type of a Time Measurement object.
+ * @note The maximum measurable time period depends on the implementation
+ * of the realtime counter and its clock frequency.
+ * @note The measurement is not 100% cycle-accurate, it can be in excess
+ * of few cycles depending on the compiler and target architecture.
+ * @note Interrupts can affect measurement if the measurement is performed
+ * with interrupts enabled.
+ */
+typedef struct {
+ rtcnt_t last; /**< @brief Last measurement. */
+ rtcnt_t worst; /**< @brief Worst measurement. */
+ rtcnt_t best; /**< @brief Best measurement. */
+} time_measurement_t;
+
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
+
/**
* @name Time conversion utilities for the realtime counter
* @{
@@ -137,6 +149,11 @@ #ifdef __cplusplus
extern "C" {
#endif
+ bool chRTIsCounterWithin(rtcnt_t start, rtcnt_t end);
+ void chRTPolledDelay(rtcnt_t cycles);
+ void chRTTimeMeasurementObjectInit(time_measurement_t *tmp);
+ NOINLINE void chRTTimeMeasurementStartX(time_measurement_t *tmp);
+ NOINLINE void chRTTimeMeasurementStopX(time_measurement_t *tmp);
#ifdef __cplusplus
}
#endif
@@ -154,74 +171,13 @@ extern "C" { *
* @special
*/
-static inline rtcnt_t chRTGetCounterValue(void) {
+static inline rtcnt_t chRTGetCounterValueX(void) {
+#if !CH_PORT_SUPPORTS_RT
return port_rt_get_counter_value();
-}
-
-/**
- * @brief Realtime window test.
- * @details This function verifies if the current realtime counter value
- * lies within the specified range or not. The test takes care
- * of the realtime counter wrapping to zero on overflow.
- * @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.
- *
- * @par Example 1
- * Example of a guarded loop using the realtime counter. The loop implements
- * a timeout after one second.
- * @code
- * rtcnt_t start = chRTGetCounterValue();
- * rtcnt_t timeout = start + S2RTC(1);
- * while (my_condition) {
- * if (!chRTIsCounterWithin(start, timeout)
- * return TIMEOUT;
- * // Do something.
- * }
- * // Continue.
- * @endcode
- *
- * @par Example 2
- * Example of a loop that lasts exactly 50 microseconds.
- * @code
- * rtcnt_t start = chRTGetCounterValue();
- * rtcnt_t timeout = start + US2RTC(50);
- * while (chRTIsCounterWithin(start, timeout)) {
- * // Do something.
- * }
- * // Continue.
- * @endcode
- *
- * @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.
- *
- * @special
- */
-static inline bool chRTIsCounterWithin(rtcnt_t start, rtcnt_t end) {
- rtcnt_t now = chRTGetCounterValue();
-
- return end > start ? (now >= start) && (now < end) :
- (now >= start) || (now < end);
-}
-
-/**
- * @brief Polled delay.
- * @note The real delay is always few cycles in excess of the specified
- * value.
- * @note This function can be called from any context.
- *
- * @param[in] ticks number of ticks
- *
- * @special
- */
-static inline void chRTPolledDelay(rtcnt_t ticks) {
- rtcnt_t start = chRTGetCounterValue();
- rtcnt_t timeout = start + (ticks);
- while (chRTIsCounterWithin(start, timeout))
- ;
+#else
+ return chVTGetSystemTimeX();
+#endif
}
#endif /* CH_CFG_USE_RT */
diff --git a/os/kernel/include/chvt.h b/os/kernel/include/chvt.h index 39f03b995..a53a3f502 100644 --- a/os/kernel/include/chvt.h +++ b/os/kernel/include/chvt.h @@ -202,14 +202,15 @@ static inline void chVTObjectInit(virtual_timer_t *vtp) { * @details Returns the number of system ticks since the @p chSysInit()
* invocation.
* @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @systime_t size.
*
* @return The system time in ticks.
*
- * @iclass
+ * @special
*/
-static inline systime_t chVTGetSystemTimeI(void) {
-
- chDbgCheckClassI();
+static inline systime_t chVTGetSystemTimeX(void) {
#if CH_CFG_TIMEDELTA == 0
return vtlist.vt_systime;
@@ -232,7 +233,7 @@ static inline systime_t chVTGetSystemTime(void) { systime_t systime;
chSysLock();
- systime = chVTGetSystemTimeI();
+ systime = chVTGetSystemTimeX();
chSysUnlock();
return systime;
}
@@ -252,7 +253,9 @@ static inline systime_t chVTGetSystemTime(void) { */
static inline bool chVTIsSystemTimeWithinI(systime_t start, systime_t end) {
- return chVTIsTimeWithin(chVTGetSystemTimeI(), start, end);
+ chDbgCheckClassI();
+
+ return chVTIsTimeWithin(chVTGetSystemTimeX(), start, end);
}
/**
@@ -395,7 +398,7 @@ static inline void chVTDoTickI(void) { }
#else /* CH_CFG_TIMEDELTA > 0 */
virtual_timer_t *vtp;
- systime_t now = chVTGetSystemTimeI();
+ systime_t now = chVTGetSystemTimeX();
systime_t delta = now - vtlist.vt_lasttime;
while ((vtp = vtlist.vt_next)->vt_delta <= delta) {
diff --git a/os/kernel/kernel.mk b/os/kernel/kernel.mk index 3ebf2ed98..d0617e536 100644 --- a/os/kernel/kernel.mk +++ b/os/kernel/kernel.mk @@ -4,6 +4,7 @@ KERNSRC = ${CHIBIOS}/os/kernel/src/chsys.c \ ${CHIBIOS}/os/kernel/src/chdebug.c \
${CHIBIOS}/os/kernel/src/chlists.c \
${CHIBIOS}/os/kernel/src/chvt.c \
+ ${CHIBIOS}/os/kernel/src/chrt.c \
${CHIBIOS}/os/kernel/src/chschd.c \
${CHIBIOS}/os/kernel/src/chthreads.c \
${CHIBIOS}/os/kernel/src/chdynamic.c \
diff --git a/os/kernel/src/chrt.c b/os/kernel/src/chrt.c new file mode 100644 index 000000000..a63ce9e32 --- /dev/null +++ b/os/kernel/src/chrt.c @@ -0,0 +1,206 @@ +/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT 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/RT 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 chvt.c
+ * @brief Real Time Counter and Measurement module code.
+ *
+ * @addtogroup realtime_counter
+ * @details Realtime Counter APIs and services.
+ *
+ * <h2>Operation mode</h2>
+ * The realtime counter is a fast HW counter that counts upward at
+ * regular intervals. This counted can be used for small and accurate
+ * delays, time stamp and time measurement.
+ *
+ * <h2>Notes</h2>
+ * On those architectures where such a counter is not implemented
+ * the system time counter is used instead. Of course the system
+ * time counter usually has a much lower resolution than a real
+ * HW counter.
+ * @{
+ */
+
+#include "ch.h"
+
+#if CH_CFG_USE_RT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Subsystem calibration value.
+ */
+static rtcnt_t measurement_offset;
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the realtime counter unit.
+ *
+ * @init
+ */
+void _rt_init(void) {
+ time_measurement_t tm;
+
+ /* Time Measurement subsystem calibration, it does a null measurement
+ and calculates the call overhead which is subtracted to real
+ measurements.*/
+ measurement_offset = 0;
+ chRTTimeMeasurementObjectInit(&tm);
+ chRTTimeMeasurementStartX(&tm);
+ chRTTimeMeasurementStopX(&tm);
+ measurement_offset = tm.last;
+}
+
+/**
+ * @brief Realtime window test.
+ * @details This function verifies if the current realtime counter value
+ * lies within the specified range or not. The test takes care
+ * of the realtime counter wrapping to zero on overflow.
+ * @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.
+ *
+ * @par Example 1
+ * Example of a guarded loop using the realtime counter. The loop implements
+ * a timeout after one second.
+ * @code
+ * rtcnt_t start = chRTGetCounterValue();
+ * rtcnt_t timeout = start + S2RTC(RTCCLK, 1);
+ * while (my_condition) {
+ * if (!chRTIsCounterWithin(start, timeout)
+ * return TIMEOUT;
+ * // Do something.
+ * }
+ * // Continue.
+ * @endcode
+ *
+ * @par Example 2
+ * Example of a loop that lasts exactly 50 microseconds.
+ * @code
+ * rtcnt_t start = chRTGetCounterValue();
+ * rtcnt_t timeout = start + US2RTC(RTCCLK, 50);
+ * while (chRTIsCounterWithin(start, timeout)) {
+ * // Do something.
+ * }
+ * // Continue.
+ * @endcode
+ *
+ * @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.
+ *
+ * @special
+ */
+bool chRTIsCounterWithin(rtcnt_t start, rtcnt_t end) {
+ rtcnt_t now = chRTGetCounterValueX();
+
+ return end > start ? (now >= start) && (now < end) :
+ (now >= start) || (now < end);
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ * @note This function can be called from any context.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @special
+ */
+void chRTPolledDelay(rtcnt_t cycles) {
+ rtcnt_t start = chRTGetCounterValueX();
+ rtcnt_t end = start + cycles;
+ while (chRTIsCounterWithin(start, end))
+ ;
+}
+
+/**
+ * @brief Initializes a @p TimeMeasurement object.
+ *
+ * @param[out] tmp pointer to a @p TimeMeasurement structure
+ *
+ * @init
+ */
+void chRTTimeMeasurementObjectInit(time_measurement_t *tmp) {
+
+ tmp->last = (rtcnt_t)0;
+ tmp->worst = (rtcnt_t)0;
+ tmp->best = (rtcnt_t)-1;
+}
+
+/**
+ * @brief Starts a measurement.
+ * @pre The @p time_measurement_t structure must be initialized.
+ * @note This function can be invoked from any context.
+ *
+ * @param[in,out] tmp pointer to a @p TimeMeasurement structure
+ *
+ * @special
+ */
+NOINLINE void chRTTimeMeasurementStartX(time_measurement_t *tmp) {
+
+ tmp->last = chRTGetCounterValueX();
+}
+
+/**
+ * @brief Stops a measurement.
+ * @pre The @p time_measurement_t structure must be initialized.
+ * @note This function can be invoked from any context.
+ *
+ * @param[in,out] tmp pointer to a @p time_measurement_t structure
+ *
+ * @special
+ */
+NOINLINE void chRTTimeMeasurementStopX(time_measurement_t *tmp) {
+
+ rtcnt_t now = chRTGetCounterValueX();
+ tmp->last = now - tmp->last - measurement_offset;
+ if (tmp->last > tmp->worst)
+ tmp->worst = tmp->last;
+ else if (tmp->last < tmp->best)
+ tmp->best = tmp->last;
+}
+
+#endif /* CH_CFG_USE_RT */
+
+/** @} */
diff --git a/os/kernel/src/chsys.c b/os/kernel/src/chsys.c index 4a67c7042..91277dc60 100644 --- a/os/kernel/src/chsys.c +++ b/os/kernel/src/chsys.c @@ -105,6 +105,9 @@ void chSysInit(void) { port_init();
_scheduler_init();
_vt_init();
+#if CH_CFG_USE_RT
+ _rt_init();
+#endif
#if CH_CFG_USE_MEMCORE
_core_init();
#endif
diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c index 9017a59b7..b707b4562 100644 --- a/os/kernel/src/chthreads.c +++ b/os/kernel/src/chthreads.c @@ -327,7 +327,7 @@ void chThdSleep(systime_t time) { void chThdSleepUntil(systime_t time) {
chSysLock();
- if ((time -= chVTGetSystemTimeI()) > 0)
+ if ((time -= chVTGetSystemTimeX()) > 0)
chThdSleepS(time);
chSysUnlock();
}
diff --git a/os/ports/GCC/ARMCMx/chtypes.h b/os/ports/GCC/ARMCMx/chtypes.h index 65f8cafeb..6870fbd6e 100644 --- a/os/ports/GCC/ARMCMx/chtypes.h +++ b/os/ports/GCC/ARMCMx/chtypes.h @@ -54,6 +54,13 @@ typedef int32_t cnt_t; /**< Resources counter. */ */
#define ROMCONST const
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then the
+ * realtime counter precision could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
#endif /* _CHTYPES_H_ */
/** @} */
|