Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Circular DMA support #244

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Breaking changes

- Replace DMA buffer types with `Deref` ans `Unpin`

## [v0.6.1] - 2020-06-25

### Added
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ version = "0.2.2"
version = "0.2.3"
features = ["unproven"]

[dependencies.stable_deref_trait]
default-features = false
version = "1.1"

[dependencies.stm32-usbd]
version = "0.5.0"
features = ["ram_access_1x16"]
Expand Down
2 changes: 1 addition & 1 deletion examples/adc-dma-circ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn main() -> ! {
let adc_dma = adc1.with_dma(adc_ch0, dma_ch1);
let buf = singleton!(: [[u16; 8]; 2] = [[0; 8]; 2]).unwrap();

let mut circ_buffer = adc_dma.circ_read(buf);
let mut circ_buffer = adc_dma.circ_double_read(buf);

while circ_buffer.readable_half().unwrap() != Half::First {}

Expand Down
99 changes: 99 additions & 0 deletions examples/serial-dma-circ-len.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! Serial interface circular DMA RX transfer test

#![deny(unsafe_code)]
#![no_std]
#![no_main]

use panic_semihosting as _;

use cortex_m::singleton;
use cortex_m_semihosting::{hprint, hprintln};

use cortex_m_rt::entry;
use stm32f1xx_hal::{
dma::CircReadDmaLen,
pac,
prelude::*,
serial::{Config, Serial},
};

#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();

let mut flash = p.FLASH.constrain();
let mut rcc = p.RCC.constrain();

let clocks = rcc.cfgr.freeze(&mut flash.acr);

let mut afio = p.AFIO.constrain(&mut rcc.apb2);
let channels = p.DMA1.split(&mut rcc.ahb);

let mut gpioa = p.GPIOA.split(&mut rcc.apb2);
// let mut gpiob = p.GPIOB.split(&mut rcc.apb2);

// USART1
let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh);
let rx = gpioa.pa10;

// USART1
// let tx = gpiob.pb6.into_alternate_push_pull(&mut gpiob.crl);
// let rx = gpiob.pb7;

// USART2
// let tx = gpioa.pa2.into_alternate_push_pull(&mut gpioa.crl);
// let rx = gpioa.pa3;

// USART3
// let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
// let rx = gpiob.pb11;

let serial = Serial::usart1(
p.USART1,
(tx, rx),
&mut afio.mapr,
Config::default().baudrate(9_600.bps()),
clocks,
&mut rcc.apb2,
);

hprintln!("waiting for 5 bytes").unwrap();

let rx = serial.split().1.with_dma(channels.5);
// increase to reasonable size (e.g. 64, 128 etc.) for actual applications
let buf = singleton!(: [u8; 8] = [0; 8]).unwrap();

let mut circ_buffer = rx.circ_read_len(buf);

// wait until we have 5 bytes
while circ_buffer.len() < 5 {}

let mut dat = [0 as u8; 4];
assert!(circ_buffer.read(&mut dat[..]) == 4);

hprintln!("[{}, {}, {}, {}]", dat[0], dat[1], dat[2], dat[3]).unwrap();

// try to read again, now only one byte is returned
hprintln!("read {}", circ_buffer.read(&mut dat)).unwrap();

hprintln!("[{}]", dat[0]).unwrap();

// wait for the buffer to have 4 bytes again
while circ_buffer.len() < 4 {}

// all four bytes should be read in one go
assert!(circ_buffer.read(&mut dat) == 4);

hprintln!("[{}, {}, {}, {}]", dat[0], dat[1], dat[2], dat[3]).unwrap();

loop {
let read = circ_buffer.read(&mut dat);

if read > 0 {
for c in &dat[..read] {
hprint!("{}", *c as char).unwrap();
}
hprintln!("").unwrap();
}
}
}
2 changes: 1 addition & 1 deletion examples/serial-dma-circ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn main() -> ! {
let rx = serial.split().1.with_dma(channels.5);
let buf = singleton!(: [[u8; 8]; 2] = [[0; 8]; 2]).unwrap();

let mut circ_buffer = rx.circ_read(buf);
let mut circ_buffer = rx.circ_double_read(buf);

while circ_buffer.readable_half().unwrap() != Half::First {}

Expand Down
8 changes: 4 additions & 4 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use core::marker::PhantomData;
use embedded_hal::adc::{Channel, OneShot};

use crate::dma::{dma1::C1, CircBuffer, Receive, RxDma, Transfer, TransferPayload, W};
use crate::dma::{dma1::C1, CircDoubleBuffer, Receive, RxDma, Transfer, TransferPayload, W};
use crate::gpio::Analog;
use crate::gpio::{gpioa, gpiob, gpioc};
use crate::rcc::{Clocks, Enable, Reset, APB2};
Expand Down Expand Up @@ -667,12 +667,12 @@ where
}
}

impl<B, PINS, MODE> crate::dma::CircReadDma<B, u16> for AdcDma<PINS, MODE>
impl<B, PINS, MODE> crate::dma::CircDoubleReadDma<B, u16> for AdcDma<PINS, MODE>
where
Self: TransferPayload,
B: as_slice::AsMutSlice<Element = u16>,
{
fn circ_read(mut self, buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
fn circ_double_read(mut self, buffer: &'static mut [B; 2]) -> CircDoubleBuffer<B, Self> {
{
let buffer = buffer[0].as_mut_slice();
self.channel
Expand Down Expand Up @@ -701,7 +701,7 @@ where

self.start();

CircBuffer::new(buffer, self)
CircDoubleBuffer::new(buffer, self)
}
}

Expand Down
Loading