1-- Cortex-M0 CPU operations. The saved mask is an ordinary explicit value.
2-- Restore it in lexical reverse order; masking does not stop DMA or faults.
3compiler.assert(compiler.arch == cortex_m0)
4
5--- Disable maskable interrupts and return the previous PRIMASK. Save the
6--- result and pass it to `restore_interrupts`, including on early returns.
7--- NMI and HardFault remain unmasked.
8public disable_interrupts: () -> (previous: u32) =
9 previous = assembler.block("mrs {mask}, primask\ncpsid i",
10 out mask: u32 at general)
11end disable_interrupts
12
13--- Restore a saved PRIMASK value. Only bit zero is implemented; use the value
14--- returned by `disable_interrupts` to preserve nesting.
15public restore_interrupts: (previous: u32) -> none =
16 assembler.block("msr primask, {mask}\nisb sy",
17 in mask: u32 at general = previous)
18end restore_interrupts
19
20--- Read the current PRIMASK interrupt mask.
21public interrupt_mask: () -> (current: u32) =
22 current = assembler.block("mrs {mask}, primask", out mask: u32 at general)
23end interrupt_mask
24
25--- Issue a completion barrier and wait for an interrupt. Wakeups can be
26--- spurious; recheck the condition after waking.
27---
28--- Architectural completion before sleep does not acknowledge a device.
29public wait_for_interrupt: () -> none =
30 assembler.block("dsb sy\nwfi")
31end wait_for_interrupt
32
33--- Issue a device memory barrier (DMB) to order memory accesses. This is not
34--- a proof that a device operation completed.
35public device_barrier: () -> none =
36 compiler.device_barrier()
37end device_barrier
38
39--- Issue a data synchronization barrier (DSB) to wait for preceding explicit
40--- memory accesses to complete.
41public completion_barrier: () -> none =
42 compiler.completion_barrier()
43end completion_barrier
44
45--- Prevent compiler memory knowledge from moving across this point. This
46--- emits no device-completion protocol.
47public compiler_barrier: () -> none =
48 compiler.compiler_barrier()
49end compiler_barrier