From 70aee6011b8f5fc985140464623019f6d57af540 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 22 Dec 2016 10:36:32 +0000 Subject: Added standalone virtual timers module. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9985 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/osal/lib/osal_vt.c | 168 +++++++++++++++++++++++++++++++++++++ os/hal/osal/lib/osal_vt.h | 131 +++++++++++++++++++++++++++++ os/hal/osal/os-less/ARMCMx/osal.c | 115 +------------------------ os/hal/osal/os-less/ARMCMx/osal.h | 49 ----------- os/hal/osal/os-less/ARMCMx/osal.mk | 6 +- readme.txt | 3 + 6 files changed, 307 insertions(+), 165 deletions(-) create mode 100644 os/hal/osal/lib/osal_vt.c create mode 100644 os/hal/osal/lib/osal_vt.h diff --git a/os/hal/osal/lib/osal_vt.c b/os/hal/osal/lib/osal_vt.c new file mode 100644 index 000000000..8954b5c8f --- /dev/null +++ b/os/hal/osal/lib/osal_vt.c @@ -0,0 +1,168 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file osal_vt.c + * @brief OSAL Virtual Timers module code. + * @details This module can be used in an OSAL implementation whenever an + * underlying RTOS is unable to provide timeout services or there + * is no underlying RTOS. + * + * @addtogroup OSAL_VT + * @{ + */ + +#include "osal.h" +#include "osal_vt.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Virtual timers delta list header. + */ +virtual_timers_list_t vtlist; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Timers initialization. + * + * @init + */ +void vtInit(void) { + + /* Virtual Timers initialization.*/ + vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist; + vtlist.vt_time = (systime_t)-1; + vtlist.vt_systime = 0; +} + +/** + * @brief Returns @p TRUE if the specified timer is armed. + * + * @param[out] vtp the @p virtual_timer_t structure pointer + * + * @iclass + */ +bool vtIsArmedI(virtual_timer_t *vtp) { + + return vtp->vt_func != NULL; +} + +/** + * @brief Virtual timers ticker. + * @note The system lock is released before entering the callback and + * re-acquired immediately after. It is callback's responsibility + * to acquire the lock if needed. This is done in order to reduce + * interrupts jitter when many timers are in use. + * + * @iclass + */ +void vtDoTickI(void) { + + vtlist.vt_systime++; + if (&vtlist != (virtual_timers_list_t *)vtlist.vt_next) { + virtual_timer_t *vtp; + + --vtlist.vt_next->vt_time; + while (!(vtp = vtlist.vt_next)->vt_time) { + vtfunc_t fn = vtp->vt_func; + vtp->vt_func = (vtfunc_t)NULL; + vtp->vt_next->vt_prev = (void *)&vtlist; + (&vtlist)->vt_next = vtp->vt_next; + osalSysUnlockFromISR(); + fn(vtp->vt_par); + osalSysLockFromISR(); + } + } +} + +/** + * @brief Enables a virtual timer. + * @note The associated function is invoked from interrupt context. + * + * @param[out] vtp the @p virtual_timer_t structure pointer + * @param[in] time the number of ticks before the operation timeouts, the + * special values are handled as follow: + * - @a TIME_INFINITE is allowed but interpreted as a + * normal time specification. + * - @a TIME_IMMEDIATE this value is not allowed. + * . + * @param[in] vtfunc the timer callback function. After invoking the + * callback the timer is disabled and the structure can + * be disposed or reused. + * @param[in] par a parameter that will be passed to the callback + * function + * + * @iclass + */ +void vtSetI(virtual_timer_t *vtp, systime_t time, + vtfunc_t vtfunc, void *par) { + virtual_timer_t *p; + + vtp->vt_par = par; + vtp->vt_func = vtfunc; + p = vtlist.vt_next; + while (p->vt_time < time) { + time -= p->vt_time; + p = p->vt_next; + } + + vtp->vt_prev = (vtp->vt_next = p)->vt_prev; + vtp->vt_prev->vt_next = p->vt_prev = vtp; + vtp->vt_time = time; + if (p != (void *)&vtlist) + p->vt_time -= time; +} + +/** + * @brief Disables a Virtual Timer. + * @note The timer MUST be active when this function is invoked. + * + * @param[in] vtp the @p virtual_timer_t structure pointer + * + * @iclass + */ +void vtResetI(virtual_timer_t *vtp) { + + if (vtp->vt_next != (void *)&vtlist) + vtp->vt_next->vt_time += vtp->vt_time; + vtp->vt_prev->vt_next = vtp->vt_next; + vtp->vt_next->vt_prev = vtp->vt_prev; + vtp->vt_func = (vtfunc_t)NULL; +} + +/** @} */ diff --git a/os/hal/osal/lib/osal_vt.h b/os/hal/osal/lib/osal_vt.h new file mode 100644 index 000000000..e46365c37 --- /dev/null +++ b/os/hal/osal/lib/osal_vt.h @@ -0,0 +1,131 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file osal_vt.h + * @brief OSAL Virtual Timers module header. + * + * @addtogroup OSAL_VT + * @{ + */ + +#ifndef _OSAL_VT_H_ +#define _OSAL_VT_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Special time constants + * @{ + */ +#define TIME_IMMEDIATE ((systime_t)0) +#define TIME_INFINITE ((systime_t)-1) +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a Virtual Timer callback function. + */ +typedef void (*vtfunc_t)(void *); + +/** + * @brief Type of a Virtual Timer structure. + */ +typedef struct virtual_timer virtual_timer_t; + +/** + * @brief Virtual timers list header. + * @note The content of this structure is not part of the API and should + * not be relied upon. Implementers may define this structure in + * an entirely different way. + * @note The delta list is implemented as a double link bidirectional list + * in order to make the unlink time constant, the reset of a virtual + * timer is often used in the code. + */ +typedef struct { + virtual_timer_t *vt_next; /**< @brief Next timer in the timers + list. */ + virtual_timer_t *vt_prev; /**< @brief Last timer in the timers + list. */ + systime_t vt_time; /**< @brief Must be initialized to -1. */ + volatile systime_t vt_systime; /**< @brief System Time counter. */ +} virtual_timers_list_t; + +/** + * @extends virtual_timers_list_t + * + * @brief Virtual Timer descriptor structure. + * @note The content of this structure is not part of the API and should + * not be relied upon. Implementers may define this structure in + * an entirely different way. + */ +struct virtual_timer { + virtual_timer_t *vt_next; /**< @brief Next timer in the timers + list. */ + virtual_timer_t *vt_prev; /**< @brief Previous timer in the timers + list. */ + systime_t vt_time; /**< @brief Time delta before timeout. */ + vtfunc_t vt_func; /**< @brief Timer callback function + pointer. */ + void *vt_par; /**< @brief Timer callback function + parameter. */ +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern virtual_timers_list_t vtlist; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void vtInit(void); + bool vtIsArmedI(virtual_timer_t *vtp); + void vtDoTickI(void); + void vtSetI(virtual_timer_t *vtp, systime_t time, + vtfunc_t vtfunc, void *par); + void vtResetI(virtual_timer_t *vtp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* _OSAL_VT_H_ */ + +/** @} */ diff --git a/os/hal/osal/os-less/ARMCMx/osal.c b/os/hal/osal/os-less/ARMCMx/osal.c index 4a272bd31..571e6d6b5 100644 --- a/os/hal/osal/os-less/ARMCMx/osal.c +++ b/os/hal/osal/os-less/ARMCMx/osal.c @@ -23,6 +23,7 @@ */ #include "osal.h" +#include "osal_vt.h" /*===========================================================================*/ /* Module local definitions. */ @@ -39,11 +40,6 @@ */ const char *osal_halt_msg; -/** - * @brief Virtual timers delta list header. - */ -virtual_timers_list_t vtlist; - /*===========================================================================*/ /* Module local types. */ /*===========================================================================*/ @@ -56,115 +52,6 @@ virtual_timers_list_t vtlist; /* Module local functions. */ /*===========================================================================*/ -/** - * @brief Timers initialization. - * - * @notapi - */ -static void vtInit(void) { - - /* Virtual Timers initialization.*/ - vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist; - vtlist.vt_time = (systime_t)-1; - vtlist.vt_systime = 0; -} - -/** - * @brief Returns @p TRUE if the specified timer is armed. - * - * @param[out] vtp the @p virtual_timer_t structure pointer - * - * @notapi - */ -static bool vtIsArmedI(virtual_timer_t *vtp) { - - return vtp->vt_func != NULL; -} - -/** - * @brief Virtual timers ticker. - * @note The system lock is released before entering the callback and - * re-acquired immediately after. It is callback's responsibility - * to acquire the lock if needed. This is done in order to reduce - * interrupts jitter when many timers are in use. - * - * @notapi - */ -static void vtDoTickI(void) { - - vtlist.vt_systime++; - if (&vtlist != (virtual_timers_list_t *)vtlist.vt_next) { - virtual_timer_t *vtp; - - --vtlist.vt_next->vt_time; - while (!(vtp = vtlist.vt_next)->vt_time) { - vtfunc_t fn = vtp->vt_func; - vtp->vt_func = (vtfunc_t)NULL; - vtp->vt_next->vt_prev = (void *)&vtlist; - (&vtlist)->vt_next = vtp->vt_next; - osalSysUnlockFromISR(); - fn(vtp->vt_par); - osalSysLockFromISR(); - } - } -} - -/** - * @brief Enables a virtual timer. - * @note The associated function is invoked from interrupt context. - * - * @param[out] vtp the @p virtual_timer_t structure pointer - * @param[in] time the number of ticks before the operation timeouts, the - * special values are handled as follow: - * - @a TIME_INFINITE is allowed but interpreted as a - * normal time specification. - * - @a TIME_IMMEDIATE this value is not allowed. - * . - * @param[in] vtfunc the timer callback function. After invoking the - * callback the timer is disabled and the structure can - * be disposed or reused. - * @param[in] par a parameter that will be passed to the callback - * function - * - * @notapi - */ -static void vtSetI(virtual_timer_t *vtp, systime_t time, - vtfunc_t vtfunc, void *par) { - virtual_timer_t *p; - - vtp->vt_par = par; - vtp->vt_func = vtfunc; - p = vtlist.vt_next; - while (p->vt_time < time) { - time -= p->vt_time; - p = p->vt_next; - } - - vtp->vt_prev = (vtp->vt_next = p)->vt_prev; - vtp->vt_prev->vt_next = p->vt_prev = vtp; - vtp->vt_time = time; - if (p != (void *)&vtlist) - p->vt_time -= time; -} - -/** - * @brief Disables a Virtual Timer. - * @note The timer MUST be active when this function is invoked. - * - * @param[in] vtp the @p virtual_timer_t structure pointer - * - * @notapi - */ -static void vtResetI(virtual_timer_t *vtp) { - - if (vtp->vt_next != (void *)&vtlist) - vtp->vt_next->vt_time += vtp->vt_time; - vtp->vt_prev->vt_next = vtp->vt_next; - vtp->vt_next->vt_prev = vtp->vt_prev; - vtp->vt_func = (vtfunc_t)NULL; -} - - static void callback_timeout(void *p) { osalSysLockFromISR(); osalThreadResumeI((thread_reference_t *)p, MSG_TIMEOUT); diff --git a/os/hal/osal/os-less/ARMCMx/osal.h b/os/hal/osal/os-less/ARMCMx/osal.h index 77500eeeb..9843cef97 100644 --- a/os/hal/osal/os-less/ARMCMx/osal.h +++ b/os/hal/osal/os-less/ARMCMx/osal.h @@ -63,7 +63,6 @@ #define MSG_WAIT (msg_t)-10 /** @} */ - /** * @name Special time constants * @{ @@ -177,54 +176,6 @@ typedef int32_t msg_t; */ typedef uint32_t systime_t; -/** - * @brief Type of a Virtual Timer callback function. - */ -typedef void (*vtfunc_t)(void *); - -/** - * @brief Type of a Virtual Timer structure. - */ -typedef struct virtual_timer virtual_timer_t; - -/** - * @brief Virtual timers list header. - * @note The content of this structure is not part of the API and should - * not be relied upon. Implementers may define this structure in - * an entirely different way. - * @note The delta list is implemented as a double link bidirectional list - * in order to make the unlink time constant, the reset of a virtual - * timer is often used in the code. - */ -typedef struct { - virtual_timer_t *vt_next; /**< @brief Next timer in the timers - list. */ - virtual_timer_t *vt_prev; /**< @brief Last timer in the timers - list. */ - systime_t vt_time; /**< @brief Must be initialized to -1. */ - volatile systime_t vt_systime; /**< @brief System Time counter. */ -} virtual_timers_list_t; - -/** - * @extends virtual_timers_list_t - * - * @brief Virtual Timer descriptor structure. - * @note The content of this structure is not part of the API and should - * not be relied upon. Implementers may define this structure in - * an entirely different way. - */ -struct virtual_timer { - virtual_timer_t *vt_next; /**< @brief Next timer in the timers - list. */ - virtual_timer_t *vt_prev; /**< @brief Previous timer in the timers - list. */ - systime_t vt_time; /**< @brief Time delta before timeout. */ - vtfunc_t vt_func; /**< @brief Timer callback function - pointer. */ - void *vt_par; /**< @brief Timer callback function - parameter. */ -}; - /** * @brief Type of realtime counter. */ diff --git a/os/hal/osal/os-less/ARMCMx/osal.mk b/os/hal/osal/os-less/ARMCMx/osal.mk index 8a6e940ce..5ecb54216 100644 --- a/os/hal/osal/os-less/ARMCMx/osal.mk +++ b/os/hal/osal/os-less/ARMCMx/osal.mk @@ -1,5 +1,7 @@ # OSAL files. -OSALSRC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx/osal.c +OSALSRC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx/osal.c \ + ${CHIBIOS}/os/hal/osal/lib/osal_vt.c # Required include directories -OSALINC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx +OSALINC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx \ + ${CHIBIOS}/os/hal/osal/lib diff --git a/readme.txt b/readme.txt index d06bc7dce..1ca997083 100644 --- a/readme.txt +++ b/readme.txt @@ -86,6 +86,9 @@ ***************************************************************************** *** Next *** +- HAL: Implemented separated virtual timers module under /os/hal/osal/lib, + it can be used by OSAL implementations where the underlying RTOS is + lacking a timeout feature or missing. - HAL: Added CAN3 support to the STM32 CANv1 driver. - HAL: Added support for all existing STM32 Nucleo and Discovery boards. - HAL: Extended STM32F4xx port by adding STM32F412 support. -- cgit v1.2.3