1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//! Abstractions for asynchronous programming on the STM32F1xx family of microcontrollers. //! //! This crate provides [`futures`]-based abstractions for asynchronous programming with peripherals from [`stm32f1xx_hal`]: //! //! - [`AsyncTimer`](crate::timer::AsyncTimer) allows delaying the current task, wrapping [`Timer`](stm32f1xx_hal::timer::Timer). //! - [`TxSink`](crate::serial::TxSink) allows [`Sink`](futures::sink::Sink)-based USART transmissions, wrapping [`TxDma`](stm32f1xx_hal::dma::TxDma). //! - [`RxStream`](crate::serial::RxStream) allows [`Stream`](futures::stream::Stream)-based USART receives, wrapping [`RxDma`](stm32f1xx_hal::dma::RxDma). //! //! To properly schedule wakeups, this crate implements the following interrupts: //! //! - [`TIM2`](stm32f1xx_hal::pac::Interrupt::TIM2), [`TIM3`](stm32f1xx_hal::pac::Interrupt::TIM3) //! - [`DMA1_CHANNEL4`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL4), [`DMA1_CHANNEL7`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL7), [`DMA1_CHANNEL2`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL2) //! - [`DMA1_CHANNEL5`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL5), [`DMA1_CHANNEL6`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL6), [`DMA1_CHANNEL3`](stm32f1xx_hal::pac::Interrupt::DMA1_CHANNEL3) #![no_std] #![deny(clippy::all, rust_2018_idioms)] #![warn(missing_docs)] /// Creates a new interrupt waking a [`Waker`]. /// /// As this interrupt will be declared in this macro, it can't be used for anything else. /// /// # Examples /// /// This macro is useful for implementing [`Future::poll`]: /// /// ``` /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { /// if self.is_ready() { /// Poll::Ready(()) /// } else { /// waker_interrupt!(TIM2, cx.waker().clone()); /// Poll::Pending /// } /// } /// ``` /// /// [`Waker`]: core::task::Waker /// [`Future::poll`]: core::future::Future::poll macro_rules! waker_interrupt { ($INT:ident, $waker:expr) => {{ use core::sync::atomic::{self, Ordering}; use stm32f1xx_hal::pac::{interrupt, Interrupt, NVIC}; static mut WAKER: Option<Waker> = None; #[interrupt] fn $INT() { // Safety: This context is disabled while the lower priority context accesses WAKER if let Some(waker) = unsafe { WAKER.as_ref() } { waker.wake_by_ref(); NVIC::mask(Interrupt::$INT); } } NVIC::mask(Interrupt::$INT); atomic::compiler_fence(Ordering::Acquire); // Safety: The other relevant context, the interrupt, is disabled unsafe { WAKER = Some($waker) } NVIC::unpend(Interrupt::$INT); atomic::compiler_fence(Ordering::Release); // Safety: This is the end of a mask-based critical section unsafe { NVIC::unmask(Interrupt::$INT) } }}; } pub mod serial; pub mod timer;