aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandros Liarokapis <[email protected]>2024-05-27 15:44:58 +0300
committerAlexandros Liarokapis <[email protected]>2024-05-27 17:49:47 +0300
commitf9324201b1d9375e12b4af9a6b2424fe3ff85d32 (patch)
tree20c548f83be76ab2b863963bd85d4c7ae557839a
parent8b9e2efec25ae36041038b70f608fe55f5061a1f (diff)
add proper rxonly support for spi_v3 and force tx dma stream requirement on others
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/dma/util.rs1
-rw-r--r--embassy-stm32/src/i2s.rs12
-rw-r--r--embassy-stm32/src/spi/mod.rs121
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"
72sdio-host = "0.5.0" 72sdio-host = "0.5.0"
73critical-section = "1.1" 73critical-section = "1.1"
74#stm32-metapac = { version = "15" } 74#stm32-metapac = { version = "15" }
75stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318" } 75stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad633a3e266151ea4d8fad630031a075ee02ab34" }
76 76
77vcell = "0.1.3" 77vcell = "0.1.3"
78nb = "1.0.0" 78nb = "1.0.0"
@@ -97,7 +97,7 @@ proc-macro2 = "1.0.36"
97quote = "1.0.15" 97quote = "1.0.15"
98 98
99#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 99#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
100stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-34c0188a682b32c32ff147d377e0629b1ebe8318", default-features = false, features = ["metadata"]} 100stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad633a3e266151ea4d8fad630031a075ee02ab34", default-features = false, features = ["metadata"]}
101 101
102[features] 102[features]
103default = ["rt"] 103default = ["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> {
48 Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) 48 Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options)
49 } 49 }
50 50
51 #[allow(dead_code)]
51 pub unsafe fn write_repeated<'a, W: Word>( 52 pub unsafe fn write_repeated<'a, W: Word>(
52 &'a mut self, 53 &'a mut self,
53 repeated: &'a W, 54 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> {
169 ws: impl Peripheral<P = impl WsPin<T>> + 'd, 169 ws: impl Peripheral<P = impl WsPin<T>> + 'd,
170 ck: impl Peripheral<P = impl CkPin<T>> + 'd, 170 ck: impl Peripheral<P = impl CkPin<T>> + 'd,
171 mck: impl Peripheral<P = impl MckPin<T>> + 'd, 171 mck: impl Peripheral<P = impl MckPin<T>> + 'd,
172 txdma: impl Peripheral<P = impl TxDma<T>> + 'd, 172 #[cfg(not(spi_v3))] txdma: impl Peripheral<P = impl TxDma<T>> + 'd,
173 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd, 173 rxdma: impl Peripheral<P = impl RxDma<T>> + 'd,
174 freq: Hertz, 174 freq: Hertz,
175 config: Config, 175 config: Config,
@@ -190,7 +190,15 @@ impl<'d> I2S<'d> {
190 190
191 let mut spi_cfg = SpiConfig::default(); 191 let mut spi_cfg = SpiConfig::default();
192 spi_cfg.frequency = freq; 192 spi_cfg.frequency = freq;
193 let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg); 193 let spi = Spi::new_internal(
194 peri,
195 #[cfg(not(spi_v3))]
196 new_dma!(txdma),
197 #[cfg(spi_v3)]
198 None,
199 new_dma!(rxdma),
200 spi_cfg,
201 );
194 202
195 // TODO move i2s to the new mux infra. 203 // TODO move i2s to the new mux infra.
196 //#[cfg(all(rcc_f4, not(stm32f410)))] 204 //#[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> {
508 peri: impl Peripheral<P = T> + 'd, 508 peri: impl Peripheral<P = T> + 'd,
509 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 509 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
510 miso: impl Peripheral<P = impl MisoPin<T>> + 'd, 510 miso: impl Peripheral<P = impl MisoPin<T>> + 'd,
511 #[cfg(not(spi_v3))] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
511 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, 512 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
512 config: Config, 513 config: Config,
513 ) -> Self { 514 ) -> Self {
@@ -516,6 +517,9 @@ impl<'d> Spi<'d, Async> {
516 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()), 517 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh, config.sck_pull_mode()),
517 None, 518 None,
518 new_pin!(miso, AFType::Input, Speed::VeryHigh), 519 new_pin!(miso, AFType::Input, Speed::VeryHigh),
520 #[cfg(not(spi_v3))]
521 new_dma!(tx_dma),
522 #[cfg(spi_v3)]
519 None, 523 None,
520 new_dma!(rx_dma), 524 new_dma!(rx_dma),
521 config, 525 config,
@@ -584,11 +588,11 @@ impl<'d> Spi<'d, Async> {
584 #[allow(dead_code)] 588 #[allow(dead_code)]
585 pub(crate) fn new_internal<T: Instance>( 589 pub(crate) fn new_internal<T: Instance>(
586 peri: impl Peripheral<P = T> + 'd, 590 peri: impl Peripheral<P = T> + 'd,
587 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, 591 tx_dma: Option<ChannelAndRequest<'d>>,
588 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, 592 rx_dma: Option<ChannelAndRequest<'d>>,
589 config: Config, 593 config: Config,
590 ) -> Self { 594 ) -> Self {
591 Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config) 595 Self::new_inner(peri, None, None, None, tx_dma, rx_dma, config)
592 } 596 }
593 597
594 /// SPI write, using DMA. 598 /// SPI write, using DMA.
@@ -623,11 +627,114 @@ impl<'d> Spi<'d, Async> {
623 627
624 /// SPI read, using DMA. 628 /// SPI read, using DMA.
625 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { 629 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
630 #[cfg(not(spi_v3))]
631 {
632 self.transmission_read(data).await
633 }
634 #[cfg(spi_v3)]
635 {
636 self.tsize_read(data).await
637 }
638 }
639
640 #[cfg(spi_v3)]
641 async fn tsize_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
642 if data.is_empty() {
643 return Ok(());
644 }
645
646 self.info.regs.cr1().modify(|w| {
647 w.set_spe(false);
648 });
649
650 let comm = self.info.regs.cfg2().modify(|w| {
651 let prev = w.comm();
652 w.set_comm(vals::Comm::RECEIVER);
653 prev
654 });
655
656 let i2scfg = self.info.regs.i2scfgr().modify(|w| {
657 let prev = w.i2scfg();
658 w.set_i2scfg(match prev {
659 vals::I2scfg::SLAVERX | vals::I2scfg::SLAVEFULLDUPLEX => vals::I2scfg::SLAVERX,
660 vals::I2scfg::MASTERRX | vals::I2scfg::MASTERFULLDUPLEX => vals::I2scfg::MASTERRX,
661 _ => panic!("unsupported configuration"),
662 });
663 prev
664 });
665
666 let tsize = self.info.regs.cr2().read().tsize();
667
668 let rx_src = self.info.regs.rx_ptr();
669
670 let mut read = 0;
671 let mut remaining = data.len();
672
673 loop {
674 self.set_word_size(W::CONFIG);
675 set_rxdmaen(self.info.regs, true);
676
677 let transfer_size = remaining.min(u16::max_value().into());
678
679 let transfer = unsafe {
680 self.rx_dma
681 .as_mut()
682 .unwrap()
683 .read(rx_src, &mut data[read..(read + transfer_size)], Default::default())
684 };
685
686 self.info.regs.cr2().modify(|w| {
687 w.set_tsize(transfer_size as u16);
688 });
689
690 self.info.regs.cr1().modify(|w| {
691 w.set_spe(true);
692 });
693
694 self.info.regs.cr1().modify(|w| {
695 w.set_cstart(true);
696 });
697
698 transfer.await;
699
700 finish_dma(self.info.regs);
701
702 remaining -= transfer_size;
703
704 if remaining == 0 {
705 break;
706 }
707
708 read += transfer_size;
709 }
710
711 self.info.regs.cr1().modify(|w| {
712 w.set_spe(false);
713 });
714
715 self.info.regs.cfg2().modify(|w| {
716 w.set_comm(comm);
717 });
718
719 self.info.regs.cr2().modify(|w| {
720 w.set_tsize(tsize);
721 });
722
723 self.info.regs.i2scfgr().modify(|w| {
724 w.set_i2scfg(i2scfg);
725 });
726
727 Ok(())
728 }
729
730 #[cfg(not(spi_v3))]
731 async fn transmission_read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
626 if data.is_empty() { 732 if data.is_empty() {
627 return Ok(()); 733 return Ok(());
628 } 734 }
629 735
630 self.set_word_size(W::CONFIG); 736 self.set_word_size(W::CONFIG);
737
631 self.info.regs.cr1().modify(|w| { 738 self.info.regs.cr1().modify(|w| {
632 w.set_spe(false); 739 w.set_spe(false);
633 }); 740 });
@@ -907,7 +1014,13 @@ fn finish_dma(regs: Regs) {
907 while regs.sr().read().ftlvl().to_bits() > 0 {} 1014 while regs.sr().read().ftlvl().to_bits() > 0 {}
908 1015
909 #[cfg(any(spi_v3, spi_v4, spi_v5))] 1016 #[cfg(any(spi_v3, spi_v4, spi_v5))]
910 while !regs.sr().read().txc() {} 1017 {
1018 if regs.cr2().read().tsize() == 0 {
1019 while !regs.sr().read().txc() {}
1020 } else {
1021 while !regs.sr().read().eot() {}
1022 }
1023 }
911 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 1024 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
912 while regs.sr().read().bsy() {} 1025 while regs.sr().read().bsy() {}
913 1026