aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-03-27 16:38:01 -0400
committerKevin O'Connor <kevin@koconnor.net>2017-03-30 11:24:42 -0400
commit6d05dd07f59ef21dc81a299e865cdee1fc1d3f8e (patch)
tree5eb3eab42f4a7e0abe0c5b790cee9938a1f65564
parent7436ec093acc6f45e0fc2389de7294be43e3f0a8 (diff)
downloadkutter-6d05dd07f59ef21dc81a299e865cdee1fc1d3f8e.tar.gz
kutter-6d05dd07f59ef21dc81a299e865cdee1fc1d3f8e.tar.xz
kutter-6d05dd07f59ef21dc81a299e865cdee1fc1d3f8e.zip
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>
-rw-r--r--docs/Code_Overview.md6
-rw-r--r--src/avr/timer.c20
-rw-r--r--src/generic/misc.h1
-rw-r--r--src/generic/timer.c16
-rw-r--r--src/sam3x8e/timer.c5
-rw-r--r--src/sched.c55
-rw-r--r--src/sched.h2
-rw-r--r--src/simulator/main.c6
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