From f9324201b1d9375e12b4af9a6b2424fe3ff85d32 Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Mon, 27 May 2024 15:44:58 +0300 Subject: [PATCH 1/7] add proper rxonly support for spi_v3 and force tx dma stream requirement on others --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/dma/util.rs | 1 + embassy-stm32/src/i2s.rs | 12 +++- embassy-stm32/src/spi/mod.rs | 121 ++++++++++++++++++++++++++++++++-- 4 files changed, 130 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 5ef2366d9..67c61a671 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -72,7 +72,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad633a3e266151ea4d8fad630031a075ee02ab34" } vcell = "0.1.3" nb = "1.0.0" @@ -97,7 +97,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad633a3e266151ea4d8fad630031a075ee02ab34", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs index 962ea2501..5aaca57c9 100644 --- a/embassy-stm32/src/dma/util.rs +++ b/embassy-stm32/src/dma/util.rs @@ -48,6 +48,7 @@ impl<'d> ChannelAndRequest<'d> { Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) } + #[allow(dead_code)] pub unsafe fn write_repeated<'a, W: Word>( &'a mut self, repeated: &'a W, diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index c78810a38..9c0bbbb87 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -169,7 +169,7 @@ impl<'d> I2S<'d> { ws: impl Peripheral<P = impl WsPin<T>> + 'd, ck: impl Peripheral<P = impl CkPin<T>> + 'd, mck: impl Peripheral<P = impl MckPin<T>> + 'd, - txdma: impl Peripheral<P = impl TxDma<T>> + 'd, + #[cfg(not(spi_v3))] txdma: impl Peripheral<P = impl TxDma<T>> + 'd, rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, freq: Hertz, config: Config, @@ -190,7 +190,15 @@ impl<'d> I2S<'d> { let mut spi_cfg = SpiConfig::default(); spi_cfg.frequency = freq; - let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg); + let spi = Spi::new_internal( + peri, + #[cfg(not(spi_v3))] + new_dma!(txdma), + #[cfg(spi_v3)] + None, + new_dma!(rxdma), + spi_cfg, + ); // TODO move i2s to the new mux infra. //#[cfg(all(rcc_f4, not(stm32f410)))] diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 5fc8691ac..0a0afafc6 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -508,6 +508,7 @@ impl<'d> Spi<'d, Async> { peri: impl Peripheral<P = T> + 'd, sck: impl Peripheral<P = impl SckPin<T>> + 'd, miso: impl Peripheral<P = impl MisoPin<T>> + 'd, + #[cfg(not(spi_v3))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, config: Config, ) -> Self { @@ -516,6 +517,9 @@ impl<'d> Spi<'d, Async> { new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), None, new_pin!(miso, AFType::Input, Speed::VeryHigh), + #[cfg(not(spi_v3))] + new_dma!(tx_dma), + #[cfg(spi_v3)] None, new_dma!(rx_dma), config, @@ -584,11 +588,11 @@ impl<'d> Spi<'d, Async> { #[allow(dead_code)] pub(crate) fn new_internal<T: Instance>( peri: impl Peripheral<P = T> + 'd, - tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, - rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, + tx_dma: Option<ChannelAndRequest<'d>>, + rx_dma: Option<ChannelAndRequest<'d>>, config: Config, ) -> Self { - Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config) + Self::new_inner(peri, None, None, None, tx_dma, rx_dma, config) } /// SPI write, using DMA. @@ -623,11 +627,114 @@ impl<'d> Spi<'d, Async> { /// SPI read, using DMA. pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { + #[cfg(not(spi_v3))] + { + self.transmission_read(data).await + } + #[cfg(spi_v3)] + { + self.tsize_read(data).await + } + } + + #[cfg(spi_v3)] + async fn tsize_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { + if data.is_empty() { + return Ok(()); + } + + self.info.regs.cr1().modify(|w| { + w.set_spe(false); + }); + + let comm = self.info.regs.cfg2().modify(|w| { + let prev = w.comm(); + w.set_comm(vals::Comm::RECEIVER); + prev + }); + + let i2scfg = self.info.regs.i2scfgr().modify(|w| { + let prev = w.i2scfg(); + w.set_i2scfg(match prev { + vals::I2scfg::SLAVERX | vals::I2scfg::SLAVEFULLDUPLEX => vals::I2scfg::SLAVERX, + vals::I2scfg::MASTERRX | vals::I2scfg::MASTERFULLDUPLEX => vals::I2scfg::MASTERRX, + _ => panic!("unsupported configuration"), + }); + prev + }); + + let tsize = self.info.regs.cr2().read().tsize(); + + let rx_src = self.info.regs.rx_ptr(); + + let mut read = 0; + let mut remaining = data.len(); + + loop { + self.set_word_size(W::CONFIG); + set_rxdmaen(self.info.regs, true); + + let transfer_size = remaining.min(u16::max_value().into()); + + let transfer = unsafe { + self.rx_dma + .as_mut() + .unwrap() + .read(rx_src, &mut data[read..(read + transfer_size)], Default::default()) + }; + + self.info.regs.cr2().modify(|w| { + w.set_tsize(transfer_size as u16); + }); + + self.info.regs.cr1().modify(|w| { + w.set_spe(true); + }); + + self.info.regs.cr1().modify(|w| { + w.set_cstart(true); + }); + + transfer.await; + + finish_dma(self.info.regs); + + remaining -= transfer_size; + + if remaining == 0 { + break; + } + + read += transfer_size; + } + + self.info.regs.cr1().modify(|w| { + w.set_spe(false); + }); + + self.info.regs.cfg2().modify(|w| { + w.set_comm(comm); + }); + + self.info.regs.cr2().modify(|w| { + w.set_tsize(tsize); + }); + + self.info.regs.i2scfgr().modify(|w| { + w.set_i2scfg(i2scfg); + }); + + Ok(()) + } + + #[cfg(not(spi_v3))] + async fn transmission_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); } self.set_word_size(W::CONFIG); + self.info.regs.cr1().modify(|w| { w.set_spe(false); }); @@ -907,7 +1014,13 @@ fn finish_dma(regs: Regs) { while regs.sr().read().ftlvl().to_bits() > 0 {} #[cfg(any(spi_v3, spi_v4, spi_v5))] - while !regs.sr().read().txc() {} + { + if regs.cr2().read().tsize() == 0 { + while !regs.sr().read().txc() {} + } else { + while !regs.sr().read().eot() {} + } + } #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] while regs.sr().read().bsy() {} From 76fbec74da30c5cd04b441aa49414a286170a491 Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Mon, 27 May 2024 20:43:17 +0300 Subject: [PATCH 2/7] fix spi panic on read due to i2s configuration conversion check --- embassy-stm32/src/spi/mod.rs | 52 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 0a0afafc6..0b12bc9b6 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -643,36 +643,40 @@ impl<'d> Spi<'d, Async> { return Ok(()); } - self.info.regs.cr1().modify(|w| { + let regs = self.info.regs; + + regs.cr1().modify(|w| { w.set_spe(false); }); - let comm = self.info.regs.cfg2().modify(|w| { + let comm = regs.cfg2().modify(|w| { let prev = w.comm(); w.set_comm(vals::Comm::RECEIVER); prev }); - let i2scfg = self.info.regs.i2scfgr().modify(|w| { - let prev = w.i2scfg(); - w.set_i2scfg(match prev { - vals::I2scfg::SLAVERX | vals::I2scfg::SLAVEFULLDUPLEX => vals::I2scfg::SLAVERX, - vals::I2scfg::MASTERRX | vals::I2scfg::MASTERFULLDUPLEX => vals::I2scfg::MASTERRX, - _ => panic!("unsupported configuration"), - }); - prev + let i2scfg = regs.i2scfgr().modify(|w| { + w.i2smod().then(|| { + let prev = w.i2scfg(); + w.set_i2scfg(match prev { + vals::I2scfg::SLAVERX | vals::I2scfg::SLAVEFULLDUPLEX => vals::I2scfg::SLAVERX, + vals::I2scfg::MASTERRX | vals::I2scfg::MASTERFULLDUPLEX => vals::I2scfg::MASTERRX, + _ => panic!("unsupported configuration"), + }); + prev + }) }); - let tsize = self.info.regs.cr2().read().tsize(); + let tsize = regs.cr2().read().tsize(); - let rx_src = self.info.regs.rx_ptr(); + let rx_src = regs.rx_ptr(); let mut read = 0; let mut remaining = data.len(); loop { self.set_word_size(W::CONFIG); - set_rxdmaen(self.info.regs, true); + set_rxdmaen(regs, true); let transfer_size = remaining.min(u16::max_value().into()); @@ -683,21 +687,21 @@ impl<'d> Spi<'d, Async> { .read(rx_src, &mut data[read..(read + transfer_size)], Default::default()) }; - self.info.regs.cr2().modify(|w| { + regs.cr2().modify(|w| { w.set_tsize(transfer_size as u16); }); - self.info.regs.cr1().modify(|w| { + regs.cr1().modify(|w| { w.set_spe(true); }); - self.info.regs.cr1().modify(|w| { + regs.cr1().modify(|w| { w.set_cstart(true); }); transfer.await; - finish_dma(self.info.regs); + finish_dma(regs); remaining -= transfer_size; @@ -708,21 +712,23 @@ impl<'d> Spi<'d, Async> { read += transfer_size; } - self.info.regs.cr1().modify(|w| { + regs.cr1().modify(|w| { w.set_spe(false); }); - self.info.regs.cfg2().modify(|w| { + regs.cfg2().modify(|w| { w.set_comm(comm); }); - self.info.regs.cr2().modify(|w| { + regs.cr2().modify(|w| { w.set_tsize(tsize); }); - self.info.regs.i2scfgr().modify(|w| { - w.set_i2scfg(i2scfg); - }); + if let Some(i2scfg) = i2scfg { + regs.i2scfgr().modify(|w| { + w.set_i2scfg(i2scfg); + }); + } Ok(()) } From 1d05015a1c6b79d9cf7f93d16718508f3f80fc7e Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Mon, 27 May 2024 20:42:29 +0300 Subject: [PATCH 3/7] broaden tsize read support to other spi versions --- embassy-stm32/src/spi/mod.rs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 0b12bc9b6..a3578dfde 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -508,7 +508,7 @@ impl<'d> Spi<'d, Async> { peri: impl Peripheral<P = T> + 'd, sck: impl Peripheral<P = impl SckPin<T>> + 'd, miso: impl Peripheral<P = impl MisoPin<T>> + 'd, - #[cfg(not(spi_v3))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, + #[cfg(any(spi_v1, spi_f1))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, config: Config, ) -> Self { @@ -517,9 +517,9 @@ impl<'d> Spi<'d, Async> { new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), None, new_pin!(miso, AFType::Input, Speed::VeryHigh), - #[cfg(not(spi_v3))] + #[cfg(any(spi_v1, spi_f1))] new_dma!(tx_dma), - #[cfg(spi_v3)] + #[cfg(any(spi_v2, spi_v3, spi_v4, spi_v5))] None, new_dma!(rx_dma), config, @@ -626,19 +626,8 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. + #[cfg(any(spi_v2, spi_v3, spi_v4, spi_v5))] pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { - #[cfg(not(spi_v3))] - { - self.transmission_read(data).await - } - #[cfg(spi_v3)] - { - self.tsize_read(data).await - } - } - - #[cfg(spi_v3)] - async fn tsize_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); } @@ -733,8 +722,9 @@ impl<'d> Spi<'d, Async> { Ok(()) } - #[cfg(not(spi_v3))] - async fn transmission_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { + /// SPI read, using DMA. + #[cfg(any(spi_v1, spi_f1))] + pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); } From 9a6ed79ad124c8a22f6833c2c4f9637661a5bbdb Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Mon, 27 May 2024 20:51:50 +0300 Subject: [PATCH 4/7] remove rx-only support for new spi versions with missing I2SCFGR register --- embassy-stm32/src/spi/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index a3578dfde..d9b6f0003 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -508,7 +508,7 @@ impl<'d> Spi<'d, Async> { peri: impl Peripheral<P = T> + 'd, sck: impl Peripheral<P = impl SckPin<T>> + 'd, miso: impl Peripheral<P = impl MisoPin<T>> + 'd, - #[cfg(any(spi_v1, spi_f1))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, + #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, config: Config, ) -> Self { @@ -517,9 +517,9 @@ impl<'d> Spi<'d, Async> { new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), None, new_pin!(miso, AFType::Input, Speed::VeryHigh), - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] new_dma!(tx_dma), - #[cfg(any(spi_v2, spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v2, spi_v3))] None, new_dma!(rx_dma), config, @@ -626,7 +626,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v2, spi_v3, spi_v4, spi_v5))] + #[cfg(any(spi_v2, spi_v3))] pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); @@ -723,7 +723,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v1, spi_f1))] + #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); From 46fc15783d226d66aa93e38c0b36c8cac9b71700 Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Tue, 28 May 2024 12:50:24 +0300 Subject: [PATCH 5/7] add spi_v4 and spi_v5 support but block i2scfg rx-only configuration --- embassy-stm32/src/spi/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index d9b6f0003..109b2738b 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -508,7 +508,7 @@ impl<'d> Spi<'d, Async> { peri: impl Peripheral<P = T> + 'd, sck: impl Peripheral<P = impl SckPin<T>> + 'd, miso: impl Peripheral<P = impl MisoPin<T>> + 'd, - #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, + #[cfg(any(spi_v1, spi_f1, spi_v2))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, config: Config, ) -> Self { @@ -517,9 +517,9 @@ impl<'d> Spi<'d, Async> { new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), None, new_pin!(miso, AFType::Input, Speed::VeryHigh), - #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] + #[cfg(any(spi_v1, spi_f1, spi_v2))] new_dma!(tx_dma), - #[cfg(any(spi_v2, spi_v3))] + #[cfg(any(spi_v3, spi_v4, spi_v5))] None, new_dma!(rx_dma), config, @@ -626,7 +626,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v2, spi_v3))] + #[cfg(any(spi_v3, spi_v4, spi_v5))] pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); @@ -644,6 +644,7 @@ impl<'d> Spi<'d, Async> { prev }); + #[cfg(spi_v3)] let i2scfg = regs.i2scfgr().modify(|w| { w.i2smod().then(|| { let prev = w.i2scfg(); @@ -713,6 +714,7 @@ impl<'d> Spi<'d, Async> { w.set_tsize(tsize); }); + #[cfg(spi_v3)] if let Some(i2scfg) = i2scfg { regs.i2scfgr().modify(|w| { w.set_i2scfg(i2scfg); @@ -723,7 +725,7 @@ impl<'d> Spi<'d, Async> { } /// SPI read, using DMA. - #[cfg(any(spi_v1, spi_f1, spi_v4, spi_v5))] + #[cfg(any(spi_v1, spi_f1, spi_v2))] pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { if data.is_empty() { return Ok(()); From 4d1fbcd9cd42ebc3169008e189fcd98dce1c427d Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Tue, 28 May 2024 13:38:27 +0300 Subject: [PATCH 6/7] address review comments --- embassy-stm32/src/spi/mod.rs | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 109b2738b..7fb8da5ac 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -657,28 +657,23 @@ impl<'d> Spi<'d, Async> { }) }); - let tsize = regs.cr2().read().tsize(); - let rx_src = regs.rx_ptr(); - let mut read = 0; - let mut remaining = data.len(); - - loop { + for mut chunk in data.chunks_mut(u16::max_value().into()) { self.set_word_size(W::CONFIG); set_rxdmaen(regs, true); - let transfer_size = remaining.min(u16::max_value().into()); + let tsize = chunk.len(); let transfer = unsafe { self.rx_dma .as_mut() .unwrap() - .read(rx_src, &mut data[read..(read + transfer_size)], Default::default()) + .read(rx_src, &mut chunk, Default::default()) }; regs.cr2().modify(|w| { - w.set_tsize(transfer_size as u16); + w.set_tsize(tsize as u16); }); regs.cr1().modify(|w| { @@ -692,14 +687,6 @@ impl<'d> Spi<'d, Async> { transfer.await; finish_dma(regs); - - remaining -= transfer_size; - - if remaining == 0 { - break; - } - - read += transfer_size; } regs.cr1().modify(|w| { @@ -711,7 +698,7 @@ impl<'d> Spi<'d, Async> { }); regs.cr2().modify(|w| { - w.set_tsize(tsize); + w.set_tsize(0); }); #[cfg(spi_v3)] From 4f76f6b9df72c10f039911d0e35ca504be750564 Mon Sep 17 00:00:00 2001 From: Alexandros Liarokapis <liarokapis.v@gmail.com> Date: Tue, 28 May 2024 15:24:05 +0300 Subject: [PATCH 7/7] add spi_dma rx-only test --- tests/stm32/src/bin/spi_dma.rs | 65 +++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs index 5d46726dd..30e679f2a 100644 --- a/tests/stm32/src/bin/spi_dma.rs +++ b/tests/stm32/src/bin/spi_dma.rs @@ -8,27 +8,33 @@ use defmt::assert_eq; use embassy_executor::Spawner; use embassy_stm32::spi::{self, Spi}; use embassy_stm32::time::Hertz; +use embassy_stm32::{into_ref, Peripheral as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config()); info!("Hello World!"); - let spi = peri!(p, SPI); + let spi_peri = peri!(p, SPI); let sck = peri!(p, SPI_SCK); let mosi = peri!(p, SPI_MOSI); let miso = peri!(p, SPI_MISO); let tx_dma = peri!(p, SPI_TX_DMA); let rx_dma = peri!(p, SPI_RX_DMA); + into_ref!(spi_peri, sck, mosi, miso, tx_dma, rx_dma); + let mut spi_config = spi::Config::default(); spi_config.frequency = Hertz(1_000_000); let mut spi = Spi::new( - spi, sck, // Arduino D13 - mosi, // Arduino D11 - miso, // Arduino D12 - tx_dma, rx_dma, spi_config, + spi_peri.reborrow(), + sck.reborrow(), // Arduino D13 + mosi.reborrow(), // Arduino D11 + miso.reborrow(), // Arduino D12 + tx_dma.reborrow(), + rx_dma.reborrow(), + spi_config, ); let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE]; @@ -76,6 +82,55 @@ async fn main(_spawner: Spawner) { spi.blocking_read(&mut buf).unwrap(); spi.write(&buf).await.unwrap(); + core::mem::drop(spi); + + // test rx-only configuration + + // stm32f207zg - spi_v1 + // stm32f103c8 - spi_f1 + // stm32g491re - spi_v2 + // stm32h753zi - spi_v3 + // stm32h563zi - spi_v4 + // stm32wba52cg - spi_v5 + + #[cfg(any(stm32f207zg, stm32f103c8, stm32g491re, stm32h753zi, stm32h563zi, stm32wba52cg))] + { + let mut spi = { + #[cfg(stm32f207zg, stm32f103c8, stm32g491re)] + { + Spi::new_rxonly( + spi_peri.reborrow(), + sck.reborrow(), + miso.reborrow(), + tx_dma.reborrow(), + rx_dma.reborrow(), + spi_config, + ) + } + #[cfg(stm32h753zi, stm32h563zi, stm32wba52cg)] + { + Spi::new_rxonly( + spi_peri.reborrow(), + sck.reborrow(), + miso.reborrow(), + rx_dma.reborrow(), + spi_config, + ) + } + }; + + use embassy_stm32::gpio; + let mut mosi = gpio::Output::new(mosi.reborrow(), gpio::Level::Low, gpio::Speed::Low); + + mosi.set_high(); + spi.read(&mut buf).await.unwrap(); + assert_eq!(buf, [0xff; 9]); + + mosi.set_low(); + spi.read(&mut buf).await.unwrap(); + assert_eq!(buf, [0x00; 9]); + }; + info!("Test OK"); cortex_m::asm::bkpt(); }