|  | 
| 1 | 1 | //! Interrupts | 
| 2 | 2 | 
 | 
| 3 | 3 | // NOTE: Adapted from cortex-m/src/interrupt.rs | 
| 4 |  | -use crate::register::mstatus; | 
| 5 |  | - | 
| 6 |  | -/// Disables all interrupts in the current hart. | 
| 7 |  | -#[inline] | 
| 8 |  | -pub unsafe fn disable() { | 
| 9 |  | -    match () { | 
| 10 |  | -        #[cfg(riscv)] | 
| 11 |  | -        () => mstatus::clear_mie(), | 
| 12 |  | -        #[cfg(not(riscv))] | 
| 13 |  | -        () => unimplemented!(), | 
|  | 4 | + | 
|  | 5 | +pub mod machine { | 
|  | 6 | +    use crate::register::mstatus; | 
|  | 7 | + | 
|  | 8 | +    /// Disables all interrupts in the current hart (machine mode). | 
|  | 9 | +    #[inline] | 
|  | 10 | +    pub fn disable() { | 
|  | 11 | +        unsafe { mstatus::clear_mie() } | 
| 14 | 12 |     } | 
| 15 |  | -} | 
| 16 | 13 | 
 | 
| 17 |  | -/// Enables all the interrupts in the current hart. | 
| 18 |  | -/// | 
| 19 |  | -/// # Safety | 
| 20 |  | -/// | 
| 21 |  | -/// - Do not call this function inside a critical section. | 
| 22 |  | -#[inline] | 
| 23 |  | -pub unsafe fn enable() { | 
| 24 |  | -    match () { | 
| 25 |  | -        #[cfg(riscv)] | 
| 26 |  | -        () => mstatus::set_mie(), | 
| 27 |  | -        #[cfg(not(riscv))] | 
| 28 |  | -        () => unimplemented!(), | 
|  | 14 | +    /// Enables all the interrupts in the current hart (machine mode). | 
|  | 15 | +    /// | 
|  | 16 | +    /// # Safety | 
|  | 17 | +    /// | 
|  | 18 | +    /// Do not call this function inside a critical section. | 
|  | 19 | +    #[inline] | 
|  | 20 | +    pub unsafe fn enable() { | 
|  | 21 | +        mstatus::set_mie() | 
| 29 | 22 |     } | 
| 30 |  | -} | 
| 31 | 23 | 
 | 
| 32 |  | -/// Execute closure `f` with interrupts disabled in the current hart. | 
| 33 |  | -/// | 
| 34 |  | -/// This method does not synchronise multiple harts, so it is not suitable for | 
| 35 |  | -/// using as a critical section. See the `critical-section` crate for a cross-platform | 
| 36 |  | -/// way to enter a critical section which provides a `CriticalSection` token. | 
| 37 |  | -/// | 
| 38 |  | -/// This crate provides an implementation for `critical-section` suitable for single-hart systems, | 
| 39 |  | -/// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | 
| 40 |  | -#[inline] | 
| 41 |  | -pub fn free<F, R>(f: F) -> R | 
| 42 |  | -where | 
| 43 |  | -    F: FnOnce() -> R, | 
| 44 |  | -{ | 
| 45 |  | -    let mstatus = mstatus::read(); | 
| 46 |  | - | 
| 47 |  | -    // disable interrupts | 
| 48 |  | -    unsafe { | 
|  | 24 | +    /// Execute closure `f` with interrupts disabled in the current hart (machine mode). | 
|  | 25 | +    /// | 
|  | 26 | +    /// This method does not synchronise multiple harts, so it is not suitable for | 
|  | 27 | +    /// using as a critical section. See the `critical-section` crate for a cross-platform | 
|  | 28 | +    /// way to enter a critical section which provides a `CriticalSection` token. | 
|  | 29 | +    /// | 
|  | 30 | +    /// This crate provides an implementation for `critical-section` suitable for single-hart systems, | 
|  | 31 | +    /// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | 
|  | 32 | +    #[inline] | 
|  | 33 | +    pub fn free<F, R>(f: F) -> R | 
|  | 34 | +    where | 
|  | 35 | +        F: FnOnce() -> R, | 
|  | 36 | +    { | 
|  | 37 | +        let mstatus = mstatus::read(); | 
|  | 38 | + | 
|  | 39 | +        // disable interrupts | 
| 49 | 40 |         disable(); | 
| 50 |  | -    } | 
| 51 | 41 | 
 | 
| 52 |  | -    let r = f(); | 
|  | 42 | +        let r = f(); | 
| 53 | 43 | 
 | 
| 54 |  | -    // If the interrupts were active before our `disable` call, then re-enable | 
| 55 |  | -    // them. Otherwise, keep them disabled | 
| 56 |  | -    if mstatus.mie() { | 
| 57 |  | -        unsafe { | 
| 58 |  | -            enable(); | 
|  | 44 | +        // If the interrupts were active before our `disable` call, then re-enable | 
|  | 45 | +        // them. Otherwise, keep them disabled | 
|  | 46 | +        if mstatus.mie() { | 
|  | 47 | +            unsafe { enable() }; | 
| 59 | 48 |         } | 
|  | 49 | + | 
|  | 50 | +        r | 
|  | 51 | +    } | 
|  | 52 | +} | 
|  | 53 | +pub mod supervisor { | 
|  | 54 | +    use crate::register::sstatus; | 
|  | 55 | + | 
|  | 56 | +    /// Disables all interrupts in the current hart (supervisor mode). | 
|  | 57 | +    #[inline] | 
|  | 58 | +    pub fn disable() { | 
|  | 59 | +        unsafe { sstatus::clear_sie() } | 
| 60 | 60 |     } | 
| 61 | 61 | 
 | 
| 62 |  | -    r | 
|  | 62 | +    /// Enables all the interrupts in the current hart (supervisor mode). | 
|  | 63 | +    /// | 
|  | 64 | +    /// # Safety | 
|  | 65 | +    /// | 
|  | 66 | +    /// Do not call this function inside a critical section. | 
|  | 67 | +    #[inline] | 
|  | 68 | +    pub unsafe fn enable() { | 
|  | 69 | +        sstatus::set_sie() | 
|  | 70 | +    } | 
|  | 71 | + | 
|  | 72 | +    /// Execute closure `f` with interrupts disabled in the current hart (supervisor mode). | 
|  | 73 | +    /// | 
|  | 74 | +    /// This method does not synchronise multiple harts, so it is not suitable for | 
|  | 75 | +    /// using as a critical section. See the `critical-section` crate for a cross-platform | 
|  | 76 | +    /// way to enter a critical section which provides a `CriticalSection` token. | 
|  | 77 | +    /// | 
|  | 78 | +    /// This crate provides an implementation for `critical-section` suitable for single-hart systems, | 
|  | 79 | +    /// based on disabling all interrupts. It can be enabled with the `critical-section-single-hart` feature. | 
|  | 80 | +    #[inline] | 
|  | 81 | +    pub fn free<F, R>(f: F) -> R | 
|  | 82 | +    where | 
|  | 83 | +        F: FnOnce() -> R, | 
|  | 84 | +    { | 
|  | 85 | +        let sstatus = sstatus::read(); | 
|  | 86 | + | 
|  | 87 | +        // disable interrupts | 
|  | 88 | +        disable(); | 
|  | 89 | + | 
|  | 90 | +        let r = f(); | 
|  | 91 | + | 
|  | 92 | +        // If the interrupts were active before our `disable` call, then re-enable | 
|  | 93 | +        // them. Otherwise, keep them disabled | 
|  | 94 | +        if sstatus.sie() { | 
|  | 95 | +            unsafe { enable() }; | 
|  | 96 | +        } | 
|  | 97 | + | 
|  | 98 | +        r | 
|  | 99 | +    } | 
| 63 | 100 | } | 
|  | 101 | + | 
|  | 102 | +#[cfg(not(feature = "s-mode"))] | 
|  | 103 | +pub use machine::*; | 
|  | 104 | +#[cfg(feature = "s-mode")] | 
|  | 105 | +pub use supervisor::*; | 
0 commit comments