Tickless mode fixed hopefully.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7837 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
Giovanni Di Sirio 2015-03-31 17:00:29 +00:00
parent 246b79ae4a
commit 2ec209bdfa
3 changed files with 58 additions and 81 deletions

View File

@ -5,7 +5,7 @@
# Compiler options here. # Compiler options here.
ifeq ($(USE_OPT),) ifeq ($(USE_OPT),)
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif endif
# C specific options here (added to USE_OPT). # C specific options here (added to USE_OPT).

View File

@ -35,31 +35,6 @@ static THD_FUNCTION(Thread1, arg) {
} }
} }
virtual_timer_t vt1, vt2, vt3;
static void cb1(void *p) {
(void)p;
chSysLockFromISR();
// if (chVTIsArmedI(&vt1))
// chVTDoResetI(&vt1);
chSysUnlockFromISR();
}
static void cb2(void *p) {
(void)p;
chSysLockFromISR();
// if (!chVTIsArmedI(&vt3))
// chVTDoSetI(&vt3, 19, cb1, NULL);
chSysUnlockFromISR();
}
static void cb3(void *p) {
(void)p;
}
/* /*
* Application entry point. * Application entry point.
*/ */
@ -95,12 +70,5 @@ int main(void) {
while (TRUE) { while (TRUE) {
if (palReadPad(GPIOA, GPIOA_BUTTON)) if (palReadPad(GPIOA, GPIOA_BUTTON))
TestThread(&SD2); TestThread(&SD2);
chVTSet(&vt1, 7, cb1, NULL);
chThdSleep(5);
chSysLock();
if (!chVTIsArmedI(&vt2))
chVTDoSetI(&vt2, 13, cb2, NULL);
chSysUnlock();
// chVTReset(&vt1);
} }
} }

View File

@ -162,21 +162,17 @@ void chVTDoSetI(virtual_timer_t *vtp, systime_t delay,
* @iclass * @iclass
*/ */
void chVTDoResetI(virtual_timer_t *vtp) { void chVTDoResetI(virtual_timer_t *vtp) {
#if CH_CFG_ST_TIMEDELTA > 0
virtual_timer_t *first;
#endif
chDbgCheckClassI(); chDbgCheckClassI();
chDbgCheck(vtp != NULL); chDbgCheck(vtp != NULL);
chDbgAssert(vtp->vt_func != NULL, "timer not set or already triggered"); chDbgAssert(vtp->vt_func != NULL, "timer not set or already triggered");
/* Checking if the element to be removed was the first in the list.*/ #if CH_CFG_ST_TIMEDELTA == 0
#if CH_CFG_ST_TIMEDELTA > 0
first = ch.vtlist.vt_next;
#endif
/* Removing the element from the delta list.*/ /* The delta of the timer is added to the next timer.*/
vtp->vt_next->vt_delta += vtp->vt_delta; vtp->vt_next->vt_delta += vtp->vt_delta;
/* Removing the element from the delta list.*/
vtp->vt_prev->vt_next = vtp->vt_next; vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev; vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = NULL; vtp->vt_func = NULL;
@ -184,50 +180,63 @@ void chVTDoResetI(virtual_timer_t *vtp) {
/* The above code changes the value in the header when the removed element /* The above code changes the value in the header when the removed element
is the last of the list, restoring it.*/ is the last of the list, restoring it.*/
ch.vtlist.vt_delta = (systime_t)-1; ch.vtlist.vt_delta = (systime_t)-1;
#else /* CH_CFG_ST_TIMEDELTA > 0 */
systime_t nowdelta, delta;
#if CH_CFG_ST_TIMEDELTA > 0 /* If the timer is not the first of the list then it is simply unlinked
{ else the operation is more complex.*/
systime_t nowdelta, delta; if (ch.vtlist.vt_next != vtp) {
/* Removing the element from the delta list.*/
vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = NULL;
/* Just removed the last element in the list, alarm timer stopped and /* The above code can change the value in the header when the removed
return.*/ element is the last of the list, restoring it.*/
if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) { ch.vtlist.vt_delta = (systime_t)-1;
port_timer_stop_alarm();
return;
}
/* If the removed element was not the first one then just return, the return;
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);
} }
/* Removing the first timer from the list.*/
ch.vtlist.vt_next = vtp->vt_next;
ch.vtlist.vt_next->vt_prev = (virtual_timer_t *)&ch.vtlist;
/* If the list become empty then the alarm timer is stopped and done.*/
if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) {
port_timer_stop_alarm();
return;
}
/* The delta of the removed timer is added to the new first timer.*/
ch.vtlist.vt_next->vt_delta += vtp->vt_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 (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);
#endif /* CH_CFG_ST_TIMEDELTA > 0 */ #endif /* CH_CFG_ST_TIMEDELTA > 0 */
} }