stm32/sai: fix build on chips with only SAI4 (like stm32h725re), improve sync config.

This commit is contained in:
Dario Nieuwenhuis 2023-11-19 22:02:57 +01:00
parent 5bc7557826
commit 5221705495
3 changed files with 40 additions and 32 deletions

1
ci.sh
View File

@ -110,6 +110,7 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h725re,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits,time \

View File

@ -61,6 +61,7 @@ fn main() {
let mut singletons: Vec<String> = Vec::new(); let mut singletons: Vec<String> = Vec::new();
for p in METADATA.peripherals { for p in METADATA.peripherals {
if let Some(r) = &p.registers { if let Some(r) = &p.registers {
println!("cargo:rustc-cfg=peri_{}", p.name.to_ascii_lowercase());
match r.kind { match r.kind {
// Generate singletons per pin, not per port // Generate singletons per pin, not per port
"gpio" => { "gpio" => {

View File

@ -207,27 +207,40 @@ impl Protocol {
} }
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum SyncEnable { pub enum SyncInput {
Asynchronous, /// Not synced to any other SAI unit.
None,
/// Syncs with the other A/B sub-block within the SAI unit /// Syncs with the other A/B sub-block within the SAI unit
Internal, Internal,
/// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input() /// Syncs with a sub-block in the other SAI unit
#[cfg(any(sai_v4))] #[cfg(sai_v4)]
External, External(SyncInputInstance),
} }
impl SyncEnable { impl SyncInput {
#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
pub const fn syncen(&self) -> vals::Syncen { pub const fn syncen(&self) -> vals::Syncen {
match self { match self {
SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, SyncInput::None => vals::Syncen::ASYNCHRONOUS,
SyncEnable::Internal => vals::Syncen::INTERNAL, SyncInput::Internal => vals::Syncen::INTERNAL,
#[cfg(any(sai_v4))] #[cfg(any(sai_v4))]
SyncEnable::External => vals::Syncen::EXTERNAL, SyncInput::External(_) => vals::Syncen::EXTERNAL,
} }
} }
} }
#[cfg(sai_v4)]
#[derive(Copy, Clone, PartialEq)]
pub enum SyncInputInstance {
#[cfg(peri_sai1)]
Sai1 = 0,
#[cfg(peri_sai2)]
Sai2 = 1,
#[cfg(peri_sai3)]
Sai3 = 2,
#[cfg(peri_sai4)]
Sai4 = 3,
}
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
pub enum StereoMono { pub enum StereoMono {
Stereo, Stereo,
@ -428,8 +441,8 @@ impl MasterClockDivider {
pub struct Config { pub struct Config {
pub mode: Mode, pub mode: Mode,
pub tx_rx: TxRx, pub tx_rx: TxRx,
pub sync_enable: SyncEnable, pub sync_input: SyncInput,
pub is_sync_output: bool, pub sync_output: bool,
pub protocol: Protocol, pub protocol: Protocol,
pub slot_size: SlotSize, pub slot_size: SlotSize,
pub slot_count: word::U4, pub slot_count: word::U4,
@ -459,8 +472,8 @@ impl Default for Config {
Self { Self {
mode: Mode::Master, mode: Mode::Master,
tx_rx: TxRx::Transmitter, tx_rx: TxRx::Transmitter,
is_sync_output: false, sync_output: false,
sync_enable: SyncEnable::Asynchronous, sync_input: SyncInput::None,
protocol: Protocol::Free, protocol: Protocol::Free,
slot_size: SlotSize::DataSize, slot_size: SlotSize::DataSize,
slot_count: word::U4(2), slot_count: word::U4(2),
@ -608,18 +621,18 @@ impl<'d, T: Instance> Sai<'d, T> {
fn update_synchronous_config(config: &mut Config) { fn update_synchronous_config(config: &mut Config) {
config.mode = Mode::Slave; config.mode = Mode::Slave;
config.is_sync_output = false; config.sync_output = false;
#[cfg(any(sai_v1, sai_v2, sai_v3))] #[cfg(any(sai_v1, sai_v2, sai_v3))]
{ {
config.sync_enable = SyncEnable::Internal; config.sync_input = SyncInput::Internal;
} }
#[cfg(any(sai_v4))] #[cfg(any(sai_v4))]
{ {
//this must either be Internal or External //this must either be Internal or External
//The asynchronous sub-block on the same SAI needs to enable is_sync_output //The asynchronous sub-block on the same SAI needs to enable sync_output
assert!(config.sync_enable != SyncEnable::Asynchronous); assert!(config.sync_input != SyncInput::None);
} }
} }
@ -866,20 +879,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
#[cfg(any(sai_v4))] #[cfg(any(sai_v4))]
{ {
// Not totally clear from the datasheet if this is right if let SyncInput::External(i) = config.sync_input {
// This is only used if using SyncEnable::External on the other SAI unit T::REGS.gcr().modify(|w| {
// Syncing from SAIX subblock A to subblock B does not require this w.set_syncin(i as u8);
// Only syncing from SAI1 subblock A/B to SAI2 subblock A/B });
let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { }
1 //this is SAI1, so sync with SAI2
} else {
0 //this is SAI2, so sync with SAI1
};
T::REGS.gcr().modify(|w| {
w.set_syncin(value);
});
if config.is_sync_output { if config.sync_output {
let syncout: u8 = match sub_block { let syncout: u8 = match sub_block {
WhichSubBlock::A => 0b01, WhichSubBlock::A => 0b01,
WhichSubBlock::B => 0b10, WhichSubBlock::B => 0b10,
@ -903,7 +909,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
w.set_ds(config.data_size.ds()); w.set_ds(config.data_size.ds());
w.set_lsbfirst(config.bit_order.lsbfirst()); w.set_lsbfirst(config.bit_order.lsbfirst());
w.set_ckstr(config.clock_strobe.ckstr()); w.set_ckstr(config.clock_strobe.ckstr());
w.set_syncen(config.sync_enable.syncen()); w.set_syncen(config.sync_input.syncen());
w.set_mono(config.stereo_mono.mono()); w.set_mono(config.stereo_mono.mono());
w.set_outdriv(config.output_drive.outdriv()); w.set_outdriv(config.output_drive.outdriv());
w.set_mckdiv(config.master_clock_divider.mckdiv()); w.set_mckdiv(config.master_clock_divider.mckdiv());