diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-06-01 02:22:46 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-06-01 03:25:19 +0200 |
| commit | 404aa292890503806a32eac5ae518dbeeadd60eb (patch) | |
| tree | b02ef548d1a95999a05655dbee4938327d487238 /embassy-cortex-m | |
| parent | 2a435e53b761182dabf9496963052f8323125f3a (diff) | |
cortex-m: remove owned interrupts.
Diffstat (limited to 'embassy-cortex-m')
| -rw-r--r-- | embassy-cortex-m/src/interrupt.rs | 160 |
1 files changed, 33 insertions, 127 deletions
diff --git a/embassy-cortex-m/src/interrupt.rs b/embassy-cortex-m/src/interrupt.rs index 3a82726df..0e790eaaf 100644 --- a/embassy-cortex-m/src/interrupt.rs +++ b/embassy-cortex-m/src/interrupt.rs | |||
| @@ -1,10 +1,8 @@ | |||
| 1 | //! Interrupt handling for cortex-m devices. | 1 | //! Interrupt handling for cortex-m devices. |
| 2 | use core::{mem, ptr}; | 2 | use core::mem; |
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 3 | 4 | ||
| 4 | use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering}; | ||
| 5 | use cortex_m::peripheral::NVIC; | 5 | use cortex_m::peripheral::NVIC; |
| 6 | use embassy_hal_common::Peripheral; | ||
| 7 | pub use embassy_macros::cortex_m_interrupt_take as take; | ||
| 8 | 6 | ||
| 9 | /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. | 7 | /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. |
| 10 | #[doc(hidden)] | 8 | #[doc(hidden)] |
| @@ -43,22 +41,6 @@ pub trait Handler<I: Interrupt> { | |||
| 43 | /// This allows drivers to check bindings at compile-time. | 41 | /// This allows drivers to check bindings at compile-time. |
| 44 | pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {} | 42 | pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {} |
| 45 | 43 | ||
| 46 | /// Implementation detail, do not use outside embassy crates. | ||
| 47 | #[doc(hidden)] | ||
| 48 | pub struct DynHandler { | ||
| 49 | pub func: AtomicPtr<()>, | ||
| 50 | pub ctx: AtomicPtr<()>, | ||
| 51 | } | ||
| 52 | |||
| 53 | impl DynHandler { | ||
| 54 | pub const fn new() -> Self { | ||
| 55 | Self { | ||
| 56 | func: AtomicPtr::new(ptr::null_mut()), | ||
| 57 | ctx: AtomicPtr::new(ptr::null_mut()), | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | #[derive(Clone, Copy)] | 44 | #[derive(Clone, Copy)] |
| 63 | pub(crate) struct NrWrap(pub(crate) u16); | 45 | pub(crate) struct NrWrap(pub(crate) u16); |
| 64 | unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { | 46 | unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { |
| @@ -69,144 +51,68 @@ unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { | |||
| 69 | 51 | ||
| 70 | /// Represents an interrupt type that can be configured by embassy to handle | 52 | /// Represents an interrupt type that can be configured by embassy to handle |
| 71 | /// interrupts. | 53 | /// interrupts. |
| 72 | pub unsafe trait Interrupt: Peripheral<P = Self> { | 54 | pub unsafe trait Interrupt { |
| 73 | /// Return the NVIC interrupt number for this interrupt. | 55 | /// Return the NVIC interrupt number for this interrupt. |
| 74 | fn number(&self) -> u16; | 56 | fn number() -> u16; |
| 75 | /// Steal an instance of this interrupt | ||
| 76 | /// | ||
| 77 | /// # Safety | ||
| 78 | /// | ||
| 79 | /// This may panic if the interrupt has already been stolen and configured. | ||
| 80 | unsafe fn steal() -> Self; | ||
| 81 | |||
| 82 | /// Implementation detail, do not use outside embassy crates. | ||
| 83 | #[doc(hidden)] | ||
| 84 | unsafe fn __handler(&self) -> &'static DynHandler; | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Represents additional behavior for all interrupts. | ||
| 88 | pub trait InterruptExt: Interrupt { | ||
| 89 | /// Configure the interrupt handler for this interrupt. | ||
| 90 | /// | ||
| 91 | /// # Safety | ||
| 92 | /// | ||
| 93 | /// It is the responsibility of the caller to ensure the handler | ||
| 94 | /// points to a valid handler as long as interrupts are enabled. | ||
| 95 | fn set_handler(&self, func: unsafe fn(*mut ())); | ||
| 96 | |||
| 97 | /// Remove the interrupt handler for this interrupt. | ||
| 98 | fn remove_handler(&self); | ||
| 99 | |||
| 100 | /// Set point to a context that is passed to the interrupt handler when | ||
| 101 | /// an interrupt is pending. | ||
| 102 | /// | ||
| 103 | /// # Safety | ||
| 104 | /// | ||
| 105 | /// It is the responsibility of the caller to ensure the context | ||
| 106 | /// points to a valid handler as long as interrupts are enabled. | ||
| 107 | fn set_handler_context(&self, ctx: *mut ()); | ||
| 108 | |||
| 109 | /// Enable the interrupt. Once enabled, the interrupt handler may | ||
| 110 | /// be called "any time". | ||
| 111 | fn enable(&self); | ||
| 112 | |||
| 113 | /// Disable the interrupt. | ||
| 114 | fn disable(&self); | ||
| 115 | |||
| 116 | /// Check if interrupt is being handled. | ||
| 117 | #[cfg(not(armv6m))] | ||
| 118 | fn is_active(&self) -> bool; | ||
| 119 | |||
| 120 | /// Check if interrupt is enabled. | ||
| 121 | fn is_enabled(&self) -> bool; | ||
| 122 | |||
| 123 | /// Check if interrupt is pending. | ||
| 124 | fn is_pending(&self) -> bool; | ||
| 125 | |||
| 126 | /// Set interrupt pending. | ||
| 127 | fn pend(&self); | ||
| 128 | |||
| 129 | /// Unset interrupt pending. | ||
| 130 | fn unpend(&self); | ||
| 131 | |||
| 132 | /// Get the priority of the interrupt. | ||
| 133 | fn get_priority(&self) -> Priority; | ||
| 134 | |||
| 135 | /// Set the interrupt priority. | ||
| 136 | fn set_priority(&self, prio: Priority); | ||
| 137 | } | ||
| 138 | |||
| 139 | impl<T: Interrupt + ?Sized> InterruptExt for T { | ||
| 140 | fn set_handler(&self, func: unsafe fn(*mut ())) { | ||
| 141 | compiler_fence(Ordering::SeqCst); | ||
| 142 | let handler = unsafe { self.__handler() }; | ||
| 143 | handler.func.store(func as *mut (), Ordering::Relaxed); | ||
| 144 | compiler_fence(Ordering::SeqCst); | ||
| 145 | } | ||
| 146 | |||
| 147 | fn remove_handler(&self) { | ||
| 148 | compiler_fence(Ordering::SeqCst); | ||
| 149 | let handler = unsafe { self.__handler() }; | ||
| 150 | handler.func.store(ptr::null_mut(), Ordering::Relaxed); | ||
| 151 | compiler_fence(Ordering::SeqCst); | ||
| 152 | } | ||
| 153 | |||
| 154 | fn set_handler_context(&self, ctx: *mut ()) { | ||
| 155 | let handler = unsafe { self.__handler() }; | ||
| 156 | handler.ctx.store(ctx, Ordering::Relaxed); | ||
| 157 | } | ||
| 158 | 57 | ||
| 58 | /// Enable the interrupt. | ||
| 159 | #[inline] | 59 | #[inline] |
| 160 | fn enable(&self) { | 60 | unsafe fn enable() { |
| 161 | compiler_fence(Ordering::SeqCst); | 61 | compiler_fence(Ordering::SeqCst); |
| 162 | unsafe { | 62 | NVIC::unmask(NrWrap(Self::number())) |
| 163 | NVIC::unmask(NrWrap(self.number())); | ||
| 164 | } | ||
| 165 | } | 63 | } |
| 166 | 64 | ||
| 65 | /// Disable the interrupt. | ||
| 167 | #[inline] | 66 | #[inline] |
| 168 | fn disable(&self) { | 67 | fn disable() { |
| 169 | NVIC::mask(NrWrap(self.number())); | 68 | NVIC::mask(NrWrap(Self::number())); |
| 170 | compiler_fence(Ordering::SeqCst); | 69 | compiler_fence(Ordering::SeqCst); |
| 171 | } | 70 | } |
| 172 | 71 | ||
| 72 | /// Check if interrupt is being handled. | ||
| 173 | #[inline] | 73 | #[inline] |
| 174 | #[cfg(not(armv6m))] | 74 | #[cfg(not(armv6m))] |
| 175 | fn is_active(&self) -> bool { | 75 | fn is_active() -> bool { |
| 176 | NVIC::is_active(NrWrap(self.number())) | 76 | NVIC::is_active(NrWrap(Self::number())) |
| 177 | } | 77 | } |
| 178 | 78 | ||
| 79 | /// Check if interrupt is enabled. | ||
| 179 | #[inline] | 80 | #[inline] |
| 180 | fn is_enabled(&self) -> bool { | 81 | fn is_enabled() -> bool { |
| 181 | NVIC::is_enabled(NrWrap(self.number())) | 82 | NVIC::is_enabled(NrWrap(Self::number())) |
| 182 | } | 83 | } |
| 183 | 84 | ||
| 85 | /// Check if interrupt is pending. | ||
| 184 | #[inline] | 86 | #[inline] |
| 185 | fn is_pending(&self) -> bool { | 87 | fn is_pending() -> bool { |
| 186 | NVIC::is_pending(NrWrap(self.number())) | 88 | NVIC::is_pending(NrWrap(Self::number())) |
| 187 | } | 89 | } |
| 188 | 90 | ||
| 91 | /// Set interrupt pending. | ||
| 189 | #[inline] | 92 | #[inline] |
| 190 | fn pend(&self) { | 93 | fn pend() { |
| 191 | NVIC::pend(NrWrap(self.number())) | 94 | NVIC::pend(NrWrap(Self::number())) |
| 192 | } | 95 | } |
| 193 | 96 | ||
| 97 | /// Unset interrupt pending. | ||
| 194 | #[inline] | 98 | #[inline] |
| 195 | fn unpend(&self) { | 99 | fn unpend() { |
| 196 | NVIC::unpend(NrWrap(self.number())) | 100 | NVIC::unpend(NrWrap(Self::number())) |
| 197 | } | 101 | } |
| 198 | 102 | ||
| 103 | /// Get the priority of the interrupt. | ||
| 199 | #[inline] | 104 | #[inline] |
| 200 | fn get_priority(&self) -> Priority { | 105 | fn get_priority() -> Priority { |
| 201 | Priority::from(NVIC::get_priority(NrWrap(self.number()))) | 106 | Priority::from(NVIC::get_priority(NrWrap(Self::number()))) |
| 202 | } | 107 | } |
| 203 | 108 | ||
| 109 | /// Set the interrupt priority. | ||
| 204 | #[inline] | 110 | #[inline] |
| 205 | fn set_priority(&self, prio: Priority) { | 111 | fn set_priority(prio: Priority) { |
| 206 | unsafe { | 112 | critical_section::with(|_| unsafe { |
| 207 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); | 113 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); |
| 208 | nvic.set_priority(NrWrap(self.number()), prio.into()) | 114 | nvic.set_priority(NrWrap(Self::number()), prio.into()) |
| 209 | } | 115 | }) |
| 210 | } | 116 | } |
| 211 | } | 117 | } |
| 212 | 118 | ||
