aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-03-31 06:22:30 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-03-31 06:22:30 +0000
commita484164f768cdea9b346b2af2c71376e8e260d21 (patch)
tree9837887373002c08698f417ba48575bb4e210f0a /os
parent330e38629d60553f3d9ab8f544361cdb3deee691 (diff)
downloadChibiOS-a484164f768cdea9b346b2af2c71376e8e260d21.tar.gz
ChibiOS-a484164f768cdea9b346b2af2c71376e8e260d21.tar.bz2
ChibiOS-a484164f768cdea9b346b2af2c71376e8e260d21.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7833 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/ports/STM32/LLD/TIMv1/st_lld.h1
-rw-r--r--os/rt/include/chvt.h30
-rw-r--r--os/rt/src/chvt.c82
3 files changed, 86 insertions, 27 deletions
diff --git a/os/hal/ports/STM32/LLD/TIMv1/st_lld.h b/os/hal/ports/STM32/LLD/TIMv1/st_lld.h
index 7e64b893b..9c5442158 100644
--- a/os/hal/ports/STM32/LLD/TIMv1/st_lld.h
+++ b/os/hal/ports/STM32/LLD/TIMv1/st_lld.h
@@ -164,6 +164,7 @@ static inline void st_lld_stop_alarm(void) {
static inline void st_lld_set_alarm(systime_t time) {
STM32_ST_TIM->CCR[0] = (uint32_t)time;
+ STM32_ST_TIM->SR = 0;
}
/**
diff --git a/os/rt/include/chvt.h b/os/rt/include/chvt.h
index 736d572b4..0bb127250 100644
--- a/os/rt/include/chvt.h
+++ b/os/rt/include/chvt.h
@@ -466,7 +466,6 @@ static inline void chVTDoTickI(void) {
}
#else /* CH_CFG_ST_TIMEDELTA > 0 */
virtual_timer_t *vtp;
- systime_t now, delta;
/* The list is assumed to be non-empty because an tick interrupt just
occurred.*/
@@ -482,6 +481,10 @@ static inline void chVTDoTickI(void) {
chVTGetSystemTimeX() + 1),
"out of time window");
+/* if (now > 21) {
+ __BKPT(0);
+ }*/
+
/* Timers processing loop.*/
while (true) {
vtfunc_t fn;
@@ -495,11 +498,6 @@ static inline void chVTDoTickI(void) {
fn = vtp->vt_func;
vtp->vt_func = NULL;
- /* If the list is empty then the timer is stopped.*/
- if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) {
- port_timer_stop_alarm();
- }
-
/* Leaving the system critical zone in order to execute the callback
and in order to give a preemption chance to higher priority
interrupts.*/
@@ -513,25 +511,33 @@ static inline void chVTDoTickI(void) {
chSysLockFromISR();
/* If the list is empty then ending the loop, the list has to be
- re-checked because new timers could have been added from within
- the callback.*/
+ re-checked because new timers could have been added/removed from
+ within the callback or other ISRs.*/
vtp = ch.vtlist.vt_next;
if (&ch.vtlist == (virtual_timers_list_t *)vtp) {
+ /* Timers list empty, stopping alarms.*/
+ port_timer_stop_alarm();
return;
}
/* Getting the current system time and calculating the time window since
the last time has expired.*/
now = chVTGetSystemTimeX();
- delta = now - ch.vtlist.vt_lasttime;
/* The next element is outside the current time window, the loop
is stopped here.*/
- if (vtp->vt_delta > delta) {
+ if (vtp->vt_delta > now - ch.vtlist.vt_lasttime) {
/* Updating the alarm to the next deadline, deadline that must not be
closer in time than the minimum time delta.*/
- delta = (vtp->vt_delta >= (systime_t)CH_CFG_ST_TIMEDELTA) ?
- vtp->vt_delta : (systime_t)CH_CFG_ST_TIMEDELTA;
+ systime_t delta = ch.vtlist.vt_lasttime + vtp->vt_delta - now;
+ if (delta < (systime_t)CH_CFG_ST_TIMEDELTA) {
+ delta = (systime_t)CH_CFG_ST_TIMEDELTA;
+ }
+
+// if (now + delta >= 23) {
+// __BKPT(0);
+// }
+
port_timer_set_alarm(now + delta);
chDbgAssert((chVTGetSystemTimeX() - ch.vtlist.vt_lasttime) < delta,
diff --git a/os/rt/src/chvt.c b/os/rt/src/chvt.c
index 61fa7e056..eae49bd3a 100644
--- a/os/rt/src/chvt.c
+++ b/os/rt/src/chvt.c
@@ -99,13 +99,18 @@ void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
chDbgCheckClassI();
chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
+/* systime_t tm = chVTGetSystemTimeX();
+ if (tm >= 23) {
+ __BKPT(0);
+ }*/
+
vtp->vt_par = par;
vtp->vt_func = vtfunc;
p = ch.vtlist.vt_next;
-#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+#if CH_CFG_ST_TIMEDELTA > 0
{
- systime_t now = port_timer_get_time();
+ systime_t now = chVTGetSystemTimeX();
/* If the requested delay is lower than the minimum safe delta then it
is raised to the minimum safe value.*/
@@ -151,6 +156,11 @@ void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
value in the header must be restored.*/;
p->vt_delta -= delay;
ch.vtlist.vt_delta = (systime_t)-1;
+
+/* systime_t tmx = chVTGetSystemTimeX();
+ if (tmx >= 23) {
+ __BKPT(0);
+ }*/
}
/**
@@ -162,11 +172,24 @@ void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
* @iclass
*/
void chVTDoResetI(virtual_timer_t *vtp) {
+#if CH_CFG_ST_TIMEDELTA > 0
+ virtual_timer_t *first;
+#endif
chDbgCheckClassI();
chDbgCheck(vtp != NULL);
chDbgAssert(vtp->vt_func != NULL, "timer not set or already triggered");
+/* systime_t tm = chVTGetSystemTimeX();
+ if (tm >= 23) {
+ __BKPT(0);
+ }*/
+
+ /* Checking if the element to be removed was the first in the list.*/
+#if CH_CFG_ST_TIMEDELTA > 0
+ first = ch.vtlist.vt_next;
+#endif
+
/* Removing the element from the delta list.*/
vtp->vt_next->vt_delta += vtp->vt_delta;
vtp->vt_prev->vt_next = vtp->vt_next;
@@ -177,24 +200,53 @@ void chVTDoResetI(virtual_timer_t *vtp) {
is the last of the list, restoring it.*/
ch.vtlist.vt_delta = (systime_t)-1;
-#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+#if CH_CFG_ST_TIMEDELTA > 0
{
+ systime_t nowdelta, delta;
+
+ /* Just removed the last element in the list, alarm timer stopped and
+ return.*/
if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) {
- /* Just removed the last element in the list, alarm timer stopped.*/
port_timer_stop_alarm();
+ return;
}
- else {
- /* Updating the alarm to the next deadline, deadline that must not be
- closer in time than the minimum time delta.*/
- if (ch.vtlist.vt_next->vt_delta >= (systime_t)CH_CFG_ST_TIMEDELTA) {
- port_timer_set_alarm(ch.vtlist.vt_lasttime +
- ch.vtlist.vt_next->vt_delta);
- }
- else {
- port_timer_set_alarm(ch.vtlist.vt_lasttime +
- (systime_t)CH_CFG_ST_TIMEDELTA);
- }
+
+ /* If the removed element was not the first one then just return, the
+ alarm is already set to the first element.*/
+ if (vtp != first) {
+ return;
}
+
+ /* If the new first element has a delta of zero then the alarm is not
+ modified, the already programmed alarm will serve it.*/
+ if (ch.vtlist.vt_next->vt_delta == 0) {
+ return;
+ }
+
+ /* Distance in ticks between the last alarm event and current time.*/
+ nowdelta = chVTGetSystemTimeX() - ch.vtlist.vt_lasttime;
+
+ /* If the current time surpassed the time of the next element in list
+ then the event interrupt is already pending, just return.*/
+ if (nowdelta >= ch.vtlist.vt_next->vt_delta) {
+ return;
+ }
+
+ /* Distance from the next scheduled event and now.*/
+ delta = ch.vtlist.vt_next->vt_delta - nowdelta;
+
+ /* Making sure to not schedule an event closer than CH_CFG_ST_TIMEDELTA
+ ticks from now.*/
+ if (delta < (systime_t)CH_CFG_ST_TIMEDELTA) {
+ delta = (systime_t)CH_CFG_ST_TIMEDELTA;
+ }
+
+ port_timer_set_alarm(ch.vtlist.vt_lasttime + nowdelta + delta);
+
+ systime_t tmx = chVTGetSystemTimeX();
+/* if (tmx >= 23) {
+ __BKPT(0);
+ }*/
}
#endif /* CH_CFG_ST_TIMEDELTA > 0 */
}