1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

sys: xtimer: some updates

- more robust underflow protection in xtimer_usleep_until()
- use relative target in xtimer_spin()
- honour reference in isr when spinning until timer target
- add XTIMER_BACKOFF to xtimer_spin_until() target when backing off in
  _timer_set_absolute()
- doxygen updates
This commit is contained in:
Kaspar Schleiser 2015-09-15 00:11:28 +02:00
parent ca540c9d07
commit a719e7d61f
3 changed files with 36 additions and 17 deletions

View File

@ -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<<XTIMER_SHIFT).
*
* For example, if the timer is running with 250khz, set XTIMER_SHIFT to 2.
*/
#ifndef XTIMER_SHIFT
@ -372,7 +375,7 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
*/
#define XTIMER_MASK (0)
#endif
#define XTIMER_MASK_SHIFTED (XTIMER_MASK<<XTIMER_SHIFT)
#define XTIMER_MASK_SHIFTED (XTIMER_MASK << XTIMER_SHIFT)
#ifndef XTIMER_USLEEP_UNTIL_OVERHEAD
/**
@ -441,10 +444,17 @@ static inline void xtimer_spin_until(uint32_t value);
*
* Use tests/xtimer_shift_on_compare to find the correct value for your MCU.
*/
#define XTIMER_SHIFT_ON_COMPARE 0
#define XTIMER_SHIFT_ON_COMPARE (0)
#endif
#endif
#ifndef XTIMER_MIN_SPIN
/**
* @brief Minimal value xtimer_spin() can spin
*/
#define XTIMER_MIN_SPIN (1<<XTIMER_SHIFT)
#endif
static inline uint32_t xtimer_now(void)
{
#if XTIMER_MASK
@ -460,13 +470,16 @@ static inline uint32_t xtimer_now(void)
}
static inline void xtimer_spin_until(uint32_t value) {
#if XTIMER_MASK
value = _mask(value);
#endif
while (_xtimer_now() > 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 */

View File

@ -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 {

View File

@ -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;