X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fdrv%2Ftimer.c;h=62f272ddc93274db3b20598edc425ebf7ba9ba56;hb=7911a6f01bc8a19f220f98e2fdc8595f65996853;hp=e8508e047f18d3f767632eaf3809cd3bf5786ec0;hpb=a5a4e29851b8de831681013945abe8764c594cec;p=bertos.git diff --git a/bertos/drv/timer.c b/bertos/drv/timer.c index e8508e04..62f272dd 100644 --- a/bertos/drv/timer.c +++ b/bertos/drv/timer.c @@ -158,6 +158,8 @@ INLINE void timer_addToList(Timer *timer, List *queue) * When the delay indicated by the timer expires, the timer * device will execute the event associated with it. * + * You should not call this function on an already running timer. + * * \note Interrupt safe */ void timer_add(Timer *timer) @@ -252,14 +254,13 @@ void timer_delayTicks(ticks_t delay) #if CONFIG_KERN_SIGNALS Timer t; - + DB(t.magic = TIMER_MAGIC_INACTIVE;) if (proc_preemptAllowed()) { - ASSERT(!sig_check(SIG_SINGLE)); - timer_setSignal(&t, proc_current(), SIG_SINGLE); + timer_setEvent(&t); timer_setDelay(&t, delay); timer_add(&t); - sig_wait(SIG_SINGLE); + timer_waitEvent(&t); } else #endif /* !CONFIG_KERN_SIGNALS */ @@ -286,15 +287,30 @@ void timer_busyWait(hptime_t delay) hptime_t now, prev = timer_hw_hpread(); hptime_t delta; - for(;;) + for (;;) { now = timer_hw_hpread(); /* - * We rely on hptime_t being unsigned here to - * reduce the modulo to an AND in the common - * case of TIMER_HW_CNT. + * The timer counter may wrap here and "prev" can become + * greater than "now". So, be sure to always evaluate a + * coherent timer difference: + * + * 0 prev now TIMER_HW_CNT + * |_____|_______________|_____| + * ^^^^^^^^^^^^^^^ + * delta = now - prev + * + * 0 now prev TIMER_HW_CNT + * |_____|_______________|_____| + * ^^^^^ ^^^^^ + * delta = (TIMER_HW_CNT - prev) + now + * + * NOTE: TIMER_HW_CNT can be any value, not necessarily a power + * of 2. For this reason the "%" operator is not suitable for + * the generic case. */ - delta = (now - prev) % TIMER_HW_CNT; + delta = (now < prev) ? ((hptime_t)TIMER_HW_CNT - prev + now) : + (now - prev); if (delta >= delay) break; delay -= delta; @@ -386,17 +402,14 @@ void timer_init(void) } -#if (ARCH & ARCH_EMUL) +#if (ARCH & ARCH_EMUL) || (CPU_ARM_AT91) /** - * Stop timer (only used by emulator) + * Stop timer */ void timer_cleanup(void) { MOD_CLEANUP(timer); timer_hw_cleanup(); - - // Hmmm... apparently, the demo app does not cleanup properly - //ASSERT(LIST_EMPTY(&timers_queue)); } -#endif /* ARCH_EMUL */ +#endif