diff --git a/src/avr/timer.c b/src/avr/timer.c index a6da9b4ff..06d8845e7 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -38,13 +38,6 @@ timer_set(uint16_t next) OCR1A = next; } -static inline void -timer_set_clear(uint16_t next) -{ - OCR1A = next; - TIFR1 = 1<TC_CHANNEL[0].TC_RA = value; } -static void -timer_set_clear(uint32_t value) -{ - TC0->TC_CHANNEL[0].TC_RA = value; - TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending -} - static void timer_init(void) { @@ -69,6 +62,15 @@ timer_init(void) } DECL_INIT(timer_init); +static void +timer_shutdown(void) +{ + // Reenable timer irq + timer_set(timer_read_time() + 50); + TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending +} +DECL_SHUTDOWN(timer_shutdown); + // Called by main code once every millisecond. (IRQs disabled.) void timer_periodic(void) @@ -82,28 +84,6 @@ timer_read_time(void) return TC0->TC_CHANNEL[0].TC_CV; } -#define TIMER_MIN_TICKS 100 - -// Set the next timer wake time (in absolute clock ticks). Caller -// must disable irqs. The caller should not schedule a time more than -// a few milliseconds in the future. -uint8_t -timer_set_next(uint32_t next) -{ - uint32_t cur = timer_read_time(); - if (sched_is_before(TC0->TC_CHANNEL[0].TC_RA, cur) - && !(TC0->TC_CHANNEL[0].TC_SR & TC_SR_CPAS)) - // Already processing timer irqs - try_shutdown("timer_set_next called during timer dispatch"); - uint32_t mintime = cur + TIMER_MIN_TICKS; - if (sched_is_before(mintime, next)) { - timer_set_clear(next); - return 0; - } - timer_set_clear(mintime); - return 1; -} - static uint32_t timer_repeat_until; #define TIMER_IDLE_REPEAT_TICKS timer_from_us(500) #define TIMER_REPEAT_TICKS timer_from_us(100) @@ -111,8 +91,9 @@ static uint32_t timer_repeat_until; #define TIMER_MIN_TRY_TICKS timer_from_us(1) #define TIMER_DEFER_REPEAT_TICKS timer_from_us(5) -// Similar to timer_set_next(), but wait for the given time if it is -// in the near future. +// Set the next timer wake time (in absolute clock ticks) or return 1 +// if the next timer is too close to schedule. Caller must disable +// irqs. uint8_t timer_try_set_next(uint32_t next) { diff --git a/src/sched.c b/src/sched.c index 19e428be6..7e4a86a1c 100644 --- a/src/sched.c +++ b/src/sched.c @@ -101,33 +101,39 @@ sched_timer(struct timer *add) { uint32_t waketime = add->waketime; irqstatus_t flag = irq_save(); - if (sched_is_before(waketime, timer_list->waketime)) { - // This timer is the next - insert at front of list and reschedule - add->next = timer_list; - timer_list = add; - uint8_t ret = timer_set_next(waketime); - if (ret) - shutdown("Timer too close"); - } else { - // Find position in list and insert - struct timer *pos = timer_list; - while (!sched_is_before(waketime, pos->next->waketime)) - pos = pos->next; - add->next = pos->next; - pos->next = add; - } + if (sched_is_before(waketime, timer_list->waketime)) + // Timer in past (or very near future) + shutdown("Timer too close"); + // Find position in list and insert + struct timer *pos = timer_list; + while (!sched_is_before(waketime, pos->next->waketime)) + pos = pos->next; + add->next = pos->next; + pos->next = add; irq_restore(flag); } +// The deleted timer is used when deleting an active timer. +static uint_fast8_t +deleted_event(struct timer *t) +{ + return SF_DONE; +} + +static struct timer deleted_timer = { + .func = deleted_event, +}; + // Remove a timer that may be live. void sched_del_timer(struct timer *del) { irqstatus_t flag = irq_save(); if (timer_list == del) { - // Deleting the next active timer - delete and reschedule - timer_list = del->next; - timer_set_next(timer_list->waketime); + // Deleting the next active timer - replace with deleted_timer + deleted_timer.waketime = del->waketime; + deleted_timer.next = del->next; + timer_list = &deleted_timer; } else { // Find and remove from timer list (if present) struct timer *pos; @@ -197,13 +203,14 @@ sched_timer_kick(void) // Shutdown all user timers on an emergency stop. static void -timer_shutdown(void) +sched_timer_shutdown(void) { - timer_list = &ms_timer; + timer_list = &deleted_timer; + deleted_timer.waketime = ms_timer.waketime; + deleted_timer.next = &ms_timer; ms_timer.next = &sentinel_timer; - timer_set_next(timer_list->waketime); } -DECL_SHUTDOWN(timer_shutdown); +DECL_SHUTDOWN(sched_timer_shutdown); /**************************************************************** diff --git a/src/simulator/main.c b/src/simulator/main.c index 1bffc265c..f45b5c459 100644 --- a/src/simulator/main.c +++ b/src/simulator/main.c @@ -69,12 +69,6 @@ timer_read_time(void) return 0; // XXX } -uint8_t -timer_set_next(uint32_t next) -{ - return 0; -} - uint8_t timer_try_set_next(uint32_t next) {