diff --git a/os/rt/src/chvt.c b/os/rt/src/chvt.c index fc61666a6..df20afac9 100644 --- a/os/rt/src/chvt.c +++ b/os/rt/src/chvt.c @@ -49,6 +49,91 @@ /*===========================================================================*/ #if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__) +#if 1 +static systime_t vt_set_alarm(systime_t basetime, sysinterval_t delta) { + sysinterval_t mindelta; + systime_t next_alarm; + + /* Initial delta is what is configured statically.*/ + mindelta = (sysinterval_t)CH_CFG_ST_TIMEDELTA; + + if (delta < mindelta) { + /* We need to avoid that the system time goes past the alarm we are + going to set before the alarm is actually set.*/ + delta = mindelta; + } +#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION + else if (delta > (sysinterval_t)TIME_MAX_SYSTIME) { + /* The delta could be too large for the physical timer to handle + this can happen when: sizeof (systime_t) < sizeof (sysinterval_t).*/ + delta = (sysinterval_t)TIME_MAX_SYSTIME; + } +#endif + + while (true) { + sysinterval_t nowdelta; + systime_t now; + + /* Absolute time for next alarm.*/ + next_alarm = chTimeAddX(basetime, delta); + + /* Setting up the alarm on the next deadline.*/ + port_timer_set_alarm(next_alarm); + + /* Check on current time, we need to detect the error condition where + current time skipped past the calculated deadline.*/ + now = chVTGetSystemTimeX(); + nowdelta = chTimeDiffX(basetime, now); + if (nowdelta < delta) { + break; + } + + /* Trying again with a more relaxed minimum delta.*/ + mindelta += (sysinterval_t)1; + + /* Current time becomes the new "base" time.*/ + basetime = now; + delta = mindelta; + +#if !defined(CH_VT_RFCU_DISABLED) + chRFCUCollectFaultsI(CH_RFCU_VT_INSUFFICIENT_DELTA); +#endif + } + + return next_alarm; +} + +#else +static systime_t vt_set_alarm(systime_t basetime, sysinterval_t delta) { + sysinterval_t mindelta; + systime_t next_alarm; + + /* Initial delta is what is configured statically.*/ + mindelta = (sysinterval_t)CH_CFG_ST_TIMEDELTA; + + if (delta < mindelta) { + /* We need to avoid that the system time goes past the alarm we are + going to set before the alarm is actually set.*/ + delta = mindelta; + } +#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION + else if (delta > (sysinterval_t)TIME_MAX_SYSTIME) { + /* The delta could be too large for the physical timer to handle + this can happen when: sizeof (systime_t) < sizeof (sysinterval_t).*/ + delta = (sysinterval_t)TIME_MAX_SYSTIME; + } +#endif + + /* Absolute time for next alarm.*/ + next_alarm = chTimeAddX(basetime, delta); + + /* Setting up the alarm on the next deadline.*/ + port_timer_set_alarm(next_alarm); + + return next_alarm; +} +#endif + /** * @brief Inserts a timer as first element in a delta list. * @note This is the special case when the delta list is initially empty. @@ -120,24 +205,8 @@ static void vt_enqueue(virtual_timers_list_t *vtlp, /* Checking if this timer would become the first in the delta list, this requires changing the current alarm setting.*/ 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; - - /* Limit delta to CH_CFG_ST_TIMEDELTA.*/ - if (deadline_delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) { - deadline_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 - this can happen when: sizeof (systime_t) < sizeof (sysinterval_t).*/ - else 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)); + (void) vt_set_alarm(vtlp->lasttime, delta); } } #else /* CH_CFG_ST_TIMEDELTA == 0 */ @@ -258,6 +327,7 @@ void chVTDoResetI(virtual_timer_t *vtp) { is the last of the list, restoring it.*/ vtlp->dlist.delta = (sysinterval_t)-1; #else /* CH_CFG_ST_TIMEDELTA > 0 */ + systime_t now; sysinterval_t nowdelta, delta; /* If the timer is not the first of the list then it is simply unlinked @@ -296,7 +366,8 @@ void chVTDoResetI(virtual_timer_t *vtp) { vtlp->dlist.next->delta += vtp->dlist.delta; /* Distance in ticks between the last alarm event and current time.*/ - nowdelta = chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()); + now = chVTGetSystemTimeX(); + nowdelta = chTimeDiffX(vtlp->lasttime, now); /* If the current time surpassed the time of the next element in list then the event interrupt is already pending, just return.*/ @@ -307,21 +378,8 @@ void chVTDoResetI(virtual_timer_t *vtp) { /* 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)); + /* Setting up the alarm.*/ + (void) vt_set_alarm(now, delta); #endif /* CH_CFG_ST_TIMEDELTA > 0 */ } @@ -407,7 +465,7 @@ void chVTDoTickI(void) { #else /* CH_CFG_ST_TIMEDELTA > 0 */ virtual_timer_t *vtp; sysinterval_t delta, nowdelta; - systime_t now; + systime_t now, next_alarm; /* Looping through timers consuming all timers with deltas lower or equal than the interval between "now" and "lasttime".*/ @@ -510,36 +568,12 @@ void chVTDoTickI(void) { /* Calculating the delta to the next alarm time.*/ delta = vtp->dlist.delta - nowdelta; - /* Limit delta to CH_CFG_ST_TIMEDELTA.*/ - 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 - /* Update alarm time to next timer.*/ - { - sysinterval_t next_alarm = chTimeAddX(now, delta); + next_alarm = vt_set_alarm(now, delta); - port_timer_set_alarm(next_alarm); - -#if !defined(CH_VT_RFCU_DISABLED) - if (chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()) > - chTimeDiffX(vtlp->lasttime, next_alarm)) { - - chDbgAssert(false, "insufficient delta"); - chRFCUCollectFaultsI(CH_RFCU_VT_INSUFFICIENT_DELTA); - } -#else - chDbgAssert(chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()) <= - chTimeDiffX(vtlp->lasttime, next_alarm), - "insufficient delta"); -#endif - } + chDbgAssert(chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()) <= + chTimeDiffX(vtlp->lasttime, next_alarm), + "insufficient delta"); #endif /* CH_CFG_ST_TIMEDELTA > 0 */ } diff --git a/testrt/VT_STORM/make/stm32g474re_nucleo64.make b/testrt/VT_STORM/make/stm32g474re_nucleo64.make index 5284ef1a0..234de33e0 100644 --- a/testrt/VT_STORM/make/stm32g474re_nucleo64.make +++ b/testrt/VT_STORM/make/stm32g474re_nucleo64.make @@ -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/testrt/VT_STORM/source/vt_storm.c b/testrt/VT_STORM/source/vt_storm.c index 09760a852..30e05785b 100644 --- a/testrt/VT_STORM/source/vt_storm.c +++ b/testrt/VT_STORM/source/vt_storm.c @@ -277,6 +277,7 @@ void vt_storm_execute(const vt_storm_config_t *cfg) { #endif for (i = 1; i <= VT_STORM_CFG_ITERATIONS; i++) { + bool dw; chprintf(cfg->out, "Iteration %d\r\n", i); chThdSleepS(TIME_MS2I(10)); @@ -305,7 +306,7 @@ void vt_storm_execute(const vt_storm_config_t *cfg) { chVTSetI(&guard2, TIME_MS2I(250) + (CH_CFG_TIME_QUANTUM + 1), guard_cb, NULL); chVTSetI(&guard3, TIME_MS2I(250) + (CH_CFG_TIME_QUANTUM * 2), guard_cb, NULL); - /* Letting them run for half second.*/ + /* Letting them run for a while.*/ chThdSleepS(TIME_MS2I(100)); /* Stopping everything.*/ @@ -323,21 +324,23 @@ void vt_storm_execute(const vt_storm_config_t *cfg) { chVTResetI(&guard3); /* Check for relevant RFCU events.*/ - delta_warning = chRFCUGetAndClearFaultsI(CH_RFCU_VT_INSUFFICIENT_DELTA | - CH_RFCU_VT_SKIPPED_DEADLINE) != (rfcu_mask_t)0; + dw = chRFCUGetAndClearFaultsI(CH_RFCU_VT_INSUFFICIENT_DELTA | + CH_RFCU_VT_SKIPPED_DEADLINE) != (rfcu_mask_t)0; chSysUnlock(); if (saturated) { chprintf(cfg->out, "#"); break; } - else if (delta_warning) { + else if (dw) { + palToggleLine(config->line); chprintf(cfg->out, "+"); - break; + delta_warning = true; + } + else { + palToggleLine(config->line); + chprintf(cfg->out, "."); } - - palToggleLine(config->line); - chprintf(cfg->out, "."); // if (delay >= TIME_US2I(1)) { // delay -= TIME_US2I(1); // }