From ec51880e28d48269ae1ce8b037305f4f7f182c84 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 19 Aug 2021 22:17:17 +0200 Subject: [PATCH] stm32/exti: unify all versions into single impl --- embassy-stm32/src/exti.rs | 270 ++++++++++++++++++++++ embassy-stm32/src/exti/mod.rs | 116 ---------- embassy-stm32/src/exti/v1.rs | 171 -------------- embassy-stm32/src/exti/v2.rs | 184 --------------- examples/stm32wb55/src/bin/button_exti.rs | 36 +++ 5 files changed, 306 insertions(+), 471 deletions(-) create mode 100644 embassy-stm32/src/exti.rs delete mode 100644 embassy-stm32/src/exti/mod.rs delete mode 100644 embassy-stm32/src/exti/v1.rs delete mode 100644 embassy-stm32/src/exti/v2.rs create mode 100644 examples/stm32wb55/src/bin/button_exti.rs diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs new file mode 100644 index 00000000..659daa37 --- /dev/null +++ b/embassy-stm32/src/exti.rs @@ -0,0 +1,270 @@ +use core::convert::Infallible; +use core::future::Future; +use core::marker::PhantomData; +use core::pin::Pin; +use core::task::{Context, Poll}; +use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; +use embassy::util::{AtomicWaker, Unborrow}; +use embassy_hal_common::unsafe_impl_unborrow; +use embedded_hal::digital::v2::InputPin; + +use crate::gpio::{AnyPin, Input, Pin as GpioPin}; +use crate::interrupt; +use crate::pac; +use crate::pac::{EXTI, SYSCFG}; +use crate::peripherals; + +const EXTI_COUNT: usize = 16; +const NEW_AW: AtomicWaker = AtomicWaker::new(); +static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT]; + +#[cfg(exti_w)] +fn cpu_regs() -> pac::exti::Cpu { + EXTI.cpu(crate::pac::CORE_INDEX) +} + +#[cfg(not(exti_w))] +fn cpu_regs() -> pac::exti::Exti { + EXTI +} + +pub unsafe fn on_irq() { + let bits = EXTI.pr(0).read(); + + // Mask all the channels that fired. + cpu_regs().imr(0).modify(|w| w.0 &= !bits.0); + + // Wake the tasks + for pin in BitIter(bits.0) { + EXTI_WAKERS[pin as usize].wake(); + } + + // Clear pending + EXTI.pr(0).write_value(bits); +} + +struct BitIter(u32); + +impl Iterator for BitIter { + type Item = u32; + + fn next(&mut self) -> Option { + match self.0.trailing_zeros() { + 32 => None, + b => { + self.0 &= !(1 << b); + Some(b) + } + } + } +} + +/// EXTI input driver +pub struct ExtiInput<'d, T: GpioPin> { + pin: Input<'d, T>, +} + +impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} + +impl<'d, T: GpioPin> ExtiInput<'d, T> { + pub fn new(pin: Input<'d, T>, _ch: impl Unborrow + 'd) -> Self { + Self { pin } + } +} + +impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> { + type Error = Infallible; + + fn is_high(&self) -> Result { + self.pin.is_high() + } + + fn is_low(&self) -> Result { + self.pin.is_low() + } +} + +impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> { + type Future<'a> = ExtiInputFuture<'a>; + + fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { + ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), true, false) + } +} + +impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> { + type Future<'a> = ExtiInputFuture<'a>; + + fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { + ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), false, true) + } +} + +impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> { + type Future<'a> = ExtiInputFuture<'a>; + + fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { + ExtiInputFuture::new(self.pin.pin.pin(), self.pin.pin.port(), true, true) + } +} + +pub struct ExtiInputFuture<'a> { + pin: u8, + phantom: PhantomData<&'a mut AnyPin>, +} + +impl<'a> ExtiInputFuture<'a> { + fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { + cortex_m::interrupt::free(|_| unsafe { + let pin = pin as usize; + SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); + EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); + EXTI.ftsr(0).modify(|w| w.set_line(pin, falling)); + EXTI.pr(0).write(|w| w.set_line(pin, true)); // clear pending bit + cpu_regs().imr(0).modify(|w| w.set_line(pin, true)); + }); + + Self { + pin, + phantom: PhantomData, + } + } +} + +impl<'a> Drop for ExtiInputFuture<'a> { + fn drop(&mut self) { + cortex_m::interrupt::free(|_| unsafe { + let pin = self.pin as _; + cpu_regs().imr(0).modify(|w| w.set_line(pin, false)); + }); + } +} + +impl<'a> Future for ExtiInputFuture<'a> { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + EXTI_WAKERS[self.pin as usize].register(cx.waker()); + + let imr = unsafe { cpu_regs().imr(0).read() }; + if !imr.line(self.pin as _) { + Poll::Ready(()) + } else { + Poll::Pending + } + } +} + +macro_rules! foreach_exti_irq { + ($action:ident) => { + crate::pac::interrupts!( + (EXTI0) => { $action!(EXTI0); }; + (EXTI1) => { $action!(EXTI1); }; + (EXTI2) => { $action!(EXTI2); }; + (EXTI3) => { $action!(EXTI3); }; + (EXTI4) => { $action!(EXTI4); }; + (EXTI5) => { $action!(EXTI5); }; + (EXTI6) => { $action!(EXTI6); }; + (EXTI7) => { $action!(EXTI7); }; + (EXTI8) => { $action!(EXTI8); }; + (EXTI9) => { $action!(EXTI9); }; + (EXTI10) => { $action!(EXTI10); }; + (EXTI11) => { $action!(EXTI11); }; + (EXTI12) => { $action!(EXTI12); }; + (EXTI13) => { $action!(EXTI13); }; + (EXTI14) => { $action!(EXTI14); }; + (EXTI15) => { $action!(EXTI15); }; + + // plus the weird ones + (EXTI0_1) => { $action!( EXTI0_1 ); }; + (EXTI15_10) => { $action!(EXTI15_10); }; + (EXTI15_4) => { $action!(EXTI15_4); }; + (EXTI1_0) => { $action!(EXTI1_0); }; + (EXTI2_3) => { $action!(EXTI2_3); }; + (EXTI2_TSC) => { $action!(EXTI2_TSC); }; + (EXTI3_2) => { $action!(EXTI3_2); }; + (EXTI4_15) => { $action!(EXTI4_15); }; + (EXTI9_5) => { $action!(EXTI9_5); }; + ); + }; +} + +macro_rules! impl_irq { + ($e:ident) => { + #[interrupt] + unsafe fn $e() { + on_irq() + } + }; +} + +foreach_exti_irq!(impl_irq); + +pub(crate) mod sealed { + pub trait Channel {} +} + +pub trait Channel: sealed::Channel + Sized { + fn number(&self) -> usize; + fn degrade(self) -> AnyChannel { + AnyChannel { + number: self.number() as u8, + } + } +} + +pub struct AnyChannel { + number: u8, +} +unsafe_impl_unborrow!(AnyChannel); +impl sealed::Channel for AnyChannel {} +impl Channel for AnyChannel { + fn number(&self) -> usize { + self.number as usize + } +} + +macro_rules! impl_exti { + ($type:ident, $number:expr) => { + impl sealed::Channel for peripherals::$type {} + impl Channel for peripherals::$type { + fn number(&self) -> usize { + $number as usize + } + } + }; +} + +impl_exti!(EXTI0, 0); +impl_exti!(EXTI1, 1); +impl_exti!(EXTI2, 2); +impl_exti!(EXTI3, 3); +impl_exti!(EXTI4, 4); +impl_exti!(EXTI5, 5); +impl_exti!(EXTI6, 6); +impl_exti!(EXTI7, 7); +impl_exti!(EXTI8, 8); +impl_exti!(EXTI9, 9); +impl_exti!(EXTI10, 10); +impl_exti!(EXTI11, 11); +impl_exti!(EXTI12, 12); +impl_exti!(EXTI13, 13); +impl_exti!(EXTI14, 14); +impl_exti!(EXTI15, 15); + +macro_rules! enable_irq { + ($e:ident) => { + crate::interrupt::$e::steal().enable(); + }; +} + +/// safety: must be called only once +pub(crate) unsafe fn init() { + use embassy::interrupt::Interrupt; + use embassy::interrupt::InterruptExt; + + foreach_exti_irq!(enable_irq); + + #[cfg(not(any(rcc_wb, rcc_wl5)))] + ::enable(); +} diff --git a/embassy-stm32/src/exti/mod.rs b/embassy-stm32/src/exti/mod.rs deleted file mode 100644 index 3f43e0bc..00000000 --- a/embassy-stm32/src/exti/mod.rs +++ /dev/null @@ -1,116 +0,0 @@ -#![macro_use] - -macro_rules! foreach_exti_irq { - ($action:ident) => { - crate::pac::interrupts!( - (EXTI0) => { $action!(EXTI0); }; - (EXTI1) => { $action!(EXTI1); }; - (EXTI2) => { $action!(EXTI2); }; - (EXTI3) => { $action!(EXTI3); }; - (EXTI4) => { $action!(EXTI4); }; - (EXTI5) => { $action!(EXTI5); }; - (EXTI6) => { $action!(EXTI6); }; - (EXTI7) => { $action!(EXTI7); }; - (EXTI8) => { $action!(EXTI8); }; - (EXTI9) => { $action!(EXTI9); }; - (EXTI10) => { $action!(EXTI10); }; - (EXTI11) => { $action!(EXTI11); }; - (EXTI12) => { $action!(EXTI12); }; - (EXTI13) => { $action!(EXTI13); }; - (EXTI14) => { $action!(EXTI14); }; - (EXTI15) => { $action!(EXTI15); }; - - // plus the weird ones - (EXTI0_1) => { $action!( EXTI0_1 ); }; - (EXTI15_10) => { $action!(EXTI15_10); }; - (EXTI15_4) => { $action!(EXTI15_4); }; - (EXTI1_0) => { $action!(EXTI1_0); }; - (EXTI2_3) => { $action!(EXTI2_3); }; - (EXTI2_TSC) => { $action!(EXTI2_TSC); }; - (EXTI3_2) => { $action!(EXTI3_2); }; - (EXTI4_15) => { $action!(EXTI4_15); }; - (EXTI9_5) => { $action!(EXTI9_5); }; - ); - }; -} - -#[cfg_attr(exti_v1, path = "v1.rs")] -#[cfg_attr(exti_h7, path = "v1.rs")] -#[cfg_attr(exti_wb55, path = "v2.rs")] -#[cfg_attr(exti_wl5x, path = "v2.rs")] -mod _version; - -#[allow(unused)] -pub use _version::*; - -use crate::peripherals; -use embassy_hal_common::unsafe_impl_unborrow; - -pub(crate) mod sealed { - pub trait Channel {} -} - -pub trait Channel: sealed::Channel + Sized { - fn number(&self) -> usize; - fn degrade(self) -> AnyChannel { - AnyChannel { - number: self.number() as u8, - } - } -} - -pub struct AnyChannel { - number: u8, -} -unsafe_impl_unborrow!(AnyChannel); -impl sealed::Channel for AnyChannel {} -impl Channel for AnyChannel { - fn number(&self) -> usize { - self.number as usize - } -} - -macro_rules! impl_exti { - ($type:ident, $number:expr) => { - impl sealed::Channel for peripherals::$type {} - impl Channel for peripherals::$type { - fn number(&self) -> usize { - $number as usize - } - } - }; -} - -impl_exti!(EXTI0, 0); -impl_exti!(EXTI1, 1); -impl_exti!(EXTI2, 2); -impl_exti!(EXTI3, 3); -impl_exti!(EXTI4, 4); -impl_exti!(EXTI5, 5); -impl_exti!(EXTI6, 6); -impl_exti!(EXTI7, 7); -impl_exti!(EXTI8, 8); -impl_exti!(EXTI9, 9); -impl_exti!(EXTI10, 10); -impl_exti!(EXTI11, 11); -impl_exti!(EXTI12, 12); -impl_exti!(EXTI13, 13); -impl_exti!(EXTI14, 14); -impl_exti!(EXTI15, 15); - -macro_rules! enable_irq { - ($e:ident) => { - crate::interrupt::$e::steal().enable(); - }; -} - -/// safety: must be called only once -pub(crate) unsafe fn init() { - use embassy::interrupt::Interrupt; - use embassy::interrupt::InterruptExt; - - foreach_exti_irq!(enable_irq); - - #[cfg(not(any(rcc_wb55, rcc_wl5x)))] - ::enable(); -} diff --git a/embassy-stm32/src/exti/v1.rs b/embassy-stm32/src/exti/v1.rs deleted file mode 100644 index caf45760..00000000 --- a/embassy-stm32/src/exti/v1.rs +++ /dev/null @@ -1,171 +0,0 @@ -use core::convert::Infallible; -use core::future::Future; -use core::marker::PhantomData; -use core::pin::Pin; -use core::task::{Context, Poll}; -use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; -use embassy::util::{AtomicWaker, Unborrow}; -use embedded_hal::digital::v2::InputPin; -use pac::exti::{regs, vals}; - -use crate::gpio::{AnyPin, Input, Pin as GpioPin}; -use crate::pac; -use crate::pac::{EXTI, SYSCFG}; - -const EXTI_COUNT: usize = 16; -const NEW_AW: AtomicWaker = AtomicWaker::new(); -static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT]; - -pub unsafe fn on_irq() { - let bits = EXTI.pr().read().0; - - // Mask all the channels that fired. - EXTI.imr().modify(|w| w.0 &= !bits); - - // Wake the tasks - for pin in BitIter(bits) { - EXTI_WAKERS[pin as usize].wake(); - } - - // Clear pending - EXTI.pr().write_value(regs::Pr(bits)); -} - -struct BitIter(u32); - -impl Iterator for BitIter { - type Item = u32; - - fn next(&mut self) -> Option { - match self.0.trailing_zeros() { - 32 => None, - b => { - self.0 &= !(1 << b); - Some(b) - } - } - } -} - -/// EXTI input driver -pub struct ExtiInput<'d, T: GpioPin> { - pin: Input<'d, T>, -} - -impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} - -impl<'d, T: GpioPin> ExtiInput<'d, T> { - pub fn new(pin: Input<'d, T>, _ch: impl Unborrow + 'd) -> Self { - Self { pin } - } -} - -impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - self.pin.is_high() - } - - fn is_low(&self) -> Result { - self.pin.is_low() - } -} - -impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Tr::ENABLED, - vals::Tr::DISABLED, - ) - } -} - -impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Tr::DISABLED, - vals::Tr::ENABLED, - ) - } -} - -impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Tr::ENABLED, - vals::Tr::ENABLED, - ) - } -} - -pub struct ExtiInputFuture<'a> { - pin: u8, - phantom: PhantomData<&'a mut AnyPin>, -} - -impl<'a> ExtiInputFuture<'a> { - fn new(pin: u8, port: u8, rising: vals::Tr, falling: vals::Tr) -> Self { - cortex_m::interrupt::free(|_| unsafe { - let pin = pin as usize; - SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); - EXTI.rtsr().modify(|w| w.set_tr(pin, rising)); - EXTI.ftsr().modify(|w| w.set_tr(pin, falling)); - EXTI.pr().write(|w| w.set_pr(pin, true)); // clear pending bit - EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::UNMASKED)); - }); - - Self { - pin, - phantom: PhantomData, - } - } -} - -impl<'a> Drop for ExtiInputFuture<'a> { - fn drop(&mut self) { - cortex_m::interrupt::free(|_| unsafe { - let pin = self.pin as _; - EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::MASKED)); - }); - } -} - -impl<'a> Future for ExtiInputFuture<'a> { - type Output = (); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - EXTI_WAKERS[self.pin as usize].register(cx.waker()); - - if unsafe { EXTI.imr().read().mr(self.pin as _) == vals::Mr::MASKED } { - Poll::Ready(()) - } else { - Poll::Pending - } - } -} - -use crate::interrupt; - -macro_rules! impl_irq { - ($e:ident) => { - #[interrupt] - unsafe fn $e() { - on_irq() - } - }; -} - -foreach_exti_irq!(impl_irq); diff --git a/embassy-stm32/src/exti/v2.rs b/embassy-stm32/src/exti/v2.rs deleted file mode 100644 index 2e62331f..00000000 --- a/embassy-stm32/src/exti/v2.rs +++ /dev/null @@ -1,184 +0,0 @@ -use core::convert::Infallible; -use core::future::Future; -use core::marker::PhantomData; -use core::pin::Pin; -use core::task::{Context, Poll}; -use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; -use embassy::util::{AtomicWaker, Unborrow}; -use embedded_hal::digital::v2::InputPin; -use pac::exti::{regs, vals}; - -use crate::gpio::{AnyPin, Input, Pin as GpioPin}; -use crate::pac; -use crate::pac::CORE_INDEX; -use crate::pac::{EXTI, SYSCFG}; - -const EXTI_COUNT: usize = 16; -const NEW_AW: AtomicWaker = AtomicWaker::new(); -static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT]; - -pub unsafe fn on_irq() { - let bits = EXTI.pr(0).read().0; - - // Mask all the channels that fired. - EXTI.cpu(CORE_INDEX) - .imr(CORE_INDEX) - .modify(|w| w.0 &= !bits); - - // Wake the tasks - for pin in BitIter(bits) { - EXTI_WAKERS[pin as usize].wake(); - } - - // Clear pending - EXTI.pr(0).write_value(regs::Pr(bits)); -} - -struct BitIter(u32); - -impl Iterator for BitIter { - type Item = u32; - - fn next(&mut self) -> Option { - match self.0.trailing_zeros() { - 32 => None, - b => { - self.0 &= !(1 << b); - Some(b) - } - } - } -} - -/// EXTI input driver -pub struct ExtiInput<'d, T: GpioPin> { - pin: Input<'d, T>, -} - -impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} - -impl<'d, T: GpioPin> ExtiInput<'d, T> { - pub fn new(pin: Input<'d, T>, _ch: impl Unborrow + 'd) -> Self { - Self { pin } - } -} - -impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> { - type Error = Infallible; - - fn is_high(&self) -> Result { - self.pin.is_high() - } - - fn is_low(&self) -> Result { - self.pin.is_low() - } -} - -impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Rt::ENABLED, - vals::Ft::DISABLED, - ) - } -} - -impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Rt::DISABLED, - vals::Ft::ENABLED, - ) - } -} - -impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> { - type Future<'a> = ExtiInputFuture<'a>; - - fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { - ExtiInputFuture::new( - self.pin.pin.pin(), - self.pin.pin.port(), - vals::Rt::ENABLED, - vals::Ft::ENABLED, - ) - } -} - -pub struct ExtiInputFuture<'a> { - pin: u8, - phantom: PhantomData<&'a mut AnyPin>, -} - -impl<'a> ExtiInputFuture<'a> { - fn new(pin: u8, port: u8, rising: vals::Rt, falling: vals::Ft) -> Self { - cortex_m::interrupt::free(|_| unsafe { - let pin = pin as usize; - SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); - EXTI.rtsr(CORE_INDEX).modify(|w| w.set_rt(pin, rising)); - EXTI.ftsr(CORE_INDEX).modify(|w| w.set_ft(pin, falling)); - EXTI.pr(CORE_INDEX).write(|w| w.set_pif(pin, true)); // clear pending bit - EXTI.cpu(CORE_INDEX) - .imr(CORE_INDEX) - .modify(|w| w.set_im(pin, vals::Mr::UNMASKED)); - }); - - Self { - pin, - phantom: PhantomData, - } - } -} - -impl<'a> Drop for ExtiInputFuture<'a> { - fn drop(&mut self) { - cortex_m::interrupt::free(|_| unsafe { - let pin = self.pin as _; - EXTI.cpu(CORE_INDEX) - .imr(CORE_INDEX) - .modify(|w| w.set_im(pin, vals::Mr::MASKED)); - }); - } -} - -impl<'a> Future for ExtiInputFuture<'a> { - type Output = (); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - EXTI_WAKERS[self.pin as usize].register(cx.waker()); - - if unsafe { - EXTI.cpu(CORE_INDEX) - .imr(CORE_INDEX) - .read() - .im(self.pin as _) - == vals::Mr::MASKED - } { - Poll::Ready(()) - } else { - Poll::Pending - } - } -} - -use crate::interrupt; - -macro_rules! impl_irq { - ($e:ident) => { - #[interrupt] - unsafe fn $e() { - on_irq() - } - }; -} - -foreach_exti_irq!(impl_irq); diff --git a/examples/stm32wb55/src/bin/button_exti.rs b/examples/stm32wb55/src/bin/button_exti.rs new file mode 100644 index 00000000..92a310c7 --- /dev/null +++ b/examples/stm32wb55/src/bin/button_exti.rs @@ -0,0 +1,36 @@ +#![no_std] +#![no_main] +#![feature(trait_alias)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +#[path = "../example_common.rs"] +mod example_common; +use embassy::executor::Spawner; +use embassy_stm32::dbgmcu::Dbgmcu; +use embassy_stm32::exti::ExtiInput; +use embassy_stm32::gpio::{Input, Pull}; +use embassy_stm32::Peripherals; +use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge}; +use example_common::*; + +#[embassy::main] +async fn main(_spawner: Spawner, p: Peripherals) { + info!("Hello World!"); + + unsafe { + Dbgmcu::enable_all(); + } + + let button = Input::new(p.PC4, Pull::Up); + let mut button = ExtiInput::new(button, p.EXTI4); + + info!("Press the USER button..."); + + loop { + button.wait_for_falling_edge().await; + info!("Pressed!"); + button.wait_for_rising_edge().await; + info!("Released!"); + } +}