embedded_c_sdk_bind_hal/gpio/
exti.rs1use crate::gpio::Pin;
2use crate::ll_api::{ll_cmd::*, GpioExtiFlag};
3
4pub enum ExtiMode {
5 Rising,
6 Falling,
7 RisingFalling,
8}
9
10impl ExtiMode {
11 pub(crate) fn to_flag(&self) -> GpioExtiFlag {
12 match self {
13 ExtiMode::Rising => GpioExtiFlag::Rising,
14 ExtiMode::Falling => GpioExtiFlag::Falling,
15 ExtiMode::RisingFalling => GpioExtiFlag::RisingFalling,
16 }
17 }
18}
19
20impl<'d> super::pin::Input<'d> {
21 pub fn exti_config(&self, mode: ExtiMode) {
26 let port = self.pin.pin.port();
27 let pin = self.pin.pin.pin();
28
29 ll_invoke_inner!(INVOKE_ID_GPIO_EXTI, port, pin, mode.to_flag());
30 }
31
32 pub fn enable_interrupt(&self) {
36 let port = self.pin.pin.port();
37 let pin = self.pin.pin.pin();
38
39 ll_invoke_inner!(INVOKE_ID_GPIO_EXTI, port, pin, GpioExtiFlag::Enable);
40 }
41
42 pub fn disable_interrupt(&self) {
46 let port = self.pin.pin.port();
47 let pin = self.pin.pin.pin();
48
49 ll_invoke_inner!(INVOKE_ID_GPIO_EXTI, port, pin, GpioExtiFlag::Disable);
50 }
51}
52
53#[allow(non_snake_case)]
54#[no_mangle]
55unsafe extern "C" fn EXTI_IRQ_hook_rs(_line: u8) {
59 #[cfg(all(feature = "embassy", feature = "exti-async"))]
60 exti_future::exti_set_status(_line);
62
63 #[cfg(feature = "exti-irq-callback")]
64 {
65 extern "Rust" {
68 fn exti_irq_callback(line: u8);
69 }
70 exti_irq_callback(_line);
71 }
72}
73
74#[cfg(all(feature = "embassy", feature = "exti-async"))]
75pub mod exti_future {
76 use crate::gpio::Pin;
77 use core::future::Future;
78 use core::task::{Context, Poll};
79 use embassy_sync::waitqueue::AtomicWaker;
80 use portable_atomic::{AtomicU16, Ordering};
81
82 const EXTI_COUNT: usize = 16;
83 const NEW_AW: AtomicWaker = AtomicWaker::new();
84 static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
85 static EXTI_STATUS: AtomicU16 = AtomicU16::new(0);
86
87 #[inline]
88 pub fn exti_set_status(line: u8) {
89 if line < EXTI_COUNT as u8 {
90 EXTI_STATUS.bit_set(line as u32, Ordering::Relaxed);
91 EXTI_WAKERS[line as usize].wake();
92 }
93 }
94
95 impl<'d> super::super::pin::Input<'d> {
96 pub async fn wait_for_high(&mut self) {
97 let port = self.pin.pin.port();
98 let pin = self.pin.pin.pin();
99 let fut = ExtiInputFuture::new(port, pin, super::ExtiMode::Rising);
100 if Self::is_high(self) {
101 return;
102 }
103 fut.await
104 }
105
106 pub async fn wait_for_low(&mut self) {
107 let port = self.pin.pin.port();
108 let pin = self.pin.pin.pin();
109 let fut = ExtiInputFuture::new(port, pin, super::ExtiMode::Falling);
110 if !Self::is_high(self) {
111 return;
112 }
113 fut.await
114 }
115
116 pub async fn wait_for_rising_edge(&mut self) {
117 let port = self.pin.pin.port();
118 let pin = self.pin.pin.pin();
119 ExtiInputFuture::new(port, pin, super::ExtiMode::Rising).await
120 }
121
122 pub async fn wait_for_falling_edge(&mut self) {
123 let port = self.pin.pin.port();
124 let pin = self.pin.pin.pin();
125 ExtiInputFuture::new(port, pin, super::ExtiMode::Falling).await
126 }
127
128 pub async fn wait_for_any_edge(&mut self) {
129 let port = self.pin.pin.port();
130 let pin = self.pin.pin.pin();
131 ExtiInputFuture::new(port, pin, super::ExtiMode::RisingFalling).await
132 }
133 }
134
135 struct ExtiInputFuture {
136 port: u8,
137 pin: u8,
138 }
139
140 impl ExtiInputFuture {
141 fn new(port: u8, pin: u8, mode: super::ExtiMode) -> Self {
142 ll_invoke_inner!(crate::INVOKE_ID_GPIO_EXTI, port, pin, mode.to_flag());
143 Self { port, pin }
145 }
146 }
147
148 impl Drop for ExtiInputFuture {
149 fn drop(&mut self) {
150 ll_invoke_inner!(
151 crate::INVOKE_ID_GPIO_EXTI,
152 self.port,
153 self.pin,
154 super::GpioExtiFlag::Disable
155 );
156 }
157 }
158
159 impl Future for ExtiInputFuture {
160 type Output = ();
161
162 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
163 EXTI_WAKERS[self.pin as usize].register(cx.waker());
164
165 if EXTI_STATUS.bit_clear(self.pin as u32, Ordering::Relaxed) {
166 Poll::Ready(())
167 } else {
168 Poll::Pending
169 }
170 }
171 }
172
173 impl<'d> embedded_hal_async::digital::Wait for super::super::Input<'d> {
174 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
175 self.wait_for_high().await;
176 Ok(())
177 }
178
179 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
180 self.wait_for_low().await;
181 Ok(())
182 }
183
184 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
185 self.wait_for_rising_edge().await;
186 Ok(())
187 }
188
189 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
190 self.wait_for_falling_edge().await;
191 Ok(())
192 }
193
194 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
195 self.wait_for_any_edge().await;
196 Ok(())
197 }
198 }
199}