-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #165 from rust-embedded/smode-riscv
`riscv`: support for S-mode
- Loading branch information
Showing
6 changed files
with
115 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,105 @@ | ||
//! Interrupts | ||
// NOTE: Adapted from cortex-m/src/interrupt.rs | ||
use crate::register::mstatus; | ||
|
||
/// Disables all interrupts in the current hart. | ||
#[inline] | ||
pub unsafe fn disable() { | ||
match () { | ||
#[cfg(riscv)] | ||
() => mstatus::clear_mie(), | ||
#[cfg(not(riscv))] | ||
() => unimplemented!(), | ||
|
||
pub mod machine { | ||
use crate::register::mstatus; | ||
|
||
/// Disables all interrupts in the current hart (machine mode). | ||
#[inline] | ||
pub fn disable() { | ||
unsafe { mstatus::clear_mie() } | ||
} | ||
} | ||
|
||
/// Enables all the interrupts in the current hart. | ||
/// | ||
/// # Safety | ||
/// | ||
/// - Do not call this function inside a critical section. | ||
#[inline] | ||
pub unsafe fn enable() { | ||
match () { | ||
#[cfg(riscv)] | ||
() => mstatus::set_mie(), | ||
#[cfg(not(riscv))] | ||
() => unimplemented!(), | ||
/// Enables all the interrupts in the current hart (machine mode). | ||
/// | ||
/// # Safety | ||
/// | ||
/// Do not call this function inside a critical section. | ||
#[inline] | ||
pub unsafe fn enable() { | ||
mstatus::set_mie() | ||
} | ||
} | ||
|
||
/// Execute closure `f` with interrupts disabled in the current hart. | ||
/// | ||
/// This method does not synchronise multiple harts, so it is not suitable for | ||
/// using as a critical section. See the `critical-section` crate for a cross-platform | ||
/// way to enter a critical section which provides a `CriticalSection` token. | ||
/// | ||
/// This crate provides an implementation for `critical-section` suitable for single-hart systems, | ||
/// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | ||
#[inline] | ||
pub fn free<F, R>(f: F) -> R | ||
where | ||
F: FnOnce() -> R, | ||
{ | ||
let mstatus = mstatus::read(); | ||
|
||
// disable interrupts | ||
unsafe { | ||
/// Execute closure `f` with interrupts disabled in the current hart (machine mode). | ||
/// | ||
/// This method does not synchronise multiple harts, so it is not suitable for | ||
/// using as a critical section. See the `critical-section` crate for a cross-platform | ||
/// way to enter a critical section which provides a `CriticalSection` token. | ||
/// | ||
/// This crate provides an implementation for `critical-section` suitable for single-hart systems, | ||
/// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | ||
#[inline] | ||
pub fn free<F, R>(f: F) -> R | ||
where | ||
F: FnOnce() -> R, | ||
{ | ||
let mstatus = mstatus::read(); | ||
|
||
// disable interrupts | ||
disable(); | ||
} | ||
|
||
let r = f(); | ||
let r = f(); | ||
|
||
// If the interrupts were active before our `disable` call, then re-enable | ||
// them. Otherwise, keep them disabled | ||
if mstatus.mie() { | ||
unsafe { | ||
enable(); | ||
// If the interrupts were active before our `disable` call, then re-enable | ||
// them. Otherwise, keep them disabled | ||
if mstatus.mie() { | ||
unsafe { enable() }; | ||
} | ||
|
||
r | ||
} | ||
} | ||
pub mod supervisor { | ||
use crate::register::sstatus; | ||
|
||
/// Disables all interrupts in the current hart (supervisor mode). | ||
#[inline] | ||
pub fn disable() { | ||
unsafe { sstatus::clear_sie() } | ||
} | ||
|
||
r | ||
/// Enables all the interrupts in the current hart (supervisor mode). | ||
/// | ||
/// # Safety | ||
/// | ||
/// Do not call this function inside a critical section. | ||
#[inline] | ||
pub unsafe fn enable() { | ||
sstatus::set_sie() | ||
} | ||
|
||
/// Execute closure `f` with interrupts disabled in the current hart (supervisor mode). | ||
/// | ||
/// This method does not synchronise multiple harts, so it is not suitable for | ||
/// using as a critical section. See the `critical-section` crate for a cross-platform | ||
/// way to enter a critical section which provides a `CriticalSection` token. | ||
/// | ||
/// This crate provides an implementation for `critical-section` suitable for single-hart systems, | ||
/// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | ||
#[inline] | ||
pub fn free<F, R>(f: F) -> R | ||
where | ||
F: FnOnce() -> R, | ||
{ | ||
let sstatus = sstatus::read(); | ||
|
||
// disable interrupts | ||
disable(); | ||
|
||
let r = f(); | ||
|
||
// If the interrupts were active before our `disable` call, then re-enable | ||
// them. Otherwise, keep them disabled | ||
if sstatus.sie() { | ||
unsafe { enable() }; | ||
} | ||
|
||
r | ||
} | ||
} | ||
|
||
#[cfg(not(feature = "s-mode"))] | ||
pub use machine::*; | ||
#[cfg(feature = "s-mode")] | ||
pub use supervisor::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters