diff options
Diffstat (limited to 'embassy-hal-internal/src')
| -rw-r--r-- | embassy-hal-internal/src/interrupt.rs | 32 | ||||
| -rw-r--r-- | embassy-hal-internal/src/macros.rs | 10 |
2 files changed, 37 insertions, 5 deletions
diff --git a/embassy-hal-internal/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs index b970aa2cd..19dabcf6f 100644 --- a/embassy-hal-internal/src/interrupt.rs +++ b/embassy-hal-internal/src/interrupt.rs | |||
| @@ -4,6 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 4 | 4 | ||
| 5 | use cortex_m::interrupt::InterruptNumber; | 5 | use cortex_m::interrupt::InterruptNumber; |
| 6 | use cortex_m::peripheral::NVIC; | 6 | use cortex_m::peripheral::NVIC; |
| 7 | use critical_section::CriticalSection; | ||
| 7 | 8 | ||
| 8 | /// Generate a standard `mod interrupt` for a HAL. | 9 | /// Generate a standard `mod interrupt` for a HAL. |
| 9 | #[macro_export] | 10 | #[macro_export] |
| @@ -91,6 +92,12 @@ macro_rules! interrupt_mod { | |||
| 91 | fn set_priority(prio: crate::interrupt::Priority) { | 92 | fn set_priority(prio: crate::interrupt::Priority) { |
| 92 | Self::IRQ.set_priority(prio) | 93 | Self::IRQ.set_priority(prio) |
| 93 | } | 94 | } |
| 95 | |||
| 96 | /// Set the interrupt priority with an already-acquired critical section | ||
| 97 | #[inline] | ||
| 98 | fn set_priority_with_cs(cs: critical_section::CriticalSection, prio: crate::interrupt::Priority) { | ||
| 99 | Self::IRQ.set_priority_with_cs(cs, prio) | ||
| 100 | } | ||
| 94 | } | 101 | } |
| 95 | 102 | ||
| 96 | $( | 103 | $( |
| @@ -195,10 +202,29 @@ pub unsafe trait InterruptExt: InterruptNumber + Copy { | |||
| 195 | /// Set the interrupt priority. | 202 | /// Set the interrupt priority. |
| 196 | #[inline] | 203 | #[inline] |
| 197 | fn set_priority(self, prio: Priority) { | 204 | fn set_priority(self, prio: Priority) { |
| 198 | critical_section::with(|_| unsafe { | 205 | unsafe { |
| 206 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); | ||
| 207 | |||
| 208 | // On thumbv6, set_priority must do a RMW to change 8bit in a 32bit reg. | ||
| 209 | #[cfg(armv6m)] | ||
| 210 | critical_section::with(|_| nvic.set_priority(self, prio.into())); | ||
| 211 | // On thumbv7+, set_priority does an atomic 8bit write, so no CS needed. | ||
| 212 | #[cfg(not(armv6m))] | ||
| 213 | nvic.set_priority(self, prio.into()); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | /// Set the interrupt priority with an already-acquired critical section | ||
| 218 | /// | ||
| 219 | /// Equivalent to `set_priority`, except you pass a `CriticalSection` to prove | ||
| 220 | /// you've already acquired a critical section. This prevents acquiring another | ||
| 221 | /// one, which saves code size. | ||
| 222 | #[inline] | ||
| 223 | fn set_priority_with_cs(self, _cs: CriticalSection, prio: Priority) { | ||
| 224 | unsafe { | ||
| 199 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); | 225 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); |
| 200 | nvic.set_priority(self, prio.into()) | 226 | nvic.set_priority(self, prio.into()); |
| 201 | }) | 227 | } |
| 202 | } | 228 | } |
| 203 | } | 229 | } |
| 204 | 230 | ||
diff --git a/embassy-hal-internal/src/macros.rs b/embassy-hal-internal/src/macros.rs index 0eea4b667..97df38954 100644 --- a/embassy-hal-internal/src/macros.rs +++ b/embassy-hal-internal/src/macros.rs | |||
| @@ -48,17 +48,23 @@ macro_rules! peripherals_struct { | |||
| 48 | ///Returns all the peripherals *once* | 48 | ///Returns all the peripherals *once* |
| 49 | #[inline] | 49 | #[inline] |
| 50 | pub(crate) fn take() -> Self { | 50 | pub(crate) fn take() -> Self { |
| 51 | critical_section::with(Self::take_with_cs) | ||
| 52 | } | ||
| 51 | 53 | ||
| 54 | ///Returns all the peripherals *once* | ||
| 55 | #[inline] | ||
| 56 | pub(crate) fn take_with_cs(_cs: critical_section::CriticalSection) -> Self { | ||
| 52 | #[no_mangle] | 57 | #[no_mangle] |
| 53 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; | 58 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; |
| 54 | 59 | ||
| 55 | critical_section::with(|_| unsafe { | 60 | // safety: OK because we're inside a CS. |
| 61 | unsafe { | ||
| 56 | if _EMBASSY_DEVICE_PERIPHERALS { | 62 | if _EMBASSY_DEVICE_PERIPHERALS { |
| 57 | panic!("init called more than once!") | 63 | panic!("init called more than once!") |
| 58 | } | 64 | } |
| 59 | _EMBASSY_DEVICE_PERIPHERALS = true; | 65 | _EMBASSY_DEVICE_PERIPHERALS = true; |
| 60 | Self::steal() | 66 | Self::steal() |
| 61 | }) | 67 | } |
| 62 | } | 68 | } |
| 63 | } | 69 | } |
| 64 | 70 | ||
