aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32f4-examples/src/serial.rs29
-rw-r--r--embassy-stm32f4/src/serial.rs49
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 @@
8use cortex_m::singleton; 8use cortex_m::singleton;
9use cortex_m_rt::entry; 9use cortex_m_rt::entry;
10use embassy::executor::{task, Executor}; 10use embassy::executor::{task, Executor};
11use embassy::uart::Uart;
11use embassy::util::Forever; 12use embassy::util::Forever;
12use embassy_stm32f4::interrupt; 13use embassy_stm32f4::interrupt;
13use embassy_stm32f4::serial; 14use 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};
10use core::task::{Context, Poll}; 10use core::task::{Context, Poll};
11 11
12use embassy::interrupt::OwnedInterrupt; 12use embassy::interrupt::OwnedInterrupt;
13use embassy::uart::{Error, Uart};
13use embassy::util::Signal; 14use embassy::util::Signal;
14use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; 15use embedded_dma::StaticWriteBuffer;
15 16
16use crate::hal::dma::config::DmaConfig; 17use crate::hal::dma::config::DmaConfig;
17use crate::hal::dma::traits::{PeriAddress, Stream}; 18use crate::hal::dma::traits::{PeriAddress, Stream};
@@ -56,7 +57,8 @@ static STATE: State = State {
56static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); 57static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut();
57 58
58impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { 59impl 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
142impl 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}