diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 7112ad02f..3c5b53b05 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,3 +1,6 @@ +#![macro_use] + +use crate::peripherals; use crate::time::Hertz; use core::mem::MaybeUninit; @@ -44,3 +47,44 @@ cfg_if::cfg_if! { } } } + +pub(crate) mod sealed { + pub trait RccPeripheral { + fn reset(); + fn enable(); + fn disable(); + } +} + +pub trait RccPeripheral: sealed::RccPeripheral + 'static {} + +crate::pac::peripheral_rcc!( + ($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { + impl sealed::RccPeripheral for peripherals::$inst { + fn enable() { + critical_section::with(|_| { + unsafe { + crate::pac::RCC.$enable().modify(|w| w.$perien(true)); + } + }) + } + fn disable() { + critical_section::with(|_| { + unsafe { + crate::pac::RCC.$enable().modify(|w| w.$perien(false)); + } + }) + } + fn reset() { + critical_section::with(|_| { + unsafe { + crate::pac::RCC.$reset().modify(|w| w.$perirst(true)); + crate::pac::RCC.$reset().modify(|w| w.$perirst(false)); + } + }) + } + } + + impl RccPeripheral for peripherals::$inst {} + }; +); diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 730169ec0..9b04c03aa 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -4,7 +4,7 @@ #[cfg_attr(spi_v2, path = "v2.rs")] #[cfg_attr(spi_v3, path = "v3.rs")] mod _version; -use crate::peripherals; +use crate::{peripherals, rcc::RccPeripheral}; pub use _version::*; use crate::gpio::Pin; @@ -64,7 +64,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static {} +pub trait Instance: sealed::Instance + RccPeripheral + 'static {} pub trait SckPin: sealed::SckPin + 'static {} diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index e3057a3b5..227a36a89 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -61,6 +61,8 @@ impl<'d, T: Instance> Spi<'d, T> { let br = Self::compute_baud_rate(pclk, freq.into()); unsafe { + T::enable(); + T::reset(); T::regs().cr1().modify(|w| { w.set_cpha( match config.mode.phase == Phase::CaptureOnSecondTransition { diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 46fe817ea..a7ac54cdd 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -63,6 +63,8 @@ impl<'d, T: Instance> Spi<'d, T> { let br = Self::compute_baud_rate(pclk, freq.into()); unsafe { + T::enable(); + T::reset(); T::regs().cr2().modify(|w| { w.set_ssoe(false); }); diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index da4686b9c..6073616bd 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs @@ -64,6 +64,8 @@ impl<'d, T: Instance> Spi<'d, T> { let br = Self::compute_baud_rate(pclk, freq.into()); unsafe { + T::enable(); + T::reset(); T::regs().ifcr().write(|w| w.0 = 0xffff_ffff); T::regs().cfg2().modify(|w| { //w.set_ssoe(true); diff --git a/stm32-data b/stm32-data index 6e4da8f04..4bb1b178c 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit 6e4da8f04205dcc48767d12fac5cdfd170e52f18 +Subproject commit 4bb1b178cd1c555cfedaea31ad0be3c6a7b99563 diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index 083e06bfd..008c9eb37 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs @@ -136,6 +136,7 @@ fn main() { let mut interrupt_table: Vec> = Vec::new(); let mut peripherals_table: Vec> = Vec::new(); let mut peripheral_pins_table: Vec> = Vec::new(); + let mut peripheral_rcc_table: Vec> = Vec::new(); let dma_base = chip .peripherals @@ -216,6 +217,29 @@ fn main() { }; assert_eq!(p.address, dma_base + dma_stride * dma_num); } + "spi" => { + if let Some(clock) = &p.clock { + // Workaround for APB1 register being split on some chip families. Assume + // first register until we can find a way to hint which register is used + let reg = clock.to_ascii_lowercase(); + let (enable_reg, reset_reg) = if chip.family == "STM32H7" && clock == "APB1" + { + (format!("{}lenr", reg), format!("{}lrstr", reg)) + } else if chip.family.starts_with("STM32L4") && clock == "APB1" { + (format!("{}enr1", reg), format!("{}rstr1", reg)) + } else { + (format!("{}enr", reg), format!("{}rstr", reg)) + }; + let field = name.to_ascii_lowercase(); + peripheral_rcc_table.push(vec![ + name.clone(), + enable_reg, + reset_reg, + format!("set_{}en", field), + format!("set_{}rst", field), + ]); + } + } _ => {} } } @@ -255,6 +279,7 @@ fn main() { make_table(&mut extra, "peripherals", &peripherals_table); make_table(&mut extra, "peripheral_versions", &peripheral_version_table); make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); + make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); for (module, version) in peripheral_versions { println!("loading {} {}", module, version);