Skip to content

Commit 66b9952

Browse files
authored
spi: add DMA support for TX (#107)
* spi: add support for TX DMA * spi: add example for DMA usage --------- Signed-off-by: Jean-Baptiste Theou <[email protected]> Co-authored-by: Jean-Baptiste Theou <[email protected]>
1 parent b708ea2 commit 66b9952

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

examples/spi-dma.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// This example is to test the SPI with DMA support. Will output a pattern
2+
// in a loop
3+
4+
#![no_main]
5+
#![no_std]
6+
7+
use crate::hal::{
8+
block,
9+
delay::DelayFromCountDownTimer,
10+
gpio::gpioa::PA5,
11+
gpio::gpioa::PA6,
12+
gpio::gpioa::PA7,
13+
gpio::Alternate,
14+
gpio::AF5,
15+
prelude::*,
16+
pwr::PwrExt,
17+
rcc::Config,
18+
spi,
19+
stm32::Peripherals,
20+
time::{ExtU32, RateExtU32},
21+
timer::Timer,
22+
};
23+
24+
use cortex_m_rt::entry;
25+
use log::info;
26+
use stm32g4xx_hal as hal;
27+
use stm32g4xx_hal::dma::config::DmaConfig;
28+
use stm32g4xx_hal::dma::stream::DMAExt;
29+
use stm32g4xx_hal::dma::TransferExt;
30+
31+
#[macro_use]
32+
mod utils;
33+
34+
const BUFFER_SIZE: usize = 254;
35+
36+
#[entry]
37+
fn main() -> ! {
38+
utils::logger::init();
39+
40+
let dp = Peripherals::take().unwrap();
41+
let rcc = dp.RCC.constrain();
42+
let pwr = dp.PWR.constrain().freeze();
43+
let mut rcc = rcc.freeze(Config::hsi(), pwr);
44+
let timer2 = Timer::new(dp.TIM2, &rcc.clocks);
45+
let mut delay_tim2 = DelayFromCountDownTimer::new(timer2.start_count_down(100.millis()));
46+
47+
let gpioa = dp.GPIOA.split(&mut rcc);
48+
let sclk: PA5<Alternate<AF5>> = gpioa.pa5.into_alternate();
49+
let miso: PA6<Alternate<AF5>> = gpioa.pa6.into_alternate();
50+
let mosi: PA7<Alternate<AF5>> = gpioa.pa7.into_alternate();
51+
52+
let mut spi = dp
53+
.SPI1
54+
.spi((sclk, miso, mosi), spi::MODE_0, 400.kHz(), &mut rcc);
55+
let mut streams = dp.DMA1.split(&rcc);
56+
let config = DmaConfig::default()
57+
.transfer_complete_interrupt(false)
58+
.circular_buffer(true)
59+
.memory_increment(true);
60+
61+
let mut buf: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
62+
for index in 0..BUFFER_SIZE {
63+
buf[index] = index as u8;
64+
}
65+
let dma_buf = cortex_m::singleton!(: [u8; BUFFER_SIZE] = buf).unwrap();
66+
let mut transfer_dma =
67+
streams
68+
.0
69+
.into_memory_to_peripheral_transfer(spi.enable_tx_dma(), &mut dma_buf[..], config);
70+
transfer_dma.start(|_spi| {});
71+
loop {
72+
delay_tim2.delay_ms(1000_u16);
73+
}
74+
}

src/spi.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use crate::dma::mux::DmaMuxResources;
2+
use crate::dma::traits::TargetAddress;
3+
use crate::dma::MemoryToPeripheral;
14
use crate::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiof::*, Alternate, AF5, AF6};
25
#[cfg(any(
36
feature = "stm32g471",
@@ -20,6 +23,7 @@ use crate::stm32::{RCC, SPI1, SPI2, SPI3};
2023
use crate::time::Hertz;
2124
use core::cell::UnsafeCell;
2225
use core::ptr;
26+
2327
pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
2428

2529
/// SPI error
@@ -74,6 +78,7 @@ macro_rules! spi {
7478
sck: [ $($( #[ $pmetasck:meta ] )* $SCK:ty,)+ ],
7579
miso: [ $($( #[ $pmetamiso:meta ] )* $MISO:ty,)+ ],
7680
mosi: [ $($( #[ $pmetamosi:meta ] )* $MOSI:ty,)+ ],
81+
$mux:expr,
7782
) => {
7883
impl PinSck<$SPIX> for NoSck {}
7984

@@ -166,6 +171,14 @@ macro_rules! spi {
166171
pub fn release(self) -> ($SPIX, PINS) {
167172
(self.spi, self.pins)
168173
}
174+
175+
pub fn enable_tx_dma(self) -> Spi<$SPIX, PINS> {
176+
self.spi.cr2.modify(|_, w| w.txdmaen().set_bit());
177+
Spi {
178+
spi: self.spi,
179+
pins: self.pins,
180+
}
181+
}
169182
}
170183

171184
impl SpiExt<$SPIX> for $SPIX {
@@ -220,6 +233,18 @@ macro_rules! spi {
220233
})
221234
}
222235
}
236+
unsafe impl<Pin> TargetAddress<MemoryToPeripheral> for Spi<$SPIX, Pin> {
237+
#[inline(always)]
238+
fn address(&self) -> u32 {
239+
// unsafe: only the Tx part accesses the Tx register
240+
&unsafe { &*<$SPIX>::ptr() }.dr as *const _ as u32
241+
}
242+
243+
type MemSize = u8;
244+
245+
const REQUEST_LINE: Option<u8> = Some($mux as u8);
246+
}
247+
223248

224249
impl<PINS> ::hal::blocking::spi::transfer::Default<u8> for Spi<$SPIX, PINS> {}
225250

@@ -266,6 +291,7 @@ spi!(
266291
))]
267292
PG4<Alternate<AF5>>,
268293
],
294+
DmaMuxResources::SPI1_TX,
269295
);
270296

271297
spi!(
@@ -285,6 +311,7 @@ spi!(
285311
PA11<Alternate<AF5>>,
286312
PB15<Alternate<AF5>>,
287313
],
314+
DmaMuxResources::SPI2_TX,
288315
);
289316

290317
spi!(
@@ -310,6 +337,7 @@ spi!(
310337
PB5<Alternate<AF6>>,
311338
PC12<Alternate<AF6>>,
312339
],
340+
DmaMuxResources::SPI3_TX,
313341
);
314342

315343
#[cfg(any(
@@ -334,4 +362,5 @@ spi!(
334362
PE6<Alternate<AF5>>,
335363
PE14<Alternate<AF5>>,
336364
],
365+
DmaMuxResources::SPI4_TX,
337366
);

0 commit comments

Comments
 (0)