Skip to content

Commit 0a5d4cf

Browse files
committed
rework SPI DMA Rx/Tx: take 2
1 parent bf445ea commit 0a5d4cf

File tree

4 files changed

+151
-66
lines changed

4 files changed

+151
-66
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2323
- Add advanced timer dead time insertion example [#585]
2424
- Cleanups [#595]
2525
- Fix comlementary for independent channels [#599] [#603]
26+
- Capability to release and reuse SPI peripheral after using it with DMA.
2627
- I2c dma can now use single DMA channel for TX or RX only [#598]
2728
- `ws2812::prerendered` in example
2829

examples/rtic-spi-slave-dma.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod app {
1616
pac::{DMA1, SPI3},
1717
prelude::*,
1818
rcc::RccExt,
19-
spi::{Rx, SpiSlave, Tx},
19+
spi::{RxCoupledSlave, SpiSlave, TxCoupledSlave},
2020
};
2121
use panic_semihosting as _;
2222
use systick_monotonic::*;
@@ -25,11 +25,21 @@ mod app {
2525

2626
const ARRAY_SIZE: usize = 3;
2727

28-
type TxTransfer =
29-
Transfer<Stream5<DMA1>, 0, Tx<SPI3>, MemoryToPeripheral, &'static mut [u8; ARRAY_SIZE]>;
30-
31-
type RxTransfer =
32-
Transfer<Stream0<DMA1>, 0, Rx<SPI3>, PeripheralToMemory, &'static mut [u8; ARRAY_SIZE]>;
28+
type TxTransfer = Transfer<
29+
Stream5<DMA1>,
30+
0,
31+
TxCoupledSlave<SPI3, false>,
32+
MemoryToPeripheral,
33+
&'static mut [u8; ARRAY_SIZE],
34+
>;
35+
36+
type RxTransfer = Transfer<
37+
Stream0<DMA1>,
38+
0,
39+
RxCoupledSlave<SPI3, false>,
40+
PeripheralToMemory,
41+
&'static mut [u8; ARRAY_SIZE],
42+
>;
3343

3444
#[shared]
3545
struct Shared {

examples/spi-dma.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const ARRAY_SIZE: usize = 100;
2222
type SpiDma = Transfer<
2323
Stream4<pac::DMA1>,
2424
0,
25-
Tx<pac::SPI2>,
25+
Tx<pac::SPI2, false>,
2626
MemoryToPeripheral,
2727
&'static mut [u8; ARRAY_SIZE],
2828
>;

src/spi.rs

Lines changed: 133 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -783,83 +783,157 @@ impl<SPI: Instance> Inner<SPI> {
783783
}
784784

785785
// Spi DMA
786+
macro_rules! dma {
787+
($Spi:ident, $DmaBuilder:ident, $Tx:ident, $Rx:ident, $TxCoupled:ident, $RxCoupled:ident) => {
788+
impl<SPI: Instance, const BIDI: bool> $Spi<SPI, BIDI, u8> {
789+
pub fn use_dma(self) -> $DmaBuilder<SPI, BIDI> {
790+
$DmaBuilder { spi: self }
791+
}
792+
}
786793

787-
impl<SPI: Instance, const BIDI: bool> Spi<SPI, BIDI, u8> {
788-
pub fn use_dma(self) -> DmaBuilder<SPI> {
789-
DmaBuilder {
790-
spi: self.inner.spi,
794+
pub struct $DmaBuilder<SPI: Instance, const BIDI: bool> {
795+
spi: $Spi<SPI, BIDI>,
791796
}
792-
}
793-
}
794797

795-
impl<SPI: Instance, const BIDI: bool> SpiSlave<SPI, BIDI, u8> {
796-
pub fn use_dma(self) -> DmaBuilder<SPI> {
797-
DmaBuilder {
798-
spi: self.inner.spi,
798+
pub struct $Tx<SPI: Instance, const BIDI: bool> {
799+
spi: $Spi<SPI, BIDI>,
799800
}
800-
}
801-
}
802801

803-
pub struct DmaBuilder<SPI> {
804-
spi: SPI,
805-
}
802+
pub struct $Rx<SPI: Instance, const BIDI: bool> {
803+
spi: $Spi<SPI, BIDI>,
804+
}
806805

807-
pub struct Tx<SPI> {
808-
spi: PhantomData<SPI>,
809-
}
806+
pub struct $TxCoupled<SPI: Instance, const BIDI: bool> {
807+
spi: $Spi<SPI, BIDI>,
808+
}
810809

811-
pub struct Rx<SPI> {
812-
spi: PhantomData<SPI>,
813-
}
810+
pub struct $RxCoupled<SPI: Instance, const BIDI: bool> {
811+
spi: PhantomData<SPI>,
812+
}
814813

815-
impl<SPI: Instance> DmaBuilder<SPI> {
816-
pub fn tx(self) -> Tx<SPI> {
817-
self.spi.cr2.modify(|_, w| w.txdmaen().enabled());
818-
Tx { spi: PhantomData }
819-
}
814+
impl<SPI: Instance, const BIDI: bool> $DmaBuilder<SPI, BIDI> {
815+
pub fn tx(self) -> $Tx<SPI, BIDI> {
816+
self.spi.spi.cr2.modify(|_, w| w.txdmaen().enabled());
817+
$Tx { spi: self.spi }
818+
}
820819

821-
pub fn rx(self) -> Rx<SPI> {
822-
self.spi.cr2.modify(|_, w| w.rxdmaen().enabled());
823-
Rx { spi: PhantomData }
824-
}
820+
pub fn rx(self) -> $Rx<SPI, BIDI> {
821+
self.spi.spi.cr2.modify(|_, w| w.rxdmaen().enabled());
822+
$Rx { spi: self.spi }
823+
}
825824

826-
pub fn txrx(self) -> (Tx<SPI>, Rx<SPI>) {
827-
self.spi.cr2.modify(|_, w| {
828-
w.txdmaen().enabled();
829-
w.rxdmaen().enabled()
830-
});
831-
(Tx { spi: PhantomData }, Rx { spi: PhantomData })
832-
}
833-
}
825+
pub fn txrx(self) -> ($TxCoupled<SPI, BIDI>, $RxCoupled<SPI, BIDI>) {
826+
self.spi.spi.cr2.modify(|_, w| {
827+
w.txdmaen().enabled();
828+
w.rxdmaen().enabled()
829+
});
830+
(
831+
$TxCoupled { spi: self.spi },
832+
$RxCoupled { spi: PhantomData },
833+
)
834+
}
835+
}
834836

835-
unsafe impl<SPI: Instance> PeriAddress for Rx<SPI> {
836-
#[inline(always)]
837-
fn address(&self) -> u32 {
838-
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
839-
}
837+
impl<SPI: Instance, const BIDI: bool> $Tx<SPI, BIDI> {
838+
pub fn release(self) -> $Spi<SPI, BIDI, u8> {
839+
self.spi.spi.cr2.modify(|_, w| w.txdmaen().disabled());
840+
self.spi
841+
}
842+
}
840843

841-
type MemSize = u8;
842-
}
844+
impl<SPI: Instance, const BIDI: bool> $Rx<SPI, BIDI> {
845+
pub fn release(self) -> $Spi<SPI, BIDI, u8> {
846+
self.spi.spi.cr2.modify(|_, w| w.rxdmaen().disabled());
847+
self.spi
848+
}
849+
}
843850

844-
unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, PeripheralToMemory> for Rx<SPI> where
845-
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>
846-
{
847-
}
851+
impl<SPI: Instance, const BIDI: bool> $TxCoupled<SPI, BIDI> {
852+
pub fn release(self, _couple: RxCoupled<SPI, BIDI>) -> $Spi<SPI, BIDI, u8> {
853+
self.spi.spi.cr2.modify(|_, w| {
854+
w.rxdmaen().disabled();
855+
w.txdmaen().disabled()
856+
});
857+
self.spi
858+
}
859+
}
848860

849-
unsafe impl<SPI: Instance> PeriAddress for Tx<SPI> {
850-
#[inline(always)]
851-
fn address(&self) -> u32 {
852-
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
853-
}
861+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $Rx<SPI, BIDI> {
862+
#[inline(always)]
863+
fn address(&self) -> u32 {
864+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
865+
}
854866

855-
type MemSize = u8;
856-
}
867+
type MemSize = u8;
868+
}
857869

858-
unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeripheral> for Tx<SPI> where
859-
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>
860-
{
870+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
871+
DMASet<STREAM, CHANNEL, PeripheralToMemory> for $Rx<SPI, BIDI>
872+
where
873+
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>,
874+
{
875+
}
876+
877+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $Tx<SPI, BIDI> {
878+
#[inline(always)]
879+
fn address(&self) -> u32 {
880+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
881+
}
882+
883+
type MemSize = u8;
884+
}
885+
886+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
887+
DMASet<STREAM, CHANNEL, MemoryToPeripheral> for $Tx<SPI, BIDI>
888+
where
889+
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
890+
{
891+
}
892+
893+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $RxCoupled<SPI, BIDI> {
894+
#[inline(always)]
895+
fn address(&self) -> u32 {
896+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
897+
}
898+
899+
type MemSize = u8;
900+
}
901+
902+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
903+
DMASet<STREAM, CHANNEL, PeripheralToMemory> for $RxCoupled<SPI, BIDI>
904+
where
905+
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>,
906+
{
907+
}
908+
909+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $TxCoupled<SPI, BIDI> {
910+
#[inline(always)]
911+
fn address(&self) -> u32 {
912+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
913+
}
914+
915+
type MemSize = u8;
916+
}
917+
918+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
919+
DMASet<STREAM, CHANNEL, MemoryToPeripheral> for $TxCoupled<SPI, BIDI>
920+
where
921+
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
922+
{
923+
}
924+
};
861925
}
862926

927+
dma!(Spi, DmaBuilder, Tx, Rx, TxCoupled, RxCoupled);
928+
dma!(
929+
SpiSlave,
930+
DmaBuilderSlave,
931+
TxSlave,
932+
RxSlave,
933+
TxCoupledSlave,
934+
RxCoupledSlave
935+
);
936+
863937
impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
864938
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
865939
if BIDI {

0 commit comments

Comments
 (0)