esp_hal/gpio/asynch.rs
1use core::{
2 sync::atomic::Ordering,
3 task::{Context, Poll},
4};
5
6use crate::gpio::{Event, Flex, GpioBank, Input, InputPin};
7
8impl Flex<'_> {
9 /// Wait until the pin experiences a particular [`Event`].
10 ///
11 /// The GPIO driver will disable listening for the event once it occurs,
12 /// or if the `Future` is dropped - which also means this method is **not**
13 /// cancellation-safe, it will always wait for a future event.
14 ///
15 /// Note that calling this function will overwrite previous
16 /// [`listen`][Self::listen] operations for this pin.
17 #[inline]
18 #[instability::unstable]
19 pub async fn wait_for(&mut self, event: Event) {
20 // Make sure this pin is not being processed by an interrupt handler. We need to
21 // always take a critical section even if the pin is not listening, because the
22 // interrupt handler may be running on another core and the interrupt handler
23 // may be in the process of processing the pin if the interrupt status is set -
24 // regardless of the pin actually listening or not.
25 if self.is_listening() || self.is_interrupt_set() {
26 self.unlisten_and_clear();
27 }
28
29 // At this point the pin is no longer listening, and not being processed, so we
30 // can safely do our setup.
31
32 // Mark pin as async. The interrupt handler clears this bit before processing a
33 // pin and unlistens it, so this call will not race with the interrupt
34 // handler (because it must have finished before `unlisten` above, or the
35 // handler no longer )
36 self.pin
37 .bank()
38 .async_operations()
39 .fetch_or(self.pin.mask(), Ordering::Relaxed);
40
41 // Start listening for the event. We only need to do this once, as disabling
42 // the interrupt will signal the future to complete.
43 self.listen(event);
44
45 PinFuture { pin: self }.await
46 }
47
48 /// Wait until the pin is high.
49 ///
50 /// See [Self::wait_for] for more information.
51 #[inline]
52 #[instability::unstable]
53 pub async fn wait_for_high(&mut self) {
54 self.wait_for(Event::HighLevel).await
55 }
56
57 /// Wait until the pin is low.
58 ///
59 /// See [Self::wait_for] for more information.
60 #[inline]
61 #[instability::unstable]
62 pub async fn wait_for_low(&mut self) {
63 self.wait_for(Event::LowLevel).await
64 }
65
66 /// Wait for the pin to undergo a transition from low to high.
67 ///
68 /// See [Self::wait_for] for more information.
69 #[inline]
70 #[instability::unstable]
71 pub async fn wait_for_rising_edge(&mut self) {
72 self.wait_for(Event::RisingEdge).await
73 }
74
75 /// Wait for the pin to undergo a transition from high to low.
76 ///
77 /// See [Self::wait_for] for more information.
78 #[inline]
79 #[instability::unstable]
80 pub async fn wait_for_falling_edge(&mut self) {
81 self.wait_for(Event::FallingEdge).await
82 }
83
84 /// Wait for the pin to undergo any transition, i.e low to high OR high
85 /// to low.
86 ///
87 /// See [Self::wait_for] for more information.
88 #[inline]
89 #[instability::unstable]
90 pub async fn wait_for_any_edge(&mut self) {
91 self.wait_for(Event::AnyEdge).await
92 }
93}
94
95impl Input<'_> {
96 #[procmacros::doc_replace]
97 /// Wait until the pin experiences a particular [`Event`].
98 ///
99 /// The GPIO driver will disable listening for the event once it occurs,
100 /// or if the `Future` is dropped - which also means this method is **not**
101 /// cancellation-safe, it will always wait for a future event.
102 ///
103 /// Note that calling this function will overwrite previous
104 /// [`listen`][Self::listen] operations for this pin.
105 ///
106 /// ## Example
107 ///
108 /// ```rust, no_run
109 /// # {before_snippet}
110 /// use esp_hal::gpio::{Event, Input, InputConfig};
111 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
112 ///
113 /// input_pin.wait_for(Event::LowLevel).await;
114 /// # {after_snippet}
115 /// ```
116 #[inline]
117 pub async fn wait_for(&mut self, event: Event) {
118 self.pin.wait_for(event).await
119 }
120
121 #[procmacros::doc_replace]
122 /// Wait until the pin is high.
123 ///
124 /// See [Self::wait_for] for more information.
125 ///
126 /// ## Example
127 ///
128 /// ```rust, no_run
129 /// # {before_snippet}
130 /// use esp_hal::gpio::{Event, Input, InputConfig};
131 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
132 ///
133 /// input_pin.wait_for_high().await;
134 /// # {after_snippet}
135 /// ```
136 #[inline]
137 pub async fn wait_for_high(&mut self) {
138 self.pin.wait_for_high().await
139 }
140
141 #[procmacros::doc_replace]
142 /// Wait until the pin is low.
143 ///
144 /// See [Self::wait_for] for more information.
145 ///
146 /// ## Example
147 ///
148 /// ```rust, no_run
149 /// # {before_snippet}
150 /// use esp_hal::gpio::{Event, Input, InputConfig};
151 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
152 ///
153 /// input_pin.wait_for_low().await;
154 /// # {after_snippet}
155 /// ```
156 #[inline]
157 pub async fn wait_for_low(&mut self) {
158 self.pin.wait_for_low().await
159 }
160
161 #[procmacros::doc_replace]
162 /// Wait for the pin to undergo a transition from low to high.
163 ///
164 /// See [Self::wait_for] for more information.
165 ///
166 /// ## Example
167 ///
168 /// ```rust, no_run
169 /// # {before_snippet}
170 /// use esp_hal::gpio::{Event, Input, InputConfig};
171 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
172 ///
173 /// input_pin.wait_for_rising_edge().await;
174 /// # {after_snippet}
175 /// ```
176 #[inline]
177 pub async fn wait_for_rising_edge(&mut self) {
178 self.pin.wait_for_rising_edge().await
179 }
180
181 #[procmacros::doc_replace]
182 /// Wait for the pin to undergo a transition from high to low.
183 ///
184 /// See [Self::wait_for] for more information.
185 ///
186 /// ## Example
187 ///
188 /// ```rust, no_run
189 /// # {before_snippet}
190 /// use esp_hal::gpio::{Event, Input, InputConfig};
191 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
192 ///
193 /// input_pin.wait_for_falling_edge().await;
194 /// # {after_snippet}
195 /// ```
196 #[inline]
197 pub async fn wait_for_falling_edge(&mut self) {
198 self.pin.wait_for_falling_edge().await
199 }
200
201 #[procmacros::doc_replace]
202 /// Wait for the pin to undergo any transition, i.e low to high OR high
203 /// to low.
204 ///
205 /// See [Self::wait_for] for more information.
206 ///
207 /// ## Example
208 ///
209 /// ```rust, no_run
210 /// # {before_snippet}
211 /// use esp_hal::gpio::{Event, Input, InputConfig};
212 /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
213 ///
214 /// input_pin.wait_for_any_edge().await;
215 /// # {after_snippet}
216 /// ```
217 #[inline]
218 pub async fn wait_for_any_edge(&mut self) {
219 self.pin.wait_for_any_edge().await
220 }
221}
222
223#[must_use = "futures do nothing unless you `.await` or poll them"]
224struct PinFuture<'f, 'd> {
225 pin: &'f mut Flex<'d>,
226}
227
228impl PinFuture<'_, '_> {
229 fn bank(&self) -> GpioBank {
230 self.pin.pin.bank()
231 }
232
233 fn mask(&self) -> u32 {
234 self.pin.pin.mask()
235 }
236
237 fn is_done(&self) -> bool {
238 // Only the interrupt handler should clear the async bit, and only if the
239 // specific pin is handling an interrupt. This way the user may clear the
240 // interrupt status without worrying about the async bit being cleared.
241 self.bank().async_operations().load(Ordering::Acquire) & self.mask() == 0
242 }
243}
244
245impl core::future::Future for PinFuture<'_, '_> {
246 type Output = ();
247
248 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
249 self.pin.pin.waker().register(cx.waker());
250
251 if self.is_done() {
252 Poll::Ready(())
253 } else {
254 Poll::Pending
255 }
256 }
257}
258
259impl Drop for PinFuture<'_, '_> {
260 fn drop(&mut self) {
261 // If the future has completed, unlistening and removing the async bit will have
262 // been done by the interrupt handler.
263
264 if !self.is_done() {
265 self.pin.unlisten_and_clear();
266
267 // Unmark pin as async so that a future listen call doesn't wake a waker for no
268 // reason.
269 self.bank()
270 .async_operations()
271 .fetch_and(!self.mask(), Ordering::Relaxed);
272 }
273 }
274}