Skip to main content

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