embassy/embassy-stm32f4/src/serial.rs

239 lines
7.0 KiB
Rust
Raw Normal View History

2020-12-31 23:40:51 +01:00
//! Async low power Serial.
2020-12-28 16:17:36 +01:00
//!
2020-12-29 03:48:26 +01:00
//! 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;
2021-03-06 06:04:20 +01:00
use core::marker::PhantomData;
2021-01-04 19:48:13 +01:00
use core::ptr;
use core::sync::atomic::{self, Ordering};
2020-12-28 16:17:36 +01:00
2021-03-05 00:20:35 +01:00
use embassy::interrupt::{Interrupt, InterruptExt};
2021-03-02 00:32:23 +01:00
use embassy::traits::uart::{Error, Uart};
2021-03-05 00:20:35 +01:00
use embassy::util::InterruptFuture;
2020-12-29 03:48:26 +01:00
2021-03-06 06:04:20 +01:00
use crate::hal::{
dma,
dma::config::DmaConfig,
dma::traits::{Channel, DMASet, PeriAddress, Stream},
dma::{MemoryToPeripheral, PeripheralToMemory, Transfer},
rcc::Clocks,
serial,
serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig},
serial::{Event as SerialEvent, Pins, Serial as HalSerial},
};
2020-12-28 16:17:36 +01:00
use crate::interrupt;
2021-03-05 00:20:35 +01:00
use crate::pac;
2020-12-28 23:43:29 +01:00
2020-12-31 23:40:51 +01:00
/// Interface to the Serial peripheral
2021-03-05 00:20:35 +01:00
pub struct Serial<
2021-03-06 05:59:54 +01:00
USART: PeriAddress<MemSize = u8> + WithInterrupt,
TSTREAM: Stream + WithInterrupt,
RSTREAM: Stream + WithInterrupt,
2021-03-05 00:20:35 +01:00
CHANNEL: dma::traits::Channel,
> {
2020-12-31 23:38:31 +01:00
tx_stream: Option<TSTREAM>,
rx_stream: Option<RSTREAM>,
usart: Option<USART>,
2021-03-06 05:59:54 +01:00
tx_int: TSTREAM::Interrupt,
rx_int: RSTREAM::Interrupt,
usart_int: USART::Interrupt,
2021-03-06 06:04:20 +01:00
channel: PhantomData<CHANNEL>,
2020-12-28 16:17:36 +01:00
}
2021-03-05 00:20:35 +01:00
// static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut();
2021-03-06 05:59:54 +01:00
impl<USART, TSTREAM, RSTREAM, CHANNEL> Serial<USART, TSTREAM, RSTREAM, CHANNEL>
2021-03-05 00:20:35 +01:00
where
USART: serial::Instance
2021-03-06 06:04:20 +01:00
+ PeriAddress<MemSize = u8>
+ DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
+ DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
2021-03-06 05:59:54 +01:00
+ WithInterrupt,
TSTREAM: Stream + WithInterrupt,
RSTREAM: Stream + WithInterrupt,
2021-03-06 06:04:20 +01:00
CHANNEL: Channel,
2021-03-05 00:20:35 +01:00
{
2021-01-06 21:31:43 +01:00
// Leaking futures is forbidden!
2021-01-14 18:42:23 +01:00
pub unsafe fn new<PINS>(
2021-03-05 00:20:35 +01:00
usart: USART,
streams: (TSTREAM, RSTREAM),
2021-01-14 18:42:23 +01:00
pins: PINS,
2021-03-06 05:59:54 +01:00
tx_int: TSTREAM::Interrupt,
rx_int: RSTREAM::Interrupt,
usart_int: USART::Interrupt,
2021-01-14 18:42:23 +01:00
mut config: SerialConfig,
2020-12-30 05:57:00 +01:00
clocks: Clocks,
2021-01-14 18:42:23 +01:00
) -> Self
where
2021-03-05 00:20:35 +01:00
PINS: Pins<USART>,
2021-01-14 18:42:23 +01:00
{
config.dma = SerialDmaConfig::TxRx;
2021-03-05 00:20:35 +01:00
let mut serial = HalSerial::new(usart, pins, config, clocks).unwrap();
2020-12-28 16:17:36 +01:00
2021-01-01 21:59:57 +01:00
serial.listen(SerialEvent::Idle);
2021-01-04 19:48:13 +01:00
// serial.listen(SerialEvent::Txe);
2020-12-30 05:57:00 +01:00
2021-01-01 21:59:57 +01:00
let (usart, _) = serial.release();
2020-12-30 05:57:00 +01:00
2021-03-05 00:20:35 +01:00
let (tx_stream, rx_stream) = streams;
2020-12-28 16:17:36 +01:00
2020-12-31 23:40:51 +01:00
Serial {
2021-03-05 00:20:35 +01:00
tx_stream: Some(tx_stream),
rx_stream: Some(rx_stream),
2020-12-30 05:57:00 +01:00
usart: Some(usart),
2021-01-04 19:48:13 +01:00
tx_int: tx_int,
rx_int: rx_int,
usart_int: usart_int,
2021-03-05 00:20:35 +01:00
channel: core::marker::PhantomData,
2020-12-29 19:33:50 +01:00
}
2020-12-28 16:17:36 +01:00
}
2021-01-06 19:12:29 +01:00
}
2021-01-04 19:48:13 +01:00
2021-03-06 05:59:54 +01:00
impl<USART, TSTREAM, RSTREAM, CHANNEL> Uart for Serial<USART, TSTREAM, RSTREAM, CHANNEL>
2021-03-05 00:20:35 +01:00
where
USART: serial::Instance
2021-03-06 06:04:20 +01:00
+ PeriAddress<MemSize = u8>
+ DMASet<TSTREAM, CHANNEL, MemoryToPeripheral>
+ DMASet<RSTREAM, CHANNEL, PeripheralToMemory>
2021-03-06 05:59:54 +01:00
+ WithInterrupt
2021-03-05 00:20:35 +01:00
+ 'static,
2021-03-06 05:59:54 +01:00
TSTREAM: Stream + WithInterrupt + 'static,
RSTREAM: Stream + WithInterrupt + 'static,
2021-03-06 06:04:20 +01:00
CHANNEL: Channel + 'static,
2021-03-05 00:20:35 +01:00
{
2021-01-06 21:12:33 +01:00
type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
2020-12-29 03:48:26 +01:00
/// Sends serial data.
2021-01-06 21:12:33 +01:00
fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> {
2021-01-14 00:40:32 +01:00
#[allow(mutable_transmutes)]
2021-01-07 04:02:02 +01:00
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),
);
2021-03-05 00:20:35 +01:00
let fut = InterruptFuture::new(&mut self.tx_int);
2021-01-07 04:02:02 +01:00
tx_transfer.start(|_usart| {});
2021-03-05 00:20:35 +01:00
fut.await;
2021-01-07 04:02:02 +01:00
let (tx_stream, usart, _buf, _) = tx_transfer.free();
self.tx_stream.replace(tx_stream);
self.usart.replace(usart);
Ok(())
2020-12-29 03:48:26 +01:00
}
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
/// Receives serial data.
///
/// The future is pending until the buffer is completely filled.
/// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
/// unfinished transfers after a timeout to prevent lockup when no more data
/// is incoming.
2021-01-06 21:12:33 +01:00
fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> {
2021-01-07 04:02:02 +01:00
let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) };
2021-03-05 00:20:35 +01:00
2021-01-07 04:02:02 +01:00
let rx_stream = self.rx_stream.take().unwrap();
let usart = self.usart.take().unwrap();
2021-03-05 00:20:35 +01:00
2021-01-07 04:02:02 +01:00
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),
);
2021-03-05 00:20:35 +01:00
let fut = InterruptFuture::new(&mut self.rx_int);
2021-01-07 04:02:02 +01:00
rx_transfer.start(|_usart| {});
2021-03-05 00:20:35 +01:00
fut.await;
2021-01-07 04:02:02 +01:00
let (rx_stream, usart, _, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream);
self.usart.replace(usart);
2021-03-05 00:20:35 +01:00
2021-01-07 04:02:02 +01:00
Ok(())
2020-12-30 18:05:52 +01:00
}
2020-12-28 16:17:36 +01:00
}
}
2021-03-05 00:20:35 +01:00
mod private {
pub trait Sealed {}
}
pub trait WithInterrupt: private::Sealed {
2021-03-06 05:59:54 +01:00
type Interrupt: Interrupt;
2021-03-05 00:20:35 +01:00
}
macro_rules! dma {
($($PER:ident => ($dma:ident, $stream:ident),)+) => {
$(
impl private::Sealed for dma::$stream<pac::$dma> {}
impl WithInterrupt for dma::$stream<pac::$dma> {
2021-03-06 05:59:54 +01:00
type Interrupt = interrupt::$PER;
2021-03-05 00:20:35 +01:00
}
)+
}
}
macro_rules! usart {
($($PER:ident => ($usart:ident),)+) => {
$(
impl private::Sealed for pac::$usart {}
impl WithInterrupt for pac::$usart {
2021-03-06 05:59:54 +01:00
type Interrupt = interrupt::$PER;
2021-03-05 00:20:35 +01:00
}
)+
}
}
2021-03-05 00:27:46 +01:00
#[cfg(any(feature = "stm32f405",))]
2021-03-05 00:20:35 +01:00
dma! {
DMA2_STREAM0 => (DMA2, Stream0),
DMA2_STREAM1 => (DMA2, Stream1),
DMA2_STREAM2 => (DMA2, Stream2),
DMA2_STREAM3 => (DMA2, Stream3),
DMA2_STREAM4 => (DMA2, Stream4),
DMA2_STREAM5 => (DMA2, Stream5),
DMA2_STREAM6 => (DMA2, Stream6),
DMA2_STREAM7 => (DMA2, Stream7),
DMA1_STREAM0 => (DMA1, Stream0),
DMA1_STREAM1 => (DMA1, Stream1),
DMA1_STREAM2 => (DMA1, Stream2),
DMA1_STREAM3 => (DMA1, Stream3),
DMA1_STREAM4 => (DMA1, Stream4),
DMA1_STREAM5 => (DMA1, Stream5),
DMA1_STREAM6 => (DMA1, Stream6),
}
2021-03-05 00:27:46 +01:00
#[cfg(any(feature = "stm32f405",))]
2021-03-05 00:20:35 +01:00
usart! {
USART1 => (USART1),
USART2 => (USART2),
USART3 => (USART3),
UART4 => (UART4),
UART5 => (UART5),
USART6 => (USART6),
}