sched: Move timer dispatch loop to board code
Rename sched_timer_kick() to sched_timer_dispatch() and move its loop into its callers in the board code. This eliminates the need to export timer_try_set_next() from the board code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
7436ec093a
commit
6d05dd07f5
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
57
src/sched.c
57
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);
|
||||
}
|
||||
|
||||
// Schedule next timer event (or run next timer if it's ready)
|
||||
res = timer_try_set_next(next_waketime);
|
||||
if (res)
|
||||
break;
|
||||
// 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);
|
||||
}
|
||||
|
||||
return next_waketime;
|
||||
}
|
||||
|
||||
// Shutdown all user timers on an emergency stop.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue