embassy/embassy-stm32f4/src/serial.rs

267 lines
7.8 KiB
Rust
Raw Normal View History

2020-12-29 03:48:26 +01:00
//! Async low power UARTE.
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()`).
2020-12-28 16:17:36 +01:00
use core::cell::UnsafeCell;
use core::cmp::min;
2020-12-29 03:48:26 +01:00
use core::future::Future;
2020-12-28 16:17:36 +01:00
use core::marker::PhantomPinned;
use core::ops::Deref;
use core::pin::Pin;
use core::ptr;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::{Context, Poll};
2020-12-28 20:13:43 +01:00
use cortex_m::singleton;
2020-12-28 16:17:36 +01:00
2020-12-29 03:48:26 +01:00
use embassy::util::Signal;
2020-12-29 19:33:50 +01:00
use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer};
2020-12-29 03:48:26 +01:00
use crate::fmt::assert;
2020-12-28 20:13:43 +01:00
use crate::hal::dma::config::DmaConfig;
use crate::hal::dma::traits::{PeriAddress, Stream};
2020-12-29 19:33:50 +01:00
use crate::hal::dma::{
Channel4, Channel7, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple,
Transfer,
};
2020-12-29 03:48:26 +01:00
use crate::hal::gpio::gpioa::{PA10, PA9};
2020-12-28 16:55:49 +01:00
use crate::hal::gpio::{Alternate, AF10, AF7, AF9};
2020-12-28 23:43:29 +01:00
use crate::hal::gpio::{Floating, Input, Output, PushPull};
2020-12-29 03:48:26 +01:00
use crate::hal::pac;
use crate::hal::prelude::*;
2020-12-28 23:43:29 +01:00
use crate::hal::rcc::Clocks;
use crate::hal::serial::config::{
Config as SerialConfig, DmaConfig as SerialDmaConfig, Parity, StopBits, WordLength,
2020-12-28 20:13:43 +01:00
};
2020-12-30 05:57:00 +01:00
use crate::hal::serial::{Event as SerialEvent, Serial};
2020-12-28 23:43:29 +01:00
use crate::hal::time::Bps;
2020-12-28 20:13:43 +01:00
2020-12-28 16:17:36 +01:00
use crate::interrupt;
2020-12-29 03:48:26 +01:00
2020-12-28 23:43:29 +01:00
use crate::pac::Interrupt;
use crate::pac::{DMA2, USART1};
2020-12-28 16:55:49 +01:00
use embedded_hal::digital::v2::OutputPin;
2020-12-28 16:17:36 +01:00
2020-12-29 03:48:26 +01:00
/// Interface to the UARTE peripheral
2020-12-31 23:38:31 +01:00
pub struct Uarte<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> {
2020-12-30 05:57:00 +01:00
// tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>,
// rx_transfer: Transfer<Stream2<DMA2>, Channel4, USART1, PeripheralToMemory, &mut [u8; 20]>,
2020-12-31 23:38:31 +01:00
tx_stream: Option<TSTREAM>,
rx_stream: Option<RSTREAM>,
usart: Option<USART>,
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
struct State {
tx_done: Signal<()>,
rx_done: Signal<u32>,
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
static STATE: State = State {
tx_done: Signal::new(),
rx_done: Signal::new(),
};
2020-12-28 16:17:36 +01:00
2020-12-31 23:38:31 +01:00
impl Uarte<USART1, Stream7<DMA2>, Stream2<DMA2>> {
2020-12-30 05:57:00 +01:00
pub fn new(
rxd: PA10<Alternate<AF7>>,
txd: PA9<Alternate<AF7>>,
dma: DMA2,
usart: USART1,
parity: Parity,
baudrate: Bps,
clocks: Clocks,
) -> Self {
let serial = Serial::usart1(
usart,
(txd, rxd),
2020-12-28 23:43:29 +01:00
SerialConfig {
baudrate: baudrate,
2020-12-28 16:55:49 +01:00
wordlength: WordLength::DataBits8,
parity: Parity::ParityNone,
stopbits: StopBits::STOP1,
2020-12-28 23:43:29 +01:00
dma: SerialDmaConfig::TxRx,
2020-12-28 16:55:49 +01:00
},
clocks,
)
.unwrap();
2020-12-28 16:17:36 +01:00
2020-12-30 05:57:00 +01:00
let (usart, _) = serial.release();
// serial.listen(SerialEvent::Idle);
let streams = StreamsTuple::new(dma);
2020-12-28 16:17:36 +01:00
2020-12-29 19:33:50 +01:00
Uarte {
2020-12-30 05:57:00 +01:00
tx_stream: Some(streams.7),
rx_stream: Some(streams.2),
usart: Some(usart),
2020-12-29 19:33:50 +01:00
}
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
/// Sends serial data.
///
/// `tx_buffer` is marked as static as per `embedded-dma` requirements.
/// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished.
2020-12-31 23:11:23 +01:00
pub fn send<'a, B>(
&'a mut self,
tx_buffer: B,
2020-12-31 23:38:31 +01:00
) -> SendFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
2020-12-29 03:48:26 +01:00
where
2020-12-29 19:33:50 +01:00
B: WriteBuffer<Word = u8> + 'static,
2020-12-29 03:48:26 +01:00
{
2020-12-30 05:57:00 +01:00
let tx_stream = self.tx_stream.take().unwrap();
let usart = self.usart.take().unwrap();
2020-12-30 18:05:52 +01:00
let mut tx_transfer = Transfer::init(
tx_stream,
usart,
tx_buffer,
None,
DmaConfig::default()
.transfer_complete_interrupt(true)
.memory_increment(true)
.double_buffer(false),
);
2020-12-30 05:57:00 +01:00
2020-12-29 03:48:26 +01:00
SendFuture {
uarte: self,
2020-12-30 18:05:52 +01:00
tx_transfer: Some(tx_transfer),
// tx_stream: Some(tx_stream),
// usart: Some(usart),
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.
///
/// `rx_buffer` is marked as static as per `embedded-dma` requirements.
/// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished.
pub fn receive<'a, B>(
&'a mut self,
rx_buffer: B,
2020-12-31 23:38:31 +01:00
) -> ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
2020-12-29 03:48:26 +01:00
where
2020-12-29 19:33:50 +01:00
B: WriteBuffer<Word = u8> + 'static,
2020-12-29 03:48:26 +01:00
{
2020-12-30 05:57:00 +01:00
let rx_stream = self.rx_stream.take().unwrap();
let usart = self.usart.take().unwrap();
2020-12-30 18:05:52 +01:00
let mut rx_transfer = Transfer::init(
rx_stream,
usart,
rx_buffer,
None,
DmaConfig::default()
.transfer_complete_interrupt(true)
.half_transfer_interrupt(true)
.memory_increment(true)
.double_buffer(false),
);
2020-12-30 05:57:00 +01:00
2020-12-29 03:48:26 +01:00
ReceiveFuture {
uarte: self,
2020-12-30 18:05:52 +01:00
rx_transfer: Some(rx_transfer),
2020-12-28 16:17:36 +01:00
}
}
2020-12-29 03:48:26 +01:00
}
2020-12-28 16:17:36 +01:00
2020-12-29 03:48:26 +01:00
/// Future for the [`LowPowerUarte::send()`] method.
2020-12-31 23:11:23 +01:00
pub struct SendFuture<
'a,
B: WriteBuffer<Word = u8> + 'static,
USART: PeriAddress<MemSize = u8>,
2020-12-31 23:38:31 +01:00
TSTREAM: Stream,
RSTREAM: Stream,
2020-12-31 23:11:23 +01:00
CHANNEL,
> {
2020-12-31 23:38:31 +01:00
uarte: &'a mut Uarte<USART, TSTREAM, RSTREAM>,
tx_transfer: Option<Transfer<TSTREAM, CHANNEL, USART, MemoryToPeripheral, B>>,
2020-12-29 03:48:26 +01:00
}
2020-12-28 16:17:36 +01:00
2020-12-31 23:11:23 +01:00
// impl<'a, B> Drop for SendFuture<'a, B>
// where
// B: WriteBuffer<Word = u8> + 'static,
// {
// fn drop(self: &mut Self) {}
// }
2020-12-28 16:17:36 +01:00
2020-12-31 23:38:31 +01:00
impl<'a, B> Future for SendFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
2020-12-29 03:48:26 +01:00
where
2020-12-29 19:33:50 +01:00
B: WriteBuffer<Word = u8> + 'static,
2020-12-29 03:48:26 +01:00
{
type Output = ();
2020-12-28 16:17:36 +01:00
2020-12-29 03:48:26 +01:00
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
2020-12-30 18:05:52 +01:00
let Self { uarte, tx_transfer } = unsafe { self.get_unchecked_mut() };
2020-12-30 19:27:47 +01:00
let mut taken = tx_transfer.take().unwrap();
if Stream7::<DMA2>::get_transfer_complete_flag() {
2020-12-30 19:27:47 +01:00
let (tx_stream, usart, buf, _) = taken.free();
2020-12-30 18:05:52 +01:00
uarte.tx_stream.replace(tx_stream);
uarte.usart.replace(usart);
2020-12-29 03:48:26 +01:00
Poll::Ready(())
} else {
2020-12-29 19:33:50 +01:00
waker_interrupt!(DMA2_STREAM7, cx.waker().clone());
2020-12-30 18:05:52 +01:00
taken.start(|usart| {});
tx_transfer.replace(taken);
2020-12-29 03:48:26 +01:00
Poll::Pending
2020-12-28 16:17:36 +01:00
}
}
}
2020-12-29 03:48:26 +01:00
/// Future for the [`Uarte::receive()`] method.
2020-12-31 23:11:23 +01:00
pub struct ReceiveFuture<
'a,
B: WriteBuffer<Word = u8> + 'static,
USART: PeriAddress<MemSize = u8>,
2020-12-31 23:38:31 +01:00
TSTREAM: Stream,
RSTREAM: Stream,
2020-12-31 23:11:23 +01:00
CHANNEL,
> {
2020-12-31 23:38:31 +01:00
uarte: &'a mut Uarte<USART, TSTREAM, RSTREAM>,
rx_transfer: Option<Transfer<RSTREAM, CHANNEL, USART, PeripheralToMemory, B>>,
2020-12-28 16:17:36 +01:00
}
// impl<'a, B> Drop for ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Channel4>
// where
// B: WriteBuffer<Word = u8> + 'static,
// {
// fn drop(self: &mut Self) {}
// }
2020-12-28 16:17:36 +01:00
2020-12-31 23:38:31 +01:00
impl<'a, B> Future for ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
2020-12-29 03:48:26 +01:00
where
2020-12-30 18:05:52 +01:00
B: WriteBuffer<Word = u8> + 'static + Unpin,
2020-12-29 03:48:26 +01:00
{
2020-12-31 02:45:07 +01:00
type Output = B;
2020-12-30 18:05:52 +01:00
2020-12-31 02:45:07 +01:00
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B> {
2020-12-30 18:05:52 +01:00
let Self { uarte, rx_transfer } = unsafe { self.get_unchecked_mut() };
2020-12-31 02:50:15 +01:00
let mut taken = rx_transfer.take().unwrap();
if Stream7::<DMA2>::get_transfer_complete_flag() {
2020-12-30 18:05:52 +01:00
let (rx_stream, usart, buf, _) = rx_transfer.take().unwrap().free();
uarte.rx_stream.replace(rx_stream);
uarte.usart.replace(usart);
2020-12-31 02:45:07 +01:00
Poll::Ready(buf)
2020-12-30 18:05:52 +01:00
} else {
waker_interrupt!(DMA2_STREAM2, cx.waker().clone());
taken.start(|usart| {});
rx_transfer.replace(taken);
Poll::Pending
}
2020-12-28 16:17:36 +01:00
}
}