aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorTyler Gilbert <[email protected]>2023-09-29 20:57:59 -0500
committerTyler Gilbert <[email protected]>2023-09-29 20:57:59 -0500
commitce91fb2bfc846570ef543a09396c428d70675245 (patch)
tree55013e7fcd2ba349ded0b333d142de9f2e6edd0f /embassy-stm32
parentf033089625b4883f9b8811f5c291292529f66767 (diff)
Issue #1974 add SAI driver
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs11
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/rcc/f4.rs54
4 files changed, 63 insertions, 8 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 150014afe..612a54f25 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,7 @@ sdio-host = "0.5.0"
58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
59critical-section = "1.1" 59critical-section = "1.1"
60atomic-polyfill = "1.0.1" 60atomic-polyfill = "1.0.1"
61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" } 61stm32-metapac = "12"
62vcell = "0.1.3" 62vcell = "0.1.3"
63bxcan = "0.7.0" 63bxcan = "0.7.0"
64nb = "1.0.0" 64nb = "1.0.0"
@@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] }
77[build-dependencies] 77[build-dependencies]
78proc-macro2 = "1.0.36" 78proc-macro2 = "1.0.36"
79quote = "1.0.15" 79quote = "1.0.15"
80stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]} 80stm32-metapac = { path = "../../stm32-data-generated/stm32-metapac", default-features = false, features = ["metadata"]}
81 81
82[features] 82[features]
83default = ["rt"] 83default = ["rt"]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 6c364f7bb..1b86dad7a 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -425,6 +425,15 @@ fn main() {
425 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), 425 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
426 (("lpuart", "CK"), quote!(crate::usart::CkPin)), 426 (("lpuart", "CK"), quote!(crate::usart::CkPin)),
427 (("lpuart", "DE"), quote!(crate::usart::DePin)), 427 (("lpuart", "DE"), quote!(crate::usart::DePin)),
428 (("sai", "SCK_A"), quote!(crate::sai::SckAPin)),
429 (("sai", "SCK_B"), quote!(crate::sai::SckBPin)),
430 (("sai", "FS_A"), quote!(crate::sai::FsAPin)),
431 (("sai", "FS_B"), quote!(crate::sai::FsBPin)),
432 (("sai", "SD_A"), quote!(crate::sai::SdAPin)),
433 (("sai", "SD_B"), quote!(crate::sai::SdBPin)),
434 (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)),
435 (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)),
436 (("sai", "WS"), quote!(crate::sai::WsPin)),
428 (("spi", "SCK"), quote!(crate::spi::SckPin)), 437 (("spi", "SCK"), quote!(crate::spi::SckPin)),
429 (("spi", "MOSI"), quote!(crate::spi::MosiPin)), 438 (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
430 (("spi", "MISO"), quote!(crate::spi::MisoPin)), 439 (("spi", "MISO"), quote!(crate::spi::MisoPin)),
@@ -708,6 +717,8 @@ fn main() {
708 (("usart", "TX"), quote!(crate::usart::TxDma)), 717 (("usart", "TX"), quote!(crate::usart::TxDma)),
709 (("lpuart", "RX"), quote!(crate::usart::RxDma)), 718 (("lpuart", "RX"), quote!(crate::usart::RxDma)),
710 (("lpuart", "TX"), quote!(crate::usart::TxDma)), 719 (("lpuart", "TX"), quote!(crate::usart::TxDma)),
720 (("sai", "A"), quote!(crate::sai::DmaA)),
721 (("sai", "B"), quote!(crate::sai::DmaB)),
711 (("spi", "RX"), quote!(crate::spi::RxDma)), 722 (("spi", "RX"), quote!(crate::spi::RxDma)),
712 (("spi", "TX"), quote!(crate::spi::TxDma)), 723 (("spi", "TX"), quote!(crate::spi::TxDma)),
713 (("i2c", "RX"), quote!(crate::i2c::RxDma)), 724 (("i2c", "RX"), quote!(crate::i2c::RxDma)),
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 8c87ea7d5..b5a128596 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -55,6 +55,8 @@ pub mod qspi;
55pub mod rng; 55pub mod rng;
56#[cfg(all(rtc, not(rtc_v1)))] 56#[cfg(all(rtc, not(rtc_v1)))]
57pub mod rtc; 57pub mod rtc;
58#[cfg(sai)]
59pub mod sai;
58#[cfg(sdmmc)] 60#[cfg(sdmmc)]
59pub mod sdmmc; 61pub mod sdmmc;
60#[cfg(spi)] 62#[cfg(spi)]
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index ee9cb2897..72bdbd5db 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -33,6 +33,9 @@ pub struct Config {
33 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] 33 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
34 pub plli2s: Option<Hertz>, 34 pub plli2s: Option<Hertz>,
35 35
36 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
37 pub pllsai: Option<Hertz>,
38
36 pub pll48: bool, 39 pub pll48: bool,
37 pub rtc: Option<RtcClockSource>, 40 pub rtc: Option<RtcClockSource>,
38} 41}
@@ -48,11 +51,9 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
48 None 51 None
49} 52}
50 53
51#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] 54fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option<u32>, ) -> Option<(u32, u32, u32)> {
52fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
53 let min_div = 2; 55 let min_div = 2;
54 let max_div = 7; 56 let target = match target {
55 let target = match plli2s {
56 Some(target) => target, 57 Some(target) => target,
57 None => return None, 58 None => return None,
58 }; 59 };
@@ -76,15 +77,41 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
76 }) 77 })
77 .min_by_key(|(_, _, _, error)| *error)?; 78 .min_by_key(|(_, _, _, error)| *error)?;
78 79
80 Some((n, outdiv, output))
81}
82
83#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
84fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
85 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?;
86
79 RCC.plli2scfgr().modify(|w| { 87 RCC.plli2scfgr().modify(|w| {
80 w.set_plli2sn(n as u16); 88 w.set_plli2sn(n as u16);
81 w.set_plli2sr(outdiv as u8); 89 w.set_plli2sr(outdiv as u8);
90 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
91 w.set_plli2sq(outdiv as u8); //set sai divider same as i2s
82 }); 92 });
83 93
84 Some(output) 94 Some(output)
85} 95}
86 96
87fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pll48clk: bool) -> PllResults { 97#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
98fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
99 None
100}
101
102#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
103fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
104 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 15, pllsai)?;
105
106 RCC.pllsaicfgr().modify(|w| {
107 w.set_pllsain(n as u16);
108 w.set_pllsaiq(outdiv as u8);
109 });
110
111 Some(output)
112}
113
114fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pllsai: Option<u32>, pll48clk: bool) -> PllResults {
88 use crate::pac::rcc::vals::{Pllp, Pllsrc}; 115 use crate::pac::rcc::vals::{Pllp, Pllsrc};
89 116
90 let sysclk = pllsysclk.unwrap_or(pllsrcclk); 117 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
@@ -96,6 +123,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
96 pllsysclk: None, 123 pllsysclk: None,
97 pll48clk: None, 124 pll48clk: None,
98 plli2sclk: None, 125 plli2sclk: None,
126 pllsaiclk: None,
99 }; 127 };
100 } 128 }
101 // Input divisor from PLL source clock, must result to frequency in 129 // 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<u32>, plli2s: Opti
146 w.set_pllp(Pllp::from_bits(pllp as u8)); 174 w.set_pllp(Pllp::from_bits(pllp as u8));
147 w.set_pllq(pllq as u8); 175 w.set_pllq(pllq as u8);
148 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); 176 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
177 w.set_pllr(0);
149 }); 178 });
150 179
151 let real_pllsysclk = vco_in * plln / sysclk_div; 180 let real_pllsysclk = vco_in * plln / sysclk_div;
@@ -155,6 +184,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
155 pllsysclk: Some(real_pllsysclk), 184 pllsysclk: Some(real_pllsysclk),
156 pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, 185 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
157 plli2sclk: setup_i2s_pll(vco_in, plli2s), 186 plli2sclk: setup_i2s_pll(vco_in, plli2s),
187 pllsaiclk: setup_sai_pll(vco_in, pllsai),
158 } 188 }
159} 189}
160 190
@@ -344,6 +374,10 @@ pub(crate) unsafe fn init(config: Config) {
344 config.plli2s.map(|i2s| i2s.0), 374 config.plli2s.map(|i2s| i2s.0),
345 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] 375 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
346 None, 376 None,
377 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
378 config.pllsai.map(|sai| sai.0),
379 #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
380 None,
347 config.pll48, 381 config.pll48,
348 ); 382 );
349 383
@@ -441,6 +475,12 @@ pub(crate) unsafe fn init(config: Config) {
441 while !RCC.cr().read().plli2srdy() {} 475 while !RCC.cr().read().plli2srdy() {}
442 } 476 }
443 477
478 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
479 if plls.pllsaiclk.is_some() {
480 RCC.cr().modify(|w| w.set_pllsaion(true));
481 while !RCC.cr().read().pllsairdy() {}
482 }
483
444 RCC.cfgr().modify(|w| { 484 RCC.cfgr().modify(|w| {
445 w.set_ppre2(Ppre::from_bits(ppre2_bits)); 485 w.set_ppre2(Ppre::from_bits(ppre2_bits));
446 w.set_ppre1(Ppre::from_bits(ppre1_bits)); 486 w.set_ppre1(Ppre::from_bits(ppre1_bits));
@@ -496,7 +536,7 @@ pub(crate) unsafe fn init(config: Config) {
496 plli2s: plls.plli2sclk.map(Hertz), 536 plli2s: plls.plli2sclk.map(Hertz),
497 537
498 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 538 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
499 pllsai: None, 539 pllsai: plls.pllsaiclk.map(Hertz),
500 540
501 rtc: rtc, 541 rtc: rtc,
502 }); 542 });
@@ -508,6 +548,8 @@ struct PllResults {
508 pll48clk: Option<u32>, 548 pll48clk: Option<u32>,
509 #[allow(dead_code)] 549 #[allow(dead_code)]
510 plli2sclk: Option<u32>, 550 plli2sclk: Option<u32>,
551 #[allow(dead_code)]
552 pllsaiclk: Option<u32>,
511} 553}
512 554
513mod max { 555mod max {