diff options
| author | xoviat <[email protected]> | 2021-03-23 21:05:01 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-03-23 21:05:01 -0500 |
| commit | 226877b16af848dbe8553eb8789d82c301b5e584 (patch) | |
| tree | c8a869edac81b4423ae40085d387a8d10f11c47a | |
| parent | 639059ba33e2440027924155df5c8a2efb7f4f6d (diff) | |
| parent | 095ba23ad30d0d019d3e47be59b2354133367212 (diff) | |
Merge pull request #104 from xoviat/idle-trait
traits: add idle trait
| -rw-r--r-- | embassy-stm32f4/src/serial.rs | 58 | ||||
| -rw-r--r-- | embassy-traits/src/uart.rs | 9 |
2 files changed, 65 insertions, 2 deletions
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index bed89288e..c8dc0598a 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs | |||
| @@ -10,7 +10,7 @@ use core::marker::PhantomData; | |||
| 10 | use futures::{select_biased, FutureExt}; | 10 | use futures::{select_biased, FutureExt}; |
| 11 | 11 | ||
| 12 | use embassy::interrupt::Interrupt; | 12 | use embassy::interrupt::Interrupt; |
| 13 | use embassy::traits::uart::{Error, Uart}; | 13 | use embassy::traits::uart::{Error, IdleUart, Uart}; |
| 14 | use embassy::util::InterruptFuture; | 14 | use embassy::util::InterruptFuture; |
| 15 | 15 | ||
| 16 | use crate::hal::{ | 16 | use crate::hal::{ |
| @@ -151,6 +151,56 @@ where | |||
| 151 | let usart = self.usart.take().unwrap(); | 151 | let usart = self.usart.take().unwrap(); |
| 152 | 152 | ||
| 153 | async move { | 153 | async move { |
| 154 | let mut rx_transfer = Transfer::init( | ||
| 155 | rx_stream, | ||
| 156 | usart, | ||
| 157 | static_buf, | ||
| 158 | None, | ||
| 159 | DmaConfig::default() | ||
| 160 | .transfer_complete_interrupt(true) | ||
| 161 | .memory_increment(true) | ||
| 162 | .double_buffer(false), | ||
| 163 | ); | ||
| 164 | |||
| 165 | let fut = InterruptFuture::new(&mut self.rx_int); | ||
| 166 | rx_transfer.start(|_usart| {}); | ||
| 167 | fut.await; | ||
| 168 | |||
| 169 | let (rx_stream, usart, _, _) = rx_transfer.free(); | ||
| 170 | self.rx_stream.replace(rx_stream); | ||
| 171 | self.usart.replace(usart); | ||
| 172 | |||
| 173 | Ok(()) | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | impl<USART, TSTREAM, RSTREAM, CHANNEL> IdleUart for Serial<USART, TSTREAM, RSTREAM, CHANNEL> | ||
| 179 | where | ||
| 180 | USART: serial::Instance | ||
| 181 | + PeriAddress<MemSize = u8> | ||
| 182 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 183 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 184 | + WithInterrupt | ||
| 185 | + 'static, | ||
| 186 | TSTREAM: Stream + WithInterrupt + 'static, | ||
| 187 | RSTREAM: Stream + WithInterrupt + 'static, | ||
| 188 | CHANNEL: Channel + 'static, | ||
| 189 | { | ||
| 190 | type ReceiveFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a; | ||
| 191 | |||
| 192 | /// Receives serial data. | ||
| 193 | /// | ||
| 194 | /// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data. | ||
| 195 | /// | ||
| 196 | /// Returns the number of bytes read. | ||
| 197 | fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { | ||
| 198 | let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; | ||
| 199 | |||
| 200 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 201 | let usart = self.usart.take().unwrap(); | ||
| 202 | |||
| 203 | async move { | ||
| 154 | unsafe { | 204 | unsafe { |
| 155 | /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ | 205 | /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ |
| 156 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); | 206 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); |
| @@ -171,6 +221,8 @@ where | |||
| 171 | .double_buffer(false), | 221 | .double_buffer(false), |
| 172 | ); | 222 | ); |
| 173 | 223 | ||
| 224 | let total_bytes = RSTREAM::get_number_of_transfers() as usize; | ||
| 225 | |||
| 174 | let fut = InterruptFuture::new(&mut self.rx_int); | 226 | let fut = InterruptFuture::new(&mut self.rx_int); |
| 175 | let fut_idle = InterruptFuture::new(&mut self.usart_int); | 227 | let fut_idle = InterruptFuture::new(&mut self.usart_int); |
| 176 | 228 | ||
| @@ -183,13 +235,15 @@ where | |||
| 183 | 235 | ||
| 184 | let (rx_stream, usart, _, _) = rx_transfer.free(); | 236 | let (rx_stream, usart, _, _) = rx_transfer.free(); |
| 185 | 237 | ||
| 238 | let remaining_bytes = RSTREAM::get_number_of_transfers() as usize; | ||
| 239 | |||
| 186 | unsafe { | 240 | unsafe { |
| 187 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); | 241 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); |
| 188 | } | 242 | } |
| 189 | self.rx_stream.replace(rx_stream); | 243 | self.rx_stream.replace(rx_stream); |
| 190 | self.usart.replace(usart); | 244 | self.usart.replace(usart); |
| 191 | 245 | ||
| 192 | Ok(()) | 246 | Ok(total_bytes - remaining_bytes) |
| 193 | } | 247 | } |
| 194 | } | 248 | } |
| 195 | } | 249 | } |
diff --git a/embassy-traits/src/uart.rs b/embassy-traits/src/uart.rs index b40b9e9bd..441747181 100644 --- a/embassy-traits/src/uart.rs +++ b/embassy-traits/src/uart.rs | |||
| @@ -10,6 +10,15 @@ pub enum Error { | |||
| 10 | pub trait Uart { | 10 | pub trait Uart { |
| 11 | type ReceiveFuture<'a>: Future<Output = Result<(), Error>>; | 11 | type ReceiveFuture<'a>: Future<Output = Result<(), Error>>; |
| 12 | type SendFuture<'a>: Future<Output = Result<(), Error>>; | 12 | type SendFuture<'a>: Future<Output = Result<(), Error>>; |
| 13 | /// Receive into the buffer until the buffer is full | ||
| 13 | fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; | 14 | fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; |
| 15 | /// Send the specified buffer, and return when the transmission has completed | ||
| 14 | fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>; | 16 | fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>; |
| 15 | } | 17 | } |
| 18 | |||
| 19 | pub trait IdleUart { | ||
| 20 | type ReceiveFuture<'a>: Future<Output = Result<usize, Error>>; | ||
| 21 | /// Receive into the buffer until the buffer is full or the line is idle after some bytes are received | ||
| 22 | /// Return the number of bytes received | ||
| 23 | fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; | ||
| 24 | } | ||
