diff options
| -rw-r--r-- | embassy-stm32-examples/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-stm32-examples/src/bin/button_exti.rs | 129 | ||||
| -rw-r--r-- | embassy-stm32/src/chip/f429.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/exti.rs | 886 | ||||
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 159 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 3 |
6 files changed, 365 insertions, 821 deletions
diff --git a/embassy-stm32-examples/Cargo.toml b/embassy-stm32-examples/Cargo.toml index af809b838..14ffcc083 100644 --- a/embassy-stm32-examples/Cargo.toml +++ b/embassy-stm32-examples/Cargo.toml | |||
| @@ -38,9 +38,9 @@ f479 = ["embassy-stm32/f469"] | |||
| 38 | [dependencies] | 38 | [dependencies] |
| 39 | embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } | 39 | embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } |
| 40 | embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } | 40 | embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } |
| 41 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } | 41 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["defmt", "defmt-trace"] } |
| 42 | embassy-extras = {version = "0.1.0", path = "../embassy-extras" } | 42 | embassy-extras = {version = "0.1.0", path = "../embassy-extras" } |
| 43 | stm32f4 = { version = "0.13", features = ["stm32f429"] } | 43 | stm32f4 = { version = "0.13", features = ["stm32f429", "rt"] } |
| 44 | 44 | ||
| 45 | defmt = "0.2.0" | 45 | defmt = "0.2.0" |
| 46 | defmt-rtt = "0.2.0" | 46 | defmt-rtt = "0.2.0" |
diff --git a/embassy-stm32-examples/src/bin/button_exti.rs b/embassy-stm32-examples/src/bin/button_exti.rs new file mode 100644 index 000000000..8f6799604 --- /dev/null +++ b/embassy-stm32-examples/src/bin/button_exti.rs | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(trait_alias)] | ||
| 4 | #![feature(min_type_alias_impl_trait)] | ||
| 5 | #![feature(impl_trait_in_bindings)] | ||
| 6 | #![feature(type_alias_impl_trait)] | ||
| 7 | |||
| 8 | #[path = "../example_common.rs"] | ||
| 9 | mod example_common; | ||
| 10 | use embassy::executor::Executor; | ||
| 11 | use embassy::time::Clock; | ||
| 12 | use embassy::util::Forever; | ||
| 13 | use embassy_stm32::exti::{self, ExtiInput}; | ||
| 14 | use embassy_stm32::gpio::{Input, Pull}; | ||
| 15 | use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge}; | ||
| 16 | use example_common::*; | ||
| 17 | |||
| 18 | use cortex_m_rt::entry; | ||
| 19 | use pac::{interrupt, NVIC}; | ||
| 20 | use stm32f4::stm32f429 as pac; | ||
| 21 | |||
| 22 | #[embassy::task] | ||
| 23 | async fn main_task() { | ||
| 24 | let p = embassy_stm32::Peripherals::take().unwrap(); | ||
| 25 | let button = Input::new(p.PC13, Pull::Down); | ||
| 26 | let mut button = ExtiInput::new(button, p.EXTI13); | ||
| 27 | |||
| 28 | info!("Press the USER button..."); | ||
| 29 | |||
| 30 | loop { | ||
| 31 | button.wait_for_rising_edge().await; | ||
| 32 | info!("Pressed!"); | ||
| 33 | button.wait_for_falling_edge().await; | ||
| 34 | info!("Released!"); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | struct ZeroClock; | ||
| 39 | |||
| 40 | impl Clock for ZeroClock { | ||
| 41 | fn now(&self) -> u64 { | ||
| 42 | 0 | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | static EXECUTOR: Forever<Executor> = Forever::new(); | ||
| 47 | |||
| 48 | #[entry] | ||
| 49 | fn main() -> ! { | ||
| 50 | info!("Hello World!"); | ||
| 51 | |||
| 52 | let pp = pac::Peripherals::take().unwrap(); | ||
| 53 | |||
| 54 | pp.DBGMCU.cr.modify(|_, w| { | ||
| 55 | w.dbg_sleep().set_bit(); | ||
| 56 | w.dbg_standby().set_bit(); | ||
| 57 | w.dbg_stop().set_bit() | ||
| 58 | }); | ||
| 59 | pp.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled()); | ||
| 60 | |||
| 61 | pp.RCC.ahb1enr.modify(|_, w| { | ||
| 62 | w.gpioaen().enabled(); | ||
| 63 | w.gpioben().enabled(); | ||
| 64 | w.gpiocen().enabled(); | ||
| 65 | w.gpioden().enabled(); | ||
| 66 | w.gpioeen().enabled(); | ||
| 67 | w.gpiofen().enabled(); | ||
| 68 | w | ||
| 69 | }); | ||
| 70 | pp.RCC.apb2enr.modify(|_, w| { | ||
| 71 | w.syscfgen().enabled(); | ||
| 72 | w | ||
| 73 | }); | ||
| 74 | |||
| 75 | unsafe { embassy::time::set_clock(&ZeroClock) }; | ||
| 76 | |||
| 77 | unsafe { | ||
| 78 | NVIC::unmask(interrupt::EXTI0); | ||
| 79 | NVIC::unmask(interrupt::EXTI1); | ||
| 80 | NVIC::unmask(interrupt::EXTI2); | ||
| 81 | NVIC::unmask(interrupt::EXTI3); | ||
| 82 | NVIC::unmask(interrupt::EXTI4); | ||
| 83 | NVIC::unmask(interrupt::EXTI9_5); | ||
| 84 | NVIC::unmask(interrupt::EXTI15_10); | ||
| 85 | } | ||
| 86 | |||
| 87 | let executor = EXECUTOR.put(Executor::new()); | ||
| 88 | |||
| 89 | executor.run(|spawner| { | ||
| 90 | unwrap!(spawner.spawn(main_task())); | ||
| 91 | }) | ||
| 92 | } | ||
| 93 | |||
| 94 | // TODO for now irq handling is done by user code using the old pac, until we figure out how interrupts work in the metapac | ||
| 95 | |||
| 96 | #[interrupt] | ||
| 97 | unsafe fn EXTI0() { | ||
| 98 | exti::on_irq() | ||
| 99 | } | ||
| 100 | |||
| 101 | #[interrupt] | ||
| 102 | unsafe fn EXTI1() { | ||
| 103 | exti::on_irq() | ||
| 104 | } | ||
| 105 | |||
| 106 | #[interrupt] | ||
| 107 | unsafe fn EXTI2() { | ||
| 108 | exti::on_irq() | ||
| 109 | } | ||
| 110 | |||
| 111 | #[interrupt] | ||
| 112 | unsafe fn EXTI3() { | ||
| 113 | exti::on_irq() | ||
| 114 | } | ||
| 115 | |||
| 116 | #[interrupt] | ||
| 117 | unsafe fn EXTI4() { | ||
| 118 | exti::on_irq() | ||
| 119 | } | ||
| 120 | |||
| 121 | #[interrupt] | ||
| 122 | unsafe fn EXTI9_5() { | ||
| 123 | exti::on_irq() | ||
| 124 | } | ||
| 125 | |||
| 126 | #[interrupt] | ||
| 127 | unsafe fn EXTI15_10() { | ||
| 128 | exti::on_irq() | ||
| 129 | } | ||
diff --git a/embassy-stm32/src/chip/f429.rs b/embassy-stm32/src/chip/f429.rs index 26956e01f..db68faa5a 100644 --- a/embassy-stm32/src/chip/f429.rs +++ b/embassy-stm32/src/chip/f429.rs | |||
| @@ -7,4 +7,9 @@ peripherals!( | |||
| 7 | PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, | 7 | PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, |
| 8 | // GPIO Port C | 8 | // GPIO Port C |
| 9 | PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15, | 9 | PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15, |
| 10 | // todo more ports | ||
| 11 | |||
| 12 | // EXTI | ||
| 13 | EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5, EXTI6, EXTI7, EXTI8, EXTI9, EXTI10, EXTI11, EXTI12, | ||
| 14 | EXTI13, EXTI14, EXTI15, | ||
| 10 | ); | 15 | ); |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 9a12f8115..d1b5eabbf 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -1,89 +1,75 @@ | |||
| 1 | use core::convert::Infallible; | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::mem; | 3 | use core::marker::PhantomData; |
| 3 | use cortex_m; | 4 | use core::pin::Pin; |
| 4 | 5 | use core::task::{Context, Poll}; | |
| 5 | use crate::hal::gpio; | 6 | use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge}; |
| 6 | 7 | use embassy::util::{AtomicWaker, Unborrow}; | |
| 7 | #[cfg(any( | 8 | use embassy_extras::impl_unborrow; |
| 8 | feature = "stm32f401", | 9 | use embedded_hal::digital::v2::InputPin; |
| 9 | feature = "stm32f405", | 10 | use futures::future::Select; |
| 10 | feature = "stm32f407", | 11 | use pac::exti::{regs, vals}; |
| 11 | feature = "stm32f410", | 12 | |
| 12 | feature = "stm32f411", | 13 | use crate::fmt::*; |
| 13 | feature = "stm32f412", | 14 | use crate::gpio::{AnyPin, Input, Pin as GpioPin}; |
| 14 | feature = "stm32f413", | 15 | use crate::pac; |
| 15 | feature = "stm32f415", | 16 | use crate::peripherals; |
| 16 | feature = "stm32f417", | 17 | |
| 17 | feature = "stm32f423", | 18 | // TODO hardcoding peripheral addrs until we figure out how these are handled in the metapac |
| 18 | feature = "stm32f427", | 19 | const SYSCFG: pac::syscfg_f4::Syscfg = pac::syscfg_f4::Syscfg(0x40013800 as *mut _); |
| 19 | feature = "stm32f429", | 20 | const EXTI: pac::exti::Exti = pac::exti::Exti(0x40013c00 as *mut _); |
| 20 | feature = "stm32f437", | 21 | |
| 21 | feature = "stm32f439", | 22 | const EXTI_COUNT: usize = 16; |
| 22 | feature = "stm32f446", | 23 | const NEW_AW: AtomicWaker = AtomicWaker::new(); |
| 23 | feature = "stm32f469", | 24 | static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT]; |
| 24 | feature = "stm32f479", | 25 | |
| 25 | ))] | 26 | // TODO for now delegate irq handling to user code until we figure out how interrupts work in the metapac |
| 26 | use crate::hal::syscfg::SysCfg; | 27 | pub unsafe fn on_irq() { |
| 27 | 28 | let bits = EXTI.pr().read().0; | |
| 28 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | 29 | |
| 29 | use crate::hal::syscfg::SYSCFG as SysCfg; | 30 | // Mask all the channels that fired. |
| 30 | 31 | EXTI.imr().modify(|w| w.0 &= !bits); | |
| 31 | use embassy::traits::gpio::{ | 32 | |
| 32 | WaitForAnyEdge, WaitForFallingEdge, WaitForHigh, WaitForLow, WaitForRisingEdge, | 33 | // Wake the tasks |
| 33 | }; | 34 | for pin in BitIter(bits) { |
| 34 | use embassy::util::InterruptFuture; | 35 | EXTI_WAKERS[pin as usize].wake(); |
| 35 | |||
| 36 | use embedded_hal::digital::v2 as digital; | ||
| 37 | |||
| 38 | use crate::interrupt; | ||
| 39 | |||
| 40 | pub struct ExtiPin<T: Instance> { | ||
| 41 | pin: T, | ||
| 42 | interrupt: T::Interrupt, | ||
| 43 | } | ||
| 44 | |||
| 45 | impl<T: Instance> ExtiPin<T> { | ||
| 46 | pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self { | ||
| 47 | cortex_m::interrupt::free(|_| { | ||
| 48 | pin.make_source(syscfg); | ||
| 49 | }); | ||
| 50 | |||
| 51 | Self { pin, interrupt } | ||
| 52 | } | 36 | } |
| 37 | |||
| 38 | // Clear pending | ||
| 39 | EXTI.pr().write_value(regs::Pr(bits)); | ||
| 53 | } | 40 | } |
| 54 | 41 | ||
| 55 | impl<T: Instance + digital::OutputPin> digital::OutputPin for ExtiPin<T> { | 42 | struct BitIter(u32); |
| 56 | type Error = T::Error; | ||
| 57 | 43 | ||
| 58 | fn set_low(&mut self) -> Result<(), Self::Error> { | 44 | impl Iterator for BitIter { |
| 59 | self.pin.set_low() | 45 | type Item = u32; |
| 60 | } | ||
| 61 | 46 | ||
| 62 | fn set_high(&mut self) -> Result<(), Self::Error> { | 47 | fn next(&mut self) -> Option<Self::Item> { |
| 63 | self.pin.set_high() | 48 | match self.0.trailing_zeros() { |
| 49 | 32 => None, | ||
| 50 | b => { | ||
| 51 | self.0 &= !(1 << b); | ||
| 52 | Some(b) | ||
| 53 | } | ||
| 54 | } | ||
| 64 | } | 55 | } |
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | impl<T: Instance + digital::StatefulOutputPin> digital::StatefulOutputPin for ExtiPin<T> { | 58 | /// EXTI input driver |
| 68 | fn is_set_low(&self) -> Result<bool, Self::Error> { | 59 | pub struct ExtiInput<'d, T: GpioPin> { |
| 69 | self.pin.is_set_low() | 60 | pin: Input<'d, T>, |
| 70 | } | ||
| 71 | |||
| 72 | fn is_set_high(&self) -> Result<bool, Self::Error> { | ||
| 73 | self.pin.is_set_high() | ||
| 74 | } | ||
| 75 | } | 61 | } |
| 76 | 62 | ||
| 77 | impl<T: Instance + digital::ToggleableOutputPin> digital::ToggleableOutputPin for ExtiPin<T> { | 63 | impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} |
| 78 | type Error = T::Error; | ||
| 79 | 64 | ||
| 80 | fn toggle(&mut self) -> Result<(), Self::Error> { | 65 | impl<'d, T: GpioPin> ExtiInput<'d, T> { |
| 81 | self.pin.toggle() | 66 | pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self { |
| 67 | Self { pin } | ||
| 82 | } | 68 | } |
| 83 | } | 69 | } |
| 84 | 70 | ||
| 85 | impl<T: Instance + digital::InputPin> digital::InputPin for ExtiPin<T> { | 71 | impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> { |
| 86 | type Error = T::Error; | 72 | type Error = Infallible; |
| 87 | 73 | ||
| 88 | fn is_high(&self) -> Result<bool, Self::Error> { | 74 | fn is_high(&self) -> Result<bool, Self::Error> { |
| 89 | self.pin.is_high() | 75 | self.pin.is_high() |
| @@ -94,697 +80,139 @@ impl<T: Instance + digital::InputPin> digital::InputPin for ExtiPin<T> { | |||
| 94 | } | 80 | } |
| 95 | } | 81 | } |
| 96 | 82 | ||
| 97 | impl<T: Instance + digital::InputPin + 'static> ExtiPin<T> { | 83 | impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> { |
| 98 | fn wait_for_state<'a>(&'a mut self, state: bool) -> impl Future<Output = ()> + 'a { | 84 | type Future<'a> = ExtiInputFuture<'a>; |
| 99 | async move { | ||
| 100 | let fut = InterruptFuture::new(&mut self.interrupt); | ||
| 101 | let pin = &mut self.pin; | ||
| 102 | cortex_m::interrupt::free(|_| { | ||
| 103 | pin.trigger_edge(if state { | ||
| 104 | EdgeOption::Rising | ||
| 105 | } else { | ||
| 106 | EdgeOption::Falling | ||
| 107 | }); | ||
| 108 | }); | ||
| 109 | |||
| 110 | if (state && self.pin.is_high().unwrap_or(false)) | ||
| 111 | || (!state && self.pin.is_low().unwrap_or(false)) | ||
| 112 | { | ||
| 113 | return; | ||
| 114 | } | ||
| 115 | |||
| 116 | fut.await; | ||
| 117 | 85 | ||
| 118 | self.pin.clear_pending_bit(); | 86 | fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { |
| 119 | } | 87 | ExtiInputFuture::new( |
| 88 | self.pin.pin.pin(), | ||
| 89 | self.pin.pin.port(), | ||
| 90 | vals::Tr::ENABLED, | ||
| 91 | vals::Tr::DISABLED, | ||
| 92 | ) | ||
| 120 | } | 93 | } |
| 121 | } | 94 | } |
| 122 | 95 | ||
| 123 | impl<T: Instance + 'static> ExtiPin<T> { | 96 | impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> { |
| 124 | fn wait_for_edge<'a>(&'a mut self, state: EdgeOption) -> impl Future<Output = ()> + 'a { | 97 | type Future<'a> = ExtiInputFuture<'a>; |
| 125 | self.pin.clear_pending_bit(); | ||
| 126 | async move { | ||
| 127 | let fut = InterruptFuture::new(&mut self.interrupt); | ||
| 128 | let pin = &mut self.pin; | ||
| 129 | cortex_m::interrupt::free(|_| { | ||
| 130 | pin.trigger_edge(state); | ||
| 131 | }); | ||
| 132 | 98 | ||
| 133 | fut.await; | 99 | fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { |
| 134 | 100 | ExtiInputFuture::new( | |
| 135 | self.pin.clear_pending_bit(); | 101 | self.pin.pin.pin(), |
| 136 | } | 102 | self.pin.pin.port(), |
| 103 | vals::Tr::DISABLED, | ||
| 104 | vals::Tr::ENABLED, | ||
| 105 | ) | ||
| 137 | } | 106 | } |
| 138 | } | 107 | } |
| 139 | 108 | ||
| 140 | impl<T: Instance + digital::InputPin + 'static> WaitForHigh for ExtiPin<T> { | 109 | impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> { |
| 141 | type Future<'a> = impl Future<Output = ()> + 'a; | 110 | type Future<'a> = ExtiInputFuture<'a>; |
| 142 | 111 | ||
| 143 | fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { | 112 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { |
| 144 | self.wait_for_state(true) | 113 | ExtiInputFuture::new( |
| 114 | self.pin.pin.pin(), | ||
| 115 | self.pin.pin.port(), | ||
| 116 | vals::Tr::ENABLED, | ||
| 117 | vals::Tr::ENABLED, | ||
| 118 | ) | ||
| 145 | } | 119 | } |
| 146 | } | 120 | } |
| 147 | 121 | ||
| 148 | impl<T: Instance + digital::InputPin + 'static> WaitForLow for ExtiPin<T> { | 122 | pub struct ExtiInputFuture<'a> { |
| 149 | type Future<'a> = impl Future<Output = ()> + 'a; | 123 | pin: u8, |
| 150 | 124 | phantom: PhantomData<&'a mut AnyPin>, | |
| 151 | fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { | ||
| 152 | self.wait_for_state(false) | ||
| 153 | } | ||
| 154 | } | 125 | } |
| 155 | 126 | ||
| 156 | /* | 127 | impl<'a> ExtiInputFuture<'a> { |
| 157 | Irq Handler Description | 128 | fn new(pin: u8, port: u8, rising: vals::Tr, falling: vals::Tr) -> Self { |
| 158 | EXTI0_IRQn EXTI0_IRQHandler Handler for pins connected to line 0 | 129 | cortex_m::interrupt::free(|_| unsafe { |
| 159 | EXTI1_IRQn EXTI1_IRQHandler Handler for pins connected to line 1 | 130 | let pin = pin as usize; |
| 160 | EXTI2_IRQn EXTI2_IRQHandler Handler for pins connected to line 2 | 131 | SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); |
| 161 | EXTI3_IRQn EXTI3_IRQHandler Handler for pins connected to line 3 | 132 | EXTI.rtsr().modify(|w| w.set_tr(pin, rising)); |
| 162 | EXTI4_IRQn EXTI4_IRQHandler Handler for pins connected to line 4 | 133 | EXTI.ftsr().modify(|w| w.set_tr(pin, falling)); |
| 163 | EXTI9_5_IRQn EXTI9_5_IRQHandler Handler for pins connected to line 5 to 9 | 134 | EXTI.pr().write(|w| w.set_pr(pin, true)); // clear pending bit |
| 164 | EXTI15_10_IRQn EXTI15_10_IRQHandler Handler for pins connected to line 10 to 15 | 135 | EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::UNMASKED)); |
| 165 | */ | 136 | }); |
| 166 | |||
| 167 | impl<T: Instance + 'static> WaitForRisingEdge for ExtiPin<T> { | ||
| 168 | type Future<'a> = impl Future<Output = ()> + 'a; | ||
| 169 | 137 | ||
| 170 | fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { | 138 | Self { |
| 171 | self.wait_for_edge(EdgeOption::Rising) | 139 | pin, |
| 140 | phantom: PhantomData, | ||
| 141 | } | ||
| 172 | } | 142 | } |
| 173 | } | 143 | } |
| 174 | 144 | ||
| 175 | impl<T: Instance + 'static> WaitForFallingEdge for ExtiPin<T> { | 145 | impl<'a> Drop for ExtiInputFuture<'a> { |
| 176 | type Future<'a> = impl Future<Output = ()> + 'a; | 146 | fn drop(&mut self) { |
| 177 | 147 | cortex_m::interrupt::free(|_| unsafe { | |
| 178 | fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { | 148 | let pin = self.pin as _; |
| 179 | self.wait_for_edge(EdgeOption::Falling) | 149 | EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::MASKED)); |
| 150 | }); | ||
| 180 | } | 151 | } |
| 181 | } | 152 | } |
| 182 | 153 | ||
| 183 | impl<T: Instance + 'static> WaitForAnyEdge for ExtiPin<T> { | 154 | impl<'a> Future for ExtiInputFuture<'a> { |
| 184 | type Future<'a> = impl Future<Output = ()> + 'a; | 155 | type Output = (); |
| 185 | 156 | ||
| 186 | fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { | 157 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 187 | self.wait_for_edge(EdgeOption::RisingFalling) | 158 | EXTI_WAKERS[self.pin as usize].register(cx.waker()); |
| 159 | |||
| 160 | if unsafe { EXTI.imr().read().mr(self.pin as _) == vals::Mr::MASKED } { | ||
| 161 | Poll::Ready(()) | ||
| 162 | } else { | ||
| 163 | Poll::Pending | ||
| 164 | } | ||
| 188 | } | 165 | } |
| 189 | } | 166 | } |
| 190 | 167 | ||
| 191 | mod private { | 168 | pub(crate) mod sealed { |
| 192 | pub trait Sealed {} | 169 | pub trait Channel {} |
| 193 | } | 170 | } |
| 194 | 171 | ||
| 195 | #[derive(Copy, Clone)] | 172 | pub trait Channel: sealed::Channel + Sized { |
| 196 | pub enum EdgeOption { | 173 | fn number(&self) -> usize; |
| 197 | Rising, | 174 | fn degrade(self) -> AnyChannel { |
| 198 | Falling, | 175 | AnyChannel { |
| 199 | RisingFalling, | 176 | number: self.number() as u8, |
| 177 | } | ||
| 178 | } | ||
| 200 | } | 179 | } |
| 201 | 180 | ||
| 202 | pub trait WithInterrupt: private::Sealed { | 181 | pub struct AnyChannel { |
| 203 | type Interrupt: interrupt::Interrupt; | 182 | number: u8, |
| 204 | } | 183 | } |
| 205 | 184 | impl_unborrow!(AnyChannel); | |
| 206 | pub trait Instance: WithInterrupt { | 185 | impl sealed::Channel for AnyChannel {} |
| 207 | fn make_source(&mut self, syscfg: &mut SysCfg); | 186 | impl Channel for AnyChannel { |
| 208 | fn clear_pending_bit(&mut self); | 187 | fn number(&self) -> usize { |
| 209 | fn trigger_edge(&mut self, edge: EdgeOption); | 188 | self.number as usize |
| 189 | } | ||
| 210 | } | 190 | } |
| 211 | 191 | ||
| 212 | macro_rules! exti { | 192 | macro_rules! impl_exti { |
| 213 | ($set:ident, [ | 193 | ($type:ident, $number:expr) => { |
| 214 | $($INT:ident => $pin:ident,)+ | 194 | impl sealed::Channel for peripherals::$type {} |
| 215 | ]) => { | 195 | impl Channel for peripherals::$type { |
| 216 | $( | 196 | fn number(&self) -> usize { |
| 217 | impl<T> private::Sealed for gpio::$set::$pin<T> {} | 197 | $number as usize |
| 218 | impl<T> WithInterrupt for gpio::$set::$pin<T> { | ||
| 219 | type Interrupt = interrupt::$INT; | ||
| 220 | } | 198 | } |
| 221 | 199 | } | |
| 222 | #[cfg(any( | ||
| 223 | feature = "stm32f401", | ||
| 224 | feature = "stm32f405", | ||
| 225 | feature = "stm32f407", | ||
| 226 | feature = "stm32f410", | ||
| 227 | feature = "stm32f411", | ||
| 228 | feature = "stm32f412", | ||
| 229 | feature = "stm32f413", | ||
| 230 | feature = "stm32f415", | ||
| 231 | feature = "stm32f417", | ||
| 232 | feature = "stm32f423", | ||
| 233 | feature = "stm32f427", | ||
| 234 | feature = "stm32f429", | ||
| 235 | feature = "stm32f437", | ||
| 236 | feature = "stm32f439", | ||
| 237 | feature = "stm32f446", | ||
| 238 | feature = "stm32f469", | ||
| 239 | feature = "stm32f479", | ||
| 240 | ))] | ||
| 241 | impl<T> Instance for gpio::$set::$pin<gpio::Input<T>> { | ||
| 242 | fn make_source(&mut self, syscfg: &mut SysCfg) { | ||
| 243 | use crate::hal::gpio::ExtiPin; | ||
| 244 | self.make_interrupt_source(syscfg); | ||
| 245 | } | ||
| 246 | |||
| 247 | fn clear_pending_bit(&mut self) { | ||
| 248 | use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; | ||
| 249 | |||
| 250 | self.clear_interrupt_pending_bit(); | ||
| 251 | } | ||
| 252 | |||
| 253 | fn trigger_edge(&mut self, edge: EdgeOption) { | ||
| 254 | use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; | ||
| 255 | use crate::pac::EXTI; | ||
| 256 | let mut exti: EXTI = unsafe { mem::transmute(()) }; | ||
| 257 | let edge = match edge { | ||
| 258 | EdgeOption::Falling => Edge::FALLING, | ||
| 259 | EdgeOption::Rising => Edge::RISING, | ||
| 260 | EdgeOption::RisingFalling => Edge::RISING_FALLING, | ||
| 261 | }; | ||
| 262 | self.trigger_on_edge(&mut exti, edge); | ||
| 263 | self.enable_interrupt(&mut exti); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 268 | impl<T> Instance for gpio::$set::$pin<T> { | ||
| 269 | fn make_source(&mut self, syscfg: &mut SysCfg) {} | ||
| 270 | |||
| 271 | fn clear_pending_bit(&mut self) { | ||
| 272 | use crate::hal::{ | ||
| 273 | exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, | ||
| 274 | syscfg::SYSCFG, | ||
| 275 | }; | ||
| 276 | |||
| 277 | Exti::unpend(GpioLine::from_raw_line(self.pin_number()).unwrap()); | ||
| 278 | } | ||
| 279 | |||
| 280 | fn trigger_edge(&mut self, edge: EdgeOption) { | ||
| 281 | use crate::hal::{ | ||
| 282 | exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, | ||
| 283 | syscfg::SYSCFG, | ||
| 284 | }; | ||
| 285 | |||
| 286 | use crate::pac::EXTI; | ||
| 287 | |||
| 288 | let edge = match edge { | ||
| 289 | EdgeOption::Falling => TriggerEdge::Falling, | ||
| 290 | EdgeOption::Rising => TriggerEdge::Rising, | ||
| 291 | EdgeOption::RisingFalling => TriggerEdge::Both, | ||
| 292 | }; | ||
| 293 | |||
| 294 | let exti: EXTI = unsafe { mem::transmute(()) }; | ||
| 295 | let mut exti = Exti::new(exti); | ||
| 296 | let port = self.port(); | ||
| 297 | let mut syscfg: SYSCFG = unsafe { mem::transmute(()) }; | ||
| 298 | let line = GpioLine::from_raw_line(self.pin_number()).unwrap(); | ||
| 299 | exti.listen_gpio(&mut syscfg, port, line, edge); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | )+ | ||
| 303 | }; | 200 | }; |
| 304 | } | 201 | } |
| 305 | 202 | ||
| 306 | #[cfg(any( | 203 | impl_exti!(EXTI0, 0); |
| 307 | feature = "stm32f401", | 204 | impl_exti!(EXTI1, 1); |
| 308 | feature = "stm32f405", | 205 | impl_exti!(EXTI2, 2); |
| 309 | feature = "stm32f407", | 206 | impl_exti!(EXTI3, 3); |
| 310 | feature = "stm32f410", | 207 | impl_exti!(EXTI4, 4); |
| 311 | feature = "stm32f411", | 208 | impl_exti!(EXTI5, 5); |
| 312 | feature = "stm32f412", | 209 | impl_exti!(EXTI6, 6); |
| 313 | feature = "stm32f413", | 210 | impl_exti!(EXTI7, 7); |
| 314 | feature = "stm32f415", | 211 | impl_exti!(EXTI8, 8); |
| 315 | feature = "stm32f417", | 212 | impl_exti!(EXTI9, 9); |
| 316 | feature = "stm32f423", | 213 | impl_exti!(EXTI10, 10); |
| 317 | feature = "stm32f427", | 214 | impl_exti!(EXTI11, 11); |
| 318 | feature = "stm32f429", | 215 | impl_exti!(EXTI12, 12); |
| 319 | feature = "stm32f437", | 216 | impl_exti!(EXTI13, 13); |
| 320 | feature = "stm32f439", | 217 | impl_exti!(EXTI14, 14); |
| 321 | feature = "stm32f446", | 218 | impl_exti!(EXTI15, 15); |
| 322 | feature = "stm32f469", | ||
| 323 | feature = "stm32f479" | ||
| 324 | ))] | ||
| 325 | exti!(gpioa, [ | ||
| 326 | EXTI0 => PA0, | ||
| 327 | EXTI1 => PA1, | ||
| 328 | EXTI2 => PA2, | ||
| 329 | EXTI3 => PA3, | ||
| 330 | EXTI4 => PA4, | ||
| 331 | EXTI9_5 => PA5, | ||
| 332 | EXTI9_5 => PA6, | ||
| 333 | EXTI9_5 => PA7, | ||
| 334 | EXTI9_5 => PA8, | ||
| 335 | EXTI9_5 => PA9, | ||
| 336 | EXTI15_10 => PA10, | ||
| 337 | EXTI15_10 => PA11, | ||
| 338 | EXTI15_10 => PA12, | ||
| 339 | EXTI15_10 => PA13, | ||
| 340 | EXTI15_10 => PA14, | ||
| 341 | EXTI15_10 => PA15, | ||
| 342 | ]); | ||
| 343 | |||
| 344 | #[cfg(any( | ||
| 345 | feature = "stm32f401", | ||
| 346 | feature = "stm32f405", | ||
| 347 | feature = "stm32f407", | ||
| 348 | feature = "stm32f410", | ||
| 349 | feature = "stm32f411", | ||
| 350 | feature = "stm32f412", | ||
| 351 | feature = "stm32f413", | ||
| 352 | feature = "stm32f415", | ||
| 353 | feature = "stm32f417", | ||
| 354 | feature = "stm32f423", | ||
| 355 | feature = "stm32f427", | ||
| 356 | feature = "stm32f429", | ||
| 357 | feature = "stm32f437", | ||
| 358 | feature = "stm32f439", | ||
| 359 | feature = "stm32f446", | ||
| 360 | feature = "stm32f469", | ||
| 361 | feature = "stm32f479" | ||
| 362 | ))] | ||
| 363 | exti!(gpiob, [ | ||
| 364 | EXTI0 => PB0, | ||
| 365 | EXTI1 => PB1, | ||
| 366 | EXTI2 => PB2, | ||
| 367 | EXTI3 => PB3, | ||
| 368 | EXTI4 => PB4, | ||
| 369 | EXTI9_5 => PB5, | ||
| 370 | EXTI9_5 => PB6, | ||
| 371 | EXTI9_5 => PB7, | ||
| 372 | EXTI9_5 => PB8, | ||
| 373 | EXTI9_5 => PB9, | ||
| 374 | EXTI15_10 => PB10, | ||
| 375 | EXTI15_10 => PB11, | ||
| 376 | EXTI15_10 => PB12, | ||
| 377 | EXTI15_10 => PB13, | ||
| 378 | EXTI15_10 => PB14, | ||
| 379 | EXTI15_10 => PB15, | ||
| 380 | ]); | ||
| 381 | |||
| 382 | #[cfg(any( | ||
| 383 | feature = "stm32f401", | ||
| 384 | feature = "stm32f405", | ||
| 385 | feature = "stm32f407", | ||
| 386 | feature = "stm32f410", | ||
| 387 | feature = "stm32f411", | ||
| 388 | feature = "stm32f412", | ||
| 389 | feature = "stm32f413", | ||
| 390 | feature = "stm32f415", | ||
| 391 | feature = "stm32f417", | ||
| 392 | feature = "stm32f423", | ||
| 393 | feature = "stm32f427", | ||
| 394 | feature = "stm32f429", | ||
| 395 | feature = "stm32f437", | ||
| 396 | feature = "stm32f439", | ||
| 397 | feature = "stm32f446", | ||
| 398 | feature = "stm32f469", | ||
| 399 | feature = "stm32f479" | ||
| 400 | ))] | ||
| 401 | exti!(gpioc, [ | ||
| 402 | EXTI0 => PC0, | ||
| 403 | EXTI1 => PC1, | ||
| 404 | EXTI2 => PC2, | ||
| 405 | EXTI3 => PC3, | ||
| 406 | EXTI4 => PC4, | ||
| 407 | EXTI9_5 => PC5, | ||
| 408 | EXTI9_5 => PC6, | ||
| 409 | EXTI9_5 => PC7, | ||
| 410 | EXTI9_5 => PC8, | ||
| 411 | EXTI9_5 => PC9, | ||
| 412 | EXTI15_10 => PC10, | ||
| 413 | EXTI15_10 => PC11, | ||
| 414 | EXTI15_10 => PC12, | ||
| 415 | EXTI15_10 => PC13, | ||
| 416 | EXTI15_10 => PC14, | ||
| 417 | EXTI15_10 => PC15, | ||
| 418 | ]); | ||
| 419 | |||
| 420 | #[cfg(any( | ||
| 421 | feature = "stm32f401", | ||
| 422 | feature = "stm32f405", | ||
| 423 | feature = "stm32f407", | ||
| 424 | feature = "stm32f411", | ||
| 425 | feature = "stm32f412", | ||
| 426 | feature = "stm32f413", | ||
| 427 | feature = "stm32f415", | ||
| 428 | feature = "stm32f417", | ||
| 429 | feature = "stm32f423", | ||
| 430 | feature = "stm32f427", | ||
| 431 | feature = "stm32f429", | ||
| 432 | feature = "stm32f437", | ||
| 433 | feature = "stm32f439", | ||
| 434 | feature = "stm32f446", | ||
| 435 | feature = "stm32f469", | ||
| 436 | feature = "stm32f479" | ||
| 437 | ))] | ||
| 438 | exti!(gpiod, [ | ||
| 439 | EXTI0 => PD0, | ||
| 440 | EXTI1 => PD1, | ||
| 441 | EXTI2 => PD2, | ||
| 442 | EXTI3 => PD3, | ||
| 443 | EXTI4 => PD4, | ||
| 444 | EXTI9_5 => PD5, | ||
| 445 | EXTI9_5 => PD6, | ||
| 446 | EXTI9_5 => PD7, | ||
| 447 | EXTI9_5 => PD8, | ||
| 448 | EXTI9_5 => PD9, | ||
| 449 | EXTI15_10 => PD10, | ||
| 450 | EXTI15_10 => PD11, | ||
| 451 | EXTI15_10 => PD12, | ||
| 452 | EXTI15_10 => PD13, | ||
| 453 | EXTI15_10 => PD14, | ||
| 454 | EXTI15_10 => PD15, | ||
| 455 | ]); | ||
| 456 | |||
| 457 | #[cfg(any( | ||
| 458 | feature = "stm32f401", | ||
| 459 | feature = "stm32f405", | ||
| 460 | feature = "stm32f407", | ||
| 461 | feature = "stm32f411", | ||
| 462 | feature = "stm32f412", | ||
| 463 | feature = "stm32f413", | ||
| 464 | feature = "stm32f415", | ||
| 465 | feature = "stm32f417", | ||
| 466 | feature = "stm32f423", | ||
| 467 | feature = "stm32f427", | ||
| 468 | feature = "stm32f429", | ||
| 469 | feature = "stm32f437", | ||
| 470 | feature = "stm32f439", | ||
| 471 | feature = "stm32f446", | ||
| 472 | feature = "stm32f469", | ||
| 473 | feature = "stm32f479" | ||
| 474 | ))] | ||
| 475 | exti!(gpioe, [ | ||
| 476 | EXTI0 => PE0, | ||
| 477 | EXTI1 => PE1, | ||
| 478 | EXTI2 => PE2, | ||
| 479 | EXTI3 => PE3, | ||
| 480 | EXTI4 => PE4, | ||
| 481 | EXTI9_5 => PE5, | ||
| 482 | EXTI9_5 => PE6, | ||
| 483 | EXTI9_5 => PE7, | ||
| 484 | EXTI9_5 => PE8, | ||
| 485 | EXTI9_5 => PE9, | ||
| 486 | EXTI15_10 => PE10, | ||
| 487 | EXTI15_10 => PE11, | ||
| 488 | EXTI15_10 => PE12, | ||
| 489 | EXTI15_10 => PE13, | ||
| 490 | EXTI15_10 => PE14, | ||
| 491 | EXTI15_10 => PE15, | ||
| 492 | ]); | ||
| 493 | |||
| 494 | #[cfg(any( | ||
| 495 | feature = "stm32f405", | ||
| 496 | feature = "stm32f407", | ||
| 497 | feature = "stm32f412", | ||
| 498 | feature = "stm32f413", | ||
| 499 | feature = "stm32f415", | ||
| 500 | feature = "stm32f417", | ||
| 501 | feature = "stm32f423", | ||
| 502 | feature = "stm32f427", | ||
| 503 | feature = "stm32f429", | ||
| 504 | feature = "stm32f437", | ||
| 505 | feature = "stm32f439", | ||
| 506 | feature = "stm32f446", | ||
| 507 | feature = "stm32f469", | ||
| 508 | feature = "stm32f479" | ||
| 509 | ))] | ||
| 510 | exti!(gpiof, [ | ||
| 511 | EXTI0 => PF0, | ||
| 512 | EXTI1 => PF1, | ||
| 513 | EXTI2 => PF2, | ||
| 514 | EXTI3 => PF3, | ||
| 515 | EXTI4 => PF4, | ||
| 516 | EXTI9_5 => PF5, | ||
| 517 | EXTI9_5 => PF6, | ||
| 518 | EXTI9_5 => PF7, | ||
| 519 | EXTI9_5 => PF8, | ||
| 520 | EXTI9_5 => PF9, | ||
| 521 | EXTI15_10 => PF10, | ||
| 522 | EXTI15_10 => PF11, | ||
| 523 | EXTI15_10 => PF12, | ||
| 524 | EXTI15_10 => PF13, | ||
| 525 | EXTI15_10 => PF14, | ||
| 526 | EXTI15_10 => PF15, | ||
| 527 | ]); | ||
| 528 | |||
| 529 | #[cfg(any( | ||
| 530 | feature = "stm32f405", | ||
| 531 | feature = "stm32f407", | ||
| 532 | feature = "stm32f412", | ||
| 533 | feature = "stm32f413", | ||
| 534 | feature = "stm32f415", | ||
| 535 | feature = "stm32f417", | ||
| 536 | feature = "stm32f423", | ||
| 537 | feature = "stm32f427", | ||
| 538 | feature = "stm32f429", | ||
| 539 | feature = "stm32f437", | ||
| 540 | feature = "stm32f439", | ||
| 541 | feature = "stm32f446", | ||
| 542 | feature = "stm32f469", | ||
| 543 | feature = "stm32f479" | ||
| 544 | ))] | ||
| 545 | exti!(gpiog, [ | ||
| 546 | EXTI0 => PG0, | ||
| 547 | EXTI1 => PG1, | ||
| 548 | EXTI2 => PG2, | ||
| 549 | EXTI3 => PG3, | ||
| 550 | EXTI4 => PG4, | ||
| 551 | EXTI9_5 => PG5, | ||
| 552 | EXTI9_5 => PG6, | ||
| 553 | EXTI9_5 => PG7, | ||
| 554 | EXTI9_5 => PG8, | ||
| 555 | EXTI9_5 => PG9, | ||
| 556 | EXTI15_10 => PG10, | ||
| 557 | EXTI15_10 => PG11, | ||
| 558 | EXTI15_10 => PG12, | ||
| 559 | EXTI15_10 => PG13, | ||
| 560 | EXTI15_10 => PG14, | ||
| 561 | EXTI15_10 => PG15, | ||
| 562 | ]); | ||
| 563 | |||
| 564 | #[cfg(any( | ||
| 565 | feature = "stm32f405", | ||
| 566 | feature = "stm32f407", | ||
| 567 | feature = "stm32f410", | ||
| 568 | feature = "stm32f411", | ||
| 569 | feature = "stm32f412", | ||
| 570 | feature = "stm32f413", | ||
| 571 | feature = "stm32f415", | ||
| 572 | feature = "stm32f417", | ||
| 573 | feature = "stm32f423", | ||
| 574 | feature = "stm32f427", | ||
| 575 | feature = "stm32f429", | ||
| 576 | feature = "stm32f437", | ||
| 577 | feature = "stm32f439", | ||
| 578 | feature = "stm32f446", | ||
| 579 | feature = "stm32f469", | ||
| 580 | feature = "stm32f479" | ||
| 581 | ))] | ||
| 582 | exti!(gpioh, [ | ||
| 583 | EXTI0 => PH0, | ||
| 584 | EXTI1 => PH1, | ||
| 585 | EXTI2 => PH2, | ||
| 586 | EXTI3 => PH3, | ||
| 587 | EXTI4 => PH4, | ||
| 588 | EXTI9_5 => PH5, | ||
| 589 | EXTI9_5 => PH6, | ||
| 590 | EXTI9_5 => PH7, | ||
| 591 | EXTI9_5 => PH8, | ||
| 592 | EXTI9_5 => PH9, | ||
| 593 | EXTI15_10 => PH10, | ||
| 594 | EXTI15_10 => PH11, | ||
| 595 | EXTI15_10 => PH12, | ||
| 596 | EXTI15_10 => PH13, | ||
| 597 | EXTI15_10 => PH14, | ||
| 598 | EXTI15_10 => PH15, | ||
| 599 | ]); | ||
| 600 | |||
| 601 | #[cfg(any(feature = "stm32f401"))] | ||
| 602 | exti!(gpioh, [ | ||
| 603 | EXTI0 => PH0, | ||
| 604 | EXTI1 => PH1, | ||
| 605 | ]); | ||
| 606 | |||
| 607 | #[cfg(any( | ||
| 608 | feature = "stm32f405", | ||
| 609 | feature = "stm32f407", | ||
| 610 | feature = "stm32f415", | ||
| 611 | feature = "stm32f417", | ||
| 612 | feature = "stm32f427", | ||
| 613 | feature = "stm32f429", | ||
| 614 | feature = "stm32f437", | ||
| 615 | feature = "stm32f439", | ||
| 616 | feature = "stm32f469", | ||
| 617 | feature = "stm32f479" | ||
| 618 | ))] | ||
| 619 | exti!(gpioi, [ | ||
| 620 | EXTI0 => PI0, | ||
| 621 | EXTI1 => PI1, | ||
| 622 | EXTI2 => PI2, | ||
| 623 | EXTI3 => PI3, | ||
| 624 | EXTI4 => PI4, | ||
| 625 | EXTI9_5 => PI5, | ||
| 626 | EXTI9_5 => PI6, | ||
| 627 | EXTI9_5 => PI7, | ||
| 628 | EXTI9_5 => PI8, | ||
| 629 | EXTI9_5 => PI9, | ||
| 630 | EXTI15_10 => PI10, | ||
| 631 | EXTI15_10 => PI11, | ||
| 632 | EXTI15_10 => PI12, | ||
| 633 | EXTI15_10 => PI13, | ||
| 634 | EXTI15_10 => PI14, | ||
| 635 | EXTI15_10 => PI15, | ||
| 636 | ]); | ||
| 637 | |||
| 638 | #[cfg(any( | ||
| 639 | feature = "stm32f427", | ||
| 640 | feature = "stm32f429", | ||
| 641 | feature = "stm32f437", | ||
| 642 | feature = "stm32f439", | ||
| 643 | feature = "stm32f469", | ||
| 644 | feature = "stm32f479" | ||
| 645 | ))] | ||
| 646 | exti!(gpioj, [ | ||
| 647 | EXTI0 => PJ0, | ||
| 648 | EXTI1 => PJ1, | ||
| 649 | EXTI2 => PJ2, | ||
| 650 | EXTI3 => PJ3, | ||
| 651 | EXTI4 => PJ4, | ||
| 652 | EXTI9_5 => PJ5, | ||
| 653 | EXTI9_5 => PJ6, | ||
| 654 | EXTI9_5 => PJ7, | ||
| 655 | EXTI9_5 => PJ8, | ||
| 656 | EXTI9_5 => PJ9, | ||
| 657 | EXTI15_10 => PJ10, | ||
| 658 | EXTI15_10 => PJ11, | ||
| 659 | EXTI15_10 => PJ12, | ||
| 660 | EXTI15_10 => PJ13, | ||
| 661 | EXTI15_10 => PJ14, | ||
| 662 | EXTI15_10 => PJ15, | ||
| 663 | ]); | ||
| 664 | |||
| 665 | #[cfg(any( | ||
| 666 | feature = "stm32f427", | ||
| 667 | feature = "stm32f429", | ||
| 668 | feature = "stm32f437", | ||
| 669 | feature = "stm32f439", | ||
| 670 | feature = "stm32f469", | ||
| 671 | feature = "stm32f479" | ||
| 672 | ))] | ||
| 673 | exti!(gpiok, [ | ||
| 674 | EXTI0 => PK0, | ||
| 675 | EXTI1 => PK1, | ||
| 676 | EXTI2 => PK2, | ||
| 677 | EXTI3 => PK3, | ||
| 678 | EXTI4 => PK4, | ||
| 679 | EXTI9_5 => PK5, | ||
| 680 | EXTI9_5 => PK6, | ||
| 681 | EXTI9_5 => PK7, | ||
| 682 | ]); | ||
| 683 | |||
| 684 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 685 | exti!(gpioa, [ | ||
| 686 | EXTI0_1 => PA0, | ||
| 687 | EXTI0_1 => PA1, | ||
| 688 | EXTI2_3 => PA2, | ||
| 689 | EXTI2_3 => PA3, | ||
| 690 | EXTI4_15 => PA4, | ||
| 691 | EXTI4_15 => PA5, | ||
| 692 | EXTI4_15 => PA6, | ||
| 693 | EXTI4_15 => PA7, | ||
| 694 | EXTI4_15 => PA8, | ||
| 695 | EXTI4_15 => PA9, | ||
| 696 | EXTI4_15 => PA10, | ||
| 697 | EXTI4_15 => PA11, | ||
| 698 | EXTI4_15 => PA12, | ||
| 699 | EXTI4_15 => PA13, | ||
| 700 | EXTI4_15 => PA14, | ||
| 701 | EXTI4_15 => PA15, | ||
| 702 | ]); | ||
| 703 | |||
| 704 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 705 | exti!(gpiob, [ | ||
| 706 | EXTI0_1 => PB0, | ||
| 707 | EXTI0_1 => PB1, | ||
| 708 | EXTI2_3 => PB2, | ||
| 709 | EXTI2_3 => PB3, | ||
| 710 | EXTI4_15 => PB4, | ||
| 711 | EXTI4_15 => PB5, | ||
| 712 | EXTI4_15 => PB6, | ||
| 713 | EXTI4_15 => PB7, | ||
| 714 | EXTI4_15 => PB8, | ||
| 715 | EXTI4_15 => PB9, | ||
| 716 | EXTI4_15 => PB10, | ||
| 717 | EXTI4_15 => PB11, | ||
| 718 | EXTI4_15 => PB12, | ||
| 719 | EXTI4_15 => PB13, | ||
| 720 | EXTI4_15 => PB14, | ||
| 721 | EXTI4_15 => PB15, | ||
| 722 | ]); | ||
| 723 | |||
| 724 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 725 | exti!(gpioc, [ | ||
| 726 | EXTI0_1 => PC0, | ||
| 727 | EXTI0_1 => PC1, | ||
| 728 | EXTI2_3 => PC2, | ||
| 729 | EXTI2_3 => PC3, | ||
| 730 | EXTI4_15 => PC4, | ||
| 731 | EXTI4_15 => PC5, | ||
| 732 | EXTI4_15 => PC6, | ||
| 733 | EXTI4_15 => PC7, | ||
| 734 | EXTI4_15 => PC8, | ||
| 735 | EXTI4_15 => PC9, | ||
| 736 | EXTI4_15 => PC10, | ||
| 737 | EXTI4_15 => PC11, | ||
| 738 | EXTI4_15 => PC12, | ||
| 739 | EXTI4_15 => PC13, | ||
| 740 | EXTI4_15 => PC14, | ||
| 741 | EXTI4_15 => PC15, | ||
| 742 | ]); | ||
| 743 | |||
| 744 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 745 | exti!(gpiod, [ | ||
| 746 | EXTI0_1 => PD0, | ||
| 747 | EXTI0_1 => PD1, | ||
| 748 | EXTI2_3 => PD2, | ||
| 749 | EXTI2_3 => PD3, | ||
| 750 | EXTI4_15 => PD4, | ||
| 751 | EXTI4_15 => PD5, | ||
| 752 | EXTI4_15 => PD6, | ||
| 753 | EXTI4_15 => PD7, | ||
| 754 | EXTI4_15 => PD8, | ||
| 755 | EXTI4_15 => PD9, | ||
| 756 | EXTI4_15 => PD10, | ||
| 757 | EXTI4_15 => PD11, | ||
| 758 | EXTI4_15 => PD12, | ||
| 759 | EXTI4_15 => PD13, | ||
| 760 | EXTI4_15 => PD14, | ||
| 761 | EXTI4_15 => PD15, | ||
| 762 | ]); | ||
| 763 | |||
| 764 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 765 | exti!(gpioe, [ | ||
| 766 | EXTI0_1 => PE0, | ||
| 767 | EXTI0_1 => PE1, | ||
| 768 | EXTI2_3 => PE2, | ||
| 769 | EXTI2_3 => PE3, | ||
| 770 | EXTI4_15 => PE4, | ||
| 771 | EXTI4_15 => PE5, | ||
| 772 | EXTI4_15 => PE6, | ||
| 773 | EXTI4_15 => PE7, | ||
| 774 | EXTI4_15 => PE8, | ||
| 775 | EXTI4_15 => PE9, | ||
| 776 | EXTI4_15 => PE10, | ||
| 777 | EXTI4_15 => PE11, | ||
| 778 | EXTI4_15 => PE12, | ||
| 779 | EXTI4_15 => PE13, | ||
| 780 | EXTI4_15 => PE14, | ||
| 781 | EXTI4_15 => PE15, | ||
| 782 | ]); | ||
| 783 | |||
| 784 | #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] | ||
| 785 | exti!(gpioh, [ | ||
| 786 | EXTI0_1 => PH0, | ||
| 787 | EXTI0_1 => PH1, | ||
| 788 | EXTI4_15 => PH9, | ||
| 789 | EXTI4_15 => PH10, | ||
| 790 | ]); | ||
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index f963400a7..e0e6cc477 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | use core::convert::Infallible; | 1 | use core::convert::Infallible; |
| 2 | use core::hint::unreachable_unchecked; | ||
| 3 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 4 | 3 | use embassy::util::Unborrow; | |
| 5 | use embassy::util::PeripheralBorrow; | ||
| 6 | use embassy_extras::{impl_unborrow, unborrow}; | 4 | use embassy_extras::{impl_unborrow, unborrow}; |
| 7 | use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; | 5 | use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; |
| 8 | use gpio::vals; | 6 | use gpio::vals; |
| @@ -10,13 +8,6 @@ use gpio::vals; | |||
| 10 | use crate::pac::gpio_v2 as gpio; | 8 | use crate::pac::gpio_v2 as gpio; |
| 11 | use crate::peripherals; | 9 | use crate::peripherals; |
| 12 | 10 | ||
| 13 | /// A GPIO port with up to 16 pins. | ||
| 14 | #[derive(Debug, Eq, PartialEq)] | ||
| 15 | pub enum Port { | ||
| 16 | PortA, | ||
| 17 | PortB, | ||
| 18 | } | ||
| 19 | |||
| 20 | /// Pull setting for an input. | 11 | /// Pull setting for an input. |
| 21 | #[derive(Debug, Eq, PartialEq)] | 12 | #[derive(Debug, Eq, PartialEq)] |
| 22 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -33,7 +24,7 @@ pub struct Input<'d, T: Pin> { | |||
| 33 | } | 24 | } |
| 34 | 25 | ||
| 35 | impl<'d, T: Pin> Input<'d, T> { | 26 | impl<'d, T: Pin> Input<'d, T> { |
| 36 | pub fn new(pin: impl PeripheralBorrow<Target = T> + 'd, pull: Pull) -> Self { | 27 | pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self { |
| 37 | unborrow!(pin); | 28 | unborrow!(pin); |
| 38 | 29 | ||
| 39 | cortex_m::interrupt::free(|_| unsafe { | 30 | cortex_m::interrupt::free(|_| unsafe { |
| @@ -94,7 +85,7 @@ pub struct Output<'d, T: Pin> { | |||
| 94 | } | 85 | } |
| 95 | 86 | ||
| 96 | impl<'d, T: Pin> Output<'d, T> { | 87 | impl<'d, T: Pin> Output<'d, T> { |
| 97 | pub fn new(pin: impl PeripheralBorrow<Target = T> + 'd, initial_output: Level) -> Self { | 88 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self { |
| 98 | unborrow!(pin); | 89 | unborrow!(pin); |
| 99 | 90 | ||
| 100 | match initial_output { | 91 | match initial_output { |
| @@ -173,6 +164,7 @@ pub(crate) mod sealed { | |||
| 173 | 164 | ||
| 174 | #[inline] | 165 | #[inline] |
| 175 | fn block(&self) -> gpio::Gpio { | 166 | fn block(&self) -> gpio::Gpio { |
| 167 | // TODO hardcoding peripheral addrs until we figure out how these are handled in the metapac | ||
| 176 | let p = 0x4002_0000 + (self._port() as u32) * 0x400; | 168 | let p = 0x4002_0000 + (self._port() as u32) * 0x400; |
| 177 | gpio::Gpio(p as *mut u8) | 169 | gpio::Gpio(p as *mut u8) |
| 178 | } | 170 | } |
| @@ -181,9 +173,8 @@ pub(crate) mod sealed { | |||
| 181 | #[inline] | 173 | #[inline] |
| 182 | fn set_high(&self) { | 174 | fn set_high(&self) { |
| 183 | unsafe { | 175 | unsafe { |
| 184 | self.block() | 176 | let n = self._pin() as _; |
| 185 | .bsrr() | 177 | self.block().bsrr().write(|w| w.set_bs(n, true)); |
| 186 | .write(|w| w.set_bs(self._pin() as _, true)); | ||
| 187 | } | 178 | } |
| 188 | } | 179 | } |
| 189 | 180 | ||
| @@ -191,9 +182,8 @@ pub(crate) mod sealed { | |||
| 191 | #[inline] | 182 | #[inline] |
| 192 | fn set_low(&self) { | 183 | fn set_low(&self) { |
| 193 | unsafe { | 184 | unsafe { |
| 194 | self.block() | 185 | let n = self._pin() as _; |
| 195 | .bsrr() | 186 | self.block().bsrr().write(|w| w.set_br(n, true)); |
| 196 | .write(|w| w.set_br(self._pin() as _, true)); | ||
| 197 | } | 187 | } |
| 198 | } | 188 | } |
| 199 | } | 189 | } |
| @@ -202,6 +192,8 @@ pub(crate) mod sealed { | |||
| 202 | } | 192 | } |
| 203 | 193 | ||
| 204 | pub trait Pin: sealed::Pin + Sized { | 194 | pub trait Pin: sealed::Pin + Sized { |
| 195 | type ExtiChannel: crate::exti::Channel; | ||
| 196 | |||
| 205 | /// Number of the pin within the port (0..31) | 197 | /// Number of the pin within the port (0..31) |
| 206 | #[inline] | 198 | #[inline] |
| 207 | fn pin(&self) -> u8 { | 199 | fn pin(&self) -> u8 { |
| @@ -210,12 +202,8 @@ pub trait Pin: sealed::Pin + Sized { | |||
| 210 | 202 | ||
| 211 | /// Port of the pin | 203 | /// Port of the pin |
| 212 | #[inline] | 204 | #[inline] |
| 213 | fn port(&self) -> Port { | 205 | fn port(&self) -> u8 { |
| 214 | match self.pin_port() / 16 { | 206 | self._port() |
| 215 | 0 => Port::PortA, | ||
| 216 | 1 => Port::PortB, | ||
| 217 | _ => unsafe { unreachable_unchecked() }, | ||
| 218 | } | ||
| 219 | } | 207 | } |
| 220 | 208 | ||
| 221 | #[inline] | 209 | #[inline] |
| @@ -245,7 +233,9 @@ impl AnyPin { | |||
| 245 | } | 233 | } |
| 246 | 234 | ||
| 247 | impl_unborrow!(AnyPin); | 235 | impl_unborrow!(AnyPin); |
| 248 | impl Pin for AnyPin {} | 236 | impl Pin for AnyPin { |
| 237 | type ExtiChannel = crate::exti::AnyChannel; | ||
| 238 | } | ||
| 249 | impl sealed::Pin for AnyPin { | 239 | impl sealed::Pin for AnyPin { |
| 250 | #[inline] | 240 | #[inline] |
| 251 | fn pin_port(&self) -> u8 { | 241 | fn pin_port(&self) -> u8 { |
| @@ -288,31 +278,20 @@ impl<T: Pin> OptionalPin for T { | |||
| 288 | } | 278 | } |
| 289 | } | 279 | } |
| 290 | 280 | ||
| 291 | // Uninhabited enum, so it's actually impossible to create a DummyPin value. | ||
| 292 | #[doc(hidden)] | ||
| 293 | pub enum DummyPin {} | ||
| 294 | impl Pin for DummyPin {} | ||
| 295 | impl sealed::Pin for DummyPin { | ||
| 296 | #[inline] | ||
| 297 | fn pin_port(&self) -> u8 { | ||
| 298 | unreachable!() | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | #[derive(Clone, Copy, Debug)] | 281 | #[derive(Clone, Copy, Debug)] |
| 303 | pub struct NoPin; | 282 | pub struct NoPin; |
| 304 | impl_unborrow!(NoPin); | 283 | impl_unborrow!(NoPin); |
| 305 | impl sealed::OptionalPin for NoPin {} | 284 | impl sealed::OptionalPin for NoPin {} |
| 306 | impl OptionalPin for NoPin { | 285 | impl OptionalPin for NoPin { |
| 307 | type Pin = DummyPin; | 286 | type Pin = AnyPin; |
| 308 | 287 | ||
| 309 | #[inline] | 288 | #[inline] |
| 310 | fn pin(&self) -> Option<&DummyPin> { | 289 | fn pin(&self) -> Option<&AnyPin> { |
| 311 | None | 290 | None |
| 312 | } | 291 | } |
| 313 | 292 | ||
| 314 | #[inline] | 293 | #[inline] |
| 315 | fn pin_mut(&mut self) -> Option<&mut DummyPin> { | 294 | fn pin_mut(&mut self) -> Option<&mut AnyPin> { |
| 316 | None | 295 | None |
| 317 | } | 296 | } |
| 318 | } | 297 | } |
| @@ -320,8 +299,10 @@ impl OptionalPin for NoPin { | |||
| 320 | // ==================== | 299 | // ==================== |
| 321 | 300 | ||
| 322 | macro_rules! impl_pin { | 301 | macro_rules! impl_pin { |
| 323 | ($type:ident, $port_num:expr, $pin_num:expr) => { | 302 | ($type:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => { |
| 324 | impl Pin for peripherals::$type {} | 303 | impl Pin for peripherals::$type { |
| 304 | type ExtiChannel = peripherals::$exti_ch; | ||
| 305 | } | ||
| 325 | impl sealed::Pin for peripherals::$type { | 306 | impl sealed::Pin for peripherals::$type { |
| 326 | #[inline] | 307 | #[inline] |
| 327 | fn pin_port(&self) -> u8 { | 308 | fn pin_port(&self) -> u8 { |
| @@ -331,51 +312,51 @@ macro_rules! impl_pin { | |||
| 331 | }; | 312 | }; |
| 332 | } | 313 | } |
| 333 | 314 | ||
| 334 | impl_pin!(PA0, 0, 0); | 315 | impl_pin!(PA0, 0, 0, EXTI0); |
| 335 | impl_pin!(PA1, 0, 1); | 316 | impl_pin!(PA1, 0, 1, EXTI1); |
| 336 | impl_pin!(PA2, 0, 2); | 317 | impl_pin!(PA2, 0, 2, EXTI2); |
| 337 | impl_pin!(PA3, 0, 3); | 318 | impl_pin!(PA3, 0, 3, EXTI3); |
| 338 | impl_pin!(PA4, 0, 4); | 319 | impl_pin!(PA4, 0, 4, EXTI4); |
| 339 | impl_pin!(PA5, 0, 5); | 320 | impl_pin!(PA5, 0, 5, EXTI5); |
| 340 | impl_pin!(PA6, 0, 6); | 321 | impl_pin!(PA6, 0, 6, EXTI6); |
| 341 | impl_pin!(PA7, 0, 7); | 322 | impl_pin!(PA7, 0, 7, EXTI7); |
| 342 | impl_pin!(PA8, 0, 8); | 323 | impl_pin!(PA8, 0, 8, EXTI8); |
| 343 | impl_pin!(PA9, 0, 9); | 324 | impl_pin!(PA9, 0, 9, EXTI9); |
| 344 | impl_pin!(PA10, 0, 10); | 325 | impl_pin!(PA10, 0, 10, EXTI10); |
| 345 | impl_pin!(PA11, 0, 11); | 326 | impl_pin!(PA11, 0, 11, EXTI11); |
| 346 | impl_pin!(PA12, 0, 12); | 327 | impl_pin!(PA12, 0, 12, EXTI12); |
| 347 | impl_pin!(PA13, 0, 13); | 328 | impl_pin!(PA13, 0, 13, EXTI13); |
| 348 | impl_pin!(PA14, 0, 14); | 329 | impl_pin!(PA14, 0, 14, EXTI14); |
| 349 | impl_pin!(PA15, 0, 15); | 330 | impl_pin!(PA15, 0, 15, EXTI15); |
| 350 | impl_pin!(PB0, 1, 0); | 331 | impl_pin!(PB0, 1, 0, EXTI0); |
| 351 | impl_pin!(PB1, 1, 1); | 332 | impl_pin!(PB1, 1, 1, EXTI1); |
| 352 | impl_pin!(PB2, 1, 2); | 333 | impl_pin!(PB2, 1, 2, EXTI2); |
| 353 | impl_pin!(PB3, 1, 3); | 334 | impl_pin!(PB3, 1, 3, EXTI3); |
| 354 | impl_pin!(PB4, 1, 4); | 335 | impl_pin!(PB4, 1, 4, EXTI4); |
| 355 | impl_pin!(PB5, 1, 5); | 336 | impl_pin!(PB5, 1, 5, EXTI5); |
| 356 | impl_pin!(PB6, 1, 6); | 337 | impl_pin!(PB6, 1, 6, EXTI6); |
| 357 | impl_pin!(PB7, 1, 7); | 338 | impl_pin!(PB7, 1, 7, EXTI7); |
| 358 | impl_pin!(PB8, 1, 8); | 339 | impl_pin!(PB8, 1, 8, EXTI8); |
| 359 | impl_pin!(PB9, 1, 9); | 340 | impl_pin!(PB9, 1, 9, EXTI9); |
| 360 | impl_pin!(PB10, 1, 10); | 341 | impl_pin!(PB10, 1, 10, EXTI10); |
| 361 | impl_pin!(PB11, 1, 11); | 342 | impl_pin!(PB11, 1, 11, EXTI11); |
| 362 | impl_pin!(PB12, 1, 12); | 343 | impl_pin!(PB12, 1, 12, EXTI12); |
| 363 | impl_pin!(PB13, 1, 13); | 344 | impl_pin!(PB13, 1, 13, EXTI13); |
| 364 | impl_pin!(PB14, 1, 14); | 345 | impl_pin!(PB14, 1, 14, EXTI14); |
| 365 | impl_pin!(PB15, 1, 15); | 346 | impl_pin!(PB15, 1, 15, EXTI15); |
| 366 | impl_pin!(PC0, 2, 0); | 347 | impl_pin!(PC0, 2, 0, EXTI0); |
| 367 | impl_pin!(PC1, 2, 1); | 348 | impl_pin!(PC1, 2, 1, EXTI1); |
| 368 | impl_pin!(PC2, 2, 2); | 349 | impl_pin!(PC2, 2, 2, EXTI2); |
| 369 | impl_pin!(PC3, 2, 3); | 350 | impl_pin!(PC3, 2, 3, EXTI3); |
| 370 | impl_pin!(PC4, 2, 4); | 351 | impl_pin!(PC4, 2, 4, EXTI4); |
| 371 | impl_pin!(PC5, 2, 5); | 352 | impl_pin!(PC5, 2, 5, EXTI5); |
| 372 | impl_pin!(PC6, 2, 6); | 353 | impl_pin!(PC6, 2, 6, EXTI6); |
| 373 | impl_pin!(PC7, 2, 7); | 354 | impl_pin!(PC7, 2, 7, EXTI7); |
| 374 | impl_pin!(PC8, 2, 8); | 355 | impl_pin!(PC8, 2, 8, EXTI8); |
| 375 | impl_pin!(PC9, 2, 9); | 356 | impl_pin!(PC9, 2, 9, EXTI9); |
| 376 | impl_pin!(PC10, 2, 10); | 357 | impl_pin!(PC10, 2, 10, EXTI10); |
| 377 | impl_pin!(PC11, 2, 11); | 358 | impl_pin!(PC11, 2, 11, EXTI11); |
| 378 | impl_pin!(PC12, 2, 12); | 359 | impl_pin!(PC12, 2, 12, EXTI12); |
| 379 | impl_pin!(PC13, 2, 13); | 360 | impl_pin!(PC13, 2, 13, EXTI13); |
| 380 | impl_pin!(PC14, 2, 14); | 361 | impl_pin!(PC14, 2, 14, EXTI14); |
| 381 | impl_pin!(PC15, 2, 15); | 362 | impl_pin!(PC15, 2, 15, EXTI15); |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 58a846229..da266f75d 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -28,8 +28,9 @@ pub mod fmt; | |||
| 28 | mod chip; | 28 | mod chip; |
| 29 | pub use chip::{peripherals, Peripherals}; | 29 | pub use chip::{peripherals, Peripherals}; |
| 30 | 30 | ||
| 31 | pub mod exti; | ||
| 31 | pub mod gpio; | 32 | pub mod gpio; |
| 32 | //pub mod exti; | 33 | //pub mod rtc; |
| 33 | //pub mod interrupt; | 34 | //pub mod interrupt; |
| 34 | 35 | ||
| 35 | pub(crate) use stm32_metapac as pac; | 36 | pub(crate) use stm32_metapac as pac; |
