From a88f0028ef2f1c57a66d7c3ed587b1ff2129bec2 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:14:14 -0400 Subject: [PATCH 1/5] 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 8f1a9f40e..518e10dcb 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 0071c597a..6c9696c71 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 cc630e0df..1239bf9c2 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"); } } From 38b1359c409e6bf285242561838d33e8c3c81927 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:35:03 -0400 Subject: [PATCH 2/5] Remove pub and cfg's, since they will be implied by the existance of TxDma in theory. --- embassy-stm32/src/usart/v3.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs index 6c9696c71..3029bf6e4 100644 --- a/embassy-stm32/src/usart/v3.rs +++ b/embassy-stm32/src/usart/v3.rs @@ -69,8 +69,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { } } - #[cfg(any(dma, dmamux))] - pub async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error> + async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error> where TxDma: crate::usart::TxDma, { From 43cb8de4344cb8400632b125c2391d128090c86e Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:37:42 -0400 Subject: [PATCH 3/5] Remove gratuitous NoDmaMarker. --- embassy-stm32/src/dma_traits.rs | 4 ---- embassy-stm32/src/usart/v3.rs | 7 ++----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/dma_traits.rs b/embassy-stm32/src/dma_traits.rs index 518e10dcb..6733d911a 100644 --- a/embassy-stm32/src/dma_traits.rs +++ b/embassy-stm32/src/dma_traits.rs @@ -21,12 +21,8 @@ pub trait ReadDma { T: 'a; } -pub trait NoDmaMarker {} - pub struct NoDma; -impl NoDmaMarker for NoDma {} - unsafe impl Unborrow for NoDma { type Target = NoDma; diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs index 3029bf6e4..4d78abb24 100644 --- a/embassy-stm32/src/usart/v3.rs +++ b/embassy-stm32/src/usart/v3.rs @@ -10,7 +10,6 @@ use core::future::Future; use futures::TryFutureExt; use crate::dma_traits::NoDma; -use crate::dma_traits::NoDmaMarker; #[allow(dead_code)] pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { @@ -114,10 +113,8 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { } } -impl<'d, T: Instance, TxDma, RxDma> embedded_hal::blocking::serial::Write - for Uart<'d, T, TxDma, RxDma> -where - TxDma: NoDmaMarker, +impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write + for Uart<'d, T, NoDma, RxDma> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { From 3fd9023fce5a1d376dccfd06e4d319b5fe213033 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:45:54 -0400 Subject: [PATCH 4/5] Fix the h7 example. --- examples/stm32h7/src/bin/usart.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs index b44d712b5..d8e60158b 100644 --- a/examples/stm32h7/src/bin/usart.rs +++ b/examples/stm32h7/src/bin/usart.rs @@ -14,6 +14,7 @@ use embassy::executor::Executor; use embassy::time::Clock; use embassy::util::Forever; use embassy_stm32::usart::{Config, Uart}; +use embassy_stm32::dma_traits::NoDma; use example_common::*; use stm32h7xx_hal as hal; @@ -27,7 +28,7 @@ async fn main_task() { let p = embassy_stm32::init(Default::default()); let config = Config::default(); - let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, config); + let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, NoDma, NoDma, config); usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); info!("wrote Hello, starting echo"); From 21e94972dc5f19f6a8620b9ef9cb98c84aa4a963 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 14 Jul 2021 14:55:20 -0400 Subject: [PATCH 5/5] Fix more warnings and examples. --- examples/stm32l4/src/bin/usart.rs | 3 ++- examples/stm32l4/src/bin/usart_dma.rs | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs index 0b14eeb59..dc0f649b7 100644 --- a/examples/stm32l4/src/bin/usart.rs +++ b/examples/stm32l4/src/bin/usart.rs @@ -18,13 +18,14 @@ use example_common::*; use cortex_m_rt::entry; use stm32l4::stm32l4x5 as pac; +use embassy_stm32::dma_traits::NoDma; #[embassy::task] async fn main_task() { let 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, NoDma, NoDma, config); usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); info!("wrote Hello, starting echo"); diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs index 1239bf9c2..6a2341859 100644 --- a/examples/stm32l4/src/bin/usart_dma.rs +++ b/examples/stm32l4/src/bin/usart_dma.rs @@ -19,11 +19,10 @@ 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 p = embassy_stm32::init(Default::default()); let config = Config::default(); let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_3, NoDma, config); @@ -32,7 +31,7 @@ async fn main_task() { let mut s: String<128> = String::new(); core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); - usart.write( s.as_bytes() ).await; + usart.write( s.as_bytes() ).await.ok(); info!("wrote DMA"); }