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}