Tentative fix for VTs and various improvements.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14340 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-05-06 11:26:08 +00:00
parent 84c18f04a5
commit f506bdca05
1 changed files with 49 additions and 72 deletions

View File

@ -461,32 +461,32 @@ void chVTDoTickI(void) {
#else /* CH_CFG_ST_TIMEDELTA > 0 */
delta_list_t *dlp;
sysinterval_t delta, nowdelta;
systime_t now = chVTGetSystemTimeX();
systime_t now;
/* Delta between current time and last execution time.*/
now = chVTGetSystemTimeX();
nowdelta = chTimeDiffX(vtlp->lasttime, now);
/* Looping through timers.*/
dlp = vtlp->dlist.next;
while (true) {
virtual_timer_t *vtp = (virtual_timer_t *)dlp;
/* 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
/* Checking if the next timer in the list is within the current
time delta. Note that 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;
/* Last time deadline is updated to the next timer's time.*/
vtlp->lasttime = chTimeAddX(vtlp->lasttime, dlp->delta);
nowdelta -= dlp->delta;
vtp->last = vtlp->lasttime;
/* Removing the timer from the list, marking it as not armed.*/
chDbgAssert((int)chTimeDiffX(vtlp->lasttime, now) >= 0, "back in time");
/* Removing the next timer from the list, marking it as not armed.*/
dlp->next->prev = &vtlp->dlist;
vtlp->dlist.next = dlp->next;
dlp->next = NULL;
@ -496,64 +496,41 @@ void chVTDoTickI(void) {
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.*/
/* The callback is invoked outside the kernel critical section, it
is re-entered on the callback return. Note that "lasttime" can
be modified within the callback if some timer function is
called.*/
chSysUnlockFromISR();
vtp->func(vtp->par);
chSysLockFromISR();
/* Getting again the system time after executing the callback in
order to reduce error.*/
/* Delta between current time and last execution time.*/
now = chVTGetSystemTimeX();
// chDbgAssert((int)chTimeDiffX(vtp->last, now) >= 0, "back in time");
nowdelta = chTimeDiffX(vtlp->lasttime, now);
/* If a reload is defined the timer needs to be restarted.*/
if (vtp->reload > (sysinterval_t)0) {
sysinterval_t skipped_delta;
#if 1
/* Calculating how much the actual current time skipped past the
predicted current deadline.*/
current deadline.*/
skipped_delta = chTimeDiffX(vtp->last, now);
// if (vtp->reload == 121) {
// chTraceWriteI(vtp, (void *)now);
// chTraceWriteI(vtp, (void *)vtp->last);
// chTraceWriteI(vtp, (void *)skipped_delta);
// }
chDbgAssert(skipped_delta <= vtp->reload, "skipped deadline");
/* Enqueuing the timer again using the calculated delta.*/
vt_enqueue(vtlp, vtp, now, vtp->reload - skipped_delta);
#else
chVTDoSetI(vtp, vtp->reload, vtp->func, vtp->par);
#endif
}
/* 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) {