aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-07-21 13:33:06 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-07-21 13:33:06 +0000
commit6a24f95f53578a4605480de03e5c68106611eefc (patch)
treec65bbd38c9b7b4145a3ea7764600d97ffa1d8c74 /os
parent56ca204ed20f7cb2cd6c95c1d739280533febfa6 (diff)
downloadChibiOS-6a24f95f53578a4605480de03e5c68106611eefc.tar.gz
ChibiOS-6a24f95f53578a4605480de03e5c68106611eefc.tar.bz2
ChibiOS-6a24f95f53578a4605480de03e5c68106611eefc.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6021 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/kernel/include/chvt.h38
-rw-r--r--os/kernel/src/chvt.c65
-rw-r--r--os/ports/GCC/ARMCMx/STM32F3xx/port.mk1
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v7m.c4
-rw-r--r--os/ports/GCC/ARMCMx/chcore_v7m.h4
5 files changed, 99 insertions, 13 deletions
diff --git a/os/kernel/include/chvt.h b/os/kernel/include/chvt.h
index e88d03d15..222b3c843 100644
--- a/os/kernel/include/chvt.h
+++ b/os/kernel/include/chvt.h
@@ -66,8 +66,17 @@ typedef struct {
list. */
virtual_timer_t *vt_prev; /**< @brief Last timer in the delta
list. */
- systime_t vt_time; /**< @brief Must be initialized to -1. */
+ systime_t vt_delta; /**< @brief Must be initialized to -1. */
+#if CH_CFG_TIMEDELTA == 0 || defined(__DOXYGEN__)
volatile systime_t vt_systime; /**< @brief System Time counter. */
+#endif
+#if CH_CFG_TIMEDELTA > 0 || defined(__DOXYGEN__)
+ /**
+ * @brief System time of the last tick event.
+ */
+ systime_t vt_lasttime;/**< @brief System time of the last
+ tick event. */
+#endif
} virtual_timers_list_t;
/**
@@ -78,7 +87,7 @@ typedef struct {
struct virtual_timer {
virtual_timer_t *vt_next; /**< @brief Next timer in the list. */
virtual_timer_t *vt_prev; /**< @brief Previous timer in the list. */
- systime_t vt_time; /**< @brief Time delta before timeout. */
+ systime_t vt_delta; /**< @brief Time delta before timeout. */
vtfunc_t vt_func; /**< @brief Timer callback function
pointer. */
void *vt_par; /**< @brief Timer callback function
@@ -190,7 +199,11 @@ static inline systime_t chVTGetSystemTimeI(void) {
chDbgCheckClassI();
+#if CH_CFG_TIMEDELTA == 0
return vtlist.vt_systime;
+#else /* CH_CFG_TIMEDELTA > 0 */
+ return port_timer_get_time();
+#endif /* CH_CFG_TIMEDELTA > 0 */
}
/**
@@ -352,12 +365,28 @@ static inline void chVTDoTickI(void) {
chDbgCheckClassI();
+#if CH_CFG_TIMEDELTA == 0
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) {
+ --vtlist.vt_next->vt_delta;
+ while (!(vtp = vtlist.vt_next)->vt_delta) {
+ 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;
+ chSysUnlockFromIsr();
+ fn(vtp->vt_par);
+ chSysLockFromIsr();
+ }
+ }
+#else /* CH_CFG_TIMEDELTA > 0 */
+ if (&vtlist != (virtual_timers_list_t *)vtlist.vt_next) {
+ virtual_timer_t *vtp;
+
+ --vtlist.vt_next->vt_delta;
+ while (!(vtp = vtlist.vt_next)->vt_delta) {
vtfunc_t fn = vtp->vt_func;
vtp->vt_func = (vtfunc_t)NULL;
vtp->vt_next->vt_prev = (void *)&vtlist;
@@ -367,6 +396,7 @@ static inline void chVTDoTickI(void) {
chSysLockFromIsr();
}
}
+#endif /* CH_CFG_TIMEDELTA > 0 */
}
#endif /* _CHVT_H_ */
diff --git a/os/kernel/src/chvt.c b/os/kernel/src/chvt.c
index 3bccd1ac8..c03d442fc 100644
--- a/os/kernel/src/chvt.c
+++ b/os/kernel/src/chvt.c
@@ -67,8 +67,12 @@ virtual_timers_list_t vtlist;
void _vt_init(void) {
vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
- vtlist.vt_time = (systime_t)-1;
+ vtlist.vt_delta = (systime_t)-1;
+#if CH_CFG_TIMEDELTA == 0
vtlist.vt_systime = 0;
+#else /* CH_CFG_TIMEDELTA > 0 */
+ vtlist.vt_lasttime = 0;
+#endif /* CH_CFG_TIMEDELTA > 0 */
}
/**
@@ -125,16 +129,42 @@ void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
vtp->vt_par = par;
vtp->vt_func = vtfunc;
p = vtlist.vt_next;
- while (p->vt_time < delay) {
- delay -= p->vt_time;
- p = p->vt_next;
+
+#if CH_CFG_TIMEDELTA > 0 || defined(__DOXYGEN__)
+ {
+ systime_t now = port_timer_get_time();
+
+ /* If the requested delay is lower than the minimum safe delta then it
+ is raised to the minimum safe value.*/
+ if (delay < CH_CFG_TIMEDELTA)
+ delay = CH_CFG_TIMEDELTA;
+
+ /* Now the delay is calculated as delta from the last tick interrupt
+ time.*/
+ delay += now - vtlist.vt_lasttime;
+
+ if (&vtlist != (virtual_timers_list_t *)p)
+ port_timer_start_alarm(vtlist.vt_lasttime + delay);
+ else if (delay < p->vt_delta)
+ port_timer_set_alarm(vtlist.vt_lasttime + delay);
}
+#endif /* CH_CFG_TIMEDELTA > 0 */
+ /* The delta list is scanned in order to find the correct position for
+ this timer. */
+ while (p->vt_delta < delay) {
+ delay -= p->vt_delta;
+ p = p->vt_next;
+ }
+ /* The timer is inserted in the delta list.*/
vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
vtp->vt_prev->vt_next = p->vt_prev = vtp;
- vtp->vt_time = delay;
- if (p != (void *)&vtlist)
- p->vt_time -= delay;
+ vtp->vt_delta = delay
+
+ /* Special case when the timer is in last position in the list, the
+ value in the header must be restored.*/;
+ p->vt_delta -= delay;
+ vtlist.vt_delta = (systime_t)-1;
}
/**
@@ -153,11 +183,28 @@ void chVTDoResetI(virtual_timer_t *vtp) {
"chVTDoResetI(), #1",
"timer not set or already triggered");
- if (vtp->vt_next != (void *)&vtlist)
- vtp->vt_next->vt_time += vtp->vt_time;
+ /* Removing the element from the delta list.*/
+ vtp->vt_next->vt_delta += vtp->vt_delta;
vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = (vtfunc_t)NULL;
+
+ /* The above code changes the value in the header when the removed element
+ is the last of the list, restoring it.*/
+ vtlist.vt_delta = (systime_t)-1;
+
+#if CH_CFG_TIMEDELTA > 0 || defined(__DOXYGEN__)
+ {
+ if (&vtlist == (virtual_timers_list_t *)vtlist.vt_next) {
+ /* Just removed the last element in the list, alarm timer stopped.*/
+ port_timer_stop_alarm();
+ }
+ else {
+ /* The alarm is set to the next element in the delta list.*/
+ port_timer_set_alarm(vtlist.vt_lasttime + vtlist.vt_next->vt_delta);
+ }
+ }
+#endif /* CH_CFG_TIMEDELTA > 0 */
}
/** @} */
diff --git a/os/ports/GCC/ARMCMx/STM32F3xx/port.mk b/os/ports/GCC/ARMCMx/STM32F3xx/port.mk
index 09cc8dfd6..e4da1ad11 100644
--- a/os/ports/GCC/ARMCMx/STM32F3xx/port.mk
+++ b/os/ports/GCC/ARMCMx/STM32F3xx/port.mk
@@ -1,6 +1,7 @@
# List of the ChibiOS/RT Cortex-M4 STM32 port files.
PORTSRC = $(CHIBIOS)/os/ports/GCC/ARMCMx/crt0.c \
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F3xx/vectors.c \
+ $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F3xx/chtimer.c \
${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v7m.c \
${CHIBIOS}/os/ports/common/ARMCMx/nvic.c
diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.c b/os/ports/GCC/ARMCMx/chcore_v7m.c
index 29d02761c..dfe2e2d5a 100644
--- a/os/ports/GCC/ARMCMx/chcore_v7m.c
+++ b/os/ports/GCC/ARMCMx/chcore_v7m.c
@@ -32,6 +32,7 @@
/* Port interrupt handlers. */
/*===========================================================================*/
+#if CH_CFG_TIMEDELTA == 0
/**
* @brief System Timer vector.
* @details This interrupt is used as system tick.
@@ -47,6 +48,7 @@ CH_IRQ_HANDLER(SysTickVector) {
CH_IRQ_EPILOGUE();
}
+#endif /* CH_CFG_TIMEDELTA == 0 */
#if !CORTEX_SIMPLIFIED_PRIORITY || defined(__DOXYGEN__)
/**
@@ -119,8 +121,10 @@ void _port_init(void) {
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL));
nvicSetSystemHandlerPriority(HANDLER_PENDSV,
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV));
+#if CH_CFG_TIMEDELTA == 0
nvicSetSystemHandlerPriority(HANDLER_SYSTICK,
CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK));
+#endif
}
#if !CH_CFG_OPTIMIZE_SPEED
diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.h b/os/ports/GCC/ARMCMx/chcore_v7m.h
index 8829872a9..8418139ff 100644
--- a/os/ports/GCC/ARMCMx/chcore_v7m.h
+++ b/os/ports/GCC/ARMCMx/chcore_v7m.h
@@ -518,6 +518,10 @@ extern "C" {
}
#endif
+#if CH_CFG_TIMEDELTA > 0
+#include "chtimer.h"
+#endif
+
#endif /* _FROM_ASM_ */
#endif /* _CHCORE_V7M_H_ */