diff --git a/embassy-stm32f4/src/exti.rs b/embassy-stm32/src/exti.rs similarity index 56% rename from embassy-stm32f4/src/exti.rs rename to embassy-stm32/src/exti.rs index 154ca45c..a0007945 100644 --- a/embassy-stm32f4/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -3,35 +3,33 @@ use core::mem; use core::pin::Pin; use cortex_m; -use embassy::traits::gpio::{WaitForFallingEdge, WaitForRisingEdge}; +use crate::hal::gpio; + +use embassy::traits::gpio::{ + WaitForAnyEdge, WaitForFallingEdge, WaitForHigh, WaitForLow, WaitForRisingEdge, +}; use embassy::util::InterruptFuture; -use crate::hal::gpio; -use crate::hal::gpio::Edge; -use crate::hal::syscfg::SysCfg; -use crate::pac::EXTI; use embedded_hal::digital::v2 as digital; use crate::interrupt; -pub struct ExtiPin { +pub struct ExtiPin { pin: T, interrupt: T::Interrupt, } -impl ExtiPin { +impl ExtiPin { pub fn new(mut pin: T, interrupt: T::Interrupt) -> Self { - let mut syscfg: SysCfg = unsafe { mem::transmute(()) }; - cortex_m::interrupt::free(|_| { - pin.make_interrupt_source(&mut syscfg); + pin.make_source(); }); Self { pin, interrupt } } } -impl digital::OutputPin for ExtiPin { +impl digital::OutputPin for ExtiPin { type Error = T::Error; fn set_low(&mut self) -> Result<(), Self::Error> { @@ -43,9 +41,7 @@ impl digital::OutputPin f } } -impl digital::StatefulOutputPin - for ExtiPin -{ +impl digital::StatefulOutputPin for ExtiPin { fn is_set_low(&self) -> Result { self.pin.is_set_low() } @@ -55,9 +51,7 @@ impl digital::Sta } } -impl digital::ToggleableOutputPin - for ExtiPin -{ +impl digital::ToggleableOutputPin for ExtiPin { type Error = T::Error; fn toggle(&mut self) -> Result<(), Self::Error> { @@ -65,7 +59,7 @@ impl digital::T } } -impl digital::InputPin for ExtiPin { +impl digital::InputPin for ExtiPin { type Error = T::Error; fn is_high(&self) -> Result { @@ -77,6 +71,73 @@ impl digital::InputPin for } } +impl ExtiPin { + fn wait_for_state<'a>(self: Pin<&'a mut Self>, state: bool) -> impl Future + 'a { + let s = unsafe { self.get_unchecked_mut() }; + + s.pin.clear_pending_bit(); + async move { + let fut = InterruptFuture::new(&mut s.interrupt); + let pin = &mut s.pin; + cortex_m::interrupt::free(|_| { + pin.trigger_edge(if state { + EdgeOption::Rising + } else { + EdgeOption::Falling + }); + }); + + if (state && s.pin.is_high().unwrap_or(false)) + || (!state && s.pin.is_low().unwrap_or(false)) + { + return; + } + + fut.await; + + s.pin.clear_pending_bit(); + } + } +} + +impl ExtiPin { + fn wait_for_edge<'a>( + self: Pin<&'a mut Self>, + state: EdgeOption, + ) -> impl Future + 'a { + let s = unsafe { self.get_unchecked_mut() }; + + s.pin.clear_pending_bit(); + async move { + let fut = InterruptFuture::new(&mut s.interrupt); + let pin = &mut s.pin; + cortex_m::interrupt::free(|_| { + pin.trigger_edge(state); + }); + + fut.await; + + s.pin.clear_pending_bit(); + } + } +} + +impl WaitForHigh for ExtiPin { + type Future<'a> = impl Future + 'a; + + fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { + self.wait_for_state(true) + } +} + +impl WaitForLow for ExtiPin { + type Future<'a> = impl Future + 'a; + + fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { + self.wait_for_state(false) + } +} + /* Irq Handler Description EXTI0_IRQn EXTI0_IRQHandler Handler for pins connected to line 0 @@ -88,49 +149,27 @@ impl digital::InputPin for EXTI15_10_IRQn EXTI15_10_IRQHandler Handler for pins connected to line 10 to 15 */ -impl WaitForRisingEdge for ExtiPin { +impl WaitForRisingEdge for ExtiPin { type Future<'a> = impl Future + 'a; fn wait_for_rising_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - let s = unsafe { self.get_unchecked_mut() }; - - s.pin.clear_interrupt_pending_bit(); - async move { - let fut = InterruptFuture::new(&mut s.interrupt); - let pin = &mut s.pin; - cortex_m::interrupt::free(|_| { - let mut exti: EXTI = unsafe { mem::transmute(()) }; - - pin.trigger_on_edge(&mut exti, Edge::RISING); - pin.enable_interrupt(&mut exti); - }); - fut.await; - - s.pin.clear_interrupt_pending_bit(); - } + self.wait_for_edge(EdgeOption::Rising) } } -impl WaitForFallingEdge for ExtiPin { +impl WaitForFallingEdge for ExtiPin { type Future<'a> = impl Future + 'a; fn wait_for_falling_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - let s = unsafe { self.get_unchecked_mut() }; + self.wait_for_edge(EdgeOption::Falling) + } +} - s.pin.clear_interrupt_pending_bit(); - async move { - let fut = InterruptFuture::new(&mut s.interrupt); - let pin = &mut s.pin; - cortex_m::interrupt::free(|_| { - let mut exti: EXTI = unsafe { mem::transmute(()) }; +impl WaitForAnyEdge for ExtiPin { + type Future<'a> = impl Future + 'a; - pin.trigger_on_edge(&mut exti, Edge::FALLING); - pin.enable_interrupt(&mut exti); - }); - fut.await; - - s.pin.clear_interrupt_pending_bit(); - } + fn wait_for_any_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { + self.wait_for_edge(EdgeOption::RisingFalling) } } @@ -138,10 +177,23 @@ mod private { pub trait Sealed {} } +#[derive(Copy, Clone)] +pub enum EdgeOption { + Rising, + Falling, + RisingFalling, +} + pub trait WithInterrupt: private::Sealed { type Interrupt: interrupt::Interrupt; } +pub trait Instance: WithInterrupt { + fn make_source(&mut self); + fn clear_pending_bit(&mut self); + fn trigger_edge(&mut self, edge: EdgeOption); +} + macro_rules! exti { ($set:ident, [ $($INT:ident => $pin:ident,)+ @@ -151,8 +203,90 @@ macro_rules! exti { impl WithInterrupt for gpio::$set::$pin { type Interrupt = interrupt::$INT; } - )+ + #[cfg(any( + feature = "stm32f401", + feature = "stm32f405", + feature = "stm32f407", + feature = "stm32f410", + feature = "stm32f411", + feature = "stm32f412", + feature = "stm32f413", + feature = "stm32f415", + feature = "stm32f417", + feature = "stm32f423", + feature = "stm32f427", + feature = "stm32f429", + feature = "stm32f437", + feature = "stm32f439", + feature = "stm32f446", + feature = "stm32f469", + feature = "stm32f479", + ))] + impl Instance for gpio::$set::$pin> { + fn make_source(&mut self) { + use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; + use crate::pac::EXTI; + let mut syscfg: SysCfg = unsafe { mem::transmute(()) }; + self.make_interrupt_source(&mut syscfg); + } + + fn clear_pending_bit(&mut self) { + use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; + + self.clear_interrupt_pending_bit(); + } + + fn trigger_edge(&mut self, edge: EdgeOption) { + use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; + use crate::pac::EXTI; + let mut exti: EXTI = unsafe { mem::transmute(()) }; + let edge = match edge { + EdgeOption::Falling => Edge::FALLING, + EdgeOption::Rising => Edge::RISING, + EdgeOption::RisingFalling => Edge::RISING_FALLING, + }; + self.trigger_on_edge(&mut exti, edge); + self.enable_interrupt(&mut exti); + } + } + + #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] + impl Instance for gpio::$set::$pin { + fn make_source(&mut self) {} + + fn clear_pending_bit(&mut self) { + use crate::hal::{ + exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, + syscfg::SYSCFG, + }; + + Exti::unpend(GpioLine::from_raw_line(self.pin_number()).unwrap()); + } + + fn trigger_edge(&mut self, edge: EdgeOption) { + use crate::hal::{ + exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, + syscfg::SYSCFG, + }; + + use crate::pac::EXTI; + + let edge = match edge { + EdgeOption::Falling => TriggerEdge::Falling, + EdgeOption::Rising => TriggerEdge::Rising, + EdgeOption::RisingFalling => TriggerEdge::Both, + }; + + let exti: EXTI = unsafe { mem::transmute(()) }; + let mut exti = Exti::new(exti); + let port = self.port(); + let mut syscfg: SYSCFG = unsafe { mem::transmute(()) }; + let line = GpioLine::from_raw_line(self.pin_number()).unwrap(); + exti.listen_gpio(&mut syscfg, port, line, edge); + } + } + )+ }; } @@ -533,3 +667,111 @@ exti!(gpiok, [ EXTI9_5 => PK6, EXTI9_5 => PK7, ]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpioa, [ + EXTI0_1 => PA0, + EXTI0_1 => PA1, + EXTI2_3 => PA2, + EXTI2_3 => PA3, + EXTI4_15 => PA4, + EXTI4_15 => PA5, + EXTI4_15 => PA6, + EXTI4_15 => PA7, + EXTI4_15 => PA8, + EXTI4_15 => PA9, + EXTI4_15 => PA10, + EXTI4_15 => PA11, + EXTI4_15 => PA12, + EXTI4_15 => PA13, + EXTI4_15 => PA14, + EXTI4_15 => PA15, +]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpiob, [ + EXTI0_1 => PB0, + EXTI0_1 => PB1, + EXTI2_3 => PB2, + EXTI2_3 => PB3, + EXTI4_15 => PB4, + EXTI4_15 => PB5, + EXTI4_15 => PB6, + EXTI4_15 => PB7, + EXTI4_15 => PB8, + EXTI4_15 => PB9, + EXTI4_15 => PB10, + EXTI4_15 => PB11, + EXTI4_15 => PB12, + EXTI4_15 => PB13, + EXTI4_15 => PB14, + EXTI4_15 => PB15, +]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpioc, [ + EXTI0_1 => PC0, + EXTI0_1 => PC1, + EXTI2_3 => PC2, + EXTI2_3 => PC3, + EXTI4_15 => PC4, + EXTI4_15 => PC5, + EXTI4_15 => PC6, + EXTI4_15 => PC7, + EXTI4_15 => PC8, + EXTI4_15 => PC9, + EXTI4_15 => PC10, + EXTI4_15 => PC11, + EXTI4_15 => PC12, + EXTI4_15 => PC13, + EXTI4_15 => PC14, + EXTI4_15 => PC15, +]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpiod, [ + EXTI0_1 => PD0, + EXTI0_1 => PD1, + EXTI2_3 => PD2, + EXTI2_3 => PD3, + EXTI4_15 => PD4, + EXTI4_15 => PD5, + EXTI4_15 => PD6, + EXTI4_15 => PD7, + EXTI4_15 => PD8, + EXTI4_15 => PD9, + EXTI4_15 => PD10, + EXTI4_15 => PD11, + EXTI4_15 => PD12, + EXTI4_15 => PD13, + EXTI4_15 => PD14, + EXTI4_15 => PD15, +]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpioe, [ + EXTI0_1 => PE0, + EXTI0_1 => PE1, + EXTI2_3 => PE2, + EXTI2_3 => PE3, + EXTI4_15 => PE4, + EXTI4_15 => PE5, + EXTI4_15 => PE6, + EXTI4_15 => PE7, + EXTI4_15 => PE8, + EXTI4_15 => PE9, + EXTI4_15 => PE10, + EXTI4_15 => PE11, + EXTI4_15 => PE12, + EXTI4_15 => PE13, + EXTI4_15 => PE14, + EXTI4_15 => PE15, +]); + +#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] +exti!(gpioh, [ + EXTI0_1 => PH0, + EXTI0_1 => PH1, + EXTI4_15 => PH9, + EXTI4_15 => PH10, +]); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a1f40b2c..954067f3 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -32,4 +32,5 @@ pub use {stm32l0xx_hal as hal, stm32l0xx_hal::pac}; pub mod fmt; +pub mod exti; pub mod interrupt; diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs index 0d490525..bdd4d0fd 100644 --- a/embassy-stm32f4/src/lib.rs +++ b/embassy-stm32f4/src/lib.rs @@ -307,11 +307,10 @@ compile_error!( "Multile chip features activated. You must activate exactly one of the following features: " ); -pub use embassy_stm32::{fmt, hal, interrupt, pac}; +pub use embassy_stm32::{exti, fmt, hal, interrupt, pac}; #[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411",)))] pub mod can; -pub mod exti; #[cfg(not(feature = "stm32f410"))] pub mod qei; pub mod rtc; diff --git a/embassy-stm32l0/src/exti.rs b/embassy-stm32l0/src/exti.rs deleted file mode 100644 index f50c3ae8..00000000 --- a/embassy-stm32l0/src/exti.rs +++ /dev/null @@ -1,268 +0,0 @@ -use core::future::Future; -use core::mem; -use core::pin::Pin; - -use embassy::traits::gpio::{ - WaitForAnyEdge, WaitForFallingEdge, WaitForHigh, WaitForLow, WaitForRisingEdge, -}; -use embassy::util::InterruptFuture; - -use crate::hal::{ - exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, - gpio, - syscfg::SYSCFG, -}; -use crate::interrupt; -use crate::pac::EXTI; -use embedded_hal::digital::v2::InputPin; - -pub struct ExtiPin { - pin: T, - interrupt: T::Interrupt, -} - -impl ExtiPin { - pub fn new(pin: T, interrupt: T::Interrupt) -> ExtiPin { - ExtiPin { pin, interrupt } - } - - fn wait_for_edge<'a>( - self: Pin<&'a mut Self>, - edge: TriggerEdge, - ) -> impl Future + 'a { - let line = self.pin.line(); - let s = unsafe { self.get_unchecked_mut() }; - - Exti::unpend(line); - - async move { - let exti: EXTI = unsafe { mem::transmute(()) }; - let mut exti = Exti::new(exti); - - let fut = InterruptFuture::new(&mut s.interrupt); - - let port = s.pin.port(); - cortex_m::interrupt::free(|_| { - let mut syscfg: SYSCFG = unsafe { mem::transmute(()) }; - exti.listen_gpio(&mut syscfg, port, line, edge); - }); - - fut.await; - - Exti::unpend(line); - } - } -} - -impl ExtiPin { - fn wait_for_state<'a>(self: Pin<&'a mut Self>, state: bool) -> impl Future + 'a { - let line = self.pin.line(); - let s = unsafe { self.get_unchecked_mut() }; - - Exti::unpend(line); - - async move { - let exti: EXTI = unsafe { mem::transmute(()) }; - let mut exti = Exti::new(exti); - - let fut = InterruptFuture::new(&mut s.interrupt); - - let port = s.pin.port(); - cortex_m::interrupt::free(|_| { - let mut syscfg: SYSCFG = unsafe { mem::transmute(()) }; - let edge = if state { - TriggerEdge::Rising - } else { - TriggerEdge::Falling - }; - exti.listen_gpio(&mut syscfg, port, line, edge); - }); - - let pin_has_state = if state { - s.pin.is_high() - } else { - s.pin.is_low() - } - .unwrap_or(false); - if pin_has_state { - return (); - } - - fut.await; - - Exti::unpend(line); - } - } -} - -impl WaitForRisingEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_rising_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - self.wait_for_edge(TriggerEdge::Rising) - } -} - -impl WaitForFallingEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_falling_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - self.wait_for_edge(TriggerEdge::Falling) - } -} - -impl WaitForAnyEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_any_edge<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - self.wait_for_edge(TriggerEdge::Both) - } -} - -impl WaitForHigh for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - self.wait_for_state(true) - } -} - -impl WaitForLow for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { - self.wait_for_state(false) - } -} - -mod private { - pub trait Sealed {} -} - -pub trait PinWithInterrupt: private::Sealed { - type Interrupt: interrupt::Interrupt; - fn port(&self) -> gpio::Port; - fn line(&self) -> GpioLine; -} - -macro_rules! exti { - ($set:ident, [ - $($INT:ident => $pin:ident,)+ - ]) => { - $( - impl private::Sealed for gpio::$set::$pin {} - impl PinWithInterrupt for gpio::$set::$pin { - type Interrupt = interrupt::$INT; - fn port(&self) -> gpio::Port { - self.port() - } - fn line(&self) -> GpioLine { - GpioLine::from_raw_line(self.pin_number()).unwrap() - } - } - )+ - - }; -} - -exti!(gpioa, [ - EXTI0_1 => PA0, - EXTI0_1 => PA1, - EXTI2_3 => PA2, - EXTI2_3 => PA3, - EXTI4_15 => PA4, - EXTI4_15 => PA5, - EXTI4_15 => PA6, - EXTI4_15 => PA7, - EXTI4_15 => PA8, - EXTI4_15 => PA9, - EXTI4_15 => PA10, - EXTI4_15 => PA11, - EXTI4_15 => PA12, - EXTI4_15 => PA13, - EXTI4_15 => PA14, - EXTI4_15 => PA15, -]); - -exti!(gpiob, [ - EXTI0_1 => PB0, - EXTI0_1 => PB1, - EXTI2_3 => PB2, - EXTI2_3 => PB3, - EXTI4_15 => PB4, - EXTI4_15 => PB5, - EXTI4_15 => PB6, - EXTI4_15 => PB7, - EXTI4_15 => PB8, - EXTI4_15 => PB9, - EXTI4_15 => PB10, - EXTI4_15 => PB11, - EXTI4_15 => PB12, - EXTI4_15 => PB13, - EXTI4_15 => PB14, - EXTI4_15 => PB15, -]); - -exti!(gpioc, [ - EXTI0_1 => PC0, - EXTI0_1 => PC1, - EXTI2_3 => PC2, - EXTI2_3 => PC3, - EXTI4_15 => PC4, - EXTI4_15 => PC5, - EXTI4_15 => PC6, - EXTI4_15 => PC7, - EXTI4_15 => PC8, - EXTI4_15 => PC9, - EXTI4_15 => PC10, - EXTI4_15 => PC11, - EXTI4_15 => PC12, - EXTI4_15 => PC13, - EXTI4_15 => PC14, - EXTI4_15 => PC15, -]); - -exti!(gpiod, [ - EXTI0_1 => PD0, - EXTI0_1 => PD1, - EXTI2_3 => PD2, - EXTI2_3 => PD3, - EXTI4_15 => PD4, - EXTI4_15 => PD5, - EXTI4_15 => PD6, - EXTI4_15 => PD7, - EXTI4_15 => PD8, - EXTI4_15 => PD9, - EXTI4_15 => PD10, - EXTI4_15 => PD11, - EXTI4_15 => PD12, - EXTI4_15 => PD13, - EXTI4_15 => PD14, - EXTI4_15 => PD15, -]); - -exti!(gpioe, [ - EXTI0_1 => PE0, - EXTI0_1 => PE1, - EXTI2_3 => PE2, - EXTI2_3 => PE3, - EXTI4_15 => PE4, - EXTI4_15 => PE5, - EXTI4_15 => PE6, - EXTI4_15 => PE7, - EXTI4_15 => PE8, - EXTI4_15 => PE9, - EXTI4_15 => PE10, - EXTI4_15 => PE11, - EXTI4_15 => PE12, - EXTI4_15 => PE13, - EXTI4_15 => PE14, - EXTI4_15 => PE15, -]); - -exti!(gpioh, [ - EXTI0_1 => PH0, - EXTI0_1 => PH1, - EXTI4_15 => PH9, - EXTI4_15 => PH10, -]); diff --git a/embassy-stm32l0/src/lib.rs b/embassy-stm32l0/src/lib.rs index e80fe6cb..a684c4e3 100644 --- a/embassy-stm32l0/src/lib.rs +++ b/embassy-stm32l0/src/lib.rs @@ -19,6 +19,4 @@ compile_error!( "Multile chip features activated. You must activate exactly one of the following features: " ); -pub use embassy_stm32::{fmt, hal, interrupt, pac}; - -pub mod exti; +pub use embassy_stm32::{exti, fmt, hal, interrupt, pac};