stm32/serial: update to new traits.

This commit is contained in:
Dario Nieuwenhuis 2021-03-29 01:14:18 +02:00
parent 5b74e326e5
commit 3a0ddb8104
2 changed files with 84 additions and 72 deletions

View File

@ -12,10 +12,11 @@ use example_common::{panic, *};
use cortex_m::singleton; use cortex_m::singleton;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embassy::executor::{task, Executor}; use embassy::executor::{task, Executor};
use embassy::traits::uart::Uart; use embassy::traits::uart::{Read, Write};
use embassy::util::Forever; use embassy::util::Forever;
use embassy_stm32f4::interrupt; use embassy_stm32f4::interrupt;
use embassy_stm32f4::serial; use embassy_stm32f4::serial;
use futures::pin_mut;
use stm32f4xx_hal::dma::StreamsTuple; use stm32f4xx_hal::dma::StreamsTuple;
use stm32f4xx_hal::prelude::*; use stm32f4xx_hal::prelude::*;
use stm32f4xx_hal::serial::config::Config; use stm32f4xx_hal::serial::config::Config;
@ -76,10 +77,12 @@ async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) {
clocks, clocks,
) )
}; };
pin_mut!(serial);
let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); let buf = singleton!(: [u8; 30] = [0; 30]).unwrap();
buf[5] = 0x01; buf[5] = 0x01;
serial.send(buf).await.unwrap(); serial.write(buf).await.unwrap();
} }
static EXECUTOR: Forever<Executor> = Forever::new(); static EXECUTOR: Forever<Executor> = Forever::new();

View File

@ -1,17 +1,12 @@
//! Async low power Serial. //! Async Serial.
//!
//! The peripheral is autmatically enabled and disabled as required to save power.
//! Lowest power consumption can only be guaranteed if the send receive futures
//! are dropped correctly (e.g. not using `mem::forget()`).
use core::future::Future; use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::pin::Pin;
use futures::{select_biased, FutureExt};
use embassy::interrupt::Interrupt; use embassy::interrupt::Interrupt;
use embassy::traits::uart::{Error, IdleUart, Uart}; use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write};
use embassy::util::InterruptFuture; use embassy::util::InterruptFuture;
use futures::{select_biased, FutureExt};
use crate::hal::{ use crate::hal::{
dma, dma,
@ -89,7 +84,7 @@ where
} }
} }
impl<USART, TSTREAM, RSTREAM, CHANNEL> Uart for Serial<USART, TSTREAM, RSTREAM, CHANNEL> impl<USART, TSTREAM, RSTREAM, CHANNEL> Read for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
where where
USART: serial::Instance USART: serial::Instance
+ PeriAddress<MemSize = u8> + PeriAddress<MemSize = u8>
@ -101,56 +96,19 @@ where
RSTREAM: Stream + WithInterrupt + 'static, RSTREAM: Stream + WithInterrupt + 'static,
CHANNEL: Channel + 'static, CHANNEL: Channel + 'static,
{ {
type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
/// Sends serial data.
fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> {
#[allow(mutable_transmutes)]
let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
let tx_stream = self.tx_stream.take().unwrap();
let usart = self.usart.take().unwrap();
async move {
let mut tx_transfer = Transfer::init(
tx_stream,
usart,
static_buf,
None,
DmaConfig::default()
.transfer_complete_interrupt(true)
.memory_increment(true)
.double_buffer(false),
);
let fut = InterruptFuture::new(&mut self.tx_int);
tx_transfer.start(|_usart| {});
fut.await;
let (tx_stream, usart, _buf, _) = tx_transfer.free();
self.tx_stream.replace(tx_stream);
self.usart.replace(usart);
Ok(())
}
}
/// Receives serial data. /// Receives serial data.
/// ///
/// The future is pending until the buffer is completely filled. /// The future is pending until the buffer is completely filled.
/// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
/// unfinished transfers after a timeout to prevent lockup when no more data let this = unsafe { self.get_unchecked_mut() };
/// is incoming.
fn receive<'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 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 {
let rx_stream = this.rx_stream.take().unwrap();
let usart = this.usart.take().unwrap();
let mut rx_transfer = Transfer::init( let mut rx_transfer = Transfer::init(
rx_stream, rx_stream,
usart, usart,
@ -162,20 +120,20 @@ where
.double_buffer(false), .double_buffer(false),
); );
let fut = InterruptFuture::new(&mut self.rx_int); let fut = InterruptFuture::new(&mut this.rx_int);
rx_transfer.start(|_usart| {}); rx_transfer.start(|_usart| {});
fut.await; fut.await;
let (rx_stream, usart, _, _) = rx_transfer.free(); let (rx_stream, usart, _, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream); this.rx_stream.replace(rx_stream);
self.usart.replace(usart); this.usart.replace(usart);
Ok(()) Ok(())
} }
} }
} }
impl<USART, TSTREAM, RSTREAM, CHANNEL> IdleUart for Serial<USART, TSTREAM, RSTREAM, CHANNEL> impl<USART, TSTREAM, RSTREAM, CHANNEL> Write for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
where where
USART: serial::Instance USART: serial::Instance
+ PeriAddress<MemSize = u8> + PeriAddress<MemSize = u8>
@ -187,20 +145,74 @@ where
RSTREAM: Stream + WithInterrupt + 'static, RSTREAM: Stream + WithInterrupt + 'static,
CHANNEL: Channel + 'static, CHANNEL: Channel + 'static,
{ {
type ReceiveFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a; type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
/// Sends serial data.
fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> Self::WriteFuture<'a> {
let this = unsafe { self.get_unchecked_mut() };
#[allow(mutable_transmutes)]
let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
async move {
let tx_stream = this.tx_stream.take().unwrap();
let usart = this.usart.take().unwrap();
let mut tx_transfer = Transfer::init(
tx_stream,
usart,
static_buf,
None,
DmaConfig::default()
.transfer_complete_interrupt(true)
.memory_increment(true)
.double_buffer(false),
);
let fut = InterruptFuture::new(&mut this.tx_int);
tx_transfer.start(|_usart| {});
fut.await;
let (tx_stream, usart, _buf, _) = tx_transfer.free();
this.tx_stream.replace(tx_stream);
this.usart.replace(usart);
Ok(())
}
}
}
impl<USART, TSTREAM, RSTREAM, CHANNEL> ReadUntilIdle 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 ReadUntilIdleFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a;
/// Receives serial data. /// Receives serial data.
/// ///
/// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some 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. /// Returns the number of bytes read.
fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> { fn read_until_idle<'a>(
self: Pin<&'a mut Self>,
buf: &'a mut [u8],
) -> Self::ReadUntilIdleFuture<'a> {
let this = unsafe { self.get_unchecked_mut() };
let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; 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 {
let rx_stream = this.rx_stream.take().unwrap();
let usart = this.usart.take().unwrap();
unsafe { unsafe {
/* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */
(*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit());
@ -223,15 +235,12 @@ where
let total_bytes = RSTREAM::get_number_of_transfers() as usize; let total_bytes = RSTREAM::get_number_of_transfers() as usize;
let fut = InterruptFuture::new(&mut self.rx_int); let fut = InterruptFuture::new(&mut this.rx_int);
let fut_idle = InterruptFuture::new(&mut self.usart_int); let fut_idle = InterruptFuture::new(&mut this.usart_int);
rx_transfer.start(|_usart| {}); rx_transfer.start(|_usart| {});
select_biased! { futures::future::select(fut, fut_idle).await;
() = fut.fuse() => {},
() = fut_idle.fuse() => {},
}
let (rx_stream, usart, _, _) = rx_transfer.free(); let (rx_stream, usart, _, _) = rx_transfer.free();
@ -240,8 +249,8 @@ where
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); this.rx_stream.replace(rx_stream);
self.usart.replace(usart); this.usart.replace(usart);
Ok(total_bytes - remaining_bytes) Ok(total_bytes - remaining_bytes)
} }