From a88f0028ef2f1c57a66d7c3ed587b1ff2129bec2 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:14:14 -0400 Subject: [PATCH] First shot at async dma usart for stm32. --- embassy-stm32/src/dma_traits.rs | 15 ++++++++++ embassy-stm32/src/usart/v3.rs | 42 +++++++++++++++++++++++---- examples/stm32l4/src/bin/usart_dma.rs | 11 +++---- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/dma_traits.rs b/embassy-stm32/src/dma_traits.rs index 8f1a9f40..518e10dc 100644 --- a/embassy-stm32/src/dma_traits.rs +++ b/embassy-stm32/src/dma_traits.rs @@ -1,4 +1,5 @@ use core::future::Future; +use embassy::util::Unborrow; pub trait WriteDma { type WriteDmaFuture<'a>: Future + 'a @@ -19,3 +20,17 @@ pub trait ReadDma { where T: 'a; } + +pub trait NoDmaMarker {} + +pub struct NoDma; + +impl NoDmaMarker for NoDma {} + +unsafe impl Unborrow for NoDma { + type Target = NoDma; + + unsafe fn unborrow(self) -> Self::Target { + self + } +} diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs index 0071c597..6c9696c7 100644 --- a/embassy-stm32/src/usart/v3.rs +++ b/embassy-stm32/src/usart/v3.rs @@ -6,20 +6,30 @@ use embassy_extras::unborrow; use crate::pac::usart::{regs, vals}; use super::*; +use core::future::Future; +use futures::TryFutureExt; -pub struct Uart<'d, T: Instance> { +use crate::dma_traits::NoDma; +use crate::dma_traits::NoDmaMarker; + +#[allow(dead_code)] +pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { inner: T, phantom: PhantomData<&'d mut T>, + tx_dma: TxDma, + rx_dma: RxDma, } -impl<'d, T: Instance> Uart<'d, T> { +impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { pub fn new( inner: impl Unborrow, rx: impl Unborrow>, tx: impl Unborrow>, + tx_dma: impl Unborrow, + rx_dma: impl Unborrow, config: Config, ) -> Self { - unborrow!(inner, rx, tx); + unborrow!(inner, rx, tx, tx_dma, rx_dma); // Uncomment once we find all of the H7's UART clocks. T::enable(); @@ -54,11 +64,17 @@ impl<'d, T: Instance> Uart<'d, T> { Self { inner, phantom: PhantomData, + tx_dma, + rx_dma, } } #[cfg(any(dma, dmamux))] - pub async fn write_dma(&mut self, ch: &mut impl TxDma, buffer: &[u8]) -> Result<(), Error> { + pub async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error> + where + TxDma: crate::usart::TxDma, + { + let ch = &mut self.tx_dma; unsafe { self.inner.regs().cr3().modify(|reg| { reg.set_dmat(true); @@ -99,7 +115,11 @@ impl<'d, T: Instance> Uart<'d, T> { } } -impl<'d, T: Instance> embedded_hal::blocking::serial::Write for Uart<'d, T> { +impl<'d, T: Instance, TxDma, RxDma> embedded_hal::blocking::serial::Write + for Uart<'d, T, TxDma, RxDma> +where + TxDma: NoDmaMarker, +{ type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { unsafe { @@ -119,3 +139,15 @@ impl<'d, T: Instance> embedded_hal::blocking::serial::Write for Uart<'d, T> Ok(()) } } + +// rustfmt::skip because intellij removes the 'where' claus on the associated type. +#[rustfmt::skip] +impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma> + where TxDma: crate::usart::TxDma +{ + type WriteFuture<'a> where Self: 'a = impl Future>; + + fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { + self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other) + } +} diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs index cc630e0d..1239bf9c 100644 --- a/examples/stm32l4/src/bin/usart_dma.rs +++ b/examples/stm32l4/src/bin/usart_dma.rs @@ -17,22 +17,23 @@ use embassy_stm32::usart::{Config, Uart}; use example_common::*; use heapless::String; use stm32l4::stm32l4x5 as pac; +use embassy_stm32::dma_traits::NoDma; +use embassy_traits::uart::Write as AsyncWrite; +use embassy::io::AsyncWriteExt; #[embassy::task] async fn main_task() { let mut p = embassy_stm32::init(Default::default()); let config = Config::default(); - let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, config); + let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_3, NoDma, config); for n in 0u32.. { let mut s: String<128> = String::new(); core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); - usart - .write_dma(&mut p.DMA1_3, s.as_bytes()) - .await - .unwrap(); + usart.write( s.as_bytes() ).await; + info!("wrote DMA"); } }