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