diff options
| -rw-r--r-- | embassy-stm32f4-examples/src/serial.rs | 29 | ||||
| -rw-r--r-- | embassy-stm32f4/src/serial.rs | 49 |
2 files changed, 36 insertions, 42 deletions
diff --git a/embassy-stm32f4-examples/src/serial.rs b/embassy-stm32f4-examples/src/serial.rs index baed2e525..ea0497016 100644 --- a/embassy-stm32f4-examples/src/serial.rs +++ b/embassy-stm32f4-examples/src/serial.rs | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | use cortex_m::singleton; | 8 | use cortex_m::singleton; |
| 9 | use cortex_m_rt::entry; | 9 | use cortex_m_rt::entry; |
| 10 | use embassy::executor::{task, Executor}; | 10 | use embassy::executor::{task, Executor}; |
| 11 | use embassy::uart::Uart; | ||
| 11 | use embassy::util::Forever; | 12 | use embassy::util::Forever; |
| 12 | use embassy_stm32f4::interrupt; | 13 | use embassy_stm32f4::interrupt; |
| 13 | use embassy_stm32f4::serial; | 14 | use embassy_stm32f4::serial; |
| @@ -27,23 +28,23 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) { | |||
| 27 | .pclk1(24.mhz()) | 28 | .pclk1(24.mhz()) |
| 28 | .freeze(); | 29 | .freeze(); |
| 29 | 30 | ||
| 30 | let mut serial = serial::Serial::new( | 31 | let mut serial = unsafe { |
| 31 | gpioa.pa9.into_alternate_af7(), | 32 | serial::Serial::new( |
| 32 | gpioa.pa10.into_alternate_af7(), | 33 | gpioa.pa9.into_alternate_af7(), |
| 33 | interrupt::take!(DMA2_STREAM7), | 34 | gpioa.pa10.into_alternate_af7(), |
| 34 | interrupt::take!(DMA2_STREAM2), | 35 | interrupt::take!(DMA2_STREAM7), |
| 35 | interrupt::take!(USART1), | 36 | interrupt::take!(DMA2_STREAM2), |
| 36 | dp.DMA2, | 37 | interrupt::take!(USART1), |
| 37 | dp.USART1, | 38 | dp.DMA2, |
| 38 | config::Parity::ParityNone, | 39 | dp.USART1, |
| 39 | 9600.bps(), | 40 | config::Parity::ParityNone, |
| 40 | clocks, | 41 | 9600.bps(), |
| 41 | ); | 42 | clocks, |
| 42 | 43 | ) | |
| 44 | }; | ||
| 43 | let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); | 45 | let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); |
| 44 | 46 | ||
| 45 | buf[5] = 0x01; | 47 | buf[5] = 0x01; |
| 46 | |||
| 47 | serial.send(buf).await; | 48 | serial.send(buf).await; |
| 48 | } | 49 | } |
| 49 | 50 | ||
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index 01348e32b..7590fe65a 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs | |||
| @@ -10,8 +10,9 @@ use core::sync::atomic::{self, Ordering}; | |||
| 10 | use core::task::{Context, Poll}; | 10 | use core::task::{Context, Poll}; |
| 11 | 11 | ||
| 12 | use embassy::interrupt::OwnedInterrupt; | 12 | use embassy::interrupt::OwnedInterrupt; |
| 13 | use embassy::uart::{Error, Uart}; | ||
| 13 | use embassy::util::Signal; | 14 | use embassy::util::Signal; |
| 14 | use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; | 15 | use embedded_dma::StaticWriteBuffer; |
| 15 | 16 | ||
| 16 | use crate::hal::dma::config::DmaConfig; | 17 | use crate::hal::dma::config::DmaConfig; |
| 17 | use crate::hal::dma::traits::{PeriAddress, Stream}; | 18 | use crate::hal::dma::traits::{PeriAddress, Stream}; |
| @@ -56,7 +57,8 @@ static STATE: State = State { | |||
| 56 | static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); | 57 | static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); |
| 57 | 58 | ||
| 58 | impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | 59 | impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { |
| 59 | pub fn new( | 60 | // Leaking futures is forbidden! |
| 61 | pub unsafe fn new( | ||
| 60 | txd: PA9<Alternate<AF7>>, | 62 | txd: PA9<Alternate<AF7>>, |
| 61 | rxd: PA10<Alternate<AF7>>, | 63 | rxd: PA10<Alternate<AF7>>, |
| 62 | tx_int: interrupt::DMA2_STREAM7Interrupt, | 64 | tx_int: interrupt::DMA2_STREAM7Interrupt, |
| @@ -135,18 +137,19 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 135 | 137 | ||
| 136 | STATE.rx_int.signal(()); | 138 | STATE.rx_int.signal(()); |
| 137 | } | 139 | } |
| 140 | } | ||
| 141 | |||
| 142 | impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | ||
| 143 | type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 144 | type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 138 | 145 | ||
| 139 | /// Sends serial data. | 146 | /// Sends serial data. |
| 140 | /// | 147 | fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> { |
| 141 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. | ||
| 142 | /// It it safe to use a buffer with a non static lifetime if memory is not | ||
| 143 | /// reused until the future has finished. | ||
| 144 | pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a | ||
| 145 | where | ||
| 146 | B: StaticWriteBuffer<Word = u8>, | ||
| 147 | { | ||
| 148 | unsafe { INSTANCE = self }; | 148 | unsafe { INSTANCE = self }; |
| 149 | 149 | ||
| 150 | #[allow(mutable_transmutes)] | ||
| 151 | let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; | ||
| 152 | |||
| 150 | let tx_stream = self.tx_stream.take().unwrap(); | 153 | let tx_stream = self.tx_stream.take().unwrap(); |
| 151 | let usart = self.usart.take().unwrap(); | 154 | let usart = self.usart.take().unwrap(); |
| 152 | STATE.tx_int.reset(); | 155 | STATE.tx_int.reset(); |
| @@ -155,7 +158,7 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 155 | let mut tx_transfer = Transfer::init( | 158 | let mut tx_transfer = Transfer::init( |
| 156 | tx_stream, | 159 | tx_stream, |
| 157 | usart, | 160 | usart, |
| 158 | tx_buffer, | 161 | static_buf, |
| 159 | None, | 162 | None, |
| 160 | DmaConfig::default() | 163 | DmaConfig::default() |
| 161 | .transfer_complete_interrupt(true) | 164 | .transfer_complete_interrupt(true) |
| @@ -172,6 +175,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 172 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); | 175 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); |
| 173 | self.tx_stream.replace(tx_stream); | 176 | self.tx_stream.replace(tx_stream); |
| 174 | self.usart.replace(usart); | 177 | self.usart.replace(usart); |
| 178 | |||
| 179 | Ok(()) | ||
| 175 | } | 180 | } |
| 176 | } | 181 | } |
| 177 | 182 | ||
| @@ -181,44 +186,32 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 181 | /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel | 186 | /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel |
| 182 | /// unfinished transfers after a timeout to prevent lockup when no more data | 187 | /// unfinished transfers after a timeout to prevent lockup when no more data |
| 183 | /// is incoming. | 188 | /// is incoming. |
| 184 | /// | 189 | fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { |
| 185 | /// `rx_buffer` is marked as static as per `embedded-dma` requirements. | ||
| 186 | /// It it safe to use a buffer with a non static lifetime if memory is not | ||
| 187 | /// reused until the future has finished. | ||
| 188 | pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a | ||
| 189 | where | ||
| 190 | B: StaticWriteBuffer<Word = u8> + Unpin, | ||
| 191 | { | ||
| 192 | unsafe { INSTANCE = self }; | 190 | unsafe { INSTANCE = self }; |
| 193 | 191 | ||
| 192 | let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; | ||
| 194 | let rx_stream = self.rx_stream.take().unwrap(); | 193 | let rx_stream = self.rx_stream.take().unwrap(); |
| 195 | let usart = self.usart.take().unwrap(); | 194 | let usart = self.usart.take().unwrap(); |
| 196 | STATE.rx_int.reset(); | 195 | STATE.rx_int.reset(); |
| 197 | |||
| 198 | async move { | 196 | async move { |
| 199 | let mut rx_transfer = Transfer::init( | 197 | let mut rx_transfer = Transfer::init( |
| 200 | rx_stream, | 198 | rx_stream, |
| 201 | usart, | 199 | usart, |
| 202 | rx_buffer, | 200 | static_buf, |
| 203 | None, | 201 | None, |
| 204 | DmaConfig::default() | 202 | DmaConfig::default() |
| 205 | .transfer_complete_interrupt(true) | 203 | .transfer_complete_interrupt(true) |
| 206 | .memory_increment(true) | 204 | .memory_increment(true) |
| 207 | .double_buffer(false), | 205 | .double_buffer(false), |
| 208 | ); | 206 | ); |
| 209 | |||
| 210 | self.rx_int.unpend(); | 207 | self.rx_int.unpend(); |
| 211 | self.rx_int.enable(); | 208 | self.rx_int.enable(); |
| 212 | |||
| 213 | rx_transfer.start(|_usart| {}); | 209 | rx_transfer.start(|_usart| {}); |
| 214 | |||
| 215 | STATE.rx_int.wait().await; | 210 | STATE.rx_int.wait().await; |
| 216 | 211 | let (rx_stream, usart, _, _) = rx_transfer.free(); | |
| 217 | let (rx_stream, usart, buf, _) = rx_transfer.free(); | ||
| 218 | self.rx_stream.replace(rx_stream); | 212 | self.rx_stream.replace(rx_stream); |
| 219 | self.usart.replace(usart); | 213 | self.usart.replace(usart); |
| 220 | 214 | Ok(()) | |
| 221 | buf | ||
| 222 | } | 215 | } |
| 223 | } | 216 | } |
| 224 | } | 217 | } |
