aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-15 01:39:38 +0000
committerGitHub <[email protected]>2022-03-15 01:39:38 +0000
commitff1215c6f9295d960c5111d30f27ca047605414d (patch)
treecf065e87589733f37d7c15c99d20b5e9132cd4c4
parent8ef8ab170766051be22cc93ec0359f1f95dc6027 (diff)
parent059b16423458a80c5cb4e1630260d6c564a88e84 (diff)
Merge #664
664: stm32: more spi fixes r=Dirbaio a=Dirbaio Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-stm32/src/spi/mod.rs77
-rw-r--r--tests/stm32/src/bin/spi.rs21
-rw-r--r--tests/stm32/src/bin/spi_dma.rs21
3 files changed, 84 insertions, 35 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 5271d941c..d8ffabb11 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -7,7 +7,7 @@ use embassy_hal_common::unborrow;
7use futures::future::join; 7use futures::future::join;
8 8
9use self::sealed::WordSize; 9use self::sealed::WordSize;
10use crate::dma::{NoDma, Transfer}; 10use crate::dma::{slice_ptr_parts, NoDma, Transfer};
11use crate::gpio::sealed::{AFType, Pin as _}; 11use crate::gpio::sealed::{AFType, Pin as _};
12use crate::gpio::AnyPin; 12use crate::gpio::AnyPin;
13use crate::pac::spi::Spi as Regs; 13use crate::pac::spi::Spi as Regs;
@@ -440,9 +440,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
440 440
441 tx_f.await; 441 tx_f.await;
442 442
443 // flush here otherwise `finish_dma` hangs waiting for the rx fifo to empty
444 flush_rx_fifo(T::REGS);
445
446 finish_dma(T::REGS); 443 finish_dma(T::REGS);
447 444
448 Ok(()) 445 Ok(())
@@ -465,6 +462,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
465 set_rxdmaen(T::REGS, true); 462 set_rxdmaen(T::REGS, true);
466 } 463 }
467 464
465 // SPIv3 clears rxfifo on SPE=0
466 #[cfg(not(spi_v3))]
467 flush_rx_fifo(T::REGS);
468
468 let clock_byte_count = data.len(); 469 let clock_byte_count = data.len();
469 470
470 let rx_request = self.rxdma.request(); 471 let rx_request = self.rxdma.request();
@@ -501,14 +502,19 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
501 Ok(()) 502 Ok(())
502 } 503 }
503 504
504 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> 505 async fn transfer_inner<W: Word>(
506 &mut self,
507 read: *mut [W],
508 write: *const [W],
509 ) -> Result<(), Error>
505 where 510 where
506 Tx: TxDma<T>, 511 Tx: TxDma<T>,
507 Rx: RxDma<T>, 512 Rx: RxDma<T>,
508 { 513 {
509 assert_eq!(read.len(), write.len()); 514 let (_, rx_len) = slice_ptr_parts(read);
510 515 let (_, tx_len) = slice_ptr_parts(write);
511 if read.len() == 0 { 516 assert_eq!(rx_len, tx_len);
517 if rx_len == 0 {
512 return Ok(()); 518 return Ok(());
513 } 519 }
514 520
@@ -520,8 +526,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
520 set_rxdmaen(T::REGS, true); 526 set_rxdmaen(T::REGS, true);
521 } 527 }
522 528
523 // TODO: This is unnecessary in some versions because 529 // SPIv3 clears rxfifo on SPE=0
524 // clearing SPE automatically clears the fifos 530 #[cfg(not(spi_v3))]
525 flush_rx_fifo(T::REGS); 531 flush_rx_fifo(T::REGS);
526 532
527 let rx_request = self.rxdma.request(); 533 let rx_request = self.rxdma.request();
@@ -552,6 +558,22 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
552 Ok(()) 558 Ok(())
553 } 559 }
554 560
561 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error>
562 where
563 Tx: TxDma<T>,
564 Rx: RxDma<T>,
565 {
566 self.transfer_inner(read, write).await
567 }
568
569 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error>
570 where
571 Tx: TxDma<T>,
572 Rx: RxDma<T>,
573 {
574 self.transfer_inner(data, data).await
575 }
576
555 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { 577 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
556 self.set_word_size(W::WORDSIZE); 578 self.set_word_size(W::WORDSIZE);
557 for word in words.iter() { 579 for word in words.iter() {
@@ -705,26 +727,7 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
705 } 727 }
706} 728}
707 729
708fn spin_until_idle(regs: Regs) { 730#[cfg(not(spi_v3))]
709 #[cfg(any(spi_v1, spi_f1))]
710 unsafe {
711 while regs.sr().read().bsy() {}
712 }
713
714 #[cfg(spi_v2)]
715 unsafe {
716 while regs.sr().read().ftlvl() > 0 {}
717 while regs.sr().read().frlvl() > 0 {}
718 while regs.sr().read().bsy() {}
719 }
720
721 #[cfg(spi_v3)]
722 unsafe {
723 while !regs.sr().read().txc() {}
724 while regs.sr().read().rxplvl().0 > 0 {}
725 }
726}
727
728fn flush_rx_fifo(regs: Regs) { 731fn flush_rx_fifo(regs: Regs) {
729 unsafe { 732 unsafe {
730 #[cfg(not(spi_v3))] 733 #[cfg(not(spi_v3))]
@@ -765,9 +768,15 @@ fn set_rxdmaen(regs: Regs, val: bool) {
765} 768}
766 769
767fn finish_dma(regs: Regs) { 770fn finish_dma(regs: Regs) {
768 spin_until_idle(regs);
769
770 unsafe { 771 unsafe {
772 #[cfg(spi_v2)]
773 while regs.sr().read().ftlvl() > 0 {}
774
775 #[cfg(spi_v3)]
776 while !regs.sr().read().txc() {}
777 #[cfg(not(spi_v3))]
778 while regs.sr().read().bsy() {}
779
771 regs.cr1().modify(|w| { 780 regs.cr1().modify(|w| {
772 w.set_spe(false); 781 w.set_spe(false);
773 }); 782 });
@@ -935,9 +944,7 @@ cfg_if::cfg_if! {
935 &'a mut self, 944 &'a mut self,
936 words: &'a mut [W], 945 words: &'a mut [W],
937 ) -> Self::TransferInPlaceFuture<'a> { 946 ) -> Self::TransferInPlaceFuture<'a> {
938 // TODO: Implement async version 947 self.transfer_in_place(words)
939 let result = self.blocking_transfer_in_place(words);
940 async move { result }
941 } 948 }
942 } 949 }
943 } 950 }
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index 47d0017ac..b079472d5 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -37,9 +37,30 @@ async fn main(_spawner: Spawner, p: Peripherals) {
37 // Arduino pins D11 and D12 (MOSI-MISO) are connected together with a 1K resistor. 37 // Arduino pins D11 and D12 (MOSI-MISO) are connected together with a 1K resistor.
38 // so we should get the data we sent back. 38 // so we should get the data we sent back.
39 let mut buf = data; 39 let mut buf = data;
40 spi.blocking_transfer(&mut buf, &data).unwrap();
41 assert_eq!(buf, data);
42
40 spi.blocking_transfer_in_place(&mut buf).unwrap(); 43 spi.blocking_transfer_in_place(&mut buf).unwrap();
41 assert_eq!(buf, data); 44 assert_eq!(buf, data);
42 45
46 // Check read/write don't hang. We can't check they transfer the right data
47 // without fancier test mechanisms.
48 spi.blocking_write(&buf).unwrap();
49 spi.blocking_read(&mut buf).unwrap();
50 spi.blocking_write(&buf).unwrap();
51 spi.blocking_read(&mut buf).unwrap();
52 spi.blocking_write(&buf).unwrap();
53
54 // Check transfer doesn't break after having done a write, due to garbage in the FIFO
55 spi.blocking_transfer(&mut buf, &data).unwrap();
56 assert_eq!(buf, data);
57
58 // Check zero-length operations, these should be noops.
59 spi.blocking_transfer::<u8>(&mut [], &[]).unwrap();
60 spi.blocking_transfer_in_place::<u8>(&mut []).unwrap();
61 spi.blocking_read::<u8>(&mut []).unwrap();
62 spi.blocking_write::<u8>(&[]).unwrap();
63
43 info!("Test OK"); 64 info!("Test OK");
44 cortex_m::asm::bkpt(); 65 cortex_m::asm::bkpt();
45} 66}
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs
index 59a5bcd0c..3e9521ae7 100644
--- a/tests/stm32/src/bin/spi_dma.rs
+++ b/tests/stm32/src/bin/spi_dma.rs
@@ -47,6 +47,27 @@ async fn main(_spawner: Spawner, p: Peripherals) {
47 spi.transfer(&mut buf, &data).await.unwrap(); 47 spi.transfer(&mut buf, &data).await.unwrap();
48 assert_eq!(buf, data); 48 assert_eq!(buf, data);
49 49
50 spi.transfer_in_place(&mut buf).await.unwrap();
51 assert_eq!(buf, data);
52
53 // Check read/write don't hang. We can't check they transfer the right data
54 // without fancier test mechanisms.
55 spi.write(&buf).await.unwrap();
56 spi.read(&mut buf).await.unwrap();
57 spi.write(&buf).await.unwrap();
58 spi.read(&mut buf).await.unwrap();
59 spi.write(&buf).await.unwrap();
60
61 // Check transfer doesn't break after having done a write, due to garbage in the FIFO
62 spi.transfer(&mut buf, &data).await.unwrap();
63 assert_eq!(buf, data);
64
65 // Check zero-length operations, these should be noops.
66 spi.transfer::<u8>(&mut [], &[]).await.unwrap();
67 spi.transfer_in_place::<u8>(&mut []).await.unwrap();
68 spi.read::<u8>(&mut []).await.unwrap();
69 spi.write::<u8>(&[]).await.unwrap();
70
50 info!("Test OK"); 71 info!("Test OK");
51 cortex_m::asm::bkpt(); 72 cortex_m::asm::bkpt();
52} 73}