Skip to content

Commit

Permalink
SPI DMA RX/TX example
Browse files Browse the repository at this point in the history
  • Loading branch information
korken89 committed May 30, 2021
1 parent 119a885 commit b209de8
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ required-features = ["rt"]
name = "rtic_frame_serial_dma"
required-features = ["rt", "stm32l4x2"]

[[example]]
name = "spi_dma_rxtx"
required-features = ["rt", "stm32l4x2"]

[[example]]
name = "serial_echo_rtic"
required-features = ["rt", "stm32l4x3"]
Expand Down
103 changes: 103 additions & 0 deletions examples/spi_dma_rxtx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! Test the SPI in RX/TX (transfer) DMA mode
#![deny(unsafe_code)]
#![no_main]
#![no_std]

use panic_rtt_target as _;
use rtt_target::rprintln;
use stm32l4xx_hal::{
dma::TransferDma,
gpio::{Speed, State as PinState},
hal::spi::{Mode, Phase, Polarity},
prelude::*,
rcc::{ClockSecuritySystem, CrystalBypass, MsiFreq},
spi::Spi,
};

#[rtic::app(device = stm32l4xx_hal::pac, peripherals = true)]
const APP: () = {
#[init]
fn init(cx: init::Context) {
static mut DMA_BUF: [u8; 5] = [0xf0, 0xaa, 0x00, 0xff, 0x0f];

rtt_target::rtt_init_print!();
rprintln!("Initializing... ");

let dp = cx.device;

let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1);
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2);
let dma1_channels = dp.DMA1.split(&mut rcc.ahb1);

//
// Initialize the clocks to 80 MHz
//
rprintln!(" - Clock init");
let clocks = rcc
.cfgr
.lse(CrystalBypass::Enable, ClockSecuritySystem::Disable)
.hsi48(true) // For RNG
.msi(MsiFreq::RANGE4M)
.sysclk(80.mhz())
.freeze(&mut flash.acr, &mut pwr);

//
// Initialize the SPI
//
let sck = gpiob
.pb3
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
.set_speed(Speed::High);
let miso = gpiob
.pb4
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
.set_speed(Speed::High);
let mosi = gpiob
.pb5
.into_af5(&mut gpiob.moder, &mut gpiob.afrl)
.set_speed(Speed::High);
let mut dummy_cs = gpiob.pb6.into_push_pull_output_with_state(
&mut gpiob.moder,
&mut gpiob.otyper,
PinState::High,
);
let spi = Spi::spi1(
dp.SPI1,
(sck, miso, mosi),
Mode {
phase: Phase::CaptureOnFirstTransition,
polarity: Polarity::IdleLow,
},
100.khz(),
clocks,
&mut rcc.apb2,
);

// Create DMA SPI
let dma_spi = spi.with_rxtx_dma(dma1_channels.2, dma1_channels.3);

// Check the buffer before using it
rprintln!("buf pre: 0x{:x?}", &DMA_BUF);

// Perform transfer and wait for it to finish (blocking), this can also be done using
// interrupts on the desired DMA channel
dummy_cs.set_low().ok();
let transfer = dma_spi.transfer(DMA_BUF);
let (buf, _dma_spi) = transfer.wait();
dummy_cs.set_high().ok();

// Inspect the extracted buffer, if the MISO is connected to VCC or GND it will be all 0 or
// 1.
rprintln!("buf post: 0x{:x?}", &buf);
}

// Idle function so RTT keeps working
#[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
continue;
}
}
};

0 comments on commit b209de8

Please sign in to comment.