diff --git a/embassy-stm32f4-examples/src/serial.rs b/embassy-stm32f4-examples/src/serial.rs index baed2e52..ea049701 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,23 +28,23 @@ 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, - ); - + let mut serial = unsafe { + 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(); buf[5] = 0x01; - serial.send(buf).await; } diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index 01348e32..7590fe65 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::{Error, 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}; @@ -56,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, @@ -135,18 +137,19 @@ impl Serial, Stream2> { STATE.rx_int.signal(()); } +} + +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. - 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 [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(); let usart = self.usart.take().unwrap(); STATE.tx_int.reset(); @@ -155,7 +158,7 @@ impl Serial, Stream2> { let mut tx_transfer = Transfer::init( tx_stream, usart, - tx_buffer, + static_buf, None, DmaConfig::default() .transfer_complete_interrupt(true) @@ -172,6 +175,8 @@ impl Serial, Stream2> { let (tx_stream, usart, _buf, _) = tx_transfer.free(); self.tx_stream.replace(tx_stream); self.usart.replace(usart); + + Ok(()) } } @@ -181,44 +186,32 @@ impl 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. - 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]) -> Self::ReceiveFuture<'a> { unsafe { INSTANCE = self }; + 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, - rx_buffer, + 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(); + let (rx_stream, usart, _, _) = rx_transfer.free(); self.rx_stream.replace(rx_stream); self.usart.replace(usart); - - buf + Ok(()) } } }