Skip to content

Commit

Permalink
WIP: make xtimer ISR safe
Browse files Browse the repository at this point in the history
  • Loading branch information
kaspar030 committed May 10, 2016
1 parent 48c408b commit 7dc9ed2
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 389 deletions.
23 changes: 8 additions & 15 deletions sys/include/xtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static inline void xtimer_spin(uint32_t microseconds);
* @param[in] usecs time in microseconds that will be added to
* last_wakeup
*/
void xtimer_usleep_until(uint32_t *last_wakeup, uint32_t usecs);
void xtimer_usleep_until(uint64_t *last_wakeup, uint32_t usecs);

/**
* @brief Set a timer that sends a message
Expand Down Expand Up @@ -398,7 +398,7 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
#if XTIMER_WIDTH != 32
#define XTIMER_MASK ((0xffffffff >> XTIMER_WIDTH) << XTIMER_WIDTH)
#else
#define XTIMER_MASK (0)
#define XTIMER_MASK (0U)
#endif

#define XTIMER_MASK_SHIFTED XTIMER_TICKS_TO_USEC(XTIMER_MASK)
Expand All @@ -407,6 +407,7 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
extern volatile uint32_t _high_cnt;
#endif

#define XTIMER_MSBMASK (((uint32_t)1)<<(XTIMER_WIDTH-1))
/**
* @brief IPC message type for xtimer msg callback
*/
Expand Down Expand Up @@ -437,7 +438,7 @@ static inline uint32_t _lltimer_mask(uint32_t val)
* @brief xtimer internal stuff
* @internal
*/
int _xtimer_set_absolute(xtimer_t *timer, uint32_t target);
void _xtimer_set_absolute(xtimer_t *timer);
void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset);
void _xtimer_sleep(uint32_t offset, uint32_t long_offset);
static inline void xtimer_spin_until(uint32_t value);
Expand All @@ -453,18 +454,10 @@ static inline void xtimer_spin_until(uint32_t value);
static inline uint32_t xtimer_now(void)
{
#if XTIMER_MASK
uint32_t latched_high_cnt, now;

/* _high_cnt can change at any time, so check the value before
* and after reading the low-level timer. If it hasn't changed,
* then it can be safely applied to the timer count. */

do {
latched_high_cnt = _high_cnt;
now = _lltimer_now();
} while (_high_cnt != latched_high_cnt);

return latched_high_cnt | now;
uint32_t high_cnt = _high_cnt;
uint32_t now = _lltimer_now();
return (high_cnt | now) +
(((high_cnt & (XTIMER_MSBMASK)) && (~now & XTIMER_MSBMASK)) * ((~XTIMER_MASK>>1)));
#else
return _lltimer_now();
#endif
Expand Down
49 changes: 8 additions & 41 deletions sys/xtimer/xtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ void _xtimer_sleep(uint32_t offset, uint32_t long_offset)
if (irq_is_in()) {
assert(!long_offset);
xtimer_spin(offset);
return;
}

xtimer_t timer;
Expand All @@ -53,54 +54,20 @@ void _xtimer_sleep(uint32_t offset, uint32_t long_offset)
mutex_lock(&mutex);
}

void xtimer_usleep_until(uint32_t *last_wakeup, uint32_t interval) {
void xtimer_usleep_until(uint64_t *last_wakeup, uint32_t interval) {
xtimer_t timer;
mutex_t mutex = MUTEX_INIT;
*last_wakeup += interval;

timer.callback = _callback_unlock_mutex;
timer.arg = (void*) &mutex;

uint32_t target = *last_wakeup + interval;
timer.long_target = (*last_wakeup)<<32;
timer.target = *last_wakeup;

uint32_t now = xtimer_now();
/* make sure we're not setting a value in the past */
if (now < *last_wakeup) {
/* base timer overflowed */
if (!((target < *last_wakeup) && (target > now))) {
goto out;
}
}
else if (! ((target < *last_wakeup) || (target > now))) {
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 * 2)) {
mutex_lock(&mutex);
if (offset >> 9) { /* >= 512 */
offset = target;
}
else {
offset += xtimer_now();
}
_xtimer_set_absolute(&timer, offset);
mutex_lock(&mutex);
}
else {
xtimer_spin(offset);
}

out:
*last_wakeup = target;
mutex_lock(&mutex);
_xtimer_set_absolute(&timer);
mutex_lock(&mutex);
}

static void _callback_msg(void* arg)
Expand Down
Loading

0 comments on commit 7dc9ed2

Please sign in to comment.