diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index e5ba746e4c..e03f024273 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -115,7 +115,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Some(miso.map_into()), txdma, rxdma, - freq, + Some(freq), config, ) } @@ -144,7 +144,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Some(miso.map_into()), txdma, rxdma, - freq, + Some(freq), config, ) } @@ -173,7 +173,33 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { None, txdma, rxdma, - freq, + Some(freq), + config, + ) + } + + pub fn new_rxonly_slave( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + mosi: impl Peripheral

> + 'd, + txdma: impl Peripheral

+ 'd, // TODO remove + rxdma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(sck, mosi); + unsafe { + sck.set_as_af(sck.af_num(), AFType::Input); + mosi.set_as_af(mosi.af_num(), AFType::Input); + } + + Self::new_inner( + peri, + Some(sck.map_into()), + None, + Some(mosi.map_into()), /* miso/mosi reversed in slave mode */ + txdma, + rxdma, + None, config, ) } @@ -188,7 +214,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { freq: Hertz, config: Config, ) -> Self { - Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) + Self::new_inner(peri, None, None, None, txdma, rxdma, Some(freq), config) } fn new_inner( @@ -198,13 +224,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso: Option>, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, - freq: Hertz, + freq: Option, /* None in slave mode */ config: Config, ) -> Self { into_ref!(peri, txdma, rxdma); let pclk = T::frequency(); - let br = compute_baud_rate(pclk, freq.into()); + let br = freq.map(|f| compute_baud_rate(pclk, f.into())); let cpha = config.raw_phase(); let cpol = config.raw_polarity(); @@ -223,12 +249,17 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { w.set_cpha(cpha); w.set_cpol(cpol); - w.set_mstr(vals::Mstr::MASTER); - w.set_br(br); + if let Some(br) = br { + w.set_mstr(vals::Mstr::MASTER); + w.set_br(br); + w.set_ssm(true); + } else { + w.set_mstr(vals::Mstr::SLAVE); + w.set_ssm(false); + } w.set_spe(true); w.set_lsbfirst(lsbfirst); w.set_ssi(true); - w.set_ssm(true); w.set_crcen(false); w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); if mosi.is_none() { @@ -248,11 +279,16 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { w.set_cpha(cpha); w.set_cpol(cpol); - w.set_mstr(vals::Mstr::MASTER); - w.set_br(br); + if let Some(br) = br { + w.set_mstr(vals::Mstr::MASTER); + w.set_br(br); + w.set_ssm(true); + } else { + w.set_mstr(vals::Mstr::SLAVE); + w.set_ssm(false); + } w.set_lsbfirst(lsbfirst); w.set_ssi(true); - w.set_ssm(true); w.set_crcen(false); w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); w.set_spe(true); @@ -267,8 +303,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { w.set_cpha(cpha); w.set_cpol(cpol); w.set_lsbfirst(lsbfirst); - w.set_ssm(true); - w.set_master(vals::Master::MASTER); + if let Some(_) = br { + w.set_mstr(vals::Mstr::MASTER); + w.set_ssm(true); + } else { + w.set_mstr(vals::Mstr::SLAVE); + w.set_ssm(false); + } w.set_comm(vals::Comm::FULLDUPLEX); w.set_ssom(vals::Ssom::ASSERTED); w.set_midi(0); @@ -278,7 +319,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); T::REGS.cfg1().modify(|w| { w.set_crcen(false); - w.set_mbr(br); + if let Some(br) = br { + w.set_br(br); + } w.set_dsize(WordSize::EightBit.dsize()); }); T::REGS.cr2().modify(|w| { @@ -456,7 +499,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::REGS.cr1().modify(|w| { w.set_spe(false); }); - set_rxdmaen(T::REGS, true); } // SPIv3 clears rxfifo on SPE=0 @@ -470,12 +512,24 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { unsafe { self.rxdma.start_read(rx_request, rx_src, data, Default::default()) }; let rx_f = Transfer::new(&mut self.rxdma); + let master = unsafe { T::REGS.cr1().read().mstr() == vals::Mstr::MASTER }; let tx_request = self.txdma.request(); let tx_dst = T::REGS.tx_ptr(); let clock_byte = 0x00u8; - let tx_f = crate::dma::write_repeated(&mut self.txdma, tx_request, &clock_byte, clock_byte_count, tx_dst); + let tx_f = if master { + Some(crate::dma::write_repeated( + &mut self.txdma, + tx_request, + &clock_byte, + clock_byte_count, + tx_dst, + )) + } else { + None + }; unsafe { + set_rxdmaen(T::REGS, true); set_txdmaen(T::REGS, true); T::REGS.cr1().modify(|w| { w.set_spe(true); @@ -486,7 +540,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { }); } - join(tx_f, rx_f).await; + if let Some(tx_f) = tx_f { + join(tx_f, rx_f).await; + } else { + rx_f.await; + } finish_dma(T::REGS); @@ -510,7 +568,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::REGS.cr1().modify(|w| { w.set_spe(false); }); - set_rxdmaen(T::REGS, true); } // SPIv3 clears rxfifo on SPE=0 @@ -528,6 +585,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let tx_f = Transfer::new(&mut self.txdma); unsafe { + set_rxdmaen(T::REGS, true); set_txdmaen(T::REGS, true); T::REGS.cr1().modify(|w| { w.set_spe(true); @@ -769,7 +827,9 @@ fn finish_dma(regs: Regs) { #[cfg(any(spi_v3, spi_v4))] while !regs.sr().read().txc() {} #[cfg(not(any(spi_v3, spi_v4)))] - while regs.sr().read().bsy() {} + if regs.cr1().read().mstr() == vals::Mstr::MASTER { + while regs.sr().read().bsy() {} + } // Disable the spi peripheral regs.cr1().modify(|w| {