aboutsummaryrefslogtreecommitdiff
path: root/embassy-cortex-m/src/interrupt.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-06-01 02:22:46 +0200
committerDario Nieuwenhuis <[email protected]>2023-06-01 03:25:19 +0200
commit404aa292890503806a32eac5ae518dbeeadd60eb (patch)
treeb02ef548d1a95999a05655dbee4938327d487238 /embassy-cortex-m/src/interrupt.rs
parent2a435e53b761182dabf9496963052f8323125f3a (diff)
cortex-m: remove owned interrupts.
Diffstat (limited to 'embassy-cortex-m/src/interrupt.rs')
-rw-r--r--embassy-cortex-m/src/interrupt.rs160
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.
2use core::{mem, ptr}; 2use core::mem;
3use core::sync::atomic::{compiler_fence, Ordering};
3 4
4use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering};
5use cortex_m::peripheral::NVIC; 5use cortex_m::peripheral::NVIC;
6use embassy_hal_common::Peripheral;
7pub 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.
44pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {} 42pub unsafe trait Binding<I: Interrupt, H: Handler<I>> {}
45 43
46/// Implementation detail, do not use outside embassy crates.
47#[doc(hidden)]
48pub struct DynHandler {
49 pub func: AtomicPtr<()>,
50 pub ctx: AtomicPtr<()>,
51}
52
53impl 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)]
63pub(crate) struct NrWrap(pub(crate) u16); 45pub(crate) struct NrWrap(pub(crate) u16);
64unsafe impl cortex_m::interrupt::InterruptNumber for NrWrap { 46unsafe 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.
72pub unsafe trait Interrupt: Peripheral<P = Self> { 54pub 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.
88pub 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
139impl<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