stm32/sai: fix build on chips with only SAI4 (like stm32h725re), improve sync config.
This commit is contained in:
		
							
								
								
									
										1
									
								
								ci.sh
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								ci.sh
									
									
									
									
									
								
							@@ -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 \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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" => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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());
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user