aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/spi/mod.rs204
-rw-r--r--embassy-stm32/src/spi/v1.rs42
-rw-r--r--embassy-stm32/src/spi/v2.rs41
-rw-r--r--embassy-stm32/src/spi/v3.rs41
-rw-r--r--embassy-stm32/src/subghz/mod.rs28
-rw-r--r--examples/stm32f4/src/bin/spi.rs3
-rw-r--r--examples/stm32f4/src/bin/spi_dma.rs3
-rw-r--r--examples/stm32h7/src/bin/spi.rs3
-rw-r--r--examples/stm32l0/src/bin/spi.rs3
-rw-r--r--examples/stm32l1/src/bin/spi.rs3
-rw-r--r--examples/stm32l4/src/bin/spi.rs3
-rw-r--r--tests/stm32/src/bin/spi.rs3
12 files changed, 203 insertions, 174 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index f83ef7852..f1ea8592d 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,5 +1,13 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::Future;
4use core::marker::PhantomData;
5use core::ptr;
6use embassy::util::Unborrow;
7use embassy_hal_common::unborrow;
8use embassy_traits::spi as traits;
9
10use self::sealed::WordSize;
3use crate::dma; 11use crate::dma;
4use crate::dma::NoDma; 12use crate::dma::NoDma;
5use crate::gpio::sealed::{AFType, Pin}; 13use crate::gpio::sealed::{AFType, Pin};
@@ -8,19 +16,14 @@ use crate::pac::spi::{regs, vals};
8use crate::peripherals; 16use crate::peripherals;
9use crate::rcc::RccPeripheral; 17use crate::rcc::RccPeripheral;
10use crate::time::Hertz; 18use crate::time::Hertz;
11use core::future::Future; 19
12use core::marker::PhantomData; 20pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
13use core::ptr;
14use embassy::util::Unborrow;
15use embassy_hal_common::unborrow;
16use embassy_traits::spi as traits;
17 21
18#[cfg_attr(spi_v1, path = "v1.rs")] 22#[cfg_attr(spi_v1, path = "v1.rs")]
19#[cfg_attr(spi_f1, path = "v1.rs")] 23#[cfg_attr(spi_f1, path = "v1.rs")]
20#[cfg_attr(spi_v2, path = "v2.rs")] 24#[cfg_attr(spi_v2, path = "v2.rs")]
21#[cfg_attr(spi_v3, path = "v3.rs")] 25#[cfg_attr(spi_v3, path = "v3.rs")]
22mod _version; 26mod _version;
23pub use _version::*;
24 27
25type Regs = &'static crate::pac::spi::Spi; 28type Regs = &'static crate::pac::spi::Spi;
26 29
@@ -40,54 +43,6 @@ pub enum BitOrder {
40 MsbFirst, 43 MsbFirst,
41} 44}
42 45
43#[derive(Copy, Clone, PartialOrd, PartialEq)]
44enum WordSize {
45 EightBit,
46 SixteenBit,
47}
48
49impl WordSize {
50 #[cfg(any(spi_v1, spi_f1))]
51 fn dff(&self) -> vals::Dff {
52 match self {
53 WordSize::EightBit => vals::Dff::EIGHTBIT,
54 WordSize::SixteenBit => vals::Dff::SIXTEENBIT,
55 }
56 }
57
58 #[cfg(spi_v2)]
59 fn ds(&self) -> vals::Ds {
60 match self {
61 WordSize::EightBit => vals::Ds::EIGHTBIT,
62 WordSize::SixteenBit => vals::Ds::SIXTEENBIT,
63 }
64 }
65
66 #[cfg(spi_v2)]
67 fn frxth(&self) -> vals::Frxth {
68 match self {
69 WordSize::EightBit => vals::Frxth::QUARTER,
70 WordSize::SixteenBit => vals::Frxth::HALF,
71 }
72 }
73
74 #[cfg(spi_v3)]
75 fn dsize(&self) -> u8 {
76 match self {
77 WordSize::EightBit => 0b0111,
78 WordSize::SixteenBit => 0b1111,
79 }
80 }
81
82 #[cfg(spi_v3)]
83 fn _frxth(&self) -> vals::Fthlv {
84 match self {
85 WordSize::EightBit => vals::Fthlv::ONEFRAME,
86 WordSize::SixteenBit => vals::Fthlv::ONEFRAME,
87 }
88 }
89}
90
91#[non_exhaustive] 46#[non_exhaustive]
92#[derive(Copy, Clone)] 47#[derive(Copy, Clone)]
93pub struct Config { 48pub struct Config {
@@ -379,6 +334,47 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
379 334
380 self.current_word_size = word_size; 335 self.current_word_size = word_size;
381 } 336 }
337
338 pub async fn write(&mut self, data: &[u8]) -> Result<(), Error>
339 where
340 Tx: TxDmaChannel<T>,
341 {
342 self.write_dma_u8(data).await
343 }
344
345 pub async fn read(&mut self, data: &mut [u8]) -> Result<(), Error>
346 where
347 Tx: TxDmaChannel<T>,
348 Rx: RxDmaChannel<T>,
349 {
350 self.read_dma_u8(data).await
351 }
352
353 pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error>
354 where
355 Tx: TxDmaChannel<T>,
356 Rx: RxDmaChannel<T>,
357 {
358 self.transfer_dma_u8(read, write).await
359 }
360
361 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
362 self.set_word_size(W::WORDSIZE);
363 let regs = T::regs();
364 for word in words.iter() {
365 let _ = transfer_word(regs, *word)?;
366 }
367 Ok(())
368 }
369
370 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
371 self.set_word_size(W::WORDSIZE);
372 let regs = T::regs();
373 for word in words.iter_mut() {
374 *word = transfer_word(regs, *word)?;
375 }
376 Ok(())
377 }
382} 378}
383 379
384impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { 380impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
@@ -537,17 +533,6 @@ fn finish_dma(regs: Regs) {
537 } 533 }
538} 534}
539 535
540trait Word {
541 const WORDSIZE: WordSize;
542}
543
544impl Word for u8 {
545 const WORDSIZE: WordSize = WordSize::EightBit;
546}
547impl Word for u16 {
548 const WORDSIZE: WordSize = WordSize::SixteenBit;
549}
550
551fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> { 536fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
552 spin_until_tx_ready(regs)?; 537 spin_until_tx_ready(regs)?;
553 538
@@ -572,14 +557,7 @@ macro_rules! impl_blocking {
572 type Error = Error; 557 type Error = Error;
573 558
574 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> { 559 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
575 self.set_word_size($w::WORDSIZE); 560 self.blocking_write(words)
576 let regs = T::regs();
577
578 for word in words.iter() {
579 let _ = transfer_word(regs, *word)?;
580 }
581
582 Ok(())
583 } 561 }
584 } 562 }
585 563
@@ -589,13 +567,7 @@ macro_rules! impl_blocking {
589 type Error = Error; 567 type Error = Error;
590 568
591 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> { 569 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
592 self.set_word_size($w::WORDSIZE); 570 self.blocking_transfer_in_place(words)?;
593 let regs = T::regs();
594
595 for word in words.iter_mut() {
596 *word = transfer_word(regs, *word)?;
597 }
598
599 Ok(words) 571 Ok(words)
600 } 572 }
601 } 573 }
@@ -616,7 +588,7 @@ impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T,
616 = impl Future<Output = Result<(), Self::Error>> + 'a; 588 = impl Future<Output = Result<(), Self::Error>> + 'a;
617 589
618 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { 590 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
619 self.write_dma_u8(data) 591 self.write(data)
620 } 592 }
621} 593}
622 594
@@ -629,7 +601,7 @@ impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
629 = impl Future<Output = Result<(), Self::Error>> + 'a; 601 = impl Future<Output = Result<(), Self::Error>> + 'a;
630 602
631 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { 603 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
632 self.read_dma_u8(data) 604 self.read(data)
633 } 605 }
634} 606}
635 607
@@ -646,7 +618,7 @@ impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDupl
646 read: &'a mut [u8], 618 read: &'a mut [u8],
647 write: &'a [u8], 619 write: &'a [u8],
648 ) -> Self::WriteReadFuture<'a> { 620 ) -> Self::WriteReadFuture<'a> {
649 self.read_write_dma_u8(read, write) 621 self.transfer(read, write)
650 } 622 }
651} 623}
652 624
@@ -676,8 +648,72 @@ pub(crate) mod sealed {
676 pub trait RxDmaChannel<T: Instance> { 648 pub trait RxDmaChannel<T: Instance> {
677 fn request(&self) -> dma::Request; 649 fn request(&self) -> dma::Request;
678 } 650 }
651
652 pub trait Word: Copy + 'static {
653 const WORDSIZE: WordSize;
654 }
655
656 impl Word for u8 {
657 const WORDSIZE: WordSize = WordSize::EightBit;
658 }
659 impl Word for u16 {
660 const WORDSIZE: WordSize = WordSize::SixteenBit;
661 }
662
663 #[derive(Copy, Clone, PartialOrd, PartialEq)]
664 pub enum WordSize {
665 EightBit,
666 SixteenBit,
667 }
668
669 impl WordSize {
670 #[cfg(any(spi_v1, spi_f1))]
671 pub fn dff(&self) -> vals::Dff {
672 match self {
673 WordSize::EightBit => vals::Dff::EIGHTBIT,
674 WordSize::SixteenBit => vals::Dff::SIXTEENBIT,
675 }
676 }
677
678 #[cfg(spi_v2)]
679 pub fn ds(&self) -> vals::Ds {
680 match self {
681 WordSize::EightBit => vals::Ds::EIGHTBIT,
682 WordSize::SixteenBit => vals::Ds::SIXTEENBIT,
683 }
684 }
685
686 #[cfg(spi_v2)]
687 pub fn frxth(&self) -> vals::Frxth {
688 match self {
689 WordSize::EightBit => vals::Frxth::QUARTER,
690 WordSize::SixteenBit => vals::Frxth::HALF,
691 }
692 }
693
694 #[cfg(spi_v3)]
695 pub fn dsize(&self) -> u8 {
696 match self {
697 WordSize::EightBit => 0b0111,
698 WordSize::SixteenBit => 0b1111,
699 }
700 }
701
702 #[cfg(spi_v3)]
703 pub fn _frxth(&self) -> vals::Fthlv {
704 match self {
705 WordSize::EightBit => vals::Fthlv::ONEFRAME,
706 WordSize::SixteenBit => vals::Fthlv::ONEFRAME,
707 }
708 }
709 }
679} 710}
680 711
712pub trait Word: Copy + 'static + sealed::Word {}
713
714impl Word for u8 {}
715impl Word for u16 {}
716
681pub trait Instance: sealed::Instance + RccPeripheral {} 717pub trait Instance: sealed::Instance + RccPeripheral {}
682pub trait SckPin<T: Instance>: sealed::SckPin<T> {} 718pub trait SckPin<T: Instance>: sealed::SckPin<T> {}
683pub trait MosiPin<T: Instance>: sealed::MosiPin<T> {} 719pub trait MosiPin<T: Instance>: sealed::MosiPin<T> {}
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index ef7e0f59c..68e5a7348 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -1,13 +1,12 @@
1#![macro_use] 1#![macro_use]
2 2
3pub use embedded_hal::blocking;
4pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
5use futures::future::join; 3use futures::future::join;
6 4
7use super::*; 5use super::*;
6use crate::dma::{slice_ptr_parts, slice_ptr_parts_mut, Transfer};
8 7
9impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
10 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 9 pub(super) async fn write_dma_u8(&mut self, write: *const [u8]) -> Result<(), Error>
11 where 10 where
12 Tx: TxDmaChannel<T>, 11 Tx: TxDmaChannel<T>,
13 { 12 {
@@ -18,9 +17,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
18 } 17 }
19 self.set_word_size(WordSize::EightBit); 18 self.set_word_size(WordSize::EightBit);
20 19
21 let request = self.txdma.request(); 20 let tx_request = self.txdma.request();
22 let dst = T::regs().tx_ptr(); 21 let tx_dst = T::regs().tx_ptr();
23 let f = crate::dma::write(&mut self.txdma, request, write, dst); 22 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
23 let tx_f = Transfer::new(&mut self.txdma);
24 24
25 unsafe { 25 unsafe {
26 T::regs().cr2().modify(|reg| { 26 T::regs().cr2().modify(|reg| {
@@ -31,14 +31,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
31 }); 31 });
32 } 32 }
33 33
34 f.await; 34 tx_f.await;
35 35
36 finish_dma(T::regs()); 36 finish_dma(T::regs());
37 37
38 Ok(()) 38 Ok(())
39 } 39 }
40 40
41 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error> 41 pub(super) async fn read_dma_u8(&mut self, read: *mut [u8]) -> Result<(), Error>
42 where 42 where
43 Tx: TxDmaChannel<T>, 43 Tx: TxDmaChannel<T>,
44 Rx: RxDmaChannel<T>, 44 Rx: RxDmaChannel<T>,
@@ -53,11 +53,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
53 } 53 }
54 self.set_word_size(WordSize::EightBit); 54 self.set_word_size(WordSize::EightBit);
55 55
56 let clock_byte_count = read.len(); 56 let (_, clock_byte_count) = slice_ptr_parts_mut(read);
57 57
58 let rx_request = self.rxdma.request(); 58 let rx_request = self.rxdma.request();
59 let rx_src = T::regs().rx_ptr(); 59 let rx_src = T::regs().rx_ptr();
60 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read); 60 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
61 let rx_f = Transfer::new(&mut self.rxdma);
61 62
62 let tx_request = self.txdma.request(); 63 let tx_request = self.txdma.request();
63 let tx_dst = T::regs().tx_ptr(); 64 let tx_dst = T::regs().tx_ptr();
@@ -86,16 +87,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
86 Ok(()) 87 Ok(())
87 } 88 }
88 89
89 pub(super) async fn read_write_dma_u8( 90 pub(super) async fn transfer_dma_u8(
90 &mut self, 91 &mut self,
91 read: &mut [u8], 92 read: *mut [u8],
92 write: &[u8], 93 write: *const [u8],
93 ) -> Result<(), Error> 94 ) -> Result<(), Error>
94 where 95 where
95 Tx: TxDmaChannel<T>, 96 Tx: TxDmaChannel<T>,
96 Rx: RxDmaChannel<T>, 97 Rx: RxDmaChannel<T>,
97 { 98 {
98 assert!(read.len() >= write.len()); 99 let (_, rx_len) = slice_ptr_parts(read);
100 let (_, tx_len) = slice_ptr_parts(write);
101 assert_eq!(rx_len, tx_len);
99 102
100 unsafe { 103 unsafe {
101 T::regs().cr1().modify(|w| { 104 T::regs().cr1().modify(|w| {
@@ -109,16 +112,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
109 112
110 let rx_request = self.rxdma.request(); 113 let rx_request = self.rxdma.request();
111 let rx_src = T::regs().rx_ptr(); 114 let rx_src = T::regs().rx_ptr();
112 let rx_f = crate::dma::read( 115 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
113 &mut self.rxdma, 116 let rx_f = Transfer::new(&mut self.rxdma);
114 rx_request,
115 rx_src,
116 &mut read[0..write.len()],
117 );
118 117
119 let tx_request = self.txdma.request(); 118 let tx_request = self.txdma.request();
120 let tx_dst = T::regs().tx_ptr(); 119 let tx_dst = T::regs().tx_ptr();
121 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst); 120 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
121 let tx_f = Transfer::new(&mut self.txdma);
122 122
123 unsafe { 123 unsafe {
124 T::regs().cr2().modify(|reg| { 124 T::regs().cr2().modify(|reg| {
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs
index f2ba3ac67..78bb1192b 100644
--- a/embassy-stm32/src/spi/v2.rs
+++ b/embassy-stm32/src/spi/v2.rs
@@ -1,12 +1,12 @@
1#![macro_use] 1#![macro_use]
2 2
3pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
4use futures::future::join; 3use futures::future::join;
5 4
6use super::*; 5use super::*;
6use crate::dma::{slice_ptr_parts, slice_ptr_parts_mut, Transfer};
7 7
8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 9 pub(super) async fn write_dma_u8(&mut self, write: *const [u8]) -> Result<(), Error>
10 where 10 where
11 Tx: TxDmaChannel<T>, 11 Tx: TxDmaChannel<T>,
12 { 12 {
@@ -22,9 +22,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
22 } 22 }
23 self.set_word_size(WordSize::EightBit); 23 self.set_word_size(WordSize::EightBit);
24 24
25 let request = self.txdma.request(); 25 let tx_request = self.txdma.request();
26 let dst = T::regs().tx_ptr(); 26 let tx_dst = T::regs().tx_ptr();
27 let f = crate::dma::write(&mut self.txdma, request, write, dst); 27 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
28 let tx_f = Transfer::new(&mut self.txdma);
28 29
29 unsafe { 30 unsafe {
30 T::regs().cr2().modify(|reg| { 31 T::regs().cr2().modify(|reg| {
@@ -35,14 +36,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
35 }); 36 });
36 } 37 }
37 38
38 f.await; 39 tx_f.await;
39 40
40 finish_dma(T::regs()); 41 finish_dma(T::regs());
41 42
42 Ok(()) 43 Ok(())
43 } 44 }
44 45
45 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error> 46 pub(super) async fn read_dma_u8(&mut self, read: *mut [u8]) -> Result<(), Error>
46 where 47 where
47 Tx: TxDmaChannel<T>, 48 Tx: TxDmaChannel<T>,
48 Rx: RxDmaChannel<T>, 49 Rx: RxDmaChannel<T>,
@@ -57,11 +58,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
57 } 58 }
58 self.set_word_size(WordSize::EightBit); 59 self.set_word_size(WordSize::EightBit);
59 60
60 let clock_byte_count = read.len(); 61 let (_, clock_byte_count) = slice_ptr_parts_mut(read);
61 62
62 let rx_request = self.rxdma.request(); 63 let rx_request = self.rxdma.request();
63 let rx_src = T::regs().rx_ptr(); 64 let rx_src = T::regs().rx_ptr();
64 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read); 65 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
66 let rx_f = Transfer::new(&mut self.rxdma);
65 67
66 let tx_request = self.txdma.request(); 68 let tx_request = self.txdma.request();
67 let tx_dst = T::regs().tx_ptr(); 69 let tx_dst = T::regs().tx_ptr();
@@ -90,16 +92,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
90 Ok(()) 92 Ok(())
91 } 93 }
92 94
93 pub(super) async fn read_write_dma_u8( 95 pub(super) async fn transfer_dma_u8(
94 &mut self, 96 &mut self,
95 read: &mut [u8], 97 read: *mut [u8],
96 write: &[u8], 98 write: *const [u8],
97 ) -> Result<(), Error> 99 ) -> Result<(), Error>
98 where 100 where
99 Tx: TxDmaChannel<T>, 101 Tx: TxDmaChannel<T>,
100 Rx: RxDmaChannel<T>, 102 Rx: RxDmaChannel<T>,
101 { 103 {
102 assert!(read.len() >= write.len()); 104 let (_, rx_len) = slice_ptr_parts(read);
105 let (_, tx_len) = slice_ptr_parts(write);
106 assert_eq!(rx_len, tx_len);
103 107
104 unsafe { 108 unsafe {
105 T::regs().cr1().modify(|w| { 109 T::regs().cr1().modify(|w| {
@@ -118,16 +122,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
118 122
119 let rx_request = self.rxdma.request(); 123 let rx_request = self.rxdma.request();
120 let rx_src = T::regs().rx_ptr(); 124 let rx_src = T::regs().rx_ptr();
121 let rx_f = crate::dma::read( 125 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
122 &mut self.rxdma, 126 let rx_f = Transfer::new(&mut self.rxdma);
123 rx_request,
124 rx_src,
125 &mut read[0..write.len()],
126 );
127 127
128 let tx_request = self.txdma.request(); 128 let tx_request = self.txdma.request();
129 let tx_dst = T::regs().tx_ptr(); 129 let tx_dst = T::regs().tx_ptr();
130 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst); 130 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
131 let tx_f = Transfer::new(&mut self.txdma);
131 132
132 unsafe { 133 unsafe {
133 T::regs().cr2().modify(|reg| { 134 T::regs().cr2().modify(|reg| {
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index b42eeed89..50650da1b 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -1,12 +1,12 @@
1#![macro_use] 1#![macro_use]
2 2
3pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
4use futures::future::join; 3use futures::future::join;
5 4
6use super::*; 5use super::*;
6use crate::dma::{slice_ptr_parts, slice_ptr_parts_mut, Transfer};
7 7
8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 9 pub(super) async fn write_dma_u8(&mut self, write: *const [u8]) -> Result<(), Error>
10 where 10 where
11 Tx: TxDmaChannel<T>, 11 Tx: TxDmaChannel<T>,
12 { 12 {
@@ -22,9 +22,10 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
22 } 22 }
23 } 23 }
24 24
25 let request = self.txdma.request(); 25 let tx_request = self.txdma.request();
26 let dst = T::regs().tx_ptr(); 26 let tx_dst = T::regs().tx_ptr();
27 let f = crate::dma::write(&mut self.txdma, request, write, dst); 27 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
28 let tx_f = Transfer::new(&mut self.txdma);
28 29
29 unsafe { 30 unsafe {
30 T::regs().cfg1().modify(|reg| { 31 T::regs().cfg1().modify(|reg| {
@@ -38,14 +39,14 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
38 }); 39 });
39 } 40 }
40 41
41 f.await; 42 tx_f.await;
42 43
43 finish_dma(T::regs()); 44 finish_dma(T::regs());
44 45
45 Ok(()) 46 Ok(())
46 } 47 }
47 48
48 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error> 49 pub(super) async fn read_dma_u8(&mut self, read: *mut [u8]) -> Result<(), Error>
49 where 50 where
50 Tx: TxDmaChannel<T>, 51 Tx: TxDmaChannel<T>,
51 Rx: RxDmaChannel<T>, 52 Rx: RxDmaChannel<T>,
@@ -60,11 +61,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
60 }); 61 });
61 } 62 }
62 63
63 let clock_byte_count = read.len(); 64 let (_, clock_byte_count) = slice_ptr_parts_mut(read);
64 65
65 let rx_request = self.rxdma.request(); 66 let rx_request = self.rxdma.request();
66 let rx_src = T::regs().rx_ptr(); 67 let rx_src = T::regs().rx_ptr();
67 let rx_f = crate::dma::read(&mut self.rxdma, rx_request, rx_src, read); 68 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
69 let rx_f = Transfer::new(&mut self.rxdma);
68 70
69 let tx_request = self.txdma.request(); 71 let tx_request = self.txdma.request();
70 let tx_dst = T::regs().tx_ptr(); 72 let tx_dst = T::regs().tx_ptr();
@@ -96,16 +98,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
96 Ok(()) 98 Ok(())
97 } 99 }
98 100
99 pub(super) async fn read_write_dma_u8( 101 pub(super) async fn transfer_dma_u8(
100 &mut self, 102 &mut self,
101 read: &mut [u8], 103 read: *mut [u8],
102 write: &[u8], 104 write: *const [u8],
103 ) -> Result<(), Error> 105 ) -> Result<(), Error>
104 where 106 where
105 Tx: TxDmaChannel<T>, 107 Tx: TxDmaChannel<T>,
106 Rx: RxDmaChannel<T>, 108 Rx: RxDmaChannel<T>,
107 { 109 {
108 assert!(read.len() >= write.len()); 110 let (_, rx_len) = slice_ptr_parts(read);
111 let (_, tx_len) = slice_ptr_parts(write);
112 assert_eq!(rx_len, tx_len);
109 113
110 self.set_word_size(WordSize::EightBit); 114 self.set_word_size(WordSize::EightBit);
111 unsafe { 115 unsafe {
@@ -124,16 +128,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
124 128
125 let rx_request = self.rxdma.request(); 129 let rx_request = self.rxdma.request();
126 let rx_src = T::regs().rx_ptr(); 130 let rx_src = T::regs().rx_ptr();
127 let rx_f = crate::dma::read( 131 unsafe { self.rxdma.start_read(rx_request, rx_src, read) };
128 &mut self.rxdma, 132 let rx_f = Transfer::new(&mut self.rxdma);
129 rx_request,
130 rx_src,
131 &mut read[0..write.len()],
132 );
133 133
134 let tx_request = self.txdma.request(); 134 let tx_request = self.txdma.request();
135 let tx_dst = T::regs().tx_ptr(); 135 let tx_dst = T::regs().tx_ptr();
136 let tx_f = crate::dma::write(&mut self.txdma, tx_request, write, tx_dst); 136 unsafe { self.txdma.start_write(tx_request, write, tx_dst) }
137 let tx_f = Transfer::new(&mut self.txdma);
137 138
138 unsafe { 139 unsafe {
139 T::regs().cfg1().modify(|reg| { 140 T::regs().cfg1().modify(|reg| {
diff --git a/embassy-stm32/src/subghz/mod.rs b/embassy-stm32/src/subghz/mod.rs
index 7d74569f3..87f376c40 100644
--- a/embassy-stm32/src/subghz/mod.rs
+++ b/embassy-stm32/src/subghz/mod.rs
@@ -82,14 +82,10 @@ use crate::{
82 pac, 82 pac,
83 peripherals::SUBGHZSPI, 83 peripherals::SUBGHZSPI,
84 rcc::sealed::RccPeripheral, 84 rcc::sealed::RccPeripheral,
85 spi::{BitOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi}, 85 spi::{BitOrder, Config as SpiConfig, MisoPin, MosiPin, SckPin, Spi, MODE_0},
86 time::Hertz, 86 time::Hertz,
87}; 87};
88use embassy::util::Unborrow; 88use embassy::util::Unborrow;
89use embedded_hal::{
90 blocking::spi::{Transfer, Write},
91 spi::MODE_0,
92};
93 89
94/// Passthrough for SPI errors (for now) 90/// Passthrough for SPI errors (for now)
95pub type Error = crate::spi::Error; 91pub type Error = crate::spi::Error;
@@ -255,8 +251,8 @@ impl<'d> SubGhz<'d, NoDma, NoDma> {
255 self.poll_not_busy(); 251 self.poll_not_busy();
256 { 252 {
257 let _nss: Nss = Nss::new(); 253 let _nss: Nss = Nss::new();
258 self.spi.write(&[opcode as u8])?; 254 self.spi.blocking_write(&[opcode as u8])?;
259 self.spi.transfer(data)?; 255 self.spi.blocking_transfer_in_place(data)?;
260 } 256 }
261 self.poll_not_busy(); 257 self.poll_not_busy();
262 Ok(()) 258 Ok(())
@@ -280,7 +276,7 @@ impl<'d> SubGhz<'d, NoDma, NoDma> {
280 self.poll_not_busy(); 276 self.poll_not_busy();
281 { 277 {
282 let _nss: Nss = Nss::new(); 278 let _nss: Nss = Nss::new();
283 self.spi.write(data)?; 279 self.spi.blocking_write(data)?;
284 } 280 }
285 self.poll_not_busy(); 281 self.poll_not_busy();
286 Ok(()) 282 Ok(())
@@ -290,8 +286,9 @@ impl<'d> SubGhz<'d, NoDma, NoDma> {
290 self.poll_not_busy(); 286 self.poll_not_busy();
291 { 287 {
292 let _nss: Nss = Nss::new(); 288 let _nss: Nss = Nss::new();
293 self.spi.write(&[OpCode::WriteBuffer as u8, offset])?; 289 self.spi
294 self.spi.write(data)?; 290 .blocking_write(&[OpCode::WriteBuffer as u8, offset])?;
291 self.spi.blocking_write(data)?;
295 } 292 }
296 self.poll_not_busy(); 293 self.poll_not_busy();
297 294
@@ -308,9 +305,10 @@ impl<'d> SubGhz<'d, NoDma, NoDma> {
308 self.poll_not_busy(); 305 self.poll_not_busy();
309 { 306 {
310 let _nss: Nss = Nss::new(); 307 let _nss: Nss = Nss::new();
311 self.spi.write(&[OpCode::ReadBuffer as u8, offset])?; 308 self.spi
312 self.spi.transfer(&mut status_buf)?; 309 .blocking_write(&[OpCode::ReadBuffer as u8, offset])?;
313 self.spi.transfer(buf)?; 310 self.spi.blocking_transfer_in_place(&mut status_buf)?;
311 self.spi.blocking_transfer_in_place(buf)?;
314 } 312 }
315 self.poll_not_busy(); 313 self.poll_not_busy();
316 314
@@ -342,8 +340,8 @@ impl<'d> SubGhz<'d, NoDma, NoDma> {
342 { 340 {
343 let _nss: Nss = Nss::new(); 341 let _nss: Nss = Nss::new();
344 self.spi 342 self.spi
345 .write(&[OpCode::WriteRegister as u8, addr[0], addr[1]])?; 343 .blocking_write(&[OpCode::WriteRegister as u8, addr[0], addr[1]])?;
346 self.spi.write(data)?; 344 self.spi.blocking_write(data)?;
347 } 345 }
348 self.poll_not_busy(); 346 self.poll_not_busy();
349 347
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index b66eb9582..6b04f1fed 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -10,7 +10,6 @@ use embassy_stm32::dma::NoDma;
10use embassy_stm32::gpio::{Level, Output, Speed}; 10use embassy_stm32::gpio::{Level, Output, Speed};
11use embassy_stm32::spi::{Config, Spi}; 11use embassy_stm32::spi::{Config, Spi};
12use embassy_stm32::time::Hertz; 12use embassy_stm32::time::Hertz;
13use embedded_hal::blocking::spi::Transfer;
14use example_common::*; 13use example_common::*;
15 14
16#[entry] 15#[entry]
@@ -35,7 +34,7 @@ fn main() -> ! {
35 loop { 34 loop {
36 let mut buf = [0x0Au8; 4]; 35 let mut buf = [0x0Au8; 4];
37 cs.set_low(); 36 cs.set_low();
38 unwrap!(spi.transfer(&mut buf)); 37 unwrap!(spi.blocking_transfer_in_place(&mut buf));
39 cs.set_high(); 38 cs.set_high();
40 info!("xfer {=[u8]:x}", buf); 39 info!("xfer {=[u8]:x}", buf);
41 } 40 }
diff --git a/examples/stm32f4/src/bin/spi_dma.rs b/examples/stm32f4/src/bin/spi_dma.rs
index b3bf6fc28..9171f7516 100644
--- a/examples/stm32f4/src/bin/spi_dma.rs
+++ b/examples/stm32f4/src/bin/spi_dma.rs
@@ -10,7 +10,6 @@ use embassy::executor::Spawner;
10use embassy_stm32::spi::{Config, Spi}; 10use embassy_stm32::spi::{Config, Spi};
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::Peripherals; 12use embassy_stm32::Peripherals;
13use embassy_traits::spi::FullDuplex;
14use example_common::*; 13use example_common::*;
15use heapless::String; 14use heapless::String;
16 15
@@ -33,7 +32,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
33 let mut write: String<128> = String::new(); 32 let mut write: String<128> = String::new();
34 let mut read = [0; 128]; 33 let mut read = [0; 128];
35 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 34 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
36 spi.read_write(&mut read[0..write.len()], write.as_bytes()) 35 spi.transfer(&mut read[0..write.len()], write.as_bytes())
37 .await 36 .await
38 .ok(); 37 .ok();
39 info!("read via spi+dma: {}", from_utf8(&read).unwrap()); 38 info!("read via spi+dma: {}", from_utf8(&read).unwrap());
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index 0b375b0d0..17e64da79 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -10,7 +10,6 @@ use embassy::executor::Executor;
10use embassy::util::Forever; 10use embassy::util::Forever;
11use embassy_stm32::dma::NoDma; 11use embassy_stm32::dma::NoDma;
12use embassy_stm32::spi; 12use embassy_stm32::spi;
13use embedded_hal::blocking::spi::Transfer;
14use example_common::*; 13use example_common::*;
15 14
16use core::str::from_utf8; 15use core::str::from_utf8;
@@ -25,7 +24,7 @@ async fn main_task(mut spi: spi::Spi<'static, SPI3, NoDma, NoDma>) {
25 let mut write: String<128> = String::new(); 24 let mut write: String<128> = String::new();
26 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); 25 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
27 unsafe { 26 unsafe {
28 let result = spi.transfer(write.as_bytes_mut()); 27 let result = spi.blocking_transfer_in_place(write.as_bytes_mut());
29 if let Err(_) = result { 28 if let Err(_) = result {
30 defmt::panic!("crap"); 29 defmt::panic!("crap");
31 } 30 }
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs
index d30bb8d7a..8d6e89d91 100644
--- a/examples/stm32l0/src/bin/spi.rs
+++ b/examples/stm32l0/src/bin/spi.rs
@@ -13,7 +13,6 @@ use embassy_stm32::dma::NoDma;
13use embassy_stm32::spi::{Config, Spi}; 13use embassy_stm32::spi::{Config, Spi};
14use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
15use embassy_stm32::Peripherals; 15use embassy_stm32::Peripherals;
16use embedded_hal::blocking::spi::Transfer;
17 16
18#[embassy::main] 17#[embassy::main]
19async fn main(_spawner: Spawner, p: Peripherals) { 18async fn main(_spawner: Spawner, p: Peripherals) {
@@ -35,7 +34,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
35 loop { 34 loop {
36 let mut buf = [0x0Au8; 4]; 35 let mut buf = [0x0Au8; 4];
37 cs.set_low(); 36 cs.set_low();
38 unwrap!(spi.transfer(&mut buf)); 37 unwrap!(spi.blocking_transfer_in_place(&mut buf));
39 cs.set_high(); 38 cs.set_high();
40 info!("xfer {=[u8]:x}", buf); 39 info!("xfer {=[u8]:x}", buf);
41 } 40 }
diff --git a/examples/stm32l1/src/bin/spi.rs b/examples/stm32l1/src/bin/spi.rs
index 9d1a2fc87..e97e3ebb4 100644
--- a/examples/stm32l1/src/bin/spi.rs
+++ b/examples/stm32l1/src/bin/spi.rs
@@ -13,7 +13,6 @@ use embassy_stm32::dma::NoDma;
13use embassy_stm32::spi::{Config, Spi}; 13use embassy_stm32::spi::{Config, Spi};
14use embassy_stm32::time::Hertz; 14use embassy_stm32::time::Hertz;
15use embassy_stm32::Peripherals; 15use embassy_stm32::Peripherals;
16use embedded_hal::blocking::spi::Transfer;
17 16
18#[embassy::main] 17#[embassy::main]
19async fn main(_spawner: Spawner, p: Peripherals) { 18async fn main(_spawner: Spawner, p: Peripherals) {
@@ -35,7 +34,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
35 loop { 34 loop {
36 let mut buf = [0x0Au8; 4]; 35 let mut buf = [0x0Au8; 4];
37 cs.set_low(); 36 cs.set_low();
38 unwrap!(spi.transfer(&mut buf)); 37 unwrap!(spi.blocking_transfer_in_place(&mut buf));
39 cs.set_high(); 38 cs.set_high();
40 info!("xfer {=[u8]:x}", buf); 39 info!("xfer {=[u8]:x}", buf);
41 } 40 }
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 1b6e3946e..8567d3062 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -9,7 +9,6 @@ use embassy_stm32::dma::NoDma;
9use embassy_stm32::gpio::{Level, Output, Speed}; 9use embassy_stm32::gpio::{Level, Output, Speed};
10use embassy_stm32::spi::{Config, Spi}; 10use embassy_stm32::spi::{Config, Spi};
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embedded_hal::blocking::spi::Transfer;
13use example_common::*; 12use example_common::*;
14 13
15#[cortex_m_rt::entry] 14#[cortex_m_rt::entry]
@@ -34,7 +33,7 @@ fn main() -> ! {
34 loop { 33 loop {
35 let mut buf = [0x0Au8; 4]; 34 let mut buf = [0x0Au8; 4];
36 cs.set_low(); 35 cs.set_low();
37 unwrap!(spi.transfer(&mut buf)); 36 unwrap!(spi.blocking_transfer_in_place(&mut buf));
38 cs.set_high(); 37 cs.set_high();
39 info!("xfer {=[u8]:x}", buf); 38 info!("xfer {=[u8]:x}", buf);
40 } 39 }
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index 043505c7b..47d0017ac 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -10,7 +10,6 @@ use embassy_stm32::dma::NoDma;
10use embassy_stm32::spi::{self, Spi}; 10use embassy_stm32::spi::{self, Spi};
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::Peripherals; 12use embassy_stm32::Peripherals;
13use embedded_hal::blocking::spi::Transfer;
14use example_common::*; 13use example_common::*;
15 14
16#[embassy::main(config = "config()")] 15#[embassy::main(config = "config()")]
@@ -38,7 +37,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
38 // 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.
39 // so we should get the data we sent back. 38 // so we should get the data we sent back.
40 let mut buf = data; 39 let mut buf = data;
41 spi.transfer(&mut buf).unwrap(); 40 spi.blocking_transfer_in_place(&mut buf).unwrap();
42 assert_eq!(buf, data); 41 assert_eq!(buf, data);
43 42
44 info!("Test OK"); 43 info!("Test OK");