embassy/embassy-stm32f4/src/serial.rs

218 lines
6.5 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-01-04 19:48:13 +01:00
use core::ptr;
use core::sync::atomic::{self, Ordering};
2020-12-28 16:17:36 +01:00
use core::task::{Context, Poll};
2021-01-01 00:59:01 +01:00
use embassy::interrupt::OwnedInterrupt;
2021-01-06 21:12:33 +01:00
use embassy::uart::{Error, Uart};
2020-12-29 03:48:26 +01:00
use embassy::util::Signal;
2021-01-06 19:12:29 +01:00
use embedded_dma::StaticWriteBuffer;
2020-12-29 03:48:26 +01:00
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::{
2021-01-01 00:59:01 +01:00
Channel4, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, Transfer,
2020-12-29 19:33:50 +01:00
};
2020-12-29 03:48:26 +01:00
use crate::hal::gpio::gpioa::{PA10, PA9};
2021-01-01 00:59:01 +01:00
use crate::hal::gpio::{Alternate, AF7};
2020-12-29 03:48:26 +01:00
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-31 23:40:51 +01:00
use crate::hal::serial::{Event as SerialEvent, Serial as HalSerial};
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-31 23:40:51 +01:00
/// Interface to the Serial peripheral
pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> {
2020-12-31 23:38:31 +01:00
tx_stream: Option<TSTREAM>,
rx_stream: Option<RSTREAM>,
usart: Option<USART>,
2021-01-04 19:48:13 +01:00
tx_int: interrupt::DMA2_STREAM7Interrupt,
rx_int: interrupt::DMA2_STREAM2Interrupt,
usart_int: interrupt::USART1Interrupt,
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
struct State {
2021-01-04 19:48:13 +01:00
tx_int: Signal<()>,
rx_int: Signal<()>,
2020-12-28 16:17:36 +01:00
}
2020-12-29 03:48:26 +01:00
static STATE: State = State {
2021-01-04 19:48:13 +01:00
tx_int: Signal::new(),
rx_int: Signal::new(),
2020-12-29 03:48:26 +01:00
};
2020-12-28 16:17:36 +01:00
2021-01-04 19:48:13 +01:00
static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut();
2020-12-31 23:40:51 +01:00
impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
2021-01-06 21:31:43 +01:00
// Leaking futures is forbidden!
pub unsafe fn new(
2020-12-30 05:57:00 +01:00
txd: PA9<Alternate<AF7>>,
2020-12-31 23:59:42 +01:00
rxd: PA10<Alternate<AF7>>,
2021-01-04 19:48:13 +01:00
tx_int: interrupt::DMA2_STREAM7Interrupt,
rx_int: interrupt::DMA2_STREAM2Interrupt,
2021-01-01 21:59:57 +01:00
usart_int: interrupt::USART1Interrupt,
2020-12-30 05:57:00 +01:00
dma: DMA2,
usart: USART1,
parity: Parity,
baudrate: Bps,
clocks: Clocks,
) -> Self {
2021-01-01 21:59:57 +01:00
let mut serial = HalSerial::usart1(
2020-12-30 05:57:00 +01:00
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
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-01-01 00:59:01 +01:00
// Register ISR
2021-01-06 17:49:08 +01:00
tx_int.set_handler(Self::on_tx_irq, core::ptr::null_mut());
rx_int.set_handler(Self::on_rx_irq, core::ptr::null_mut());
usart_int.set_handler(Self::on_rx_irq, core::ptr::null_mut());
2021-01-01 21:59:57 +01:00
// usart_int.unpend();
// usart_int.enable();
2020-12-30 05:57:00 +01:00
let streams = StreamsTuple::new(dma);
2020-12-28 16:17:36 +01:00
2020-12-31 23:40:51 +01:00
Serial {
2020-12-30 05:57:00 +01:00
tx_stream: Some(streams.7),
rx_stream: Some(streams.2),
usart: Some(usart),
2021-01-04 19:48:13 +01:00
tx_int: tx_int,
rx_int: rx_int,
usart_int: usart_int,
2020-12-29 19:33:50 +01:00
}
2020-12-28 16:17:36 +01:00
}
2021-01-06 17:49:08 +01:00
unsafe fn on_tx_irq(_ctx: *mut ()) {
2021-01-04 19:48:13 +01:00
let s = &(*INSTANCE);
s.tx_int.disable();
STATE.tx_int.signal(());
2021-01-01 00:59:01 +01:00
}
2021-01-06 17:49:08 +01:00
unsafe fn on_rx_irq(_ctx: *mut ()) {
2021-01-04 19:48:13 +01:00
let s = &(*INSTANCE);
atomic::compiler_fence(Ordering::Acquire);
s.rx_int.disable();
s.usart_int.disable();
atomic::compiler_fence(Ordering::Release);
STATE.rx_int.signal(());
2021-01-01 00:59:01 +01:00
}
2021-01-01 21:59:57 +01:00
2021-01-06 17:49:08 +01:00
unsafe fn on_usart_irq(_ctx: *mut ()) {
2021-01-04 19:48:13 +01:00
let s = &(*INSTANCE);
2021-01-01 21:59:57 +01:00
2021-01-04 19:48:13 +01:00
atomic::compiler_fence(Ordering::Acquire);
s.rx_int.disable();
s.usart_int.disable();
atomic::compiler_fence(Ordering::Release);
2021-01-01 21:59:57 +01:00
2021-01-04 19:48:13 +01:00
STATE.rx_int.signal(());
2021-01-01 21:59:57 +01:00
}
2021-01-06 19:12:29 +01:00
}
2021-01-04 19:48:13 +01:00
2021-01-06 19:12:29 +01:00
impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
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-04 19:48:13 +01:00
unsafe { INSTANCE = self };
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();
STATE.tx_int.reset();
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),
);
self.tx_int.unpend();
self.tx_int.enable();
tx_transfer.start(|_usart| {});
STATE.tx_int.wait().await;
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-04 19:48:13 +01:00
unsafe { INSTANCE = self };
2021-01-07 04:02:02 +01:00
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();
STATE.rx_int.reset();
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),
);
self.rx_int.unpend();
self.rx_int.enable();
rx_transfer.start(|_usart| {});
STATE.rx_int.wait().await;
let (rx_stream, usart, _, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream);
self.usart.replace(usart);
Ok(())
2020-12-30 18:05:52 +01:00
}
2020-12-28 16:17:36 +01:00
}
}