aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/avr/timer.c42
-rw-r--r--src/generic/misc.h1
-rw-r--r--src/sam3x8e/timer.c43
-rw-r--r--src/sched.c51
-rw-r--r--src/simulator/main.c6
5 files changed, 53 insertions, 90 deletions
diff --git a/src/avr/timer.c b/src/avr/timer.c
index a6da9b4f..06d8845e 100644
--- a/src/avr/timer.c
+++ b/src/avr/timer.c
@@ -39,13 +39,6 @@ timer_set(uint16_t next)
}
static inline void
-timer_set_clear(uint16_t next)
-{
- OCR1A = next;
- TIFR1 = 1<<OCF1A;
-}
-
-static inline void
timer_repeat_set(uint16_t next)
{
// Timer1B is used to limit the number of timers run from a timer1A irq
@@ -78,6 +71,15 @@ timer_init(void)
}
DECL_INIT(timer_init);
+static void
+timer_shutdown(void)
+{
+ // Reenable timer irq
+ timer_set(timer_get() + 50);
+ TIFR1 = 1<<OCF1A;
+}
+DECL_SHUTDOWN(timer_shutdown);
+
/****************************************************************
* 32bit timer wrappers
@@ -120,35 +122,15 @@ timer_periodic(void)
}
}
-#define TIMER_MIN_TICKS 100
-
-// Set the next timer wake time (in absolute clock ticks). Caller
-// must disable irqs. The caller should not schedule a time more than
-// a few milliseconds in the future.
-uint8_t
-timer_set_next(uint32_t next)
-{
- uint32_t cur = timer_read_time();
- if ((int16_t)(OCR1A - (uint16_t)cur) < 0 && !(TIFR1 & (1<<OCF1A)))
- // Already processing timer irqs
- try_shutdown("timer_set_next called during timer dispatch");
- uint32_t mintime = cur + TIMER_MIN_TICKS;
- if (sched_is_before(mintime, next)) {
- timer_set_clear(next);
- return 0;
- }
- timer_set_clear(mintime);
- return 1;
-}
-
#define TIMER_IDLE_REPEAT_TICKS 8000
#define TIMER_REPEAT_TICKS 3000
#define TIMER_MIN_TRY_TICKS 60 // 40 ticks to exit irq; 20 ticks of progress
#define TIMER_DEFER_REPEAT_TICKS 200
-// Similar to timer_set_next(), but wait for the given time if it is
-// in the near future.
+// 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
timer_try_set_next(uint32_t target)
{
diff --git a/src/generic/misc.h b/src/generic/misc.h
index ce1c8f02..92d4d145 100644
--- a/src/generic/misc.h
+++ b/src/generic/misc.h
@@ -12,7 +12,6 @@ void console_push_output(uint8_t len);
uint32_t timer_from_us(uint32_t us);
void timer_periodic(void);
uint32_t timer_read_time(void);
-uint8_t timer_set_next(uint32_t next);
uint8_t timer_try_set_next(uint32_t next);
size_t alloc_maxsize(size_t reqsize);
diff --git a/src/sam3x8e/timer.c b/src/sam3x8e/timer.c
index bab2512f..dbc7700e 100644
--- a/src/sam3x8e/timer.c
+++ b/src/sam3x8e/timer.c
@@ -44,13 +44,6 @@ timer_set(uint32_t value)
}
static void
-timer_set_clear(uint32_t value)
-{
- TC0->TC_CHANNEL[0].TC_RA = value;
- TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending
-}
-
-static void
timer_init(void)
{
TcChannel *tc = &TC0->TC_CHANNEL[0];
@@ -69,6 +62,15 @@ timer_init(void)
}
DECL_INIT(timer_init);
+static void
+timer_shutdown(void)
+{
+ // Reenable timer irq
+ timer_set(timer_read_time() + 50);
+ TC0->TC_CHANNEL[0].TC_SR; // read to clear irq pending
+}
+DECL_SHUTDOWN(timer_shutdown);
+
// Called by main code once every millisecond. (IRQs disabled.)
void
timer_periodic(void)
@@ -82,28 +84,6 @@ timer_read_time(void)
return TC0->TC_CHANNEL[0].TC_CV;
}
-#define TIMER_MIN_TICKS 100
-
-// Set the next timer wake time (in absolute clock ticks). Caller
-// must disable irqs. The caller should not schedule a time more than
-// a few milliseconds in the future.
-uint8_t
-timer_set_next(uint32_t next)
-{
- uint32_t cur = timer_read_time();
- if (sched_is_before(TC0->TC_CHANNEL[0].TC_RA, cur)
- && !(TC0->TC_CHANNEL[0].TC_SR & TC_SR_CPAS))
- // Already processing timer irqs
- try_shutdown("timer_set_next called during timer dispatch");
- uint32_t mintime = cur + TIMER_MIN_TICKS;
- if (sched_is_before(mintime, next)) {
- timer_set_clear(next);
- return 0;
- }
- timer_set_clear(mintime);
- return 1;
-}
-
static uint32_t timer_repeat_until;
#define TIMER_IDLE_REPEAT_TICKS timer_from_us(500)
#define TIMER_REPEAT_TICKS timer_from_us(100)
@@ -111,8 +91,9 @@ static uint32_t timer_repeat_until;
#define TIMER_MIN_TRY_TICKS timer_from_us(1)
#define TIMER_DEFER_REPEAT_TICKS timer_from_us(5)
-// Similar to timer_set_next(), but wait for the given time if it is
-// in the near future.
+// 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
timer_try_set_next(uint32_t next)
{
diff --git a/src/sched.c b/src/sched.c
index 19e428be..7e4a86a1 100644
--- a/src/sched.c
+++ b/src/sched.c
@@ -101,33 +101,39 @@ sched_timer(struct timer *add)
{
uint32_t waketime = add->waketime;
irqstatus_t flag = irq_save();
- if (sched_is_before(waketime, timer_list->waketime)) {
- // This timer is the next - insert at front of list and reschedule
- add->next = timer_list;
- timer_list = add;
- uint8_t ret = timer_set_next(waketime);
- if (ret)
- shutdown("Timer too close");
- } else {
- // Find position in list and insert
- struct timer *pos = timer_list;
- while (!sched_is_before(waketime, pos->next->waketime))
- pos = pos->next;
- add->next = pos->next;
- pos->next = add;
- }
+ if (sched_is_before(waketime, timer_list->waketime))
+ // Timer in past (or very near future)
+ shutdown("Timer too close");
+ // Find position in list and insert
+ struct timer *pos = timer_list;
+ while (!sched_is_before(waketime, pos->next->waketime))
+ pos = pos->next;
+ add->next = pos->next;
+ pos->next = add;
irq_restore(flag);
}
+// The deleted timer is used when deleting an active timer.
+static uint_fast8_t
+deleted_event(struct timer *t)
+{
+ return SF_DONE;
+}
+
+static struct timer deleted_timer = {
+ .func = deleted_event,
+};
+
// Remove a timer that may be live.
void
sched_del_timer(struct timer *del)
{
irqstatus_t flag = irq_save();
if (timer_list == del) {
- // Deleting the next active timer - delete and reschedule
- timer_list = del->next;
- timer_set_next(timer_list->waketime);
+ // Deleting the next active timer - replace with deleted_timer
+ deleted_timer.waketime = del->waketime;
+ deleted_timer.next = del->next;
+ timer_list = &deleted_timer;
} else {
// Find and remove from timer list (if present)
struct timer *pos;
@@ -197,13 +203,14 @@ sched_timer_kick(void)
// Shutdown all user timers on an emergency stop.
static void
-timer_shutdown(void)
+sched_timer_shutdown(void)
{
- timer_list = &ms_timer;
+ timer_list = &deleted_timer;
+ deleted_timer.waketime = ms_timer.waketime;
+ deleted_timer.next = &ms_timer;
ms_timer.next = &sentinel_timer;
- timer_set_next(timer_list->waketime);
}
-DECL_SHUTDOWN(timer_shutdown);
+DECL_SHUTDOWN(sched_timer_shutdown);
/****************************************************************
diff --git a/src/simulator/main.c b/src/simulator/main.c
index 1bffc265..f45b5c45 100644
--- a/src/simulator/main.c
+++ b/src/simulator/main.c
@@ -70,12 +70,6 @@ timer_read_time(void)
}
uint8_t
-timer_set_next(uint32_t next)
-{
- return 0;
-}
-
-uint8_t
timer_try_set_next(uint32_t next)
{
return 1;