diff --git a/demos/STM32/RT-STM32G474RE-NUCLEO64/Makefile b/demos/STM32/RT-STM32G474RE-NUCLEO64/Makefile
index 636ed0cf4..e2b9c6eeb 100644
--- a/demos/STM32/RT-STM32G474RE-NUCLEO64/Makefile
+++ b/demos/STM32/RT-STM32G474RE-NUCLEO64/Makefile
@@ -5,7 +5,7 @@
# Compiler options here.
ifeq ($(USE_OPT),)
- USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
+ USE_OPT = -Og -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
diff --git a/demos/STM32/RT-STM32G474RE-NUCLEO64/main.c b/demos/STM32/RT-STM32G474RE-NUCLEO64/main.c
index 20d98a53d..341123b09 100644
--- a/demos/STM32/RT-STM32G474RE-NUCLEO64/main.c
+++ b/demos/STM32/RT-STM32G474RE-NUCLEO64/main.c
@@ -19,6 +19,7 @@
#include "rt_test_root.h"
#include "oslib_test_root.h"
+#if 0
/*
* Green LED blinker thread, times are in milliseconds.
*/
@@ -34,6 +35,14 @@ static THD_FUNCTION(Thread1, arg) {
chThdSleepMilliseconds(500);
}
}
+#endif
+
+virtual_timer_t vt1;
+void vtfunc(void *par) {
+
+ (void)par;
+ palToggleLine(LINE_LED_GREEN);
+}
/*
* Application entry point.
@@ -60,7 +69,8 @@ int main(void) {
/*
* Creates the blinker thread.
*/
- chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
+// chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
+ chVTSetContinuous(&vt1, TIME_MS2I(500), vtfunc, NULL);
/*
* Normal main() thread activity, in this demo it does nothing except
diff --git a/os/rt/include/chobjects.h b/os/rt/include/chobjects.h
index 647a492b3..86c140db4 100644
--- a/os/rt/include/chobjects.h
+++ b/os/rt/include/chobjects.h
@@ -98,6 +98,14 @@ typedef struct ch_virtual_timer {
* @brief Timer callback function parameter.
*/
void *par;
+ /**
+ * @brief Time of the last activation.
+ */
+ systime_t last;
+ /**
+ * @brief Current reload interval.
+ */
+ sysinterval_t reload;
} virtual_timer_t;
/**
diff --git a/os/rt/include/chobjects_alt.h b/os/rt/include/chobjects_alt.h
deleted file mode 100644
index 86c140db4..000000000
--- a/os/rt/include/chobjects_alt.h
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
- 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
-
- This file is part of ChibiOS.
-
- ChibiOS 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 version 3 of the License.
-
- ChibiOS 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 chobjects.h
- * @brief Operating System Objects macros and structures.
- *
- * @addtogroup os_structures
- * @{
- */
-
-#ifndef CHOBJECTS_H
-#define CHOBJECTS_H
-
-/*===========================================================================*/
-/* Module constants. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module pre-compile time settings. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module data structures and types. */
-/*===========================================================================*/
-
-/**
- * @brief Global state of the operating system.
- */
-typedef enum {
- ch_sys_uninit = 0,
- ch_sys_initializing = 1,
- ch_sys_running = 2,
- ch_sys_halted = 3
-} system_state_t;
-
-/**
- * @brief Type of a Virtual Timer callback function.
- */
-typedef void (*vtfunc_t)(void *p);
-
-/**
- * @brief Type of a Virtual Timer structure.
- */
-typedef struct ch_delta_list delta_list_t;
-
-/**
- * @brief Virtual Timer delta list element and header structure.
- */
-struct ch_delta_list {
- /**
- * @brief Next timer in the list.
- */
- delta_list_t *next;
- /**
- * @brief Previous timer in the list.
- */
- delta_list_t *prev;
- /**
- * @brief Time delta before timeout.
- */
- sysinterval_t delta;
-};
-
-/**
- * @brief Type of a Virtual Timer.
- */
-typedef struct ch_virtual_timer {
- /**
- * @brief Delta list element.
- */
- delta_list_t dlist;
- /**
- * @brief Timer callback function pointer.
- */
- vtfunc_t func;
- /**
- * @brief Timer callback function parameter.
- */
- void *par;
- /**
- * @brief Time of the last activation.
- */
- systime_t last;
- /**
- * @brief Current reload interval.
- */
- sysinterval_t reload;
-} virtual_timer_t;
-
-/**
- * @brief Type of virtual timers list header.
- * @note The timers 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 ch_virtual_timers_list {
- /**
- * @brief Delta list header.
- */
- delta_list_t dlist;
-#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
- /**
- * @brief System Time counter.
- */
- volatile systime_t systime;
-#endif
-#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
- /**
- * @brief System time of the last tick event.
- */
- systime_t lasttime;
-#endif
-#if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Last generated time stamp.
- */
- volatile uint64_t laststamp;
-#endif
-} virtual_timers_list_t;
-
-/**
- * @brief Type of a registry structure.
- */
-typedef struct ch_registry {
- /**
- * @brief Registry queue header.
- */
- ch_queue_t queue;
-} registry_t;
-
-/**
- * @brief Type of a thread reference.
- */
-typedef thread_t * thread_reference_t;
-
-/**
- * @brief Type of a threads queue.
- */
-typedef struct ch_threads_queue {
- /**
- * @brief Threads queue header.
- */
- ch_queue_t queue;
-} threads_queue_t;
-
-/**
- * @brief Structure representing a thread.
- * @note Not all the listed fields are always needed, by switching off some
- * not needed ChibiOS/RT subsystems it is possible to save RAM space
- * by shrinking this structure.
- */
-struct ch_thread {
- /**
- * @brief Shared list headers.
- */
- union {
- /**
- * @brief Threads lists element.
- */
- ch_list_t list;
- /**
- * @brief Threads queues element.
- */
- ch_queue_t queue;
- /**
- * @brief Threads ordered queues element.
- */
- ch_priority_queue_t pqueue;
- } hdr;
- /**
- * @brief Processor context.
- */
- struct port_context ctx;
-#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Registry queue element.
- */
- ch_queue_t rqueue;
-#endif
- /**
- * @brief OS instance owner of this thread.
- */
- os_instance_t *owner;
-#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Thread name or @p NULL.
- */
- const char *name;
-#endif
-#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
- defined(__DOXYGEN__)
- /**
- * @brief Working area base address.
- * @note This pointer is used for stack overflow checks and for
- * dynamic threading.
- */
- stkalign_t *wabase;
-#endif
- /**
- * @brief Current thread state.
- */
- tstate_t state;
- /**
- * @brief Various thread flags.
- */
- tmode_t flags;
-#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief References to this thread.
- */
- trefs_t refs;
-#endif
- /**
- * @brief Number of ticks remaining to this thread.
- */
-#if (CH_CFG_TIME_QUANTUM > 0) || defined(__DOXYGEN__)
- tslices_t ticks;
-#endif
-#if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Thread consumed time in ticks.
- * @note This field can overflow.
- */
- volatile systime_t time;
-#endif
- /**
- * @brief State-specific fields.
- * @note All the fields declared in this union are only valid in the
- * specified state or condition and are thus volatile.
- */
- union {
- /**
- * @brief Thread wakeup code.
- * @note This field contains the low level message sent to the thread
- * by the waking thread or interrupt handler. The value is valid
- * after exiting the @p chSchWakeupS() function.
- */
- msg_t rdymsg;
- /**
- * @brief Thread exit code.
- * @note The thread termination code is stored in this field in order
- * to be retrieved by the thread performing a @p chThdWait() on
- * this thread.
- */
- msg_t exitcode;
- /**
- * @brief Pointer to a generic "wait" object.
- * @note This field is used to get a generic pointer to a synchronization
- * object and is valid when the thread is in one of the wait
- * states.
- */
- void *wtobjp;
- /**
- * @brief Pointer to a generic thread reference object.
- * @note This field is used to get a pointer to a synchronization
- * object and is valid when the thread is in @p CH_STATE_SUSPENDED
- * state.
- */
- thread_reference_t *wttrp;
-#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Thread sent message.
- */
- msg_t sentmsg;
-#endif
-#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Pointer to a generic semaphore object.
- * @note This field is used to get a pointer to a synchronization
- * object and is valid when the thread is in @p CH_STATE_WTSEM
- * state.
- */
- struct ch_semaphore *wtsemp;
-#endif
-#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Pointer to a generic mutex object.
- * @note This field is used to get a pointer to a synchronization
- * object and is valid when the thread is in @p CH_STATE_WTMTX
- * state.
- */
- struct ch_mutex *wtmtxp;
-#endif
-#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Enabled events mask.
- * @note This field is only valid while the thread is in the
- * @p CH_STATE_WTOREVT or @p CH_STATE_WTANDEVT states.
- */
- eventmask_t ewmask;
-#endif
- } u;
-#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Termination waiting list.
- */
- ch_list_t waiting;
-#endif
-#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Messages queue.
- */
- ch_queue_t msgqueue;
-#endif
-#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Pending events mask.
- */
- eventmask_t epending;
-#endif
-#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief List of the mutexes owned by this thread.
- * @note The list is terminated by a @p NULL in this field.
- */
- struct ch_mutex *mtxlist;
- /**
- * @brief Thread's own, non-inherited, priority.
- */
- tprio_t realprio;
-#endif
-#if ((CH_CFG_USE_DYNAMIC == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE)) || \
- defined(__DOXYGEN__)
- /**
- * @brief Memory Pool where the thread workspace is returned.
- */
- void *mpool;
-#endif
-#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Thread statistics.
- */
- time_measurement_t stats;
-#endif
-#if defined(CH_CFG_THREAD_EXTRA_FIELDS)
- /* Extra fields defined in chconf.h.*/
- CH_CFG_THREAD_EXTRA_FIELDS
-#endif
-};
-
-/**
- * @brief Type of a ready list header.
- */
-typedef struct ch_ready_list {
- /**
- * @brief Threads ordered queues header.
- * @note The priority field must be initialized to zero.
- */
- ch_priority_queue_t pqueue;
- /**
- * @brief The currently running thread.
- */
- thread_t *current;
-} ready_list_t;
-
-/**
- * @brief Type of an system instance configuration.
- */
-typedef struct ch_os_instance_config {
- /**
- * @brief Instance name.
- */
- const char *name;
-#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
- defined(__DOXYGEN__)
- /**
- * @brief Lower limit of the main function thread stack.
- */
- stkalign_t *mainthread_base;
- /**
- * @brief Upper limit of the main function thread stack.
- */
- stkalign_t *mainthread_end;
-#endif
-#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
- /**
- * @brief Lower limit of the dedicated idle thread stack.
- */
- stkalign_t *idlethread_base;
- /**
- * @brief Upper limit of the dedicated idle thread stack.
- */
- stkalign_t *idlethread_end;
-#endif
-} os_instance_config_t;
-
-/**
- * @brief System instance data structure.
- */
-struct ch_os_instance {
- /**
- * @brief Ready list header.
- */
- ready_list_t rlist;
- /**
- * @brief Virtual timers delta list header.
- */
- virtual_timers_list_t vtlist;
-#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == FALSE)) || \
- defined(__DOXYGEN__)
- /**
- * @brief Registry header.
- * @note This field is present only if the SMP mode is disabled.
- */
- registry_t reglist;
-#endif
- /**
- * @brief Core associated to this instance.
- */
- core_id_t core_id;
- /**
- * @brief Pointer to the instance configuration data.
- */
- const os_instance_config_t *config;
- /**
- * @brief Main thread descriptor.
- */
- thread_t mainthread;
- /**
- * @brief System debug.
- */
- system_debug_t dbg;
-#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
- /**
- * @brief Trace buffer.
- */
- trace_buffer_t trace_buffer;
-#endif
-#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Global kernel statistics.
- */
- kernel_stats_t kernel_stats;
-#endif
-#if defined(PORT_INSTANCE_EXTRA_FIELDS) || defined(__DOXYGEN__)
- /* Extra fields from port layer.*/
- PORT_INSTANCE_EXTRA_FIELDS
-#endif
- /* Extra fields from configuration.*/
- CH_CFG_OS_INSTANCE_EXTRA_FIELDS
-};
-
-/**
- * @brief Type of system data structure.
- */
-typedef struct ch_system {
- /**
- * @brief Operating system state.
- */
- system_state_t state;
- /**
- * @brief Initialized OS instances or @p NULL.
- */
- os_instance_t *instances[PORT_CORES_NUMBER];
-#if (CH_CFG_USE_TM == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief Time measurement calibration data.
- */
- tm_calibration_t tmc;
-#endif
-#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == TRUE)) || \
- defined(__DOXYGEN__)
- /**
- * @brief Registry header.
- * @note This field is present only if the SMP mode is enabled.
- */
- registry_t reglist;
-#endif
-#if defined(PORT_SYSTEM_EXTRA_FIELDS) || defined(__DOXYGEN__)
- /* Extra fields from port layer.*/
- PORT_SYSTEM_EXTRA_FIELDS
-#endif
- /* Extra fields from configuration.*/
- CH_CFG_SYSTEM_EXTRA_FIELDS
-} ch_system_t;
-
-/*===========================================================================*/
-/* Module macros. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-/*===========================================================================*/
-/* Module inline functions. */
-/*===========================================================================*/
-
-#endif /* CHOBJECTS_H */
-
-/** @} */
diff --git a/os/rt/include/chvt.h b/os/rt/include/chvt.h
index 2193faf3d..4f2e79722 100644
--- a/os/rt/include/chvt.h
+++ b/os/rt/include/chvt.h
@@ -73,6 +73,8 @@ extern "C" {
#endif
void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
vtfunc_t vtfunc, void *par);
+ void chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par);
void chVTDoResetI(virtual_timer_t *vtp);
void chVTDoTickI(void);
#if CH_CFG_USE_TIMESTAMP == TRUE
@@ -100,7 +102,7 @@ extern "C" {
*/
static inline void chVTObjectInit(virtual_timer_t *vtp) {
- vtp->func = NULL;
+ vtp->dlist.next = NULL;
}
/**
@@ -246,7 +248,7 @@ static inline bool chVTIsArmedI(const virtual_timer_t *vtp) {
chDbgCheckClassI();
- return (bool)(vtp->func != NULL);
+ return (bool)(vtp->dlist.next != NULL);
}
/**
@@ -304,7 +306,7 @@ static inline void chVTReset(virtual_timer_t *vtp) {
}
/**
- * @brief Enables a virtual timer.
+ * @brief Enables a one-shot virtual timer.
* @details If the virtual timer was already enabled then it is re-enabled
* using the new parameters.
* @pre The timer must have been initialized using @p chVTObjectInit()
@@ -333,7 +335,7 @@ static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay,
}
/**
- * @brief Enables a virtual timer.
+ * @brief Enables a one-shot virtual timer.
* @details If the virtual timer was already enabled then it is re-enabled
* using the new parameters.
* @pre The timer must have been initialized using @p chVTObjectInit()
@@ -362,6 +364,121 @@ static inline void chVTSet(virtual_timer_t *vtp, sysinterval_t delay,
chSysUnlock();
}
+/**
+ * @brief Enables a continuous virtual timer.
+ * @details If the virtual timer was already enabled then it is re-enabled
+ * using the new parameters.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay 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
+ */
+static inline void chVTSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+
+ chVTResetI(vtp);
+ chVTDoSetContinuousI(vtp, delay, vtfunc, par);
+}
+
+/**
+ * @brief Enables a continuous virtual timer.
+ * @details If the virtual timer was already enabled then it is re-enabled
+ * using the new parameters.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay 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
+ *
+ * @api
+ */
+static inline void chVTSetContinuous(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+
+ chSysLock();
+ chVTSetContinuousI(vtp, delay, vtfunc, par);
+ chSysUnlock();
+}
+
+/**
+ * @brief Returns the current reload value.
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @return The reload value.
+ *
+ * @xclass
+ */
+static inline sysinterval_t chVTGetReloadIntervalX(virtual_timer_t *vtp) {
+
+ return vtp->reload;
+}
+
+/**
+ * @brief Changes a timer reload time interval.
+ * @note This function is meant to be called from a timer callback, it
+ * does nothing in any other context.
+ * @note Calling this function from a one-shot timer callback turns it
+ * into a continuous timer.
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @param[in] reload the new reload value, zero means no reload
+ *
+ * @xclass
+ */
+static inline void chVTSetReloadIntervalX(virtual_timer_t *vtp,
+ sysinterval_t reload) {
+
+ vtp->reload = reload;
+}
+
+/**
+ * @brief Returns the remaining time interval before next timer trigger.
+ * @note This function can be called while the timer is active or
+ * after stopping it.
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @return The remaining time interval.
+ *
+ * @xclass
+ */
+static inline sysinterval_t chVTGetRemainingIntervalX(virtual_timer_t *vtp) {
+ sysinterval_t elapsed_time;
+
+ /* Time elapsed since last triggering or 1st activation.*/
+ elapsed_time = chTimeDiffX(vtp->last, chVTGetSystemTimeX());
+
+ /* Current time could have slipped past the next deadline, compensating.*/
+ if (elapsed_time > vtp->reload) {
+ elapsed_time = vtp->reload;
+ }
+
+ /* Returning the remaining time interval.*/
+ return vtp->reload - elapsed_time;
+}
+
#if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__)
/**
* @brief Generates a monotonic time stamp.
diff --git a/os/rt/include/chvt_alt.h b/os/rt/include/chvt_alt.h
deleted file mode 100644
index 1c0d7d904..000000000
--- a/os/rt/include/chvt_alt.h
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
- 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
-
- This file is part of ChibiOS.
-
- ChibiOS 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 version 3 of the License.
-
- ChibiOS 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 rt/include/chvt.h
- * @brief Time and Virtual Timers module macros and structures.
- *
- * @addtogroup time
- * @{
- */
-
-#ifndef CHVT_H
-#define CHVT_H
-
-/*===========================================================================*/
-/* Module constants. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module pre-compile time settings. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
-#error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
- "be zero or greater than one"
-#endif
-
-#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_CFG_TIME_QUANTUM > 0)
-#error "CH_CFG_TIME_QUANTUM not supported in tickless mode"
-#endif
-
-#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_DBG_THREADS_PROFILING == TRUE)
-#error "CH_DBG_THREADS_PROFILING not supported in tickless mode"
-#endif
-
-/*===========================================================================*/
-/* Module data structures and types. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module macros. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-/*
- * Virtual Timers APIs.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
- void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par);
- void chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par);
- void chVTDoResetI(virtual_timer_t *vtp);
- void chVTDoTickI(void);
-#if CH_CFG_USE_TIMESTAMP == TRUE
- systimestamp_t chVTGetTimeStampI(void);
- void chVTResetTimeStampI(void);
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/*===========================================================================*/
-/* Module inline functions. */
-/*===========================================================================*/
-
-/**
- * @brief Initializes a @p virtual_timer_t object.
- * @note Initializing a timer object is not strictly required because
- * the function @p chVTSetI() initializes the object too. This
- * function is only useful if you need to perform a @p chVTIsArmed()
- * check before calling @p chVTSetI().
- *
- * @param[out] vtp the @p virtual_timer_t structure pointer
- *
- * @init
- */
-static inline void chVTObjectInit(virtual_timer_t *vtp) {
-
- vtp->dlist.next = NULL;
-}
-
-/**
- * @brief Current system time.
- * @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
- * @p systime_t size.
- *
- * @return The system time in ticks.
- *
- * @xclass
- */
-static inline systime_t chVTGetSystemTimeX(void) {
-
-#if CH_CFG_ST_TIMEDELTA == 0
- return currcore->vtlist.systime;
-#else /* CH_CFG_ST_TIMEDELTA > 0 */
- return port_timer_get_time();
-#endif /* CH_CFG_ST_TIMEDELTA > 0 */
-}
-
-/**
- * @brief Current system time.
- * @details Returns the number of system ticks since the @p chSysInit()
- * invocation.
- * @note The counter can reach its maximum and then restart from zero.
- *
- * @return The system time in ticks.
- *
- * @api
- */
-static inline systime_t chVTGetSystemTime(void) {
- systime_t systime;
-
- chSysLock();
- systime = chVTGetSystemTimeX();
- chSysUnlock();
-
- return systime;
-}
-
-/**
- * @brief Returns the elapsed time since the specified start time.
- *
- * @param[in] start start time
- * @return The elapsed time.
- *
- * @xclass
- */
-static inline sysinterval_t chVTTimeElapsedSinceX(systime_t start) {
-
- return chTimeDiffX(start, chVTGetSystemTimeX());
-}
-
-/**
- * @brief Checks if the current system time is within the specified time
- * window.
- * @note When start==end then the function returns always false because the
- * time window has zero size.
- *
- * @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.
- *
- * @xclass
- */
-static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) {
-
- return chTimeIsInRangeX(chVTGetSystemTimeX(), start, end);
-}
-
-/**
- * @brief Checks if the current system time is within the specified time
- * window.
- * @note When start==end then the function returns always false because the
- * time window has zero size.
- *
- * @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.
- *
- * @api
- */
-static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
-
- return chTimeIsInRangeX(chVTGetSystemTime(), start, end);
-}
-
-/**
- * @brief Returns the time interval until the next timer event.
- * @note The return value is not perfectly accurate and can report values
- * in excess of @p CH_CFG_ST_TIMEDELTA ticks.
- * @note The interval returned by this function is only meaningful if
- * more timers are not added to the list until the returned time.
- *
- * @param[out] timep pointer to a variable that will contain the time
- * interval until the next timer elapses. This pointer
- * can be @p NULL if the information is not required.
- * @return The time, in ticks, until next time event.
- * @retval false if the timers list is empty.
- * @retval true if the timers list contains at least one timer.
- *
- * @iclass
- */
-static inline bool chVTGetTimersStateI(sysinterval_t *timep) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
- delta_list_t *dlp = &vtlp->dlist;
-
- chDbgCheckClassI();
-
- if (dlp == dlp->next) {
- return false;
- }
-
- if (timep != NULL) {
-#if CH_CFG_ST_TIMEDELTA == 0
- *timep = dlp->next->delta;
-#else
- *timep = (dlp->next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
- chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX());
-#endif
- }
-
- return true;
-}
-
-/**
- * @brief Returns @p true if the specified timer is armed.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @return true if the timer is armed.
- *
- * @iclass
- */
-static inline bool chVTIsArmedI(const virtual_timer_t *vtp) {
-
- chDbgCheckClassI();
-
- return (bool)(vtp->dlist.next != NULL);
-}
-
-/**
- * @brief Returns @p true if the specified timer is armed.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @return true if the timer is armed.
- *
- * @api
- */
-static inline bool chVTIsArmed(const virtual_timer_t *vtp) {
- bool b;
-
- chSysLock();
- b = chVTIsArmedI(vtp);
- chSysUnlock();
-
- return b;
-}
-
-/**
- * @brief Disables a Virtual Timer.
- * @note The timer is first checked and disabled only if armed.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- *
- * @iclass
- */
-static inline void chVTResetI(virtual_timer_t *vtp) {
-
- if (chVTIsArmedI(vtp)) {
- chVTDoResetI(vtp);
- }
-}
-
-/**
- * @brief Disables a Virtual Timer.
- * @note The timer is first checked and disabled only if armed.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- *
- * @api
- */
-static inline void chVTReset(virtual_timer_t *vtp) {
-
- chSysLock();
- chVTResetI(vtp);
- chSysUnlock();
-}
-
-/**
- * @brief Enables a one-shot virtual timer.
- * @details If the virtual timer was already enabled then it is re-enabled
- * using the new parameters.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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
- */
-static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
-
- chVTResetI(vtp);
- chVTDoSetI(vtp, delay, vtfunc, par);
-}
-
-/**
- * @brief Enables a one-shot virtual timer.
- * @details If the virtual timer was already enabled then it is re-enabled
- * using the new parameters.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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
- *
- * @api
- */
-static inline void chVTSet(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
-
- chSysLock();
- chVTSetI(vtp, delay, vtfunc, par);
- chSysUnlock();
-}
-
-/**
- * @brief Enables a continuous virtual timer.
- * @details If the virtual timer was already enabled then it is re-enabled
- * using the new parameters.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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
- */
-static inline void chVTSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
-
- chVTResetI(vtp);
- chVTDoSetContinuousI(vtp, delay, vtfunc, par);
-}
-
-/**
- * @brief Enables a continuous virtual timer.
- * @details If the virtual timer was already enabled then it is re-enabled
- * using the new parameters.
- * @pre The timer must have been initialized using @p chVTObjectInit()
- * or @p chVTDoSetI().
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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
- *
- * @api
- */
-static inline void chVTContinuousSet(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
-
- chSysLock();
- chVTSetContinuousI(vtp, delay, vtfunc, par);
- chSysUnlock();
-}
-
-/**
- * @brief Changes a timer reload time interval.
- * @note This function is meant to be called from a timer callback, it
- * does nothing in any other context.
- * @note Calling this function from a one-shot timer callback turns it
- * into a continuous timer.
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- * @param[in] reload the new reload value, zero means no reload
- * @return The previous reload value
- *
- * @special
- */
-static inline sysinterval_t chVTSetReload(virtual_timer_t *vtp,
- sysinterval_t reload) {
- sysinterval_t old_reload;
-
- old_reload = vtp->reload;
- vtp->reload = reload;
-
- return old_reload;
-}
-
-#if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__)
-/**
- * @brief Generates a monotonic time stamp.
- * @details This function generates a monotonic time stamp synchronized with
- * the system time. The time stamp has the same resolution of
- * system time.
- * @note There is an assumption, this function must be called at
- * least once before the system time wraps back to zero or
- * synchronization is lost. You may use a periodic virtual timer with
- * a very large interval in order to keep time stamps synchronized
- * by calling this function.
- *
- * @return The time stamp.
- *
- * @api
- */
-static inline systimestamp_t chVTGetTimeStamp(void) {
- systimestamp_t stamp;
-
- chSysLock();
-
- stamp = chVTGetTimeStampI();
-
- chSysUnlock();
-
- return stamp;
-}
-
-/**
- * @brief Resets and re-synchronizes the time stamps monotonic counter.
- *
- * @api
- */
-static inline void chVTResetTimeStamp(void) {
-
- chDbgCheckClassI();
-
- chSysLock();
-
- chVTResetTimeStampI();
-
- chSysUnlock();
-}
-#endif /* CH_CFG_USE_TIMESTAMP == TRUE */
-
-/**
- * @brief Virtual Timers instance initialization.
- * @note Internal use only.
- *
- * @param[out] vtlp pointer to the @p virtual_timers_list_t structure
- *
- * @notapi
- */
-static inline void __vt_object_init(virtual_timers_list_t *vtlp) {
-
- vtlp->dlist.next = &vtlp->dlist;
- vtlp->dlist.prev = &vtlp->dlist;
- vtlp->dlist.delta = (sysinterval_t)-1;
-#if CH_CFG_ST_TIMEDELTA == 0
- vtlp->systime = (systime_t)0;
-#else /* CH_CFG_ST_TIMEDELTA > 0 */
- vtlp->lasttime = (systime_t)0;
-#endif /* CH_CFG_ST_TIMEDELTA > 0 */
-#if CH_CFG_USE_TIMESTAMP == TRUE
- currcore->vtlist.laststamp = (systimestamp_t)chVTGetSystemTimeX();
-#endif
-}
-
-#endif /* CHVT_H */
-
-/** @} */
diff --git a/os/rt/src/chvt.c b/os/rt/src/chvt.c
index c95c8c4a2..2aa160481 100644
--- a/os/rt/src/chvt.c
+++ b/os/rt/src/chvt.c
@@ -129,47 +129,18 @@ static void vt_list_compress(virtual_timers_list_t *vtlp,
}
#endif
-/*===========================================================================*/
-/* Module exported functions. */
-/*===========================================================================*/
-
/**
- * @brief Enables a virtual timer.
- * @details The timer is enabled and programmed to trigger after the delay
- * specified as parameter.
- * @pre The timer must not be already armed before calling this function.
- * @note The callback function is invoked from interrupt context.
- *
- * @param[out] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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
+ * @brief Enqueues a virtual timer in a virtual timers list.
*/
-void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
+static void vt_enqueue(virtual_timers_list_t *vtlp,
+ virtual_timer_t *vtp,
+ systime_t now,
+ sysinterval_t delay) {
delta_list_t *dlp;
sysinterval_t delta;
- chDbgCheckClassI();
- chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
-
- vtp->par = par;
- vtp->func = vtfunc;
-
#if CH_CFG_ST_TIMEDELTA > 0
{
- systime_t now = chVTGetSystemTimeX();
sysinterval_t deltanow;
/* If the requested delay is lower than the minimum safe delta then it
@@ -260,6 +231,96 @@ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
vtlp->dlist.delta = (sysinterval_t)-1;
}
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables a one-shot virtual timer.
+ * @details The timer is enabled and programmed to trigger after the delay
+ * specified as parameter.
+ * @pre The timer must not be already armed before calling this function.
+ * @note The callback function is invoked from interrupt context.
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay 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 chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+ virtual_timers_list_t *vtlp = &currcore->vtlist;
+ systime_t now;
+
+ chDbgCheckClassI();
+ chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
+
+ /* Current system time.*/
+ now = chVTGetSystemTimeX();
+
+ /* Timer initialization.*/
+ vtp->par = par;
+ vtp->func = vtfunc;
+ vtp->last = now;
+ vtp->reload = (sysinterval_t)0;
+
+ /* Inserting the timer in the delta list.*/
+ vt_enqueue(vtlp, vtp, vtp->last, delay);
+}
+
+/**
+ * @brief Enables a continuous virtual timer.
+ * @details The timer is enabled and programmed to trigger after the delay
+ * specified as parameter.
+ * @pre The timer must not be already armed before calling this function.
+ * @note The callback function is invoked from interrupt context.
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay 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 chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+ virtual_timers_list_t *vtlp = &currcore->vtlist;
+ systime_t now;
+
+ chDbgCheckClassI();
+ chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
+
+ /* Current system time.*/
+ now = chVTGetSystemTimeX();
+
+ /* Timer initialization.*/
+ vtp->par = par;
+ vtp->func = vtfunc;
+ vtp->last = now;
+ vtp->reload = delay;
+
+ /* Inserting the timer in the delta list.*/
+ vt_enqueue(vtlp, vtp, vtp->last, delay);
+}
+
/**
* @brief Disables a Virtual Timer.
* @pre The timer must be in armed state before calling this function.
@@ -273,17 +334,17 @@ void chVTDoResetI(virtual_timer_t *vtp) {
chDbgCheckClassI();
chDbgCheck(vtp != NULL);
- chDbgAssert(vtp->func != NULL, "timer not set or already triggered");
+ chDbgAssert(chVTIsArmedI(vtp), "timer not armed");
#if CH_CFG_ST_TIMEDELTA == 0
/* The delta of the timer is added to the next timer.*/
vtp->dlist.next->delta += vtp->dlist.delta;
- /* Removing the element from the delta list.*/
+ /* Removing the element from the delta list, marking it as not armed.*/
vtp->dlist.prev->next = vtp->dlist.next;
vtp->dlist.next->prev = vtp->dlist.prev;
- vtp->func = NULL;
+ vtp->dlist.next = NULL;
/* The above code changes the value in the header when the removed element
is the last of the list, restoring it.*/
@@ -297,19 +358,21 @@ void chVTDoResetI(virtual_timer_t *vtp) {
/* Removing the element from the delta list.*/
vtp->dlist.prev->next = vtp->dlist.next;
vtp->dlist.next->prev = vtp->dlist.prev;
- vtp->func = NULL;
/* Adding delta to the next element, if it is not the last one.*/
if (is_timer(&vtlp->dlist, vtp->dlist.next))
vtp->dlist.next->delta += vtp->dlist.delta;
+ /* Marking timer as not armed.*/
+ vtp->dlist.next = NULL;
+
return;
}
- /* Removing the first timer from the list.*/
+ /* Removing the first timer from the list, marking it as not armed.*/
vtlp->dlist.next = vtp->dlist.next;
vtlp->dlist.next->prev = &vtlp->dlist;
- vtp->func = NULL;
+ vtp->dlist.next = NULL;
/* If the list become empty then the alarm timer is stopped and done.*/
if (is_vtlist_empty(&vtlp->dlist)) {
@@ -378,29 +441,30 @@ void chVTDoTickI(void) {
--vtlp->dlist.next->delta;
while (vtlp->dlist.next->delta == (sysinterval_t)0) {
virtual_timer_t *vtp;
- vtfunc_t fn;
+ /* Triggered timer.*/
vtp = (virtual_timer_t *)vtlp->dlist.next;
- fn = vtp->func;
- vtp->func = NULL;
+
+ /* Removing the element from the delta list, marking it as not armed.*/
vtp->dlist.next->prev = &vtlp->dlist;
vtlp->dlist.next = vtp->dlist.next;
+ vtp->dlist.next = NULL;
+
chSysUnlockFromISR();
- fn(vtp->par);
+ vtp->func(vtp->par);
chSysLockFromISR();
}
}
#else /* CH_CFG_ST_TIMEDELTA > 0 */
delta_list_t *dlp;
- systime_t now;
sysinterval_t delta, nowdelta;
+ systime_t now = chVTGetSystemTimeX();
/* Looping through timers.*/
dlp = vtlp->dlist.next;
while (true) {
- /* Getting the system time as reference.*/
- now = chVTGetSystemTimeX();
+ /* Delta between current time and last execution time.*/
nowdelta = chTimeDiffX(vtlp->lasttime, now);
/* The list scan is limited by the timers header having
@@ -412,32 +476,51 @@ void chVTDoTickI(void) {
/* Consuming all timers between "vtp->lasttime" and now.*/
do {
- vtfunc_t fn;
virtual_timer_t *vtp = (virtual_timer_t *)dlp;
/* The "last time" becomes this timer's expiration time.*/
vtlp->lasttime += dlp->delta;
nowdelta -= dlp->delta;
- /* Removing the timer from the list.*/
+ /* Removing the timer from the list, marking it as not armed.*/
dlp->next->prev = &vtlp->dlist;
vtlp->dlist.next = dlp->next;
-
- /* Calling the associated function and then marking the timer as
- non active.*/
- fn = vtp->func;
- vtp->func = NULL;
+ dlp->next = NULL;
/* If the list becomes empty then the timer is stopped.*/
if (is_vtlist_empty(&vtlp->dlist)) {
port_timer_stop_alarm();
}
+ /* Now "last" marks the current deadline based on the stored
+ reload value. It is done before calling the callback because
+ the reload value could change. Note that "reload" could be
+ zero, no harm.*/
+ vtp->last = chTimeAddX(vtp->last, vtp->reload);
+
/* The callback is invoked outside the kernel critical zone.*/
chSysUnlockFromISR();
- fn(vtp->par);
+ vtp->func(vtp->par);
chSysLockFromISR();
+ /* Getting again the system time after executing the callback in
+ order to reduce error.*/
+ now = chVTGetSystemTimeX();
+
+ /* If a reload is defined the timer needs to be restarted.*/
+ if (vtp->reload > (sysinterval_t)0) {
+ sysinterval_t skipped_delta;
+
+ /* Calculating how much the real current time skipped past the
+ hypothetical current deadline.*/
+ skipped_delta = chTimeDiffX(vtp->last, now);
+
+ chDbgAssert(skipped_delta < vtp->reload, "skipped deadline");
+
+ /* Enqueuing the timer again using the calculated delta.*/
+ vt_enqueue(vtlp, vtp, now, vtp->reload - skipped_delta);
+ }
+
/* Next element in the list.*/
dlp = vtlp->dlist.next;
}
@@ -451,7 +534,8 @@ void chVTDoTickI(void) {
/* The "unprocessed nowdelta" time slice is added to "last time"
and subtracted to next timer's delta.*/
- vtlp->lasttime += nowdelta;
+// vtlp->lasttime += nowdelta;
+ vtlp->lasttime = chTimeAddX(vtlp->lasttime, nowdelta);
vtlp->dlist.next->delta -= nowdelta;
/* Recalculating the next alarm time.*/
diff --git a/os/rt/src/chvt_alt.c b/os/rt/src/chvt_alt.c
deleted file mode 100644
index 2aa160481..000000000
--- a/os/rt/src/chvt_alt.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
- 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
-
- This file is part of ChibiOS.
-
- ChibiOS 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 version 3 of the License.
-
- ChibiOS 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 rt/src/chvt.c
- * @brief Time and Virtual Timers module code.
- *
- * @addtogroup time
- * @details Time and Virtual Timers related APIs and services.
- * @{
- */
-
-#include "ch.h"
-
-/*===========================================================================*/
-/* Module local definitions. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module exported variables. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module local types. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module local variables. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module local functions. */
-/*===========================================================================*/
-
-/**
- * @brief List empty check.
- *
- * @param[in] dlhp pointer to the delta list header
- *
- * @notapi
- */
-static inline bool is_vtlist_empty(delta_list_t *dlhp) {
-
- return (bool)(dlhp == dlhp->next);
-}
-
-#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
-/**
- * @brief Last timer in the list check.
- *
- * @param[in] dlhp pointer to the delta list header
- * @param[in] dlp pointer to the delta list element
- *
- * @notapi
- */
-static inline bool is_last_timer(delta_list_t *dlhp, delta_list_t *dlp) {
-
- return (bool)(dlp->next == dlhp);
-}
-
-/**
- * @brief Fist timer in the list check.
- *
- * @param[in] dlhp pointer to the delta list header
- * @param[in] dlp pointer to the delta list element
- *
- * @notapi
- */
-static inline bool is_first_timer(delta_list_t *dlhp, delta_list_t *dlp) {
-
- return (bool)(dlhp->next == dlp);
-}
-
-/**
- * @brief Timer check.
- *
- * @param[in] dlhp pointer to the delta list header
- * @param[in] dlp pointer to the delta list element
- *
- * @notapi
- */
-static inline bool is_timer(delta_list_t *dlhp, delta_list_t *dlp) {
-
- return (bool)(dlp != dlhp);
-}
-
-/**
- * @brief Delta list compression.
- *
- * @param[in] vtlp pointer to the delta list to be compressed
- * @param[in] deltanow interval to be compacted starting from "lasttime"
- *
- * @notapi
- */
-static void vt_list_compress(virtual_timers_list_t *vtlp,
- sysinterval_t deltanow) {
- delta_list_t *dlp = vtlp->dlist.next;
-
- /* The loop is bounded because the delta list header has the delta field
- set to (sysinterval_t)-1 which is larger than all deltas.*/
- while (dlp->delta < deltanow) {
- deltanow -= dlp->delta;
- dlp->delta = (sysinterval_t)0;
- dlp = dlp->next;
- }
-
- vtlp->lasttime = vtlp->lasttime + deltanow;
-
- /* Adjusting next timer in the list, if any.*/
- if (is_timer(&vtlp->dlist, dlp)) {
- dlp->delta -= deltanow;
- }
-}
-#endif
-
-/**
- * @brief Enqueues a virtual timer in a virtual timers list.
- */
-static void vt_enqueue(virtual_timers_list_t *vtlp,
- virtual_timer_t *vtp,
- systime_t now,
- sysinterval_t delay) {
- delta_list_t *dlp;
- sysinterval_t delta;
-
-#if CH_CFG_ST_TIMEDELTA > 0
- {
- sysinterval_t deltanow;
-
- /* If the requested delay is lower than the minimum safe delta then it
- is raised to the minimum safe value.*/
- if (delay < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
- delay = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
- }
-
- /* Special case where the timers list is empty.*/
- if (is_vtlist_empty(&vtlp->dlist)) {
-
- /* The delta list is empty, the current time becomes the new
- delta list base time, the timer is inserted.*/
- vtlp->lasttime = now;
- vtlp->dlist.next = &vtp->dlist;
- vtlp->dlist.prev = &vtp->dlist;
- vtp->dlist.next = &vtlp->dlist;
- vtp->dlist.prev = &vtlp->dlist;
- vtp->dlist.delta = delay;
-
-#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
- /* The delta could be too large for the physical timer to handle.*/
- if (delay > (sysinterval_t)TIME_MAX_SYSTIME) {
- delay = (sysinterval_t)TIME_MAX_SYSTIME;
- }
-#endif
-
- /* Being the first element in the list the alarm timer is started.*/
- port_timer_start_alarm(chTimeAddX(vtlp->lasttime, delay));
-
- return;
- }
-
- /* Delay as delta from 'lasttime'. Note, it can overflow and the value
- becomes lower than 'deltanow'.*/
- deltanow = chTimeDiffX(vtlp->lasttime, now);
- delta = deltanow + delay;
-
- /* Scenario where a very large delay exceeded the numeric range, it
- requires a special handling, the compression procedure.*/
- if (delta < deltanow) {
- vt_list_compress(vtlp, deltanow);
- delta -= deltanow;
- }
- else if (delta < vtlp->dlist.next->delta) {
- sysinterval_t deadline_delta;
-
- /* A small delay that will become the first element in the delta list
- and next deadline.*/
- deadline_delta = delta;
-#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
- /* The delta could be too large for the physical timer to handle.*/
- if (deadline_delta > (sysinterval_t)TIME_MAX_SYSTIME) {
- deadline_delta = (sysinterval_t)TIME_MAX_SYSTIME;
- }
-#endif
- port_timer_set_alarm(chTimeAddX(vtlp->lasttime, deadline_delta));
- }
- }
-#else /* CH_CFG_ST_TIMEDELTA == 0 */
- /* Delta is initially equal to the specified delay.*/
- delta = delay;
-#endif /* CH_CFG_ST_TIMEDELTA == 0 */
-
- /* The delta list is scanned in order to find the correct position for
- this timer. */
- dlp = vtlp->dlist.next;
- while (dlp->delta < delta) {
- /* Debug assert if the timer is already in the list.*/
- chDbgAssert(dlp != &vtp->dlist, "timer already armed");
-
- delta -= dlp->delta;
- dlp = dlp->next;
- }
-
- /* The timer is inserted in the delta list.*/
- vtp->dlist.next = dlp;
- vtp->dlist.prev = vtp->dlist.next->prev;
- vtp->dlist.prev->next = &vtp->dlist;
- dlp->prev = &vtp->dlist;
- vtp->dlist.delta = delta;
-
- /* Calculate new delta for the following entry.*/
- dlp->delta -= delta;
-
- /* Special case when the timer is in last position in the list, the
- value in the header must be restored.*/
- vtlp->dlist.delta = (sysinterval_t)-1;
-}
-
-/*===========================================================================*/
-/* Module exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Enables a one-shot virtual timer.
- * @details The timer is enabled and programmed to trigger after the delay
- * specified as parameter.
- * @pre The timer must not be already armed before calling this function.
- * @note The callback function is invoked from interrupt context.
- *
- * @param[out] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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 chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
- systime_t now;
-
- chDbgCheckClassI();
- chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
-
- /* Current system time.*/
- now = chVTGetSystemTimeX();
-
- /* Timer initialization.*/
- vtp->par = par;
- vtp->func = vtfunc;
- vtp->last = now;
- vtp->reload = (sysinterval_t)0;
-
- /* Inserting the timer in the delta list.*/
- vt_enqueue(vtlp, vtp, vtp->last, delay);
-}
-
-/**
- * @brief Enables a continuous virtual timer.
- * @details The timer is enabled and programmed to trigger after the delay
- * specified as parameter.
- * @pre The timer must not be already armed before calling this function.
- * @note The callback function is invoked from interrupt context.
- *
- * @param[out] vtp the @p virtual_timer_t structure pointer
- * @param[in] delay 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 chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay,
- vtfunc_t vtfunc, void *par) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
- systime_t now;
-
- chDbgCheckClassI();
- chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
-
- /* Current system time.*/
- now = chVTGetSystemTimeX();
-
- /* Timer initialization.*/
- vtp->par = par;
- vtp->func = vtfunc;
- vtp->last = now;
- vtp->reload = delay;
-
- /* Inserting the timer in the delta list.*/
- vt_enqueue(vtlp, vtp, vtp->last, delay);
-}
-
-/**
- * @brief Disables a Virtual Timer.
- * @pre The timer must be in armed state before calling this function.
- *
- * @param[in] vtp the @p virtual_timer_t structure pointer
- *
- * @iclass
- */
-void chVTDoResetI(virtual_timer_t *vtp) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
-
- chDbgCheckClassI();
- chDbgCheck(vtp != NULL);
- chDbgAssert(chVTIsArmedI(vtp), "timer not armed");
-
-#if CH_CFG_ST_TIMEDELTA == 0
-
- /* The delta of the timer is added to the next timer.*/
- vtp->dlist.next->delta += vtp->dlist.delta;
-
- /* Removing the element from the delta list, marking it as not armed.*/
- vtp->dlist.prev->next = vtp->dlist.next;
- vtp->dlist.next->prev = vtp->dlist.prev;
- vtp->dlist.next = NULL;
-
- /* The above code changes the value in the header when the removed element
- is the last of the list, restoring it.*/
- vtlp->dlist.delta = (sysinterval_t)-1;
-#else /* CH_CFG_ST_TIMEDELTA > 0 */
- sysinterval_t nowdelta, delta;
-
- /* If the timer is not the first of the list then it is simply unlinked
- else the operation is more complex.*/
- if (!is_first_timer(&vtlp->dlist, &vtp->dlist)) {
- /* Removing the element from the delta list.*/
- vtp->dlist.prev->next = vtp->dlist.next;
- vtp->dlist.next->prev = vtp->dlist.prev;
-
- /* Adding delta to the next element, if it is not the last one.*/
- if (is_timer(&vtlp->dlist, vtp->dlist.next))
- vtp->dlist.next->delta += vtp->dlist.delta;
-
- /* Marking timer as not armed.*/
- vtp->dlist.next = NULL;
-
- return;
- }
-
- /* Removing the first timer from the list, marking it as not armed.*/
- vtlp->dlist.next = vtp->dlist.next;
- vtlp->dlist.next->prev = &vtlp->dlist;
- vtp->dlist.next = NULL;
-
- /* If the list become empty then the alarm timer is stopped and done.*/
- if (is_vtlist_empty(&vtlp->dlist)) {
- port_timer_stop_alarm();
-
- return;
- }
-
- /* The delta of the removed timer is added to the new first timer.*/
- vtlp->dlist.next->delta += vtp->dlist.delta;
-
- /* If the new first timer has a delta of zero then the alarm is not
- modified, the already programmed alarm will serve it.*/
-/* if (vtlp->dlist.next->delta == 0) {
- return;
- }*/
-
- /* Distance in ticks between the last alarm event and current time.*/
- nowdelta = chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX());
-
- /* If the current time surpassed the time of the next element in list
- then the event interrupt is already pending, just return.*/
- if (nowdelta >= vtlp->dlist.next->delta) {
- return;
- }
-
- /* Distance from the next scheduled event and now.*/
- delta = vtlp->dlist.next->delta - nowdelta;
-
- /* Making sure to not schedule an event closer than CH_CFG_ST_TIMEDELTA
- ticks from now.*/
- if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
- delta = nowdelta + (sysinterval_t)CH_CFG_ST_TIMEDELTA;
- }
- else {
- delta = nowdelta + delta;
-#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
- /* The delta could be too large for the physical timer to handle.*/
- if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
- delta = (sysinterval_t)TIME_MAX_SYSTIME;
- }
-#endif
- }
- port_timer_set_alarm(chTimeAddX(vtlp->lasttime, delta));
-#endif /* CH_CFG_ST_TIMEDELTA > 0 */
-}
-
-/**
- * @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 chVTDoTickI(void) {
- virtual_timers_list_t *vtlp = &currcore->vtlist;
-
- chDbgCheckClassI();
-
-#if CH_CFG_ST_TIMEDELTA == 0
- vtlp->systime++;
- if (!is_vtlist_empty(&vtlp->dlist)) {
- /* The list is not empty, processing elements on top.*/
- --vtlp->dlist.next->delta;
- while (vtlp->dlist.next->delta == (sysinterval_t)0) {
- virtual_timer_t *vtp;
-
- /* Triggered timer.*/
- vtp = (virtual_timer_t *)vtlp->dlist.next;
-
- /* Removing the element from the delta list, marking it as not armed.*/
- vtp->dlist.next->prev = &vtlp->dlist;
- vtlp->dlist.next = vtp->dlist.next;
- vtp->dlist.next = NULL;
-
- chSysUnlockFromISR();
- vtp->func(vtp->par);
- chSysLockFromISR();
- }
- }
-#else /* CH_CFG_ST_TIMEDELTA > 0 */
- delta_list_t *dlp;
- sysinterval_t delta, nowdelta;
- systime_t now = chVTGetSystemTimeX();
-
- /* Looping through timers.*/
- dlp = vtlp->dlist.next;
- while (true) {
-
- /* Delta between current time and last execution time.*/
- nowdelta = chTimeDiffX(vtlp->lasttime, now);
-
- /* The list scan is limited by the timers header having
- "vtlp->dlist.delta == (sysinterval_t)-1" which is
- greater than all deltas.*/
- if (nowdelta < dlp->delta) {
- break;
- }
-
- /* Consuming all timers between "vtp->lasttime" and now.*/
- do {
- virtual_timer_t *vtp = (virtual_timer_t *)dlp;
-
- /* The "last time" becomes this timer's expiration time.*/
- vtlp->lasttime += dlp->delta;
- nowdelta -= dlp->delta;
-
- /* Removing the timer from the list, marking it as not armed.*/
- dlp->next->prev = &vtlp->dlist;
- vtlp->dlist.next = dlp->next;
- dlp->next = NULL;
-
- /* If the list becomes empty then the timer is stopped.*/
- if (is_vtlist_empty(&vtlp->dlist)) {
- port_timer_stop_alarm();
- }
-
- /* Now "last" marks the current deadline based on the stored
- reload value. It is done before calling the callback because
- the reload value could change. Note that "reload" could be
- zero, no harm.*/
- vtp->last = chTimeAddX(vtp->last, vtp->reload);
-
- /* The callback is invoked outside the kernel critical zone.*/
- chSysUnlockFromISR();
- vtp->func(vtp->par);
- chSysLockFromISR();
-
- /* Getting again the system time after executing the callback in
- order to reduce error.*/
- now = chVTGetSystemTimeX();
-
- /* If a reload is defined the timer needs to be restarted.*/
- if (vtp->reload > (sysinterval_t)0) {
- sysinterval_t skipped_delta;
-
- /* Calculating how much the real current time skipped past the
- hypothetical current deadline.*/
- skipped_delta = chTimeDiffX(vtp->last, now);
-
- chDbgAssert(skipped_delta < vtp->reload, "skipped deadline");
-
- /* Enqueuing the timer again using the calculated delta.*/
- vt_enqueue(vtlp, vtp, now, vtp->reload - skipped_delta);
- }
-
- /* Next element in the list.*/
- dlp = vtlp->dlist.next;
- }
- while (dlp->delta <= nowdelta);
- }
-
- /* If the list is empty, nothing else to do.*/
- if (is_vtlist_empty(&vtlp->dlist)) {
- return;
- }
-
- /* The "unprocessed nowdelta" time slice is added to "last time"
- and subtracted to next timer's delta.*/
-// vtlp->lasttime += nowdelta;
- vtlp->lasttime = chTimeAddX(vtlp->lasttime, nowdelta);
- vtlp->dlist.next->delta -= nowdelta;
-
- /* Recalculating the next alarm time.*/
- delta = dlp->delta - chTimeDiffX(vtlp->lasttime, now);
- if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
- delta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
- }
-#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
- /* The delta could be too large for the physical timer to handle.*/
- else if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
- delta = (sysinterval_t)TIME_MAX_SYSTIME;
- }
-#endif
- port_timer_set_alarm(chTimeAddX(now, delta));
-
- chDbgAssert(chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()) <=
- chTimeDiffX(vtlp->lasttime, chTimeAddX(now, delta)),
- "exceeding delta");
-#endif /* CH_CFG_ST_TIMEDELTA > 0 */
-}
-
-#if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__)
-/**
- * @brief Generates a monotonic time stamp.
- * @details This function generates a monotonic time stamp synchronized with
- * the system time. The time stamp has the same resolution of
- * system time.
- * @note There is an assumption, this function must be called at
- * least once before the system time wraps back to zero or
- * synchronization is lost. You may use a periodic virtual timer with
- * a very large interval in order to keep time stamps synchronized
- * by calling this function.
- *
- * @return The time stamp.
- *
- * @iclass
- */
-systimestamp_t chVTGetTimeStampI(void) {
- os_instance_t * oip = currcore;
- systimestamp_t last, stamp;
- systime_t now;
-
- chDbgCheckClassI();
-
- /* Current system time.*/
- now = chVTGetSystemTimeX();
-
- /* Last time stamp generated.*/
- last = oip->vtlist.laststamp;
-
- /* Interval between the last time stamp and current time used for a new
- time stamp. Note that this fails if the interval is larger than a
- systime_t type.*/
- stamp = last + (systimestamp_t)chTimeDiffX((systime_t)last, now);
-
- chDbgAssert(oip->vtlist.laststamp <= stamp, "wrapped");
-
- /* Storing the new stamp.*/
- oip->vtlist.laststamp = stamp;
-
- return stamp;
-}
-
-/**
- * @brief Resets and re-synchronizes the time stamps monotonic counter.
- *
- * @iclass
- */
-void chVTResetTimeStampI(void) {
-
- chDbgCheckClassI();
-
- currcore->vtlist.laststamp = (systimestamp_t)chVTGetSystemTimeX();
-}
-
-#endif /* CH_CFG_USE_TIMESTAMP == TRUE */
-
-/** @} */
diff --git a/readme.txt b/readme.txt
index f82413003..36c6f2277 100644
--- a/readme.txt
+++ b/readme.txt
@@ -74,6 +74,7 @@
*****************************************************************************
*** Next ***
+- NEW: Reload feature added to RT virtual timers.
- NEW: Upgraded the clock initialization for STM32G0, STM32L4 and STM32L4++
to the new standard (started with STM32G4).
- NEW: Added support for STM32L422.
diff --git a/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Flash and Run).launch b/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Flash and Run).launch
index b66442fc0..73496f85f 100644
--- a/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Flash and Run).launch
+++ b/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Flash and Run).launch
@@ -1,49 +1,42 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Just Run).launch b/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Just Run).launch
index 5b5f68d54..998e73c46 100644
--- a/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Just Run).launch
+++ b/testrt/VT_STORM/debug/TEST-RT-VT_STORM (build-stm32g474re_nucleo64-ch.elf)(OpenOCD, Just Run).launch
@@ -3,7 +3,7 @@
-
+
@@ -17,12 +17,12 @@
-
+
-
-
-
-
+
+
+
+
@@ -31,18 +31,11 @@
-
+
-
-
-
-
-
-
-