Skip to content

Commit e471eeb

Browse files
committed
rework SPI DMA Rx/Tx: take 2
1 parent be8a84b commit e471eeb

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
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
- Add advanced timer dead time insertion example [#585]
1919
- Cleanups [#595]
2020
- Fix comlementary for independent channels [#599] [#603]
21+
- Capability to release and reuse SPI peripheral after using it with DMA.
2122
- I2c dma can now use single DMA channel for TX or RX only [#598]
2223
- `ws2812::prerendered` in example
2324

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
@@ -800,83 +800,157 @@ impl<SPI: Instance> Inner<SPI> {
800800
}
801801

802802
// Spi DMA
803+
macro_rules! dma {
804+
($Spi:ident, $DmaBuilder:ident, $Tx:ident, $Rx:ident, $TxCoupled:ident, $RxCoupled:ident) => {
805+
impl<SPI: Instance, const BIDI: bool> $Spi<SPI, BIDI, u8> {
806+
pub fn use_dma(self) -> $DmaBuilder<SPI, BIDI> {
807+
$DmaBuilder { spi: self }
808+
}
809+
}
803810

804-
impl<SPI: Instance, const BIDI: bool> Spi<SPI, BIDI, u8> {
805-
pub fn use_dma(self) -> DmaBuilder<SPI> {
806-
DmaBuilder {
807-
spi: self.inner.spi,
811+
pub struct $DmaBuilder<SPI: Instance, const BIDI: bool> {
812+
spi: $Spi<SPI, BIDI>,
808813
}
809-
}
810-
}
811814

812-
impl<SPI: Instance, const BIDI: bool> SpiSlave<SPI, BIDI, u8> {
813-
pub fn use_dma(self) -> DmaBuilder<SPI> {
814-
DmaBuilder {
815-
spi: self.inner.spi,
815+
pub struct $Tx<SPI: Instance, const BIDI: bool> {
816+
spi: $Spi<SPI, BIDI>,
816817
}
817-
}
818-
}
819818

820-
pub struct DmaBuilder<SPI> {
821-
spi: SPI,
822-
}
819+
pub struct $Rx<SPI: Instance, const BIDI: bool> {
820+
spi: $Spi<SPI, BIDI>,
821+
}
823822

824-
pub struct Tx<SPI> {
825-
spi: PhantomData<SPI>,
826-
}
823+
pub struct $TxCoupled<SPI: Instance, const BIDI: bool> {
824+
spi: $Spi<SPI, BIDI>,
825+
}
827826

828-
pub struct Rx<SPI> {
829-
spi: PhantomData<SPI>,
830-
}
827+
pub struct $RxCoupled<SPI: Instance, const BIDI: bool> {
828+
spi: PhantomData<SPI>,
829+
}
831830

832-
impl<SPI: Instance> DmaBuilder<SPI> {
833-
pub fn tx(self) -> Tx<SPI> {
834-
self.spi.cr2.modify(|_, w| w.txdmaen().enabled());
835-
Tx { spi: PhantomData }
836-
}
831+
impl<SPI: Instance, const BIDI: bool> $DmaBuilder<SPI, BIDI> {
832+
pub fn tx(self) -> $Tx<SPI, BIDI> {
833+
self.spi.spi.cr2.modify(|_, w| w.txdmaen().enabled());
834+
$Tx { spi: self.spi }
835+
}
837836

838-
pub fn rx(self) -> Rx<SPI> {
839-
self.spi.cr2.modify(|_, w| w.rxdmaen().enabled());
840-
Rx { spi: PhantomData }
841-
}
837+
pub fn rx(self) -> $Rx<SPI, BIDI> {
838+
self.spi.spi.cr2.modify(|_, w| w.rxdmaen().enabled());
839+
$Rx { spi: self.spi }
840+
}
842841

843-
pub fn txrx(self) -> (Tx<SPI>, Rx<SPI>) {
844-
self.spi.cr2.modify(|_, w| {
845-
w.txdmaen().enabled();
846-
w.rxdmaen().enabled()
847-
});
848-
(Tx { spi: PhantomData }, Rx { spi: PhantomData })
849-
}
850-
}
842+
pub fn txrx(self) -> ($TxCoupled<SPI, BIDI>, $RxCoupled<SPI, BIDI>) {
843+
self.spi.spi.cr2.modify(|_, w| {
844+
w.txdmaen().enabled();
845+
w.rxdmaen().enabled()
846+
});
847+
(
848+
$TxCoupled { spi: self.spi },
849+
$RxCoupled { spi: PhantomData },
850+
)
851+
}
852+
}
851853

852-
unsafe impl<SPI: Instance> PeriAddress for Rx<SPI> {
853-
#[inline(always)]
854-
fn address(&self) -> u32 {
855-
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
856-
}
854+
impl<SPI: Instance, const BIDI: bool> $Tx<SPI, BIDI> {
855+
pub fn release(self) -> $Spi<SPI, BIDI, u8> {
856+
self.spi.spi.cr2.modify(|_, w| w.txdmaen().disabled());
857+
self.spi
858+
}
859+
}
857860

858-
type MemSize = u8;
859-
}
861+
impl<SPI: Instance, const BIDI: bool> $Rx<SPI, BIDI> {
862+
pub fn release(self) -> $Spi<SPI, BIDI, u8> {
863+
self.spi.spi.cr2.modify(|_, w| w.rxdmaen().disabled());
864+
self.spi
865+
}
866+
}
860867

861-
unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, PeripheralToMemory> for Rx<SPI> where
862-
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>
863-
{
864-
}
868+
impl<SPI: Instance, const BIDI: bool> $TxCoupled<SPI, BIDI> {
869+
pub fn release(self, _couple: RxCoupled<SPI, BIDI>) -> $Spi<SPI, BIDI, u8> {
870+
self.spi.spi.cr2.modify(|_, w| {
871+
w.rxdmaen().disabled();
872+
w.txdmaen().disabled()
873+
});
874+
self.spi
875+
}
876+
}
865877

866-
unsafe impl<SPI: Instance> PeriAddress for Tx<SPI> {
867-
#[inline(always)]
868-
fn address(&self) -> u32 {
869-
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
870-
}
878+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $Rx<SPI, BIDI> {
879+
#[inline(always)]
880+
fn address(&self) -> u32 {
881+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
882+
}
871883

872-
type MemSize = u8;
873-
}
884+
type MemSize = u8;
885+
}
874886

875-
unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeripheral> for Tx<SPI> where
876-
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>
877-
{
887+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
888+
DMASet<STREAM, CHANNEL, PeripheralToMemory> for $Rx<SPI, BIDI>
889+
where
890+
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>,
891+
{
892+
}
893+
894+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $Tx<SPI, BIDI> {
895+
#[inline(always)]
896+
fn address(&self) -> u32 {
897+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
898+
}
899+
900+
type MemSize = u8;
901+
}
902+
903+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
904+
DMASet<STREAM, CHANNEL, MemoryToPeripheral> for $Tx<SPI, BIDI>
905+
where
906+
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
907+
{
908+
}
909+
910+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $RxCoupled<SPI, BIDI> {
911+
#[inline(always)]
912+
fn address(&self) -> u32 {
913+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
914+
}
915+
916+
type MemSize = u8;
917+
}
918+
919+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
920+
DMASet<STREAM, CHANNEL, PeripheralToMemory> for $RxCoupled<SPI, BIDI>
921+
where
922+
SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>,
923+
{
924+
}
925+
926+
unsafe impl<SPI: Instance, const BIDI: bool> PeriAddress for $TxCoupled<SPI, BIDI> {
927+
#[inline(always)]
928+
fn address(&self) -> u32 {
929+
unsafe { &(*SPI::ptr()).dr as *const _ as u32 }
930+
}
931+
932+
type MemSize = u8;
933+
}
934+
935+
unsafe impl<SPI: Instance, const BIDI: bool, STREAM, const CHANNEL: u8>
936+
DMASet<STREAM, CHANNEL, MemoryToPeripheral> for $TxCoupled<SPI, BIDI>
937+
where
938+
SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
939+
{
940+
}
941+
};
878942
}
879943

944+
dma!(Spi, DmaBuilder, Tx, Rx, TxCoupled, RxCoupled);
945+
dma!(
946+
SpiSlave,
947+
DmaBuilderSlave,
948+
TxSlave,
949+
RxSlave,
950+
TxCoupledSlave,
951+
RxCoupledSlave
952+
);
953+
880954
impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
881955
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
882956
if BIDI {

0 commit comments

Comments
 (0)