Added standalone virtual timers module.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9985 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2016-12-22 10:36:32 +00:00
parent ded823da22
commit 70aee6011b
6 changed files with 307 additions and 165 deletions

168
os/hal/osal/lib/osal_vt.c Normal file
View File

@ -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;
}
/** @} */

131
os/hal/osal/lib/osal_vt.h Normal file
View File

@ -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_ */
/** @} */

View File

@ -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);

View File

@ -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.
*/

View File

@ -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

View File

@ -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.