Skip to content

Commit fc59268

Browse files
committed
SPI DMA RX/TX example
1 parent ec73c4e commit fc59268

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ required-features = ["rt"]
120120
name = "rtic_frame_serial_dma"
121121
required-features = ["rt", "stm32l4x2"]
122122

123+
[[example]]
124+
name = "spi_dma_rxtx"
125+
required-features = ["rt", "stm32l4x2"]
126+
123127
[[example]]
124128
name = "serial_echo_rtic"
125129
required-features = ["rt", "stm32l4x3"]

examples/spi_dma_rxtx.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Test the SPI in RX/TX (transfer) DMA mode
2+
#![deny(unsafe_code)]
3+
#![no_main]
4+
#![no_std]
5+
6+
use panic_rtt_target as _;
7+
use rtt_target::rprintln;
8+
use stm32l4xx_hal::{
9+
dma::TransferDma,
10+
gpio::{Speed, State as PinState},
11+
hal::spi::{Mode, Phase, Polarity},
12+
prelude::*,
13+
rcc::{ClockSecuritySystem, CrystalBypass, MsiFreq},
14+
spi::Spi,
15+
};
16+
17+
#[rtic::app(device = stm32l4xx_hal::pac, peripherals = true)]
18+
const APP: () = {
19+
#[init]
20+
fn init(cx: init::Context) {
21+
static mut DMA_BUF: [u8; 5] = [0xf0, 0xaa, 0x00, 0xff, 0x0f];
22+
23+
rtt_target::rtt_init_print!();
24+
rprintln!("Initializing... ");
25+
26+
let dp = cx.device;
27+
28+
let mut flash = dp.FLASH.constrain();
29+
let mut rcc = dp.RCC.constrain();
30+
let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1);
31+
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2);
32+
let dma1_channels = dp.DMA1.split(&mut rcc.ahb1);
33+
34+
//
35+
// Initialize the clocks to 80 MHz
36+
//
37+
rprintln!(" - Clock init");
38+
let clocks = rcc
39+
.cfgr
40+
.lse(CrystalBypass::Enable, ClockSecuritySystem::Disable)
41+
.hsi48(true) // For RNG
42+
.msi(MsiFreq::RANGE4M)
43+
.sysclk(80.mhz())
44+
.freeze(&mut flash.acr, &mut pwr);
45+
46+
//
47+
// Initialize the SPI
48+
//
49+
let sck = gpiob
50+
.pb3
51+
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
52+
.set_speed(Speed::High);
53+
let miso = gpiob
54+
.pb4
55+
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
56+
.set_speed(Speed::High);
57+
let mosi = gpiob
58+
.pb5
59+
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
60+
.set_speed(Speed::High);
61+
let mut dummy_cs = gpiob.pb6.into_push_pull_output_with_state(
62+
&mut gpiob.moder,
63+
&mut gpiob.otyper,
64+
PinState::High,
65+
);
66+
let spi = Spi::spi1(
67+
dp.SPI1,
68+
(sck, miso, mosi),
69+
Mode {
70+
phase: Phase::CaptureOnFirstTransition,
71+
polarity: Polarity::IdleLow,
72+
},
73+
100.khz(),
74+
clocks,
75+
&mut rcc.apb2,
76+
);
77+
78+
// Create DMA SPI
79+
let dma_spi = spi.with_rxtx_dma(dma1_channels.2, dma1_channels.3);
80+
81+
// Check the buffer before using it
82+
rprintln!("buf pre: 0x{:x?}", &DMA_BUF);
83+
84+
// Perform transfer and wait for it to finish (blocking), this can also be done using
85+
// interrupts on the desired DMA channel
86+
dummy_cs.set_low().ok();
87+
let transfer = dma_spi.transfer(DMA_BUF);
88+
let (buf, _dma_spi) = transfer.wait();
89+
dummy_cs.set_high().ok();
90+
91+
// Inspect the extracted buffer, if the MISO is connected to VCC or GND it will be all 0 or
92+
// 1.
93+
rprintln!("buf post: 0x{:x?}", &buf);
94+
}
95+
96+
// Idle function so RTT keeps working
97+
#[idle]
98+
fn idle(_cx: idle::Context) -> ! {
99+
loop {
100+
continue;
101+
}
102+
}
103+
};

0 commit comments

Comments
 (0)