summaryrefslogtreecommitdiff
path: root/src/avr
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2012-10-25 13:40:54 -0700
committerKeith Packard <keithp@keithp.com>2012-10-26 14:07:04 -0700
commitccf0faa7d26d56deca7928b521d07be40504466a (patch)
treea7faa1cc9e2998e8e0754b3af939c030019405e4 /src/avr
parent9b978cd467f9128f3069765dd8fbf8abad3459a4 (diff)
altos: Leave interrupts disabled while checking for task to run
Otherwise, we run the risk of an interrupt waking a task after we've decided to idle the CPU. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/avr')
-rw-r--r--src/avr/ao_arch.h19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h
index c82612a8..d626e830 100644
--- a/src/avr/ao_arch.h
+++ b/src/avr/ao_arch.h
@@ -112,7 +112,6 @@ extern uint8_t ao_cpu_sleep_disable;
asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \
asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \
asm("in r0, __SREG__" "\n\t" "push r0"); \
- sei(); \
} while (0)
#define ao_arch_save_stack() do { \
@@ -124,16 +123,28 @@ extern uint8_t ao_cpu_sleep_disable;
#define ao_arch_isr_stack() /* nothing */
-#define ao_arch_cpu_idle() do { \
- if (!ao_cpu_sleep_disable) \
+/* Idle the CPU (if possible) waiting for an interrupt. Enabling
+ * interrupts and sleeping the CPU must be adjacent to eliminate race
+ * conditions. In all cases, we execute a single nop with interrupts
+ * enabled
+ */
+#define ao_arch_wait_interrupt() do { \
+ if (!ao_cpu_sleep_disable) { \
+ sleep_enable(); \
+ sei(); \
sleep_cpu(); \
+ sleep_disable(); \
+ } else { \
+ sei(); \
+ } \
+ ao_arch_nop(); \
+ cli(); \
} while (0)
#define ao_arch_restore_stack() do { \
uint8_t sp_l, sp_h; \
sp_l = (uint16_t) ao_cur_task->sp; \
sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \
- cli(); \
asm("out __SP_H__,%0" : : "r" (sp_h) ); \
asm("out __SP_L__,%0" : : "r" (sp_l) ); \
asm("pop r0" "\n\t" \