diff --git a/sys/include/xtimer.h b/sys/include/xtimer.h index 88d10c1027..b717e147fd 100644 --- a/sys/include/xtimer.h +++ b/sys/include/xtimer.h @@ -333,6 +333,9 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us); * If the timer is slower by a power of two, XTIMER_SHIFT can be used to * adjust the difference. * + * This will also initialize the underlying periph timer with + * us_per_tick == (1< value); while (_xtimer_now() < value); } static inline void xtimer_spin(uint32_t offset) { - xtimer_spin_until(_xtimer_now() + offset + 1); + uint32_t start = _xtimer_now(); + while ((_xtimer_now() - start) < offset); } static inline void xtimer_usleep(uint32_t offset) @@ -489,16 +502,9 @@ static inline void xtimer_nanosleep(uint32_t nanoseconds) _xtimer_sleep(nanoseconds/1000, 0); } -/** @} */ - -#if XTIMER_OVERHEAD + XTIMER_USLEEP_UNTIL_OVERHEAD > XTIMER_BACKOFF -#warning (XTIMER_OVERHEAD + XTIMER_USLEEP_UNTIL_OVERHEAD > XTIMER_BACKOFF !!) -#warning This will lead to underruns. Check if tests/xtimer_usleep_until runs through. -#endif - -/** @} */ - #ifdef __cplusplus } #endif + +/** @} */ #endif /* XTIMER_H */ diff --git a/sys/xtimer/xtimer.c b/sys/xtimer/xtimer.c index 9b3f2f3927..09906783bd 100644 --- a/sys/xtimer/xtimer.c +++ b/sys/xtimer/xtimer.c @@ -72,11 +72,25 @@ void xtimer_usleep_until(uint32_t *last_wakeup, uint32_t interval) { goto out; } + /* For large offsets, set an absolute target time, as + * it is more exact. + * + * As that might cause an underflow, for small offsets, + * use a relative offset, as that can never underflow. + * + * For very small offsets, spin. + */ uint32_t offset = target - now; - if (offset > XTIMER_BACKOFF+XTIMER_USLEEP_UNTIL_OVERHEAD+1) { + if (offset > (XTIMER_BACKOFF * 2)) { mutex_lock(&mutex); - _xtimer_set_absolute(&timer, target - XTIMER_USLEEP_UNTIL_OVERHEAD); + if (offset >> 9) { /* >= 512 */ + offset = target; + } + else { + offset += xtimer_now(); + } + _xtimer_set_absolute(&timer, offset); mutex_lock(&mutex); } else { diff --git a/sys/xtimer/xtimer_core.c b/sys/xtimer/xtimer_core.c index 2b248a47f5..750d7465f7 100644 --- a/sys/xtimer/xtimer_core.c +++ b/sys/xtimer/xtimer_core.c @@ -167,7 +167,7 @@ int _xtimer_set_absolute(xtimer_t *timer, uint32_t target) timer->next = NULL; if ((target >= now) && ((target - XTIMER_BACKOFF) < now)) { /* backoff */ - xtimer_spin_until(target); + xtimer_spin_until(target+XTIMER_BACKOFF); _shoot(timer); return 0; } @@ -410,7 +410,6 @@ static void _next_period(void) overflow_list_head = NULL; _select_long_timers(); - } /** @@ -453,7 +452,7 @@ overflow: /* check if next timers are close to expiring */ while (timer_list_head && (_time_left(_mask(timer_list_head->target), reference) < XTIMER_ISR_BACKOFF)) { /* make sure we don't fire too early */ - while (_time_left(_mask(timer_list_head->target), 0)); + while (_time_left(_mask(timer_list_head->target), reference)); /* pick first timer in list */ xtimer_t *timer = timer_list_head;