diff options
-rw-r--r-- | docs/Code_Overview.md | 6 | ||||
-rw-r--r-- | src/avr/timer.c | 20 | ||||
-rw-r--r-- | src/generic/misc.h | 1 | ||||
-rw-r--r-- | src/generic/timer.c | 16 | ||||
-rw-r--r-- | src/sam3x8e/timer.c | 5 | ||||
-rw-r--r-- | src/sched.c | 55 | ||||
-rw-r--r-- | src/sched.h | 2 | ||||
-rw-r--r-- | src/simulator/main.c | 6 |
8 files changed, 62 insertions, 49 deletions
diff --git a/docs/Code_Overview.md b/docs/Code_Overview.md index ee640457..8b1ca06c 100644 --- a/docs/Code_Overview.md +++ b/docs/Code_Overview.md @@ -58,9 +58,9 @@ Timer functions are scheduled by calling sched_add_timer() (located in **src/sched.c**). The scheduler code will arrange for the given function to be called at the requested clock time. Timer interrupts are initially handled in an architecture specific interrupt handler -(eg, **src/avr/timer.c**), but this just calls sched_timer_kick() -located in **src/sched.c**. The timer interrupt leads to execution of -schedule timer functions. Timer functions always run with interrupts +(eg, **src/avr/timer.c**) which calls sched_timer_dispatch() located +in **src/sched.c**. The timer interrupt leads to execution of schedule +timer functions. Timer functions always run with interrupts disabled. The timer functions should always complete within a few micro-seconds. At completion of the timer event, the function may choose to reschedule itself. diff --git a/src/avr/timer.c b/src/avr/timer.c index e9ec8dd0..f8686998 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -70,11 +70,6 @@ timer_repeat_set(uint16_t next) TIFR1 = 1<<OCF1B; } -ISR(TIMER1_COMPA_vect) -{ - sched_timer_kick(); -} - static void timer_init(void) { @@ -143,7 +138,7 @@ timer_periodic(void) // 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 +static uint8_t timer_try_set_next(unsigned int target) { uint16_t next = target; @@ -189,6 +184,19 @@ fail: shutdown("Rescheduled timer in the past"); } +// Harware OCR1A interrupt handler +ISR(TIMER1_COMPA_vect) +{ + for (;;) { + uint16_t next_waketime = sched_timer_dispatch(); + + // Schedule next timer event (or run next timer if it's ready) + uint8_t res = timer_try_set_next(next_waketime); + if (res) + break; + } +} + // Periodic background task that temporarily boosts priority of // timers. This helps prioritize timers when tasks are idling. static void diff --git a/src/generic/misc.h b/src/generic/misc.h index bc3223e7..e8a13c00 100644 --- a/src/generic/misc.h +++ b/src/generic/misc.h @@ -13,7 +13,6 @@ uint32_t timer_from_us(uint32_t us); uint8_t timer_is_before(uint32_t time1, uint32_t time2); uint32_t timer_read_time(void); void timer_periodic(void); -uint8_t timer_try_set_next(unsigned int next); size_t alloc_maxsize(size_t reqsize); diff --git a/src/generic/timer.c b/src/generic/timer.c index 5185ed54..fba56051 100644 --- a/src/generic/timer.c +++ b/src/generic/timer.c @@ -49,7 +49,7 @@ static uint32_t timer_repeat_until; // 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 +static int timer_try_set_next(unsigned int next) { uint32_t now = timer_read_time(); @@ -84,6 +84,20 @@ fail: shutdown("Rescheduled timer in the past"); } +// Invoke timers - called from board irq code. +void +timer_dispatch_many(void) +{ + for (;;) { + uint32_t next_waketime = sched_timer_dispatch(); + + // Schedule next timer event (or run next timer if it's ready) + int res = timer_try_set_next(next_waketime); + if (res) + break; + } +} + // Periodic background task that temporarily boosts priority of // timers. This helps prioritize timers when tasks are idling. static void diff --git a/src/sam3x8e/timer.c b/src/sam3x8e/timer.c index e450d21e..dcc8dbd2 100644 --- a/src/sam3x8e/timer.c +++ b/src/sam3x8e/timer.c @@ -10,6 +10,9 @@ #include "sam3x8e.h" // TC0 #include "sched.h" // sched_timer_kick +// From generic/timer.c +extern void timer_dispatch_many(void); + // IRQ handler void __visible TC0_Handler(void) @@ -17,7 +20,7 @@ TC0_Handler(void) irq_disable(); uint32_t status = TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending if (likely(status & TC_SR_CPAS)) - sched_timer_kick(); + timer_dispatch_many(); irq_enable(); } diff --git a/src/sched.c b/src/sched.c index 2b96465f..8617108a 100644 --- a/src/sched.c +++ b/src/sched.c @@ -135,39 +135,34 @@ sched_del_timer(struct timer *del) irq_restore(flag); } -// Invoke timers - called from board timer irq code. -void -sched_timer_kick(void) +// Invoke the next timer - called from board hardware irq code. +unsigned int +sched_timer_dispatch(void) { - for (;;) { - // Invoke timer callback - struct timer *t = timer_list; - uint_fast8_t res; - uint32_t updated_waketime; - if (CONFIG_INLINE_STEPPER_HACK && likely(!t->func)) { - res = stepper_event(t); - updated_waketime = t->waketime; - } else { - res = t->func(t); - updated_waketime = t->waketime; - } - - // Update timer_list (rescheduling current timer if necessary) - unsigned int next_waketime = updated_waketime; - if (unlikely(res == SF_DONE)) { - next_waketime = t->next->waketime; - timer_list = t->next; - } else if (!timer_is_before(updated_waketime, t->next->waketime)) { - next_waketime = t->next->waketime; - timer_list = t->next; - insert_timer(t, updated_waketime); - } + // Invoke timer callback + struct timer *t = timer_list; + uint_fast8_t res; + uint32_t updated_waketime; + if (CONFIG_INLINE_STEPPER_HACK && likely(!t->func)) { + res = stepper_event(t); + updated_waketime = t->waketime; + } else { + res = t->func(t); + updated_waketime = t->waketime; + } - // Schedule next timer event (or run next timer if it's ready) - res = timer_try_set_next(next_waketime); - if (res) - break; + // Update timer_list (rescheduling current timer if necessary) + unsigned int next_waketime = updated_waketime; + if (unlikely(res == SF_DONE)) { + next_waketime = t->next->waketime; + timer_list = t->next; + } else if (!timer_is_before(updated_waketime, t->next->waketime)) { + next_waketime = t->next->waketime; + timer_list = t->next; + insert_timer(t, updated_waketime); } + + return next_waketime; } // Shutdown all user timers on an emergency stop. diff --git a/src/sched.h b/src/sched.h index 7a98257a..d2d3471e 100644 --- a/src/sched.h +++ b/src/sched.h @@ -25,7 +25,7 @@ enum { SF_DONE=0, SF_RESCHEDULE=1 }; uint8_t sched_check_periodic(uint16_t time, uint16_t *pnext); void sched_add_timer(struct timer*); void sched_del_timer(struct timer *del); -void sched_timer_kick(void); +unsigned int sched_timer_dispatch(void); uint8_t sched_is_shutdown(void); uint16_t sched_shutdown_reason(void); void sched_clear_shutdown(void); diff --git a/src/simulator/main.c b/src/simulator/main.c index eb3025ca..42fb7a25 100644 --- a/src/simulator/main.c +++ b/src/simulator/main.c @@ -75,12 +75,6 @@ timer_read_time(void) return 0; // XXX } -uint8_t -timer_try_set_next(unsigned int next) -{ - return 1; -} - /**************************************************************** * Turn stdin/stdout into serial console |