From 27cfcbacb8e54c0182e118d3170c6f8be83a6b7c Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 6 Jan 2021 12:12:29 -0600 Subject: [PATCH 1/5] try uart implementation --- embassy-stm32f4/src/serial.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index 01348e32..ea84a227 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -10,8 +10,9 @@ use core::sync::atomic::{self, Ordering}; use core::task::{Context, Poll}; use embassy::interrupt::OwnedInterrupt; +use embassy::uart::Uart; use embassy::util::Signal; -use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; +use embedded_dma::StaticWriteBuffer; use crate::hal::dma::config::DmaConfig; use crate::hal::dma::traits::{PeriAddress, Stream}; @@ -135,16 +136,15 @@ impl Serial, Stream2> { STATE.rx_int.signal(()); } +} +impl Uart for Serial, Stream2> { /// Sends serial data. /// /// `tx_buffer` is marked as static as per `embedded-dma` requirements. /// It it safe to use a buffer with a non static lifetime if memory is not /// reused until the future has finished. - pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future + 'a - where - B: StaticWriteBuffer, - { + fn send<'a>(&'a mut self, buf: &'a mut [u8]) -> dyn Future> { unsafe { INSTANCE = self }; let tx_stream = self.tx_stream.take().unwrap(); @@ -155,7 +155,7 @@ impl Serial, Stream2> { let mut tx_transfer = Transfer::init( tx_stream, usart, - tx_buffer, + buf, None, DmaConfig::default() .transfer_complete_interrupt(true) @@ -185,10 +185,7 @@ impl Serial, Stream2> { /// `rx_buffer` is marked as static as per `embedded-dma` requirements. /// It it safe to use a buffer with a non static lifetime if memory is not /// reused until the future has finished. - pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future + 'a - where - B: StaticWriteBuffer + Unpin, - { + fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> dyn Future> { unsafe { INSTANCE = self }; let rx_stream = self.rx_stream.take().unwrap(); @@ -199,7 +196,7 @@ impl Serial, Stream2> { let mut rx_transfer = Transfer::init( rx_stream, usart, - rx_buffer, + buf.static_write_buffer(), None, DmaConfig::default() .transfer_complete_interrupt(true) @@ -217,8 +214,6 @@ impl Serial, Stream2> { let (rx_stream, usart, buf, _) = rx_transfer.free(); self.rx_stream.replace(rx_stream); self.usart.replace(usart); - - buf } } } From 1c3b7541cbfb7793899b002d50700d62c5e1a205 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 6 Jan 2021 14:12:33 -0600 Subject: [PATCH 2/5] use transmute for now --- embassy-stm32f4/src/serial.rs | 109 ++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index ea84a227..a34db9de 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -10,7 +10,7 @@ use core::sync::atomic::{self, Ordering}; use core::task::{Context, Poll}; use embassy::interrupt::OwnedInterrupt; -use embassy::uart::Uart; +use embassy::uart::{Error, Uart}; use embassy::util::Signal; use embedded_dma::StaticWriteBuffer; @@ -139,39 +139,49 @@ impl Serial, Stream2> { } impl Uart for Serial, Stream2> { + type SendFuture<'a> = impl Future> + 'a; + type ReceiveFuture<'a> = impl Future> + 'a; + /// Sends serial data. /// /// `tx_buffer` is marked as static as per `embedded-dma` requirements. /// It it safe to use a buffer with a non static lifetime if memory is not /// reused until the future has finished. - fn send<'a>(&'a mut self, buf: &'a mut [u8]) -> dyn Future> { + #[allow(mutable_transmutes)] + fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> { unsafe { INSTANCE = self }; - let tx_stream = self.tx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - STATE.tx_int.reset(); + unsafe { + let static_buf = core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf); - async move { - let mut tx_transfer = Transfer::init( - tx_stream, - usart, - buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); + let tx_stream = self.tx_stream.take().unwrap(); + let usart = self.usart.take().unwrap(); + STATE.tx_int.reset(); - self.tx_int.unpend(); - self.tx_int.enable(); - tx_transfer.start(|_usart| {}); + async move { + let mut tx_transfer = Transfer::init( + tx_stream, + usart, + static_buf, + None, + DmaConfig::default() + .transfer_complete_interrupt(true) + .memory_increment(true) + .double_buffer(false), + ); - STATE.tx_int.wait().await; + self.tx_int.unpend(); + self.tx_int.enable(); + tx_transfer.start(|_usart| {}); - let (tx_stream, usart, _buf, _) = tx_transfer.free(); - self.tx_stream.replace(tx_stream); - self.usart.replace(usart); + STATE.tx_int.wait().await; + + let (tx_stream, usart, _buf, _) = tx_transfer.free(); + self.tx_stream.replace(tx_stream); + self.usart.replace(usart); + + Ok(()) + } } } @@ -185,35 +195,34 @@ impl Uart for Serial, Stream2> { /// `rx_buffer` is marked as static as per `embedded-dma` requirements. /// It it safe to use a buffer with a non static lifetime if memory is not /// reused until the future has finished. - fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> dyn Future> { + fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { unsafe { INSTANCE = self }; - let rx_stream = self.rx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - STATE.rx_int.reset(); - - async move { - let mut rx_transfer = Transfer::init( - rx_stream, - usart, - buf.static_write_buffer(), - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - - self.rx_int.unpend(); - self.rx_int.enable(); - - rx_transfer.start(|_usart| {}); - - STATE.rx_int.wait().await; - - let (rx_stream, usart, buf, _) = rx_transfer.free(); - self.rx_stream.replace(rx_stream); - self.usart.replace(usart); + unsafe { + let static_buf = core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf); + let rx_stream = self.rx_stream.take().unwrap(); + let usart = self.usart.take().unwrap(); + STATE.rx_int.reset(); + async move { + let mut rx_transfer = Transfer::init( + rx_stream, + usart, + static_buf, + None, + DmaConfig::default() + .transfer_complete_interrupt(true) + .memory_increment(true) + .double_buffer(false), + ); + self.rx_int.unpend(); + self.rx_int.enable(); + rx_transfer.start(|_usart| {}); + STATE.rx_int.wait().await; + let (rx_stream, usart, buf, _) = rx_transfer.free(); + self.rx_stream.replace(rx_stream); + self.usart.replace(usart); + Ok(()) + } } } } From 31ba052f14b9573cfa5669a06b04da451c091ff6 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 6 Jan 2021 14:31:43 -0600 Subject: [PATCH 3/5] mark new unsafe --- embassy-stm32f4-examples/src/serial.rs | 35 +++++++++++++------------- embassy-stm32f4/src/serial.rs | 3 ++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/embassy-stm32f4-examples/src/serial.rs b/embassy-stm32f4-examples/src/serial.rs index baed2e52..11a5b890 100644 --- a/embassy-stm32f4-examples/src/serial.rs +++ b/embassy-stm32f4-examples/src/serial.rs @@ -8,6 +8,7 @@ use cortex_m::singleton; use cortex_m_rt::entry; use embassy::executor::{task, Executor}; +use embassy::uart::Uart; use embassy::util::Forever; use embassy_stm32f4::interrupt; use embassy_stm32f4::serial; @@ -27,24 +28,24 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) { .pclk1(24.mhz()) .freeze(); - let mut serial = serial::Serial::new( - gpioa.pa9.into_alternate_af7(), - gpioa.pa10.into_alternate_af7(), - interrupt::take!(DMA2_STREAM7), - interrupt::take!(DMA2_STREAM2), - interrupt::take!(USART1), - dp.DMA2, - dp.USART1, - config::Parity::ParityNone, - 9600.bps(), - clocks, - ); + unsafe { + let mut serial = serial::Serial::new( + gpioa.pa9.into_alternate_af7(), + gpioa.pa10.into_alternate_af7(), + interrupt::take!(DMA2_STREAM7), + interrupt::take!(DMA2_STREAM2), + interrupt::take!(USART1), + dp.DMA2, + dp.USART1, + config::Parity::ParityNone, + 9600.bps(), + clocks, + ); + let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); - let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); - - buf[5] = 0x01; - - serial.send(buf).await; + buf[5] = 0x01; + serial.send(buf).await; + } } static EXECUTOR: Forever = Forever::new(); diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index a34db9de..b1343827 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -57,7 +57,8 @@ static STATE: State = State { static mut INSTANCE: *const Serial, Stream2> = ptr::null_mut(); impl Serial, Stream2> { - pub fn new( + // Leaking futures is forbidden! + pub unsafe fn new( txd: PA9>, rxd: PA10>, tx_int: interrupt::DMA2_STREAM7Interrupt, From a168b9ef51999e09b18c23453e24d3980cfaccb0 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 6 Jan 2021 21:02:02 -0600 Subject: [PATCH 4/5] restrict unsafe block --- embassy-stm32f4-examples/src/serial.rs | 14 ++-- embassy-stm32f4/src/serial.rs | 96 ++++++++++++-------------- 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/embassy-stm32f4-examples/src/serial.rs b/embassy-stm32f4-examples/src/serial.rs index 11a5b890..ea049701 100644 --- a/embassy-stm32f4-examples/src/serial.rs +++ b/embassy-stm32f4-examples/src/serial.rs @@ -28,8 +28,8 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) { .pclk1(24.mhz()) .freeze(); - unsafe { - let mut serial = serial::Serial::new( + let mut serial = unsafe { + serial::Serial::new( gpioa.pa9.into_alternate_af7(), gpioa.pa10.into_alternate_af7(), interrupt::take!(DMA2_STREAM7), @@ -40,12 +40,12 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) { config::Parity::ParityNone, 9600.bps(), clocks, - ); - let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); + ) + }; + let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); - buf[5] = 0x01; - serial.send(buf).await; - } + buf[5] = 0x01; + serial.send(buf).await; } static EXECUTOR: Forever = Forever::new(); diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index b1343827..c430ee95 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -152,37 +152,35 @@ impl Uart for Serial, Stream2> { fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> { unsafe { INSTANCE = self }; - unsafe { - let static_buf = core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf); + let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; - let tx_stream = self.tx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - STATE.tx_int.reset(); + let tx_stream = self.tx_stream.take().unwrap(); + let usart = self.usart.take().unwrap(); + STATE.tx_int.reset(); - async move { - let mut tx_transfer = Transfer::init( - tx_stream, - usart, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); + async move { + let mut tx_transfer = Transfer::init( + tx_stream, + usart, + static_buf, + None, + DmaConfig::default() + .transfer_complete_interrupt(true) + .memory_increment(true) + .double_buffer(false), + ); - self.tx_int.unpend(); - self.tx_int.enable(); - tx_transfer.start(|_usart| {}); + self.tx_int.unpend(); + self.tx_int.enable(); + tx_transfer.start(|_usart| {}); - STATE.tx_int.wait().await; + STATE.tx_int.wait().await; - let (tx_stream, usart, _buf, _) = tx_transfer.free(); - self.tx_stream.replace(tx_stream); - self.usart.replace(usart); + let (tx_stream, usart, _buf, _) = tx_transfer.free(); + self.tx_stream.replace(tx_stream); + self.usart.replace(usart); - Ok(()) - } + Ok(()) } } @@ -199,31 +197,29 @@ impl Uart for Serial, Stream2> { fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { unsafe { INSTANCE = self }; - unsafe { - let static_buf = core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf); - let rx_stream = self.rx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - STATE.rx_int.reset(); - async move { - let mut rx_transfer = Transfer::init( - rx_stream, - usart, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - self.rx_int.unpend(); - self.rx_int.enable(); - rx_transfer.start(|_usart| {}); - STATE.rx_int.wait().await; - let (rx_stream, usart, buf, _) = rx_transfer.free(); - self.rx_stream.replace(rx_stream); - self.usart.replace(usart); - Ok(()) - } + let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; + let rx_stream = self.rx_stream.take().unwrap(); + let usart = self.usart.take().unwrap(); + STATE.rx_int.reset(); + async move { + let mut rx_transfer = Transfer::init( + rx_stream, + usart, + static_buf, + None, + DmaConfig::default() + .transfer_complete_interrupt(true) + .memory_increment(true) + .double_buffer(false), + ); + self.rx_int.unpend(); + self.rx_int.enable(); + rx_transfer.start(|_usart| {}); + STATE.rx_int.wait().await; + let (rx_stream, usart, _, _) = rx_transfer.free(); + self.rx_stream.replace(rx_stream); + self.usart.replace(usart); + Ok(()) } } } From 7adf99eff3cf5f8c407168ad618bbe354a4f28eb Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 13 Jan 2021 17:40:32 -0600 Subject: [PATCH 5/5] implement changes --- embassy-stm32f4/src/serial.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index c430ee95..7590fe65 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -144,14 +144,10 @@ impl Uart for Serial, Stream2> { type ReceiveFuture<'a> = impl Future> + 'a; /// Sends serial data. - /// - /// `tx_buffer` is marked as static as per `embedded-dma` requirements. - /// It it safe to use a buffer with a non static lifetime if memory is not - /// reused until the future has finished. - #[allow(mutable_transmutes)] fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> { unsafe { INSTANCE = self }; + #[allow(mutable_transmutes)] let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; let tx_stream = self.tx_stream.take().unwrap(); @@ -190,10 +186,6 @@ impl Uart for Serial, Stream2> { /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel /// unfinished transfers after a timeout to prevent lockup when no more data /// is incoming. - /// - /// `rx_buffer` is marked as static as per `embedded-dma` requirements. - /// It it safe to use a buffer with a non static lifetime if memory is not - /// reused until the future has finished. fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { unsafe { INSTANCE = self };