cortex_m/
interrupt.rs

1//! Interrupts
2
3pub use bare_metal::{CriticalSection, Mutex, Nr};
4
5/// Trait for enums of external interrupt numbers.
6///
7/// This trait should be implemented by a peripheral access crate (PAC)
8/// on its enum of available external interrupts for a specific device.
9/// Each variant must convert to a u16 of its interrupt number,
10/// which is its exception number - 16.
11///
12/// # Safety
13///
14/// This trait must only be implemented on enums of device interrupts. Each
15/// enum variant must represent a distinct value (no duplicates are permitted),
16/// and must always return the same value (do not change at runtime).
17///
18/// These requirements ensure safe nesting of critical sections.
19pub unsafe trait InterruptNumber: Copy {
20    /// Return the interrupt number associated with this variant.
21    ///
22    /// See trait documentation for safety requirements.
23    fn number(self) -> u16;
24}
25
26/// Implement InterruptNumber for the old bare_metal::Nr trait.
27/// This implementation is for backwards compatibility only and will be removed in cortex-m 0.8.
28unsafe impl<T: Nr + Copy> InterruptNumber for T {
29    #[inline]
30    fn number(self) -> u16 {
31        self.nr() as u16
32    }
33}
34
35/// Disables all interrupts
36#[inline]
37pub fn disable() {
38    call_asm!(__cpsid());
39}
40
41/// Enables all the interrupts
42///
43/// # Safety
44///
45/// - Do not call this function inside an `interrupt::free` critical section
46#[inline]
47pub unsafe fn enable() {
48    call_asm!(__cpsie());
49}
50
51/// Execute closure `f` in an interrupt-free context.
52///
53/// This as also known as a "critical section".
54#[inline]
55pub fn free<F, R>(f: F) -> R
56where
57    F: FnOnce(&CriticalSection) -> R,
58{
59    let primask = crate::register::primask::read();
60
61    // disable interrupts
62    disable();
63
64    let r = f(unsafe { &CriticalSection::new() });
65
66    // If the interrupts were active before our `disable` call, then re-enable
67    // them. Otherwise, keep them disabled
68    if primask.is_active() {
69        unsafe { enable() }
70    }
71
72    r
73}