diff options
Diffstat (limited to 'embassy-hal-internal/src/interrupt.rs')
| -rw-r--r-- | embassy-hal-internal/src/interrupt.rs | 32 |
1 files changed, 29 insertions, 3 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 | ||
