diff --git a/Cargo.toml b/Cargo.toml index 76c019670..bcdc06f16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/serial.rs b/src/serial.rs index 93b0e2ba7..7a16a7305 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -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", @@ -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 { @@ -85,9 +68,9 @@ pub unsafe trait TxPin {} /// RX pin - DO NOT IMPLEMENT THIS TRAIT pub unsafe trait RxPin {} -unsafe impl TxPin for PA9 {} -unsafe impl TxPin for PB6 {} -unsafe impl TxPin for PC4 {} +unsafe impl TxPin for gpioa::PA9 {} +unsafe impl TxPin for gpiob::PB6 {} +unsafe impl TxPin for gpioc::PC4 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -100,11 +83,11 @@ unsafe impl TxPin for PC4 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl TxPin for PE0 {} +unsafe impl TxPin for gpioe::PE0 {} -unsafe impl RxPin for PA10 {} -unsafe impl RxPin for PB7 {} -unsafe impl RxPin for PC5 {} +unsafe impl RxPin for gpioa::PA10 {} +unsafe impl RxPin for gpiob::PB7 {} +unsafe impl RxPin for gpioc::PC5 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -117,11 +100,11 @@ unsafe impl RxPin for PC5 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl RxPin for PE1 {} +unsafe impl RxPin for gpioe::PE1 {} -unsafe impl TxPin for PA2 {} -// unsafe impl TxPin for PA14 {} -// unsafe impl TxPin for PB3 {} +unsafe impl TxPin for gpioa::PA2 {} +// unsafe impl TxPin for gpioa::PA14 {} +// unsafe impl TxPin for gpiob::PB3 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -135,11 +118,11 @@ unsafe impl TxPin for PA2 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl TxPin for PD5 {} +unsafe impl TxPin for gpiod::PD5 {} -unsafe impl RxPin for PA3 {} -// unsafe impl RxPin for PA15 {} -// unsafe impl RxPin for PB4 {} +unsafe impl RxPin for gpioa::PA3 {} +// unsafe impl RxPin for gpioa::PA15 {} +// unsafe impl RxPin for gpiob::PB4 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -153,10 +136,10 @@ unsafe impl RxPin for PA3 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl RxPin for PD6 {} +unsafe impl RxPin for gpiod::PD6 {} -unsafe impl TxPin for PB10 {} -unsafe impl TxPin for PC10 {} +unsafe impl TxPin for gpiob::PB10 {} +unsafe impl TxPin for gpioc::PC10 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -170,7 +153,7 @@ unsafe impl TxPin for PC10 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl TxPin for PD8 {} +unsafe impl TxPin for gpiod::PD8 {} #[cfg(any( feature = "stm32f301", @@ -182,8 +165,8 @@ unsafe impl TxPin for PD8 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl RxPin for PB11 {} -unsafe impl RxPin for PC11 {} +unsafe impl RxPin for gpiob::PB11 {} +unsafe impl RxPin for gpioc::PC11 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -197,7 +180,7 @@ unsafe impl RxPin for PC11 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl RxPin for PD9 {} +unsafe impl RxPin for gpiod::PD9 {} #[cfg(any( feature = "stm32f302", feature = "stm32f303xb", @@ -210,7 +193,7 @@ unsafe impl RxPin for PD9 {} feature = "stm32f358", feature = "stm32f398" ))] -unsafe impl RxPin for PE15 {} +unsafe impl RxPin for gpioe::PE15 {} /// Serial abstraction pub struct Serial { @@ -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 } } @@ -373,7 +356,67 @@ macro_rules! hal { } } - impl Default for Tx<$USARTX> {} + impl blocking::serial::write::Default for Tx<$USARTX> {} + + #[cfg(feature = "stm32f303")] + impl Rx<$USARTX> { + /// Fill the buffer with received data using DMA. + pub fn read_all( + self, + mut buffer: Pin, + mut channel: C + ) -> dma::Transfer + where + Self: dma::Target, + B: DerefMut + 'static, + B::Target: AsMutSlice + 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( + self, + buffer: Pin, + mut channel: C + ) -> dma::Transfer + where + Self: dma::Target, + B: Deref + 'static, + B::Target: AsSlice, + 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) } + } + } )+ } }