Skip to content

Commit

Permalink
Add DMA support for serial receive and transmit
Browse files Browse the repository at this point in the history
  • Loading branch information
teskje committed Apr 5, 2020
1 parent 485d119 commit 3ac50a3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 72 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ targets = ["thumbv7em-none-eabihf"]
travis-ci = { repository = "stm32-rs/stm32f3xx-hal" }

[dependencies]
as-slice = "0.1"
cortex-m = ">=0.5.8,<0.7"
cortex-m-rt = "0.6.8"
embedded-hal = "0.2.3"
Expand Down
187 changes: 115 additions & 72 deletions src/serial.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
//! Serial
use core::convert::Infallible;
use core::marker::PhantomData;
use core::ptr;

use crate::hal::blocking::serial::write::Default;
use crate::hal::serial;
use crate::stm32::{USART1, USART2, USART3};
use crate::{
gpio::{gpioa, gpiob, gpioc, AF7},
hal::{blocking, serial},
rcc::{Clocks, APB1, APB2},
stm32::{USART1, USART2, USART3},
time::Bps,
};
use core::{convert::Infallible, marker::PhantomData, ptr};
use nb;

use crate::gpio::gpioa::{PA10, PA2, PA3, PA9};
#[cfg(any(
feature = "stm32f301",
feature = "stm32f318",
feature = "stm32f302",
feature = "stm32f303",
feature = "stm32f334",
feature = "stm32f328",
feature = "stm32f358",
feature = "stm32f398"
))]
use crate::gpio::gpiob::PB11;
use crate::gpio::gpiob::{PB10, PB6, PB7};
use crate::gpio::gpioc::{PC10, PC11, PC4, PC5};
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -36,24 +23,20 @@ use crate::gpio::gpioc::{PC10, PC11, PC4, PC5};
feature = "stm32f358",
feature = "stm32f398"
))]
use crate::gpio::gpiod::{PD5, PD6, PD8, PD9};
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
feature = "stm32f303xc",
feature = "stm32f303xd",
feature = "stm32f303xe",
feature = "stm32f373",
feature = "stm32f378",
feature = "stm32f328",
feature = "stm32f358",
feature = "stm32f398"
))]
use crate::gpio::gpioe::{PE0, PE1, PE15};
use crate::gpio::{gpiod, gpioe};

#[cfg(feature = "stm32f303")]
mod dma_imports {
pub use crate::dma;
pub use as_slice::{AsMutSlice, AsSlice};
pub use core::{
ops::{Deref, DerefMut},
pin::Pin,
};
}

use crate::gpio::AF7;
use crate::rcc::{Clocks, APB1, APB2};
use crate::time::Bps;
#[cfg(feature = "stm32f303")]
use dma_imports::*;

/// Interrupt event
pub enum Event {
Expand Down Expand Up @@ -85,9 +68,9 @@ pub unsafe trait TxPin<USART> {}
/// RX pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RxPin<USART> {}

unsafe impl TxPin<USART1> for PA9<AF7> {}
unsafe impl TxPin<USART1> for PB6<AF7> {}
unsafe impl TxPin<USART1> for PC4<AF7> {}
unsafe impl TxPin<USART1> for gpioa::PA9<AF7> {}
unsafe impl TxPin<USART1> for gpiob::PB6<AF7> {}
unsafe impl TxPin<USART1> for gpioc::PC4<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -100,11 +83,11 @@ unsafe impl TxPin<USART1> for PC4<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl TxPin<USART1> for PE0<AF7> {}
unsafe impl TxPin<USART1> for gpioe::PE0<AF7> {}

unsafe impl RxPin<USART1> for PA10<AF7> {}
unsafe impl RxPin<USART1> for PB7<AF7> {}
unsafe impl RxPin<USART1> for PC5<AF7> {}
unsafe impl RxPin<USART1> for gpioa::PA10<AF7> {}
unsafe impl RxPin<USART1> for gpiob::PB7<AF7> {}
unsafe impl RxPin<USART1> for gpioc::PC5<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -117,11 +100,11 @@ unsafe impl RxPin<USART1> for PC5<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl RxPin<USART1> for PE1<AF7> {}
unsafe impl RxPin<USART1> for gpioe::PE1<AF7> {}

unsafe impl TxPin<USART2> for PA2<AF7> {}
// unsafe impl TxPin<USART2> for PA14<AF7> {}
// unsafe impl TxPin<USART2> for PB3<AF7> {}
unsafe impl TxPin<USART2> for gpioa::PA2<AF7> {}
// unsafe impl TxPin<USART2> for gpioa::PA14<AF7> {}
// unsafe impl TxPin<USART2> for gpiob::PB3<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -135,11 +118,11 @@ unsafe impl TxPin<USART2> for PA2<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl TxPin<USART2> for PD5<AF7> {}
unsafe impl TxPin<USART2> for gpiod::PD5<AF7> {}

unsafe impl RxPin<USART2> for PA3<AF7> {}
// unsafe impl RxPin<USART2> for PA15<AF7> {}
// unsafe impl RxPin<USART2> for PB4<AF7> {}
unsafe impl RxPin<USART2> for gpioa::PA3<AF7> {}
// unsafe impl RxPin<USART2> for gpioa::PA15<AF7> {}
// unsafe impl RxPin<USART2> for gpiob::PB4<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -153,10 +136,10 @@ unsafe impl RxPin<USART2> for PA3<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl RxPin<USART2> for PD6<AF7> {}
unsafe impl RxPin<USART2> for gpiod::PD6<AF7> {}

unsafe impl TxPin<USART3> for PB10<AF7> {}
unsafe impl TxPin<USART3> for PC10<AF7> {}
unsafe impl TxPin<USART3> for gpiob::PB10<AF7> {}
unsafe impl TxPin<USART3> for gpioc::PC10<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -170,7 +153,7 @@ unsafe impl TxPin<USART3> for PC10<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl TxPin<USART3> for PD8<AF7> {}
unsafe impl TxPin<USART3> for gpiod::PD8<AF7> {}

#[cfg(any(
feature = "stm32f301",
Expand All @@ -182,8 +165,8 @@ unsafe impl TxPin<USART3> for PD8<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl RxPin<USART3> for PB11<AF7> {}
unsafe impl RxPin<USART3> for PC11<AF7> {}
unsafe impl RxPin<USART3> for gpiob::PB11<AF7> {}
unsafe impl RxPin<USART3> for gpioc::PC11<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -197,7 +180,7 @@ unsafe impl RxPin<USART3> for PC11<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl RxPin<USART3> for PD9<AF7> {}
unsafe impl RxPin<USART3> for gpiod::PD9<AF7> {}
#[cfg(any(
feature = "stm32f302",
feature = "stm32f303xb",
Expand All @@ -210,7 +193,7 @@ unsafe impl RxPin<USART3> for PD9<AF7> {}
feature = "stm32f358",
feature = "stm32f398"
))]
unsafe impl RxPin<USART3> for PE15<AF7> {}
unsafe impl RxPin<USART3> for gpioe::PE15<AF7> {}

/// Serial abstraction
pub struct Serial<USART, PINS> {
Expand Down Expand Up @@ -251,21 +234,21 @@ macro_rules! hal {
apb.rstr().modify(|_, w| w.$usartXrst().set_bit());
apb.rstr().modify(|_, w| w.$usartXrst().clear_bit());

// disable hardware flow control
// TODO enable DMA
// usart.cr3.write(|w| w.rtse().clear_bit().ctse().clear_bit());

let brr = clocks.$pclkX().0 / baud_rate.0;
assert!(brr >= 16, "impossible baud rate");
// NOTE(write): uses all bits of this register.
usart.brr.write(|w| unsafe { w.bits(brr) });

// UE: enable USART
// RE: enable receiver
// TE: enable transceiver
usart
.cr1
.modify(|_, w| w.ue().set_bit().re().set_bit().te().set_bit());
usart.cr3.modify(|_, w| {
w.dmar().enabled(); // enable DMA for reception
w.dmat().enabled() // enable DMA for transmission
});

usart.cr1.modify(|_, w| {
w.ue().enabled(); // enable USART
w.re().enabled(); // enable receiver
w.te().enabled() // enable transmitter
});

Serial { usart, pins }
}
Expand Down Expand Up @@ -373,7 +356,67 @@ macro_rules! hal {
}
}

impl Default<u8> for Tx<$USARTX> {}
impl blocking::serial::write::Default<u8> for Tx<$USARTX> {}

#[cfg(feature = "stm32f303")]
impl Rx<$USARTX> {
/// Fill the buffer with received data using DMA.
pub fn read_all<B, C>(
self,
mut buffer: Pin<B>,
mut channel: C
) -> dma::Transfer<B, C, Self>
where
Self: dma::Target<C>,
B: DerefMut + 'static,
B::Target: AsMutSlice<Element = u8> + Unpin,
C: dma::Channel,
{
// NOTE(unsafe) taking the address of a register
let pa = unsafe { &(*$USARTX::ptr()).rdr } as *const _ as u32;
channel.set_peripheral_address(pa, dma::Increment::Disable);

let slice = buffer.as_mut_slice();
let (ma, len) = (slice.as_mut_ptr() as u32, slice.len());
channel.set_memory_address(ma, dma::Increment::Enable);
channel.set_transfer_length(len);
channel.set_word_size(dma::WordSize::Bits8);

channel.set_direction(dma::Direction::FromPeripheral);

unsafe { dma::Transfer::start(buffer, channel, self) }
}
}

#[cfg(feature = "stm32f303")]
impl Tx<$USARTX> {
/// Transmit all data in the buffer using DMA.
pub fn write_all<B, C>(
self,
buffer: Pin<B>,
mut channel: C
) -> dma::Transfer<B, C, Self>
where
Self: dma::Target<C>,
B: Deref + 'static,
B::Target: AsSlice<Element = u8>,
C: dma::Channel,
{
// NOTE(unsafe) taking the address of a register
let pa = unsafe { &(*$USARTX::ptr()).tdr } as *const _ as u32;
channel.set_peripheral_address(pa, dma::Increment::Disable);

let slice = buffer.as_slice();
let (ma, len) = (slice.as_ptr() as u32, slice.len());
channel.set_memory_address(ma, dma::Increment::Enable);
channel.set_transfer_length(len);
channel.set_word_size(dma::WordSize::Bits8);

channel.set_direction(dma::Direction::FromMemory);

unsafe { dma::Transfer::start(buffer, channel, self) }
}
}
)+
}
}
Expand Down

0 comments on commit 3ac50a3

Please sign in to comment.