diff --git a/os/rt/include/chobjects.h b/os/rt/include/chobjects.h index 86c140db4..66ea8dccd 100644 --- a/os/rt/include/chobjects.h +++ b/os/rt/include/chobjects.h @@ -98,10 +98,6 @@ typedef struct ch_virtual_timer { * @brief Timer callback function parameter. */ void *par; - /** - * @brief Time of the last activation. - */ - systime_t last; /** * @brief Current reload interval. */ diff --git a/os/rt/include/chvt.h b/os/rt/include/chvt.h index 4f2e79722..d72b92a3d 100644 --- a/os/rt/include/chvt.h +++ b/os/rt/include/chvt.h @@ -76,6 +76,7 @@ extern "C" { void chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par); void chVTDoResetI(virtual_timer_t *vtp); + sysinterval_t chVTGetRemainingIntervalI(virtual_timer_t *vtp); void chVTDoTickI(void); #if CH_CFG_USE_TIMESTAMP == TRUE systimestamp_t chVTGetTimeStampI(void); @@ -454,31 +455,6 @@ static inline void chVTSetReloadIntervalX(virtual_timer_t *vtp, vtp->reload = reload; } -/** - * @brief Returns the remaining time interval before next timer trigger. - * @note This function can be called while the timer is active or - * after stopping it. - * - * @param[in] vtp the @p virtual_timer_t structure pointer - * @return The remaining time interval. - * - * @xclass - */ -static inline sysinterval_t chVTGetRemainingIntervalX(virtual_timer_t *vtp) { - sysinterval_t elapsed_time; - - /* Time elapsed since last triggering or 1st activation.*/ - elapsed_time = chTimeDiffX(vtp->last, chVTGetSystemTimeX()); - - /* Current time could have slipped past the next deadline, compensating.*/ - if (elapsed_time > vtp->reload) { - elapsed_time = vtp->reload; - } - - /* Returning the remaining time interval.*/ - return vtp->reload - elapsed_time; -} - #if (CH_CFG_USE_TIMESTAMP == TRUE) || defined(__DOXYGEN__) /** * @brief Generates a monotonic time stamp. diff --git a/os/rt/src/chvt.c b/os/rt/src/chvt.c index 9f845f5cb..9dcdab940 100644 --- a/os/rt/src/chvt.c +++ b/os/rt/src/chvt.c @@ -204,6 +204,8 @@ static void vt_enqueue(virtual_timers_list_t *vtlp, } } #else /* CH_CFG_ST_TIMEDELTA == 0 */ + (void)now; + /* Delta is initially equal to the specified delay.*/ delta = delay; #endif /* CH_CFG_ST_TIMEDELTA == 0 */ @@ -274,11 +276,10 @@ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay, /* Timer initialization.*/ vtp->par = par; vtp->func = vtfunc; - vtp->last = now; vtp->reload = (sysinterval_t)0; /* Inserting the timer in the delta list.*/ - vt_enqueue(vtlp, vtp, vtp->last, delay); + vt_enqueue(vtlp, vtp, now, delay); } /** @@ -317,11 +318,10 @@ void chVTDoSetContinuousI(virtual_timer_t *vtp, sysinterval_t delay, /* Timer initialization.*/ vtp->par = par; vtp->func = vtfunc; - vtp->last = now; vtp->reload = delay; /* Inserting the timer in the delta list.*/ - vt_enqueue(vtlp, vtp, vtp->last, delay); + vt_enqueue(vtlp, vtp, now, delay); } /** @@ -423,6 +423,43 @@ void chVTDoResetI(virtual_timer_t *vtp) { #endif /* CH_CFG_ST_TIMEDELTA > 0 */ } +/** + * @brief Returns the remaining time interval before next timer trigger. + * @note This function can be called while the timer is active or + * after stopping it. + * + * @param[in] vtp the @p virtual_timer_t structure pointer + * @return The remaining time interval. + * + * @iclass + */ +sysinterval_t chVTGetRemainingIntervalI(virtual_timer_t *vtp) { + virtual_timers_list_t *vtlp = &currcore->vtlist; + sysinterval_t deadline; + delta_list_t *dlp; + + chDbgCheckClassI(); + + deadline = (sysinterval_t)0; + dlp = vtlp->dlist.next; + do { + deadline += dlp->delta; + if (dlp == &vtp->dlist) { + systime_t now = chVTGetSystemTimeX(); + sysinterval_t nowdelta = chTimeDiffX(vtlp->lasttime, now); + if (nowdelta > deadline) { + return (sysinterval_t)0; + } + return nowdelta - deadline; + } + dlp = dlp->next; + } while (dlp != &vtlp->dlist); + + chDbgAssert(false, "timer not in list"); + + return (sysinterval_t)-1; +} + /** * @brief Virtual timers ticker. * @note The system lock is released before entering the callback and @@ -471,6 +508,7 @@ void chVTDoTickI(void) { dlp = vtlp->dlist.next; while (true) { virtual_timer_t *vtp = (virtual_timer_t *)dlp; + systime_t lasttime; /* Checking if the next timer in the list is within the current time delta. Note that the list scan is limited by the timers @@ -481,8 +519,8 @@ void chVTDoTickI(void) { } /* Last time deadline is updated to the next timer's time.*/ - vtlp->lasttime = chTimeAddX(vtlp->lasttime, dlp->delta); - vtp->last = vtlp->lasttime; + lasttime = chTimeAddX(vtlp->lasttime, dlp->delta); + vtlp->lasttime = lasttime; chDbgAssert((int)chTimeDiffX(vtlp->lasttime, now) >= 0, "back in time"); @@ -514,7 +552,7 @@ void chVTDoTickI(void) { /* Calculating how much the actual current time skipped past the current deadline.*/ - skipped_delta = chTimeDiffX(vtp->last, now); + skipped_delta = chTimeDiffX(lasttime, now); chDbgAssert(skipped_delta <= vtp->reload, "skipped deadline");