Issue #1974 add SAI driver
This commit is contained in:
parent
f033089625
commit
ce91fb2bfc
@ -58,7 +58,7 @@ sdio-host = "0.5.0"
|
|||||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
atomic-polyfill = "1.0.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"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] }
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = "1.0.36"
|
proc-macro2 = "1.0.36"
|
||||||
quote = "1.0.15"
|
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]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
|
@ -425,6 +425,15 @@ fn main() {
|
|||||||
(("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
|
(("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
|
||||||
(("lpuart", "CK"), quote!(crate::usart::CkPin)),
|
(("lpuart", "CK"), quote!(crate::usart::CkPin)),
|
||||||
(("lpuart", "DE"), quote!(crate::usart::DePin)),
|
(("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", "SCK"), quote!(crate::spi::SckPin)),
|
||||||
(("spi", "MOSI"), quote!(crate::spi::MosiPin)),
|
(("spi", "MOSI"), quote!(crate::spi::MosiPin)),
|
||||||
(("spi", "MISO"), quote!(crate::spi::MisoPin)),
|
(("spi", "MISO"), quote!(crate::spi::MisoPin)),
|
||||||
@ -708,6 +717,8 @@ fn main() {
|
|||||||
(("usart", "TX"), quote!(crate::usart::TxDma)),
|
(("usart", "TX"), quote!(crate::usart::TxDma)),
|
||||||
(("lpuart", "RX"), quote!(crate::usart::RxDma)),
|
(("lpuart", "RX"), quote!(crate::usart::RxDma)),
|
||||||
(("lpuart", "TX"), quote!(crate::usart::TxDma)),
|
(("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", "RX"), quote!(crate::spi::RxDma)),
|
||||||
(("spi", "TX"), quote!(crate::spi::TxDma)),
|
(("spi", "TX"), quote!(crate::spi::TxDma)),
|
||||||
(("i2c", "RX"), quote!(crate::i2c::RxDma)),
|
(("i2c", "RX"), quote!(crate::i2c::RxDma)),
|
||||||
|
@ -55,6 +55,8 @@ pub mod qspi;
|
|||||||
pub mod rng;
|
pub mod rng;
|
||||||
#[cfg(all(rtc, not(rtc_v1)))]
|
#[cfg(all(rtc, not(rtc_v1)))]
|
||||||
pub mod rtc;
|
pub mod rtc;
|
||||||
|
#[cfg(sai)]
|
||||||
|
pub mod sai;
|
||||||
#[cfg(sdmmc)]
|
#[cfg(sdmmc)]
|
||||||
pub mod sdmmc;
|
pub mod sdmmc;
|
||||||
#[cfg(spi)]
|
#[cfg(spi)]
|
||||||
|
@ -33,6 +33,9 @@ pub struct Config {
|
|||||||
#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
|
#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
|
||||||
pub plli2s: Option<Hertz>,
|
pub plli2s: Option<Hertz>,
|
||||||
|
|
||||||
|
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
|
||||||
|
pub pllsai: Option<Hertz>,
|
||||||
|
|
||||||
pub pll48: bool,
|
pub pll48: bool,
|
||||||
pub rtc: Option<RtcClockSource>,
|
pub rtc: Option<RtcClockSource>,
|
||||||
}
|
}
|
||||||
@ -48,11 +51,9 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
|
fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option<u32>, ) -> Option<(u32, u32, u32)> {
|
||||||
fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
|
|
||||||
let min_div = 2;
|
let min_div = 2;
|
||||||
let max_div = 7;
|
let target = match target {
|
||||||
let target = match plli2s {
|
|
||||||
Some(target) => target,
|
Some(target) => target,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
@ -76,15 +77,41 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
|
|||||||
})
|
})
|
||||||
.min_by_key(|(_, _, _, error)| *error)?;
|
.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<u32>) -> Option<u32> {
|
||||||
|
let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?;
|
||||||
|
|
||||||
RCC.plli2scfgr().modify(|w| {
|
RCC.plli2scfgr().modify(|w| {
|
||||||
w.set_plli2sn(n as u16);
|
w.set_plli2sn(n as u16);
|
||||||
w.set_plli2sr(outdiv as u8);
|
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)
|
Some(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pll48clk: bool) -> PllResults {
|
#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
|
||||||
|
fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
|
||||||
|
fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
|
||||||
|
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<u32>, plli2s: Option<u32>, pllsai: Option<u32>, pll48clk: bool) -> PllResults {
|
||||||
use crate::pac::rcc::vals::{Pllp, Pllsrc};
|
use crate::pac::rcc::vals::{Pllp, Pllsrc};
|
||||||
|
|
||||||
let sysclk = pllsysclk.unwrap_or(pllsrcclk);
|
let sysclk = pllsysclk.unwrap_or(pllsrcclk);
|
||||||
@ -96,6 +123,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
|
|||||||
pllsysclk: None,
|
pllsysclk: None,
|
||||||
pll48clk: None,
|
pll48clk: None,
|
||||||
plli2sclk: None,
|
plli2sclk: None,
|
||||||
|
pllsaiclk: None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Input divisor from PLL source clock, must result to frequency in
|
// 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
|
|||||||
w.set_pllp(Pllp::from_bits(pllp as u8));
|
w.set_pllp(Pllp::from_bits(pllp as u8));
|
||||||
w.set_pllq(pllq as u8);
|
w.set_pllq(pllq as u8);
|
||||||
w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
|
w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
|
||||||
|
w.set_pllr(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
let real_pllsysclk = vco_in * plln / sysclk_div;
|
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
|
|||||||
pllsysclk: Some(real_pllsysclk),
|
pllsysclk: Some(real_pllsysclk),
|
||||||
pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
|
pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
|
||||||
plli2sclk: setup_i2s_pll(vco_in, plli2s),
|
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),
|
config.plli2s.map(|i2s| i2s.0),
|
||||||
#[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
|
#[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
|
||||||
None,
|
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,
|
config.pll48,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -441,6 +475,12 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
while !RCC.cr().read().plli2srdy() {}
|
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| {
|
RCC.cfgr().modify(|w| {
|
||||||
w.set_ppre2(Ppre::from_bits(ppre2_bits));
|
w.set_ppre2(Ppre::from_bits(ppre2_bits));
|
||||||
w.set_ppre1(Ppre::from_bits(ppre1_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),
|
plli2s: plls.plli2sclk.map(Hertz),
|
||||||
|
|
||||||
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
|
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
|
||||||
pllsai: None,
|
pllsai: plls.pllsaiclk.map(Hertz),
|
||||||
|
|
||||||
rtc: rtc,
|
rtc: rtc,
|
||||||
});
|
});
|
||||||
@ -508,6 +548,8 @@ struct PllResults {
|
|||||||
pll48clk: Option<u32>,
|
pll48clk: Option<u32>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
plli2sclk: Option<u32>,
|
plli2sclk: Option<u32>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pllsaiclk: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod max {
|
mod max {
|
||||||
|
Loading…
Reference in New Issue
Block a user