aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32f4-examples/src/bin/serial.rs7
-rw-r--r--embassy-stm32f4/src/serial.rs127
2 files changed, 73 insertions, 61 deletions
diff --git a/embassy-stm32f4-examples/src/bin/serial.rs b/embassy-stm32f4-examples/src/bin/serial.rs
index 49a588c25..c8e7f288f 100644
--- a/embassy-stm32f4-examples/src/bin/serial.rs
+++ b/embassy-stm32f4-examples/src/bin/serial.rs
@@ -12,10 +12,11 @@ use example_common::{panic, *};
12use cortex_m::singleton; 12use cortex_m::singleton;
13use cortex_m_rt::entry; 13use cortex_m_rt::entry;
14use embassy::executor::{task, Executor}; 14use embassy::executor::{task, Executor};
15use embassy::traits::uart::Uart; 15use embassy::traits::uart::{Read, Write};
16use embassy::util::Forever; 16use embassy::util::Forever;
17use embassy_stm32f4::interrupt; 17use embassy_stm32f4::interrupt;
18use embassy_stm32f4::serial; 18use embassy_stm32f4::serial;
19use futures::pin_mut;
19use stm32f4xx_hal::dma::StreamsTuple; 20use stm32f4xx_hal::dma::StreamsTuple;
20use stm32f4xx_hal::prelude::*; 21use stm32f4xx_hal::prelude::*;
21use stm32f4xx_hal::serial::config::Config; 22use stm32f4xx_hal::serial::config::Config;
@@ -76,10 +77,12 @@ async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) {
76 clocks, 77 clocks,
77 ) 78 )
78 }; 79 };
80 pin_mut!(serial);
81
79 let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); 82 let buf = singleton!(: [u8; 30] = [0; 30]).unwrap();
80 83
81 buf[5] = 0x01; 84 buf[5] = 0x01;
82 serial.send(buf).await.unwrap(); 85 serial.write(buf).await.unwrap();
83} 86}
84 87
85static EXECUTOR: Forever<Executor> = Forever::new(); 88static EXECUTOR: Forever<Executor> = Forever::new();
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs
index c8dc0598a..7539abf51 100644
--- a/embassy-stm32f4/src/serial.rs
+++ b/embassy-stm32f4/src/serial.rs
@@ -1,17 +1,12 @@
1//! Async low power Serial. 1//! Async Serial.
2//!
3//! The peripheral is autmatically enabled and disabled as required to save power.
4//! Lowest power consumption can only be guaranteed if the send receive futures
5//! are dropped correctly (e.g. not using `mem::forget()`).
6 2
7use core::future::Future; 3use core::future::Future;
8use core::marker::PhantomData; 4use core::marker::PhantomData;
9 5use core::pin::Pin;
10use futures::{select_biased, FutureExt};
11
12use embassy::interrupt::Interrupt; 6use embassy::interrupt::Interrupt;
13use embassy::traits::uart::{Error, IdleUart, Uart}; 7use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write};
14use embassy::util::InterruptFuture; 8use embassy::util::InterruptFuture;
9use futures::{select_biased, FutureExt};
15 10
16use crate::hal::{ 11use crate::hal::{
17 dma, 12 dma,
@@ -89,7 +84,7 @@ where
89 } 84 }
90} 85}
91 86
92impl<USART, TSTREAM, RSTREAM, CHANNEL> Uart for Serial<USART, TSTREAM, RSTREAM, CHANNEL> 87impl<USART, TSTREAM, RSTREAM, CHANNEL> Read for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
93where 88where
94 USART: serial::Instance 89 USART: serial::Instance
95 + PeriAddress<MemSize = u8> 90 + PeriAddress<MemSize = u8>
@@ -101,20 +96,21 @@ where
101 RSTREAM: Stream + WithInterrupt + 'static, 96 RSTREAM: Stream + WithInterrupt + 'static,
102 CHANNEL: Channel + 'static, 97 CHANNEL: Channel + 'static,
103{ 98{
104 type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; 99 type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
105 type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
106
107 /// Sends serial data.
108 fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> {
109 #[allow(mutable_transmutes)]
110 let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
111 100
112 let tx_stream = self.tx_stream.take().unwrap(); 101 /// Receives serial data.
113 let usart = self.usart.take().unwrap(); 102 ///
103 /// The future is pending until the buffer is completely filled.
104 fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
105 let this = unsafe { self.get_unchecked_mut() };
106 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) };
114 107
115 async move { 108 async move {
116 let mut tx_transfer = Transfer::init( 109 let rx_stream = this.rx_stream.take().unwrap();
117 tx_stream, 110 let usart = this.usart.take().unwrap();
111
112 let mut rx_transfer = Transfer::init(
113 rx_stream,
118 usart, 114 usart,
119 static_buf, 115 static_buf,
120 None, 116 None,
@@ -124,35 +120,45 @@ where
124 .double_buffer(false), 120 .double_buffer(false),
125 ); 121 );
126 122
127 let fut = InterruptFuture::new(&mut self.tx_int); 123 let fut = InterruptFuture::new(&mut this.rx_int);
128 124 rx_transfer.start(|_usart| {});
129 tx_transfer.start(|_usart| {});
130 fut.await; 125 fut.await;
131 126
132 let (tx_stream, usart, _buf, _) = tx_transfer.free(); 127 let (rx_stream, usart, _, _) = rx_transfer.free();
133 128 this.rx_stream.replace(rx_stream);
134 self.tx_stream.replace(tx_stream); 129 this.usart.replace(usart);
135 self.usart.replace(usart);
136 130
137 Ok(()) 131 Ok(())
138 } 132 }
139 } 133 }
134}
140 135
141 /// Receives serial data. 136impl<USART, TSTREAM, RSTREAM, CHANNEL> Write for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
142 /// 137where
143 /// The future is pending until the buffer is completely filled. 138 USART: serial::Instance
144 /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel 139 + PeriAddress<MemSize = u8>
145 /// unfinished transfers after a timeout to prevent lockup when no more data 140 + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
146 /// is incoming. 141 + DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
147 fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { 142 + WithInterrupt
148 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; 143 + 'static,
144 TSTREAM: Stream + WithInterrupt + 'static,
145 RSTREAM: Stream + WithInterrupt + 'static,
146 CHANNEL: Channel + 'static,
147{
148 type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
149 149
150 let rx_stream = self.rx_stream.take().unwrap(); 150 /// Sends serial data.
151 let usart = self.usart.take().unwrap(); 151 fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> Self::WriteFuture<'a> {
152 let this = unsafe { self.get_unchecked_mut() };
153 #[allow(mutable_transmutes)]
154 let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
152 155
153 async move { 156 async move {
154 let mut rx_transfer = Transfer::init( 157 let tx_stream = this.tx_stream.take().unwrap();
155 rx_stream, 158 let usart = this.usart.take().unwrap();
159
160 let mut tx_transfer = Transfer::init(
161 tx_stream,
156 usart, 162 usart,
157 static_buf, 163 static_buf,
158 None, 164 None,
@@ -162,20 +168,22 @@ where
162 .double_buffer(false), 168 .double_buffer(false),
163 ); 169 );
164 170
165 let fut = InterruptFuture::new(&mut self.rx_int); 171 let fut = InterruptFuture::new(&mut this.tx_int);
166 rx_transfer.start(|_usart| {}); 172
173 tx_transfer.start(|_usart| {});
167 fut.await; 174 fut.await;
168 175
169 let (rx_stream, usart, _, _) = rx_transfer.free(); 176 let (tx_stream, usart, _buf, _) = tx_transfer.free();
170 self.rx_stream.replace(rx_stream); 177
171 self.usart.replace(usart); 178 this.tx_stream.replace(tx_stream);
179 this.usart.replace(usart);
172 180
173 Ok(()) 181 Ok(())
174 } 182 }
175 } 183 }
176} 184}
177 185
178impl<USART, TSTREAM, RSTREAM, CHANNEL> IdleUart for Serial<USART, TSTREAM, RSTREAM, CHANNEL> 186impl<USART, TSTREAM, RSTREAM, CHANNEL> ReadUntilIdle for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
179where 187where
180 USART: serial::Instance 188 USART: serial::Instance
181 + PeriAddress<MemSize = u8> 189 + PeriAddress<MemSize = u8>
@@ -187,20 +195,24 @@ where
187 RSTREAM: Stream + WithInterrupt + 'static, 195 RSTREAM: Stream + WithInterrupt + 'static,
188 CHANNEL: Channel + 'static, 196 CHANNEL: Channel + 'static,
189{ 197{
190 type ReceiveFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a; 198 type ReadUntilIdleFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a;
191 199
192 /// Receives serial data. 200 /// Receives serial data.
193 /// 201 ///
194 /// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data. 202 /// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data.
195 /// 203 ///
196 /// Returns the number of bytes read. 204 /// Returns the number of bytes read.
197 fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { 205 fn read_until_idle<'a>(
206 self: Pin<&'a mut Self>,
207 buf: &'a mut [u8],
208 ) -> Self::ReadUntilIdleFuture<'a> {
209 let this = unsafe { self.get_unchecked_mut() };
198 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; 210 let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) };
199 211
200 let rx_stream = self.rx_stream.take().unwrap();
201 let usart = self.usart.take().unwrap();
202
203 async move { 212 async move {
213 let rx_stream = this.rx_stream.take().unwrap();
214 let usart = this.usart.take().unwrap();
215
204 unsafe { 216 unsafe {
205 /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ 217 /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */
206 (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); 218 (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit());
@@ -223,15 +235,12 @@ where
223 235
224 let total_bytes = RSTREAM::get_number_of_transfers() as usize; 236 let total_bytes = RSTREAM::get_number_of_transfers() as usize;
225 237
226 let fut = InterruptFuture::new(&mut self.rx_int); 238 let fut = InterruptFuture::new(&mut this.rx_int);
227 let fut_idle = InterruptFuture::new(&mut self.usart_int); 239 let fut_idle = InterruptFuture::new(&mut this.usart_int);
228 240
229 rx_transfer.start(|_usart| {}); 241 rx_transfer.start(|_usart| {});
230 242
231 select_biased! { 243 futures::future::select(fut, fut_idle).await;
232 () = fut.fuse() => {},
233 () = fut_idle.fuse() => {},
234 }
235 244
236 let (rx_stream, usart, _, _) = rx_transfer.free(); 245 let (rx_stream, usart, _, _) = rx_transfer.free();
237 246
@@ -240,8 +249,8 @@ where
240 unsafe { 249 unsafe {
241 (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); 250 (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit());
242 } 251 }
243 self.rx_stream.replace(rx_stream); 252 this.rx_stream.replace(rx_stream);
244 self.usart.replace(usart); 253 this.usart.replace(usart);
245 254
246 Ok(total_bytes - remaining_bytes) 255 Ok(total_bytes - remaining_bytes)
247 } 256 }