From 0cb6bc9b9d260beb05fcc9e2ec4d72f0ba621b71 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 28 Jul 2013 12:15:57 +0000 Subject: 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 --- os/kernel/src/chrt.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++ os/kernel/src/chsys.c | 3 + os/kernel/src/chthreads.c | 2 +- 3 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 os/kernel/src/chrt.c (limited to 'os/kernel/src') 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 . +*/ + +/** + * @file chvt.c + * @brief Real Time Counter and Measurement module code. + * + * @addtogroup realtime_counter + * @details Realtime Counter APIs and services. + * + *

Operation mode

+ * 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. + * + *

Notes

+ * 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(); } -- cgit v1.2.3