interrupt.rs 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. //! Interrupts
  2. // NOTE: Adapted from cortex-m/src/interrupt.rs
  3. pub use bare_metal::{CriticalSection, Mutex, Nr};
  4. use register::mstatus;
  5. /// Disables all interrupts
  6. #[inline]
  7. pub unsafe fn disable() {
  8. match () {
  9. #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
  10. () => mstatus::clear_mie(),
  11. #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
  12. () => unimplemented!(),
  13. }
  14. }
  15. /// Enables all the interrupts
  16. ///
  17. /// # Safety
  18. ///
  19. /// - Do not call this function inside an `interrupt::free` critical section
  20. #[inline]
  21. pub unsafe fn enable() {
  22. match () {
  23. #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
  24. () => mstatus::set_mie(),
  25. #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
  26. () => unimplemented!(),
  27. }
  28. }
  29. /// Execute closure `f` in an interrupt-free context.
  30. ///
  31. /// This as also known as a "critical section".
  32. pub fn free<F, R>(f: F) -> R
  33. where
  34. F: FnOnce(&CriticalSection) -> R,
  35. {
  36. let mstatus = mstatus::read();
  37. // disable interrupts
  38. unsafe { disable(); }
  39. let r = f(unsafe { &CriticalSection::new() });
  40. // If the interrupts were active before our `disable` call, then re-enable
  41. // them. Otherwise, keep them disabled
  42. if mstatus.mie() {
  43. unsafe { enable(); }
  44. }
  45. r
  46. }