async_stm32f1xx/
timer.rs

1//! [`Future`]-based abstractions for timers.
2
3use core::{
4    future::Future,
5    pin::Pin,
6    task::{Context, Poll, Waker},
7};
8use embedded_hal::timer::CountDown;
9use stm32f1xx_hal::{
10    pac::{TIM2, TIM3},
11    time::U32Ext,
12    timer::{CountDownTimer, Event, Timer},
13};
14
15/// An asynchronous abstraction over a timer.
16///
17/// # Examples
18///
19/// ```
20/// let mut timer: AsyncTimer<_> = Timer::tim2(dp.TIM2, &clocks, &mut apb1).into();
21/// loop {
22///     led.toggle();
23///     timer.delay_for(2.hz()).await;
24/// }
25/// ```
26pub struct AsyncTimer<T>(T);
27
28impl<T> AsMut<T> for AsyncTimer<T> {
29    fn as_mut(&mut self) -> &mut T {
30        &mut self.0
31    }
32}
33
34impl<T> AsyncTimer<T>
35where
36    T: CountDown,
37{
38    /// Creates a [`Future`] that resolves after the given time has been count down.
39    pub fn delay_for<C>(&mut self, count: C) -> Delay<'_, T>
40    where
41        C: Into<T::Time>,
42    {
43        self.as_mut().start(count);
44        Delay(&mut self.0)
45    }
46}
47
48/// [`Future`] returned by [`delay_for`].
49///
50/// [`delay_for`]: AsyncTimer::delay_for
51#[must_use = "futures do nothing unless you `.await` or poll them"]
52pub struct Delay<'a, T>(&'a mut T);
53
54impl<T> AsMut<T> for Delay<'_, T> {
55    fn as_mut(&mut self) -> &mut T {
56        self.0
57    }
58}
59
60macro_rules! timer {
61    ($(
62        $TIMX:ident
63    ),+) => {
64        $(
65            impl AsyncTimer<CountDownTimer<$TIMX>> {
66                /// Releases the TIM peripheral
67                pub fn release(self) -> $TIMX {
68                    self.0.release()
69                }
70            }
71
72            impl From<Timer<$TIMX>> for AsyncTimer<CountDownTimer<$TIMX>> {
73                fn from(timer: Timer<$TIMX>) -> Self {
74                    let mut count_down_timer = timer.start_count_down(1.hz());
75                    count_down_timer.listen(Event::Update);
76                    Self(count_down_timer)
77                }
78            }
79
80            impl Future for Delay<'_, CountDownTimer<$TIMX>> {
81                type Output = ();
82
83                fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
84                    use nb::{Error, Result};
85
86                    match self.get_mut().as_mut().wait() {
87                        Result::Ok(ok) => Poll::Ready(ok),
88                        Result::Err(Error::Other(err)) => void::unreachable(err),
89                        Result::Err(Error::WouldBlock) => {
90                            waker_interrupt!($TIMX, cx.waker().clone());
91                            Poll::Pending
92                        }
93                    }
94                }
95            }
96        )+
97    }
98}
99
100timer!(TIM2, TIM3);