vexriscv-rust/src/interrupt.rs

55 lines
1.2 KiB
Rust
Raw Normal View History

2017-09-19 22:04:12 +08:00
//! Interrupts
// NOTE: Adapted from cortex-m/src/interrupt.rs
pub use bare_metal::{CriticalSection, Mutex, Nr};
2018-03-28 02:17:44 +08:00
use register::mstatus;
2017-09-19 22:04:12 +08:00
/// Disables all interrupts
2018-03-25 02:27:00 +08:00
#[inline]
2018-03-28 02:17:44 +08:00
pub unsafe fn disable() {
2017-09-19 22:04:12 +08:00
match () {
#[cfg(target_arch = "riscv")]
2018-03-28 02:17:44 +08:00
() => mstatus::clear_mie(),
2017-09-19 22:04:12 +08:00
#[cfg(not(target_arch = "riscv"))]
() => {}
}
}
/// Enables all the interrupts
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
2018-03-25 02:27:00 +08:00
#[inline]
2017-09-19 22:04:12 +08:00
pub unsafe fn enable() {
match () {
#[cfg(target_arch = "riscv")]
2018-03-28 02:17:44 +08:00
() => mstatus::set_mie(),
2017-09-19 22:04:12 +08:00
#[cfg(not(target_arch = "riscv"))]
() => {}
}
}
/// Execute closure `f` in an interrupt-free context.
///
/// This as also known as a "critical section".
pub fn free<F, R>(f: F) -> R
where
F: FnOnce(&CriticalSection) -> R,
{
2018-03-28 02:17:44 +08:00
let mstatus = mstatus::read();
2017-09-19 22:04:12 +08:00
// disable interrupts
2018-03-28 02:17:44 +08:00
unsafe { disable(); }
2017-09-19 22:04:12 +08:00
let r = f(unsafe { &CriticalSection::new() });
// If the interrupts were active before our `disable` call, then re-enable
// them. Otherwise, keep them disabled
if mstatus.mie() {
2018-03-28 02:17:44 +08:00
unsafe { enable(); }
2017-09-19 22:04:12 +08:00
}
r
}