stm32: implement idle trait

This commit is contained in:
xoviat 2021-03-23 21:04:36 -05:00
parent 3c9d5b61bb
commit 095ba23ad3

View File

@ -10,7 +10,7 @@ use core::marker::PhantomData;
use futures::{select_biased, FutureExt}; use futures::{select_biased, FutureExt};
use embassy::interrupt::Interrupt; use embassy::interrupt::Interrupt;
use embassy::traits::uart::{Error, Uart}; use embassy::traits::uart::{Error, IdleUart, Uart};
use embassy::util::InterruptFuture; use embassy::util::InterruptFuture;
use crate::hal::{ use crate::hal::{
@ -150,6 +150,56 @@ where
let rx_stream = self.rx_stream.take().unwrap(); let rx_stream = self.rx_stream.take().unwrap();
let usart = self.usart.take().unwrap(); let usart = self.usart.take().unwrap();
async move {
let mut rx_transfer = Transfer::init(
rx_stream,
usart,
static_buf,
None,
DmaConfig::default()
.transfer_complete_interrupt(true)
.memory_increment(true)
.double_buffer(false),
);
let fut = InterruptFuture::new(&mut self.rx_int);
rx_transfer.start(|_usart| {});
fut.await;
let (rx_stream, usart, _, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream);
self.usart.replace(usart);
Ok(())
}
}
}
impl<USART, TSTREAM, RSTREAM, CHANNEL> IdleUart for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
where
USART: serial::Instance
+ PeriAddress<MemSize = u8>
+ DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
+ DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
+ WithInterrupt
+ 'static,
TSTREAM: Stream + WithInterrupt + 'static,
RSTREAM: Stream + WithInterrupt + 'static,
CHANNEL: Channel + 'static,
{
type ReceiveFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a;
/// Receives serial data.
///
/// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data.
///
/// Returns the number of bytes read.
fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> {
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();
async move { async move {
unsafe { unsafe {
/* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */
@ -171,6 +221,8 @@ where
.double_buffer(false), .double_buffer(false),
); );
let total_bytes = RSTREAM::get_number_of_transfers() as usize;
let fut = InterruptFuture::new(&mut self.rx_int); let fut = InterruptFuture::new(&mut self.rx_int);
let fut_idle = InterruptFuture::new(&mut self.usart_int); let fut_idle = InterruptFuture::new(&mut self.usart_int);
@ -183,13 +235,15 @@ where
let (rx_stream, usart, _, _) = rx_transfer.free(); let (rx_stream, usart, _, _) = rx_transfer.free();
let remaining_bytes = RSTREAM::get_number_of_transfers() as usize;
unsafe { unsafe {
(*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit());
} }
self.rx_stream.replace(rx_stream); self.rx_stream.replace(rx_stream);
self.usart.replace(usart); self.usart.replace(usart);
Ok(()) Ok(total_bytes - remaining_bytes)
} }
} }
} }