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:
parent
ded823da22
commit
70aee6011b
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue