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 <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-07-27 12:05:29 -04:00
parent 88a10fb31c
commit 62f77f6bc5
4 changed files with 53 additions and 37 deletions

View File

@ -18,6 +18,8 @@ struct analog_in {
uint8_t state, sample_count; uint8_t state, sample_count;
}; };
static struct task_wake analog_wake;
static uint_fast8_t static uint_fast8_t
analog_in_event(struct timer *timer) 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) if (a->value < a->min_value || a->value > a->max_value)
shutdown("adc out of range"); shutdown("adc out of range");
sched_wake_task(&analog_wake);
a->next_begin_time += a->rest_time; a->next_begin_time += a->rest_time;
a->timer.waketime = a->next_begin_time; a->timer.waketime = a->next_begin_time;
return SF_RESCHEDULE; return SF_RESCHEDULE;
@ -83,8 +86,7 @@ DECL_COMMAND(command_query_analog_in,
void void
analog_in_task(void) analog_in_task(void)
{ {
static uint16_t next; if (!sched_check_wake(&analog_wake))
if (!sched_check_periodic(3, &next))
return; return;
uint8_t oid; uint8_t oid;
struct analog_in *a; struct analog_in *a;

View File

@ -21,6 +21,8 @@ struct end_stop {
enum { ESF_PIN_HIGH=1<<0, ESF_HOMING=1<<1, ESF_REPORT=1<<2 }; enum { ESF_PIN_HIGH=1<<0, ESF_HOMING=1<<1, ESF_REPORT=1<<2 };
static struct task_wake endstop_wake;
static void static void
stop_steppers(struct end_stop *e) stop_steppers(struct end_stop *e)
{ {
@ -29,6 +31,7 @@ stop_steppers(struct end_stop *e)
while (count--) while (count--)
if (e->steppers[count]) if (e->steppers[count])
stepper_stop(e->steppers[count]); stepper_stop(e->steppers[count]);
sched_wake_task(&endstop_wake);
} }
// Timer callback for an end stop // Timer callback for an end stop
@ -115,8 +118,7 @@ DECL_COMMAND(command_end_stop_query, "end_stop_query oid=%c");
void void
end_stop_task(void) end_stop_task(void)
{ {
static uint16_t next; if (!sched_check_wake(&endstop_wake))
if (!sched_check_periodic(50, &next))
return; return;
uint8_t oid; uint8_t oid;
struct end_stop *e; struct end_stop *e;

View File

@ -6,6 +6,7 @@
#include <setjmp.h> // setjmp #include <setjmp.h> // setjmp
#include "autoconf.h" // CONFIG_* #include "autoconf.h" // CONFIG_*
#include "board/io.h" // readb
#include "board/irq.h" // irq_save #include "board/irq.h" // irq_save
#include "board/misc.h" // timer_from_us #include "board/misc.h" // timer_from_us
#include "board/pgm.h" // READP #include "board/pgm.h" // READP
@ -18,48 +19,31 @@
* Timers * 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 // The periodic_timer simplifies the timer code by ensuring there is
uint8_t // always a timer on the timer list and that there is always a timer
sched_check_periodic(uint16_t time, uint16_t *pnext) // not more than 1ms in the future.
{
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.
static uint_fast8_t static uint_fast8_t
ms_event(struct timer *t) periodic_event(struct timer *t)
{ {
millis++;
timer_periodic(); timer_periodic();
ms_timer.waketime += timer_from_us(1000); periodic_timer.waketime += timer_from_us(1000);
sentinel_timer.waketime = ms_timer.waketime + 0x80000000; sentinel_timer.waketime = periodic_timer.waketime + 0x80000000;
return SF_RESCHEDULE; return SF_RESCHEDULE;
} }
static struct timer ms_timer = { static struct timer periodic_timer = {
.func = ms_event, .func = periodic_event,
.next = &sentinel_timer, .next = &sentinel_timer,
}; };
// The sentinel timer is always the last timer on timer_list - its // The sentinel timer is always the last timer on timer_list - its
// presence allows the code to avoid checking for NULL while // presence allows the code to avoid checking for NULL while
// traversing timer_list. Since sentinel_timer.waketime is always // traversing timer_list. Since sentinel_timer.waketime is always
// equal to (ms_timer.waketime + 0x80000000) any added timer must // equal to (periodic_timer.waketime + 0x80000000) any added timer
// always have a waketime less than one of these two timers. // must always have a waketime less than one of these two timers.
static uint_fast8_t static uint_fast8_t
sentinel_event(struct timer *t) sentinel_event(struct timer *t)
{ {
@ -171,13 +155,35 @@ void
sched_timer_shutdown(void) sched_timer_shutdown(void)
{ {
timer_list = &deleted_timer; timer_list = &deleted_timer;
deleted_timer.waketime = ms_timer.waketime; deleted_timer.waketime = periodic_timer.waketime;
deleted_timer.next = &ms_timer; deleted_timer.next = &periodic_timer;
ms_timer.next = &sentinel_timer; periodic_timer.next = &sentinel_timer;
} }
DECL_SHUTDOWN(sched_timer_shutdown); 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 * Shutdown processing
****************************************************************/ ****************************************************************/

View File

@ -20,11 +20,17 @@ struct timer {
enum { SF_DONE=0, SF_RESCHEDULE=1 }; enum { SF_DONE=0, SF_RESCHEDULE=1 };
// Task waking struct
struct task_wake {
uint8_t wake;
};
// sched.c // sched.c
uint8_t sched_check_periodic(uint16_t time, uint16_t *pnext);
void sched_add_timer(struct timer*); void sched_add_timer(struct timer*);
void sched_del_timer(struct timer *del); void sched_del_timer(struct timer *del);
unsigned int sched_timer_dispatch(void); 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); uint8_t sched_is_shutdown(void);
void sched_clear_shutdown(void); void sched_clear_shutdown(void);
void sched_try_shutdown(uint_fast8_t reason); void sched_try_shutdown(uint_fast8_t reason);