cortex_ar/interrupt.rs
1//! Interrupts on Arm Cortex-R
2
3use core::sync::atomic::{compiler_fence, Ordering};
4
5/// Enable interrupts
6///
7/// * Doesn't work in User mode.
8/// * Doesn't enable FIQ.
9///
10/// # Safety
11///
12/// Do not call this function inside an interrupt-based critical section
13#[inline]
14pub unsafe fn enable() {
15 // Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
16 compiler_fence(Ordering::SeqCst);
17 // Safety: We're atomically setting a bit in a special register, and we're
18 // in an unsafe function that places restrictions on when you can call it
19 #[cfg(target_arch = "arm")]
20 unsafe {
21 core::arch::asm!("dsb", "cpsie i", options(nomem, nostack, preserves_flags));
22 };
23}
24
25/// Disable IRQ
26///
27/// * Doesn't work in User mode.
28/// * Doesn't disable FIQ.
29#[inline]
30pub fn disable() {
31 // Safety: We're atomically clearing a bit in a special register
32 #[cfg(target_arch = "arm")]
33 unsafe {
34 core::arch::asm!("cpsid i", "dsb", options(nomem, nostack, preserves_flags));
35 };
36 // Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
37 compiler_fence(Ordering::SeqCst);
38}
39
40/// Run with interrupts disabled
41///
42/// * Doesn't work in User mode.
43/// * Doesn't disable FIQ.
44#[inline]
45pub fn free<F, T>(f: F) -> T
46where
47 F: FnOnce() -> T,
48{
49 let cpsr = crate::register::Cpsr::read();
50 disable();
51 let result = f();
52 if cpsr.i() {
53 // Safety: We're only turning them back on if they were on previously
54 unsafe {
55 enable();
56 }
57 }
58 result
59}