diff options
author | Keith Packard <keithp@keithp.com> | 2012-10-25 13:40:54 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2012-10-26 14:07:04 -0700 |
commit | ccf0faa7d26d56deca7928b521d07be40504466a (patch) | |
tree | a7faa1cc9e2998e8e0754b3af939c030019405e4 /src/avr | |
parent | 9b978cd467f9128f3069765dd8fbf8abad3459a4 (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.h | 19 |
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" \ |