diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 150014af..612a54f2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" } +stm32-metapac = "12" vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]} +stm32-metapac = { path = "../../stm32-data-generated/stm32-metapac", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 6c364f7b..1b86dad7 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -425,6 +425,15 @@ fn main() { (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), (("lpuart", "CK"), quote!(crate::usart::CkPin)), (("lpuart", "DE"), quote!(crate::usart::DePin)), + (("sai", "SCK_A"), quote!(crate::sai::SckAPin)), + (("sai", "SCK_B"), quote!(crate::sai::SckBPin)), + (("sai", "FS_A"), quote!(crate::sai::FsAPin)), + (("sai", "FS_B"), quote!(crate::sai::FsBPin)), + (("sai", "SD_A"), quote!(crate::sai::SdAPin)), + (("sai", "SD_B"), quote!(crate::sai::SdBPin)), + (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)), + (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)), + (("sai", "WS"), quote!(crate::sai::WsPin)), (("spi", "SCK"), quote!(crate::spi::SckPin)), (("spi", "MOSI"), quote!(crate::spi::MosiPin)), (("spi", "MISO"), quote!(crate::spi::MisoPin)), @@ -708,6 +717,8 @@ fn main() { (("usart", "TX"), quote!(crate::usart::TxDma)), (("lpuart", "RX"), quote!(crate::usart::RxDma)), (("lpuart", "TX"), quote!(crate::usart::TxDma)), + (("sai", "A"), quote!(crate::sai::DmaA)), + (("sai", "B"), quote!(crate::sai::DmaB)), (("spi", "RX"), quote!(crate::spi::RxDma)), (("spi", "TX"), quote!(crate::spi::TxDma)), (("i2c", "RX"), quote!(crate::i2c::RxDma)), diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 8c87ea7d..b5a12859 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -55,6 +55,8 @@ pub mod qspi; pub mod rng; #[cfg(all(rtc, not(rtc_v1)))] pub mod rtc; +#[cfg(sai)] +pub mod sai; #[cfg(sdmmc)] pub mod sdmmc; #[cfg(spi)] diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ee9cb289..72bdbd5d 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -33,6 +33,9 @@ pub struct Config { #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] pub plli2s: Option, + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + pub pllsai: Option, + pub pll48: bool, pub rtc: Option, } @@ -48,11 +51,9 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } -#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] -fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option, ) -> Option<(u32, u32, u32)> { let min_div = 2; - let max_div = 7; - let target = match plli2s { + let target = match target { Some(target) => target, None => return None, }; @@ -76,15 +77,41 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { }) .min_by_key(|(_, _, _, error)| *error)?; + Some((n, outdiv, output)) +} + +#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] +fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { + let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?; + RCC.plli2scfgr().modify(|w| { w.set_plli2sn(n as u16); w.set_plli2sr(outdiv as u8); + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + w.set_plli2sq(outdiv as u8); //set sai divider same as i2s }); Some(output) } -fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pll48clk: bool) -> PllResults { +#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] +fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { + None +} + +#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] +fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { + let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 15, pllsai)?; + + RCC.pllsaicfgr().modify(|w| { + w.set_pllsain(n as u16); + w.set_pllsaiq(outdiv as u8); + }); + + Some(output) +} + +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pllsai: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -96,6 +123,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti pllsysclk: None, pll48clk: None, plli2sclk: None, + pllsaiclk: None, }; } // Input divisor from PLL source clock, must result to frequency in @@ -146,6 +174,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti w.set_pllp(Pllp::from_bits(pllp as u8)); w.set_pllq(pllq as u8); w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); + w.set_pllr(0); }); let real_pllsysclk = vco_in * plln / sysclk_div; @@ -155,6 +184,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti pllsysclk: Some(real_pllsysclk), pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, plli2sclk: setup_i2s_pll(vco_in, plli2s), + pllsaiclk: setup_sai_pll(vco_in, pllsai), } } @@ -344,6 +374,10 @@ pub(crate) unsafe fn init(config: Config) { config.plli2s.map(|i2s| i2s.0), #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] None, + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + config.pllsai.map(|sai| sai.0), + #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] + None, config.pll48, ); @@ -441,6 +475,12 @@ pub(crate) unsafe fn init(config: Config) { while !RCC.cr().read().plli2srdy() {} } + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + if plls.pllsaiclk.is_some() { + RCC.cr().modify(|w| w.set_pllsaion(true)); + while !RCC.cr().read().pllsairdy() {} + } + RCC.cfgr().modify(|w| { w.set_ppre2(Ppre::from_bits(ppre2_bits)); w.set_ppre1(Ppre::from_bits(ppre1_bits)); @@ -496,7 +536,7 @@ pub(crate) unsafe fn init(config: Config) { plli2s: plls.plli2sclk.map(Hertz), #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] - pllsai: None, + pllsai: plls.pllsaiclk.map(Hertz), rtc: rtc, }); @@ -508,6 +548,8 @@ struct PllResults { pll48clk: Option, #[allow(dead_code)] plli2sclk: Option, + #[allow(dead_code)] + pllsaiclk: Option, } mod max {