1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//! Interrupts

/// Disable interrupts, globally
#[inline(always)]
pub unsafe fn disable() {
    match () {
        #[cfg(target_arch = "arm")]
        () => {
            asm!("cpsid i" :::: "volatile");
        }
        #[cfg(not(target_arch = "arm"))]
        () => {}
    }
}

/// Enable interrupts, globally
#[inline(always)]
pub unsafe fn enable() {
    match () {
        #[cfg(target_arch = "arm")]
        () => {
            asm!("cpsie i" :::: "volatile");
        }
        #[cfg(not(target_arch = "arm"))]
        () => {}
    }
}

/// Execute closure `f` in an interrupt-free context.
/// This as also known as a "critical section".
pub unsafe fn free<F>(f: F)
    where F: FnOnce()
{
    let primask = ::register::primask::read();

    disable();

    f();

    // If the interrupts were enabled before our `disable` call, then re-enable them
    // Otherwise, keep them disabled
    // PRIMASK & 1 = 1 indicates that the interrupts were disabled
    // PRIMASK & 1 = 0 indicates that they were enabled
    if primask & 1 == 0 {
        enable();
    }
}