1use core::convert::Infallible;
8use core::future::Future;
9use core::marker::PhantomData;
10use core::pin::Pin;
11use core::task::{Context, Poll};
12
13use embassy_hal_internal::{impl_peripheral, into_ref};
14use embassy_sync::waitqueue::AtomicWaker;
15
16use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, Pull};
17use crate::pac::exti::regs::Lines;
18use crate::pac::EXTI;
19use crate::{interrupt, pac, peripherals, Peripheral};
20
21const EXTI_COUNT: usize = 16;
22const NEW_AW: AtomicWaker = AtomicWaker::new();
23static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
24
25fn cpu_regs() -> pac::exti::Exti {
26 EXTI
27}
28
29fn exticr_regs() -> pac::exti::Exti {
30 EXTI
31}
32
33unsafe fn on_irq() {
34 let bits = EXTI.pr().read().0;
35
36 let bits = bits & 0x0000FFFF;
38
39 cpu_regs().imr().modify(|w| w.0 &= !bits);
41
42 for pin in BitIter(bits) {
44 EXTI_WAKERS[pin as usize].wake();
45 }
46
47 EXTI.pr().write_value(Lines(bits));
49
50 }
53
54struct BitIter(u32);
55
56impl Iterator for BitIter {
57 type Item = u32;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 match self.0.trailing_zeros() {
61 32 => None,
62 b => {
63 self.0 &= !(1 << b);
64 Some(b)
65 }
66 }
67 }
68}
69
70pub struct ExtiInput<'d> {
78 pin: Input<'d>,
79}
80
81impl<'d> Unpin for ExtiInput<'d> {}
82
83impl<'d> ExtiInput<'d> {
84 pub fn new<T: GpioPin>(
86 pin: impl Peripheral<P = T> + 'd,
87 ch: impl Peripheral<P = T::ExtiChannel> + 'd,
88 pull: Pull,
89 ) -> Self {
90 into_ref!(pin, ch);
91
92 assert_eq!(pin.pin(), ch.number());
94
95 Self {
96 pin: Input::new(pin, pull),
97 }
98 }
99
100 pub fn is_high(&self) -> bool {
102 self.pin.is_high()
103 }
104
105 pub fn is_low(&self) -> bool {
107 self.pin.is_low()
108 }
109
110 pub fn get_level(&self) -> Level {
112 self.pin.get_level()
113 }
114
115 pub async fn wait_for_high(&mut self) {
119 let fut =
120 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false);
121 if self.is_high() {
122 return;
123 }
124 fut.await
125 }
126
127 pub async fn wait_for_low(&mut self) {
131 let fut =
132 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true);
133 if self.is_low() {
134 return;
135 }
136 fut.await
137 }
138
139 pub async fn wait_for_rising_edge(&mut self) {
143 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await
144 }
145
146 pub async fn wait_for_falling_edge(&mut self) {
150 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await
151 }
152
153 pub async fn wait_for_any_edge(&mut self) {
155 ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await
156 }
157}
158
159impl<'d> embedded_hal_02::digital::v2::InputPin for ExtiInput<'d> {
160 type Error = Infallible;
161
162 fn is_high(&self) -> Result<bool, Self::Error> {
163 Ok(self.is_high())
164 }
165
166 fn is_low(&self) -> Result<bool, Self::Error> {
167 Ok(self.is_low())
168 }
169}
170
171impl<'d> embedded_hal_1::digital::ErrorType for ExtiInput<'d> {
172 type Error = Infallible;
173}
174
175impl<'d> embedded_hal_1::digital::InputPin for ExtiInput<'d> {
176 fn is_high(&mut self) -> Result<bool, Self::Error> {
177 Ok((*self).is_high())
178 }
179
180 fn is_low(&mut self) -> Result<bool, Self::Error> {
181 Ok((*self).is_low())
182 }
183}
184
185impl<'d> embedded_hal_async::digital::Wait for ExtiInput<'d> {
186 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
187 self.wait_for_high().await;
188 Ok(())
189 }
190
191 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
192 self.wait_for_low().await;
193 Ok(())
194 }
195
196 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
197 self.wait_for_rising_edge().await;
198 Ok(())
199 }
200
201 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
202 self.wait_for_falling_edge().await;
203 Ok(())
204 }
205
206 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
207 self.wait_for_any_edge().await;
208 Ok(())
209 }
210}
211
212#[must_use = "futures do nothing unless you `.await` or poll them"]
213struct ExtiInputFuture<'a> {
214 pin: u8,
215 phantom: PhantomData<&'a mut AnyPin>,
216}
217
218impl<'a> ExtiInputFuture<'a> {
219 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self {
220 critical_section::with(|_| {
221 let pin = pin as usize;
222
223 exticr_regs()
225 .exticr(pin / 4)
226 .modify(|w| w.set_exti(pin % 4, port));
227 EXTI.rtsr().modify(|w| w.set_line(pin, rising));
228 EXTI.ftsr().modify(|w| w.set_line(pin, falling));
229
230 EXTI.pr().write(|w| w.set_line(pin, true));
232
233 cpu_regs().imr().modify(|w| w.set_line(pin, true));
234 });
235
236 Self {
237 pin,
238 phantom: PhantomData,
239 }
240 }
241}
242
243impl<'a> Drop for ExtiInputFuture<'a> {
244 fn drop(&mut self) {
245 critical_section::with(|_| {
246 let pin = self.pin as _;
247 cpu_regs().imr().modify(|w| w.set_line(pin, false));
248 });
249 }
250}
251
252impl<'a> Future for ExtiInputFuture<'a> {
253 type Output = ();
254
255 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
256 EXTI_WAKERS[self.pin as usize].register(cx.waker());
257
258 let imr = cpu_regs().imr().read();
259 if !imr.line(self.pin as _) {
260 Poll::Ready(())
261 } else {
262 Poll::Pending
263 }
264 }
265}
266
267macro_rules! foreach_exti_irq {
268 ($action:ident) => {
269 foreach_interrupt!(
270 (EXTI0) => { $action!(EXTI0); };
271 (EXTI1) => { $action!(EXTI1); };
272 (EXTI2) => { $action!(EXTI2); };
273 (EXTI3) => { $action!(EXTI3); };
274 (EXTI4) => { $action!(EXTI4); };
275 (EXTI5) => { $action!(EXTI5); };
276 (EXTI6) => { $action!(EXTI6); };
277 (EXTI7) => { $action!(EXTI7); };
278 (EXTI8) => { $action!(EXTI8); };
279 (EXTI9) => { $action!(EXTI9); };
280 (EXTI10) => { $action!(EXTI10); };
281 (EXTI11) => { $action!(EXTI11); };
282 (EXTI12) => { $action!(EXTI12); };
283 (EXTI13) => { $action!(EXTI13); };
284 (EXTI14) => { $action!(EXTI14); };
285 (EXTI15) => { $action!(EXTI15); };
286
287 (EXTI0_1) => { $action!( EXTI0_1 ); };
289 (EXTI15_10) => { $action!(EXTI15_10); };
290 (EXTI15_4) => { $action!(EXTI15_4); };
291 (EXTI1_0) => { $action!(EXTI1_0); };
292 (EXTI2_3) => { $action!(EXTI2_3); };
293 (EXTI2_TSC) => { $action!(EXTI2_TSC); };
294 (EXTI3_2) => { $action!(EXTI3_2); };
295 (EXTI4_15) => { $action!(EXTI4_15); };
296 (EXTI9_5) => { $action!(EXTI9_5); };
297 );
298 };
299}
300
301macro_rules! impl_irq {
302 ($e:ident) => {
303 #[allow(non_snake_case)]
304 #[cfg(feature = "rt")]
305 #[interrupt]
306 unsafe fn $e() {
307 on_irq()
308 }
309 };
310}
311
312foreach_exti_irq!(impl_irq);
313
314trait SealedChannel {}
315
316#[allow(private_bounds)]
318pub trait Channel: SealedChannel + Sized {
319 fn number(&self) -> u8;
321
322 fn degrade(self) -> AnyChannel {
328 AnyChannel {
329 number: self.number() as u8,
330 }
331 }
332}
333
334pub struct AnyChannel {
338 number: u8,
339}
340
341impl_peripheral!(AnyChannel);
342impl SealedChannel for AnyChannel {}
343impl Channel for AnyChannel {
344 fn number(&self) -> u8 {
345 self.number
346 }
347}
348
349macro_rules! impl_exti {
350 ($type:ident, $number:expr) => {
351 impl SealedChannel for peripherals::$type {}
352 impl Channel for peripherals::$type {
353 fn number(&self) -> u8 {
354 $number
355 }
356 }
357 };
358}
359
360impl_exti!(EXTI0, 0);
361impl_exti!(EXTI1, 1);
362impl_exti!(EXTI2, 2);
363impl_exti!(EXTI3, 3);
364impl_exti!(EXTI4, 4);
365impl_exti!(EXTI5, 5);
366impl_exti!(EXTI6, 6);
367impl_exti!(EXTI7, 7);
368impl_exti!(EXTI8, 8);
369impl_exti!(EXTI9, 9);
370impl_exti!(EXTI10, 10);
371impl_exti!(EXTI11, 11);
372impl_exti!(EXTI12, 12);
373impl_exti!(EXTI13, 13);
374impl_exti!(EXTI14, 14);
375impl_exti!(EXTI15, 15);
376
377macro_rules! enable_irq {
378 ($e:ident) => {
379 crate::interrupt::typelevel::$e::enable();
380 };
381}
382
383pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) {
385 use crate::interrupt::typelevel::Interrupt;
386
387 foreach_exti_irq!(enable_irq);
388}