summaryrefslogtreecommitdiff
path: root/src/stm/ao_arch.h
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2012-10-24 22:35:32 -0700
committerKeith Packard <keithp@keithp.com>2012-10-25 00:07:14 -0700
commite80fa6de4ccc5c4851eab9fb941f9282d2e3eb16 (patch)
tree716c76a2a0aae0ade116f1c9d959d68fedeb112a /src/stm/ao_arch.h
parentb119e19604aa557a40e848c60d98a67b5f259bbd (diff)
altos: Replace __critical usage with ao_arch_critical as needed
sdcc offers __critical as a machine-independent way to block interrupts, but as gcc doesn't, we need to use a compiler-independent construct instead. ao_arch_critical has been around since the AVR port, but some old __critical usages remained. This fixes a bunch of random hangs when communicating with MM over USB or the radio as the various stdio loops were running without interrupts blocked between the test and the sleep. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/stm/ao_arch.h')
-rw-r--r--src/stm/ao_arch.h26
1 files changed, 23 insertions, 3 deletions
diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h
index f2de719c..0c3cfc91 100644
--- a/src/stm/ao_arch.h
+++ b/src/stm/ao_arch.h
@@ -43,7 +43,6 @@
#define __xdata
#define __code const
#define __reentrant
-#define __critical
#define __interrupt(n)
#define __at(n)
@@ -83,8 +82,29 @@ extern const uint32_t ao_radio_cal;
#define ao_arch_task_members\
uint32_t *sp; /* saved stack pointer */
-#define cli() asm("cpsid i")
-#define sei() asm("cpsie i")
+#define ao_arch_block_interrupts() asm("cpsid i")
+#define ao_arch_release_interrupts() asm("cpsie i")
+
+#define cli() ao_arch_block_interrupts()
+#define sei() ao_arch_release_interrupts()
+
+static uint32_t
+ao_arch_irqsave(void) {
+ uint32_t primask;
+ asm("mrs %0,primask" : "=&r" (primask));
+ ao_arch_block_interrupts();
+ return primask;
+}
+
+static void
+ao_arch_irqrestore(uint32_t primask) {
+ asm("msr primask,%0" : : "r" (primask));
+}
+
+static void
+ao_arch_memory_barrier() {
+ asm volatile("" ::: "memory");
+}
#define ao_arch_init_stack(task, start) do { \
uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \