diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs index fc411088..f2304c94 100644 --- a/embassy-stm32f4/src/lib.rs +++ b/embassy-stm32f4/src/lib.rs @@ -307,6 +307,55 @@ compile_error!( pub use stm32f4xx_hal as hal; pub use stm32f4xx_hal::stm32 as pac; +/// 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 { +/// 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 stm32f4xx_hal::pac::{interrupt, Interrupt, NVIC}; + + static mut WAKER: Option = 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) } + }}; +} + // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; diff --git a/embassy-stm32f4/src/uarte.rs b/embassy-stm32f4/src/uarte.rs index 222d4ba4..2d0fd9af 100644 --- a/embassy-stm32f4/src/uarte.rs +++ b/embassy-stm32f4/src/uarte.rs @@ -554,13 +554,12 @@ pub trait Instance: Deref + Sized + private::Sea } #[interrupt] -unsafe fn UARTE0_UART0() { +unsafe fn DMA2_CHANNEL2() { interrupt::free(|cs| UARTE0::get_state(cs).as_mut().unwrap().on_interrupt()); } -#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] #[interrupt] -unsafe fn UARTE1() { +unsafe fn DMA2_CHANNEL7() { interrupt::free(|cs| UARTE1::get_state(cs).as_mut().unwrap().on_interrupt()); }