From 62f77f6bc56e0fcffdcdd4dcf2cfd6a7669099f2 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Thu, 27 Jul 2017 12:05:29 -0400 Subject: [PATCH] sched: Don't count milliseconds in the periodic timer It's not necessary to keep a millisecond counter. Replace the two users of sched_check_periodic() with explicit task wakeup flags. Signed-off-by: Kevin O'Connor --- src/adccmds.c | 6 +++-- src/endstop.c | 6 +++-- src/sched.c | 70 ++++++++++++++++++++++++++++----------------------- src/sched.h | 8 +++++- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/adccmds.c b/src/adccmds.c index 526325ad..55900ab1 100644 --- a/src/adccmds.c +++ b/src/adccmds.c @@ -18,6 +18,8 @@ struct analog_in { uint8_t state, sample_count; }; +static struct task_wake analog_wake; + static uint_fast8_t analog_in_event(struct timer *timer) { @@ -42,6 +44,7 @@ analog_in_event(struct timer *timer) } if (a->value < a->min_value || a->value > a->max_value) shutdown("adc out of range"); + sched_wake_task(&analog_wake); a->next_begin_time += a->rest_time; a->timer.waketime = a->next_begin_time; return SF_RESCHEDULE; @@ -83,8 +86,7 @@ DECL_COMMAND(command_query_analog_in, void analog_in_task(void) { - static uint16_t next; - if (!sched_check_periodic(3, &next)) + if (!sched_check_wake(&analog_wake)) return; uint8_t oid; struct analog_in *a; diff --git a/src/endstop.c b/src/endstop.c index aaaf1baa..5bd863ea 100644 --- a/src/endstop.c +++ b/src/endstop.c @@ -21,6 +21,8 @@ struct end_stop { enum { ESF_PIN_HIGH=1<<0, ESF_HOMING=1<<1, ESF_REPORT=1<<2 }; +static struct task_wake endstop_wake; + static void stop_steppers(struct end_stop *e) { @@ -29,6 +31,7 @@ stop_steppers(struct end_stop *e) while (count--) if (e->steppers[count]) stepper_stop(e->steppers[count]); + sched_wake_task(&endstop_wake); } // Timer callback for an end stop @@ -115,8 +118,7 @@ DECL_COMMAND(command_end_stop_query, "end_stop_query oid=%c"); void end_stop_task(void) { - static uint16_t next; - if (!sched_check_periodic(50, &next)) + if (!sched_check_wake(&endstop_wake)) return; uint8_t oid; struct end_stop *e; diff --git a/src/sched.c b/src/sched.c index 8fee61f2..758fa71c 100644 --- a/src/sched.c +++ b/src/sched.c @@ -6,6 +6,7 @@ #include // setjmp #include "autoconf.h" // CONFIG_* +#include "board/io.h" // readb #include "board/irq.h" // irq_save #include "board/misc.h" // timer_from_us #include "board/pgm.h" // READP @@ -18,48 +19,31 @@ * Timers ****************************************************************/ -static uint16_t millis; +static struct timer periodic_timer, *timer_list = &periodic_timer; +static struct timer sentinel_timer; -// Check if ready for a recurring periodic event -uint8_t -sched_check_periodic(uint16_t time, uint16_t *pnext) -{ - uint16_t next = *pnext, cur; - irqstatus_t flag = irq_save(); - cur = millis; - irq_restore(flag); - if ((int16_t)(cur - next) < 0) - return 0; - *pnext = cur + time; - return 1; -} - -static struct timer ms_timer, sentinel_timer, *timer_list = &ms_timer; - -// Default millisecond timer. This timer counts milliseconds. It -// also simplifies the timer code by ensuring there is always a timer -// on the timer list and that there is always a timer not more than -// 1ms in the future. +// The periodic_timer simplifies the timer code by ensuring there is +// always a timer on the timer list and that there is always a timer +// not more than 1ms in the future. static uint_fast8_t -ms_event(struct timer *t) +periodic_event(struct timer *t) { - millis++; timer_periodic(); - ms_timer.waketime += timer_from_us(1000); - sentinel_timer.waketime = ms_timer.waketime + 0x80000000; + periodic_timer.waketime += timer_from_us(1000); + sentinel_timer.waketime = periodic_timer.waketime + 0x80000000; return SF_RESCHEDULE; } -static struct timer ms_timer = { - .func = ms_event, +static struct timer periodic_timer = { + .func = periodic_event, .next = &sentinel_timer, }; // The sentinel timer is always the last timer on timer_list - its // presence allows the code to avoid checking for NULL while // traversing timer_list. Since sentinel_timer.waketime is always -// equal to (ms_timer.waketime + 0x80000000) any added timer must -// always have a waketime less than one of these two timers. +// equal to (periodic_timer.waketime + 0x80000000) any added timer +// must always have a waketime less than one of these two timers. static uint_fast8_t sentinel_event(struct timer *t) { @@ -171,13 +155,35 @@ void sched_timer_shutdown(void) { timer_list = &deleted_timer; - deleted_timer.waketime = ms_timer.waketime; - deleted_timer.next = &ms_timer; - ms_timer.next = &sentinel_timer; + deleted_timer.waketime = periodic_timer.waketime; + deleted_timer.next = &periodic_timer; + periodic_timer.next = &sentinel_timer; } DECL_SHUTDOWN(sched_timer_shutdown); +/**************************************************************** + * Task waking + ****************************************************************/ + +// Note that a task is ready to run +void +sched_wake_task(struct task_wake *w) +{ + writeb(&w->wake, 1); +} + +// Check if a task is ready to run (as indicated by sched_wake_task) +uint8_t +sched_check_wake(struct task_wake *w) +{ + if (!readb(&w->wake)) + return 0; + writeb(&w->wake, 0); + return 1; +} + + /**************************************************************** * Shutdown processing ****************************************************************/ diff --git a/src/sched.h b/src/sched.h index ad5c2c08..bb6bb975 100644 --- a/src/sched.h +++ b/src/sched.h @@ -20,11 +20,17 @@ struct timer { enum { SF_DONE=0, SF_RESCHEDULE=1 }; +// Task waking struct +struct task_wake { + uint8_t wake; +}; + // sched.c -uint8_t sched_check_periodic(uint16_t time, uint16_t *pnext); void sched_add_timer(struct timer*); void sched_del_timer(struct timer *del); unsigned int sched_timer_dispatch(void); +void sched_wake_task(struct task_wake *w); +uint8_t sched_check_wake(struct task_wake *w); uint8_t sched_is_shutdown(void); void sched_clear_shutdown(void); void sched_try_shutdown(uint_fast8_t reason);