aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/spi
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-04-26 23:57:26 +0200
committerDario Nieuwenhuis <[email protected]>2022-04-27 01:16:14 +0200
commit009bb8e4e1b7afbe9d9d7d89135f8d4dd3c4e808 (patch)
treed734f3e82f9fb3c22b7517a70e1f47969624d248 /embassy-stm32/src/spi
parenta39d796c3de9c96ea4df6b9da525cb0d5ef60fc0 (diff)
stm32: add stm32u5 GPDMA, SPIv4 support, add HIL tests.
Diffstat (limited to 'embassy-stm32/src/spi')
-rw-r--r--embassy-stm32/src/spi/mod.rs87
1 files changed, 43 insertions, 44 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index ea0c496db..23240ad82 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -100,13 +100,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
100 unborrow!(sck, mosi, miso); 100 unborrow!(sck, mosi, miso);
101 unsafe { 101 unsafe {
102 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 102 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
103 #[cfg(any(spi_v2, spi_v3))] 103 #[cfg(any(spi_v2, spi_v3, spi_v4))]
104 sck.set_speed(crate::gpio::Speed::VeryHigh); 104 sck.set_speed(crate::gpio::Speed::VeryHigh);
105 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 105 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
106 #[cfg(any(spi_v2, spi_v3))] 106 #[cfg(any(spi_v2, spi_v3, spi_v4))]
107 mosi.set_speed(crate::gpio::Speed::VeryHigh); 107 mosi.set_speed(crate::gpio::Speed::VeryHigh);
108 miso.set_as_af(miso.af_num(), AFType::Input); 108 miso.set_as_af(miso.af_num(), AFType::Input);
109 #[cfg(any(spi_v2, spi_v3))] 109 #[cfg(any(spi_v2, spi_v3, spi_v4))]
110 miso.set_speed(crate::gpio::Speed::VeryHigh); 110 miso.set_speed(crate::gpio::Speed::VeryHigh);
111 } 111 }
112 112
@@ -137,10 +137,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
137 unborrow!(sck, miso); 137 unborrow!(sck, miso);
138 unsafe { 138 unsafe {
139 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 139 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
140 #[cfg(any(spi_v2, spi_v3))] 140 #[cfg(any(spi_v2, spi_v3, spi_v4))]
141 sck.set_speed(crate::gpio::Speed::VeryHigh); 141 sck.set_speed(crate::gpio::Speed::VeryHigh);
142 miso.set_as_af(miso.af_num(), AFType::Input); 142 miso.set_as_af(miso.af_num(), AFType::Input);
143 #[cfg(any(spi_v2, spi_v3))] 143 #[cfg(any(spi_v2, spi_v3, spi_v4))]
144 miso.set_speed(crate::gpio::Speed::VeryHigh); 144 miso.set_speed(crate::gpio::Speed::VeryHigh);
145 } 145 }
146 146
@@ -171,10 +171,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
171 unborrow!(sck, mosi); 171 unborrow!(sck, mosi);
172 unsafe { 172 unsafe {
173 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 173 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
174 #[cfg(any(spi_v2, spi_v3))] 174 #[cfg(any(spi_v2, spi_v3, spi_v4))]
175 sck.set_speed(crate::gpio::Speed::VeryHigh); 175 sck.set_speed(crate::gpio::Speed::VeryHigh);
176 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); 176 mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull);
177 #[cfg(any(spi_v2, spi_v3))] 177 #[cfg(any(spi_v2, spi_v3, spi_v4))]
178 mosi.set_speed(crate::gpio::Speed::VeryHigh); 178 mosi.set_speed(crate::gpio::Speed::VeryHigh);
179 } 179 }
180 180
@@ -260,7 +260,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
260 w.set_spe(true); 260 w.set_spe(true);
261 }); 261 });
262 } 262 }
263 #[cfg(spi_v3)] 263 #[cfg(any(spi_v3, spi_v4))]
264 unsafe { 264 unsafe {
265 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff); 265 T::REGS.ifcr().write(|w| w.0 = 0xffff_ffff);
266 T::REGS.cfg2().modify(|w| { 266 T::REGS.cfg2().modify(|w| {
@@ -285,7 +285,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
285 }); 285 });
286 T::REGS.cr2().modify(|w| { 286 T::REGS.cr2().modify(|w| {
287 w.set_tsize(0); 287 w.set_tsize(0);
288 w.set_tser(0);
289 }); 288 });
290 T::REGS.cr1().modify(|w| { 289 T::REGS.cr1().modify(|w| {
291 w.set_ssi(false); 290 w.set_ssi(false);
@@ -320,7 +319,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
320 }); 319 });
321 } 320 }
322 321
323 #[cfg(spi_v3)] 322 #[cfg(any(spi_v3, spi_v4))]
324 unsafe { 323 unsafe {
325 T::REGS.cfg2().modify(|w| { 324 T::REGS.cfg2().modify(|w| {
326 w.set_cpha(cpha); 325 w.set_cpha(cpha);
@@ -333,7 +332,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
333 pub fn get_current_config(&self) -> Config { 332 pub fn get_current_config(&self) -> Config {
334 #[cfg(any(spi_v1, spi_f1, spi_v2))] 333 #[cfg(any(spi_v1, spi_f1, spi_v2))]
335 let cfg = unsafe { T::REGS.cr1().read() }; 334 let cfg = unsafe { T::REGS.cr1().read() };
336 #[cfg(spi_v3)] 335 #[cfg(any(spi_v3, spi_v4))]
337 let cfg = unsafe { T::REGS.cfg2().read() }; 336 let cfg = unsafe { T::REGS.cfg2().read() };
338 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { 337 let polarity = if cfg.cpol() == vals::Cpol::IDLELOW {
339 Polarity::IdleLow 338 Polarity::IdleLow
@@ -386,7 +385,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
386 w.set_spe(true); 385 w.set_spe(true);
387 }); 386 });
388 } 387 }
389 #[cfg(spi_v3)] 388 #[cfg(any(spi_v3, spi_v4))]
390 unsafe { 389 unsafe {
391 T::REGS.cr1().modify(|w| { 390 T::REGS.cr1().modify(|w| {
392 w.set_csusp(true); 391 w.set_csusp(true);
@@ -435,7 +434,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
435 T::REGS.cr1().modify(|w| { 434 T::REGS.cr1().modify(|w| {
436 w.set_spe(true); 435 w.set_spe(true);
437 }); 436 });
438 #[cfg(spi_v3)] 437 #[cfg(any(spi_v3, spi_v4))]
439 T::REGS.cr1().modify(|w| { 438 T::REGS.cr1().modify(|w| {
440 w.set_cstart(true); 439 w.set_cstart(true);
441 }); 440 });
@@ -466,7 +465,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
466 } 465 }
467 466
468 // SPIv3 clears rxfifo on SPE=0 467 // SPIv3 clears rxfifo on SPE=0
469 #[cfg(not(spi_v3))] 468 #[cfg(not(any(spi_v3, spi_v4)))]
470 flush_rx_fifo(T::REGS); 469 flush_rx_fifo(T::REGS);
471 470
472 let clock_byte_count = data.len(); 471 let clock_byte_count = data.len();
@@ -495,7 +494,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
495 T::REGS.cr1().modify(|w| { 494 T::REGS.cr1().modify(|w| {
496 w.set_spe(true); 495 w.set_spe(true);
497 }); 496 });
498 #[cfg(spi_v3)] 497 #[cfg(any(spi_v3, spi_v4))]
499 T::REGS.cr1().modify(|w| { 498 T::REGS.cr1().modify(|w| {
500 w.set_cstart(true); 499 w.set_cstart(true);
501 }); 500 });
@@ -533,7 +532,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
533 } 532 }
534 533
535 // SPIv3 clears rxfifo on SPE=0 534 // SPIv3 clears rxfifo on SPE=0
536 #[cfg(not(spi_v3))] 535 #[cfg(not(any(spi_v3, spi_v4)))]
537 flush_rx_fifo(T::REGS); 536 flush_rx_fifo(T::REGS);
538 537
539 let rx_request = self.rxdma.request(); 538 let rx_request = self.rxdma.request();
@@ -557,7 +556,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
557 T::REGS.cr1().modify(|w| { 556 T::REGS.cr1().modify(|w| {
558 w.set_spe(true); 557 w.set_spe(true);
559 }); 558 });
560 #[cfg(spi_v3)] 559 #[cfg(any(spi_v3, spi_v4))]
561 T::REGS.cr1().modify(|w| { 560 T::REGS.cr1().modify(|w| {
562 w.set_cstart(true); 561 w.set_cstart(true);
563 }); 562 });
@@ -642,9 +641,9 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
642 } 641 }
643} 642}
644 643
645#[cfg(not(spi_v3))] 644#[cfg(not(any(spi_v3, spi_v4)))]
646use vals::Br; 645use vals::Br;
647#[cfg(spi_v3)] 646#[cfg(any(spi_v3, spi_v4))]
648use vals::Mbr as Br; 647use vals::Mbr as Br;
649 648
650fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br { 649fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br {
@@ -670,17 +669,17 @@ trait RegsExt {
670 669
671impl RegsExt for Regs { 670impl RegsExt for Regs {
672 fn tx_ptr<W>(&self) -> *mut W { 671 fn tx_ptr<W>(&self) -> *mut W {
673 #[cfg(not(spi_v3))] 672 #[cfg(not(any(spi_v3, spi_v4)))]
674 let dr = self.dr(); 673 let dr = self.dr();
675 #[cfg(spi_v3)] 674 #[cfg(any(spi_v3, spi_v4))]
676 let dr = self.txdr(); 675 let dr = self.txdr();
677 dr.ptr() as *mut W 676 dr.ptr() as *mut W
678 } 677 }
679 678
680 fn rx_ptr<W>(&self) -> *mut W { 679 fn rx_ptr<W>(&self) -> *mut W {
681 #[cfg(not(spi_v3))] 680 #[cfg(not(any(spi_v3, spi_v4)))]
682 let dr = self.dr(); 681 let dr = self.dr();
683 #[cfg(spi_v3)] 682 #[cfg(any(spi_v3, spi_v4))]
684 let dr = self.rxdr(); 683 let dr = self.rxdr();
685 dr.ptr() as *mut W 684 dr.ptr() as *mut W
686 } 685 }
@@ -690,22 +689,22 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
690 if sr.ovr() { 689 if sr.ovr() {
691 return Err(Error::Overrun); 690 return Err(Error::Overrun);
692 } 691 }
693 #[cfg(not(any(spi_f1, spi_v3)))] 692 #[cfg(not(any(spi_f1, spi_v3, spi_v4)))]
694 if sr.fre() { 693 if sr.fre() {
695 return Err(Error::Framing); 694 return Err(Error::Framing);
696 } 695 }
697 #[cfg(spi_v3)] 696 #[cfg(any(spi_v3, spi_v4))]
698 if sr.tifre() { 697 if sr.tifre() {
699 return Err(Error::Framing); 698 return Err(Error::Framing);
700 } 699 }
701 if sr.modf() { 700 if sr.modf() {
702 return Err(Error::ModeFault); 701 return Err(Error::ModeFault);
703 } 702 }
704 #[cfg(not(spi_v3))] 703 #[cfg(not(any(spi_v3, spi_v4)))]
705 if sr.crcerr() { 704 if sr.crcerr() {
706 return Err(Error::Crc); 705 return Err(Error::Crc);
707 } 706 }
708 #[cfg(spi_v3)] 707 #[cfg(any(spi_v3, spi_v4))]
709 if sr.crce() { 708 if sr.crce() {
710 return Err(Error::Crc); 709 return Err(Error::Crc);
711 } 710 }
@@ -719,11 +718,11 @@ fn spin_until_tx_ready(regs: Regs) -> Result<(), Error> {
719 718
720 check_error_flags(sr)?; 719 check_error_flags(sr)?;
721 720
722 #[cfg(not(spi_v3))] 721 #[cfg(not(any(spi_v3, spi_v4)))]
723 if sr.txe() { 722 if sr.txe() {
724 return Ok(()); 723 return Ok(());
725 } 724 }
726 #[cfg(spi_v3)] 725 #[cfg(any(spi_v3, spi_v4))]
727 if sr.txp() { 726 if sr.txp() {
728 return Ok(()); 727 return Ok(());
729 } 728 }
@@ -736,11 +735,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
736 735
737 check_error_flags(sr)?; 736 check_error_flags(sr)?;
738 737
739 #[cfg(not(spi_v3))] 738 #[cfg(not(any(spi_v3, spi_v4)))]
740 if sr.rxne() { 739 if sr.rxne() {
741 return Ok(()); 740 return Ok(());
742 } 741 }
743 #[cfg(spi_v3)] 742 #[cfg(any(spi_v3, spi_v4))]
744 if sr.rxp() { 743 if sr.rxp() {
745 return Ok(()); 744 return Ok(());
746 } 745 }
@@ -749,11 +748,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
749 748
750fn flush_rx_fifo(regs: Regs) { 749fn flush_rx_fifo(regs: Regs) {
751 unsafe { 750 unsafe {
752 #[cfg(not(spi_v3))] 751 #[cfg(not(any(spi_v3, spi_v4)))]
753 while regs.sr().read().rxne() { 752 while regs.sr().read().rxne() {
754 let _ = regs.dr().read(); 753 let _ = regs.dr().read();
755 } 754 }
756 #[cfg(spi_v3)] 755 #[cfg(any(spi_v3, spi_v4))]
757 while regs.sr().read().rxp() { 756 while regs.sr().read().rxp() {
758 let _ = regs.rxdr().read(); 757 let _ = regs.rxdr().read();
759 } 758 }
@@ -762,11 +761,11 @@ fn flush_rx_fifo(regs: Regs) {
762 761
763fn set_txdmaen(regs: Regs, val: bool) { 762fn set_txdmaen(regs: Regs, val: bool) {
764 unsafe { 763 unsafe {
765 #[cfg(not(spi_v3))] 764 #[cfg(not(any(spi_v3, spi_v4)))]
766 regs.cr2().modify(|reg| { 765 regs.cr2().modify(|reg| {
767 reg.set_txdmaen(val); 766 reg.set_txdmaen(val);
768 }); 767 });
769 #[cfg(spi_v3)] 768 #[cfg(any(spi_v3, spi_v4))]
770 regs.cfg1().modify(|reg| { 769 regs.cfg1().modify(|reg| {
771 reg.set_txdmaen(val); 770 reg.set_txdmaen(val);
772 }); 771 });
@@ -775,11 +774,11 @@ fn set_txdmaen(regs: Regs, val: bool) {
775 774
776fn set_rxdmaen(regs: Regs, val: bool) { 775fn set_rxdmaen(regs: Regs, val: bool) {
777 unsafe { 776 unsafe {
778 #[cfg(not(spi_v3))] 777 #[cfg(not(any(spi_v3, spi_v4)))]
779 regs.cr2().modify(|reg| { 778 regs.cr2().modify(|reg| {
780 reg.set_rxdmaen(val); 779 reg.set_rxdmaen(val);
781 }); 780 });
782 #[cfg(spi_v3)] 781 #[cfg(any(spi_v3, spi_v4))]
783 regs.cfg1().modify(|reg| { 782 regs.cfg1().modify(|reg| {
784 reg.set_rxdmaen(val); 783 reg.set_rxdmaen(val);
785 }); 784 });
@@ -791,21 +790,21 @@ fn finish_dma(regs: Regs) {
791 #[cfg(spi_v2)] 790 #[cfg(spi_v2)]
792 while regs.sr().read().ftlvl() > 0 {} 791 while regs.sr().read().ftlvl() > 0 {}
793 792
794 #[cfg(spi_v3)] 793 #[cfg(any(spi_v3, spi_v4))]
795 while !regs.sr().read().txc() {} 794 while !regs.sr().read().txc() {}
796 #[cfg(not(spi_v3))] 795 #[cfg(not(any(spi_v3, spi_v4)))]
797 while regs.sr().read().bsy() {} 796 while regs.sr().read().bsy() {}
798 797
799 regs.cr1().modify(|w| { 798 regs.cr1().modify(|w| {
800 w.set_spe(false); 799 w.set_spe(false);
801 }); 800 });
802 801
803 #[cfg(not(spi_v3))] 802 #[cfg(not(any(spi_v3, spi_v4)))]
804 regs.cr2().modify(|reg| { 803 regs.cr2().modify(|reg| {
805 reg.set_txdmaen(false); 804 reg.set_txdmaen(false);
806 reg.set_rxdmaen(false); 805 reg.set_rxdmaen(false);
807 }); 806 });
808 #[cfg(spi_v3)] 807 #[cfg(any(spi_v3, spi_v4))]
809 regs.cfg1().modify(|reg| { 808 regs.cfg1().modify(|reg| {
810 reg.set_txdmaen(false); 809 reg.set_txdmaen(false);
811 reg.set_rxdmaen(false); 810 reg.set_rxdmaen(false);
@@ -819,7 +818,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
819 unsafe { 818 unsafe {
820 ptr::write_volatile(regs.tx_ptr(), tx_word); 819 ptr::write_volatile(regs.tx_ptr(), tx_word);
821 820
822 #[cfg(spi_v3)] 821 #[cfg(any(spi_v3, spi_v4))]
823 regs.cr1().modify(|reg| reg.set_cstart(true)); 822 regs.cr1().modify(|reg| reg.set_cstart(true));
824 } 823 }
825 824
@@ -1018,7 +1017,7 @@ pub(crate) mod sealed {
1018 } 1017 }
1019 } 1018 }
1020 1019
1021 #[cfg(spi_v3)] 1020 #[cfg(any(spi_v3, spi_v4))]
1022 pub fn dsize(&self) -> u8 { 1021 pub fn dsize(&self) -> u8 {
1023 match self { 1022 match self {
1024 WordSize::EightBit => 0b0111, 1023 WordSize::EightBit => 0b0111,
@@ -1026,7 +1025,7 @@ pub(crate) mod sealed {
1026 } 1025 }
1027 } 1026 }
1028 1027
1029 #[cfg(spi_v3)] 1028 #[cfg(any(spi_v3, spi_v4))]
1030 pub fn _frxth(&self) -> vals::Fthlv { 1029 pub fn _frxth(&self) -> vals::Fthlv {
1031 match self { 1030 match self {
1032 WordSize::EightBit => vals::Fthlv::ONEFRAME, 1031 WordSize::EightBit => vals::Fthlv::ONEFRAME,