#[cfg(feature = "embassy")]
mod future;
mod hal;
mod pins;
mod types;
use crate::clock;
use crate::clock::peripheral::{
PeripheralClockIndex, PeripheralIdToClockIndex, PeripheralInterrupt,
};
use crate::dma::{self, DmaChannel};
use crate::gpio::{self, AnyPin};
use crate::macro_def::pin_af_for_instance_def;
use crate::mcu::peripherals::DMA;
#[cfg(feature = "embassy")]
use crate::mode::Async;
use crate::mode::{Blocking, Mode};
use crate::syscfg::DmaChannelMap;
#[cfg(feature = "embassy")]
use core::future::poll_fn;
use core::marker::PhantomData;
#[cfg(feature = "embassy")]
use core::task::Poll;
use drop_move::DropGuard;
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use enumset::{EnumSet, EnumSetType};
#[cfg(feature = "embassy")]
use future::EventFuture;
use hal::sealed;
use types::*;
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {}
pin_af_for_instance_def!(TxPin, Instance);
pin_af_for_instance_def!(RxPin, Instance);
pin_af_for_instance_def!(RtsPin, Instance);
pin_af_for_instance_def!(CtsPin, Instance);
#[derive(Default)]
pub struct Config {
pub baud_rate: BaudRate,
pub stop_bit: StopBits,
pub word_len: WordLen,
pub parity: Parity,
pub data_bits: DataBits,
pub over_sampling: OverSampling,
}
#[derive(Clone, Copy, PartialEq)]
pub enum Id {
USART1,
USART2,
}
impl_sealed_peripheral_id!(USART1, USART1);
impl_sealed_peripheral_id!(USART2, USART2);
impl PeripheralIdToClockIndex for Id {
fn clock(&self) -> PeripheralClockIndex {
match *self {
Self::USART1 => PeripheralClockIndex::USART1,
Self::USART2 => PeripheralClockIndex::UART2,
}
}
}
impl PeripheralInterrupt for Id {
fn interrupt(&self) -> PY32f030xx_pac::interrupt {
match *self {
Self::USART1 => PY32f030xx_pac::interrupt::USART1,
Self::USART2 => PY32f030xx_pac::interrupt::USART2,
}
}
}
impl Id {
fn dma_channel_map(&self) -> (DmaChannelMap, DmaChannelMap) {
match *self {
Self::USART1 => (DmaChannelMap::USART1_RX, DmaChannelMap::USART1_TX),
Self::USART2 => (DmaChannelMap::USART2_RX, DmaChannelMap::USART2_TX),
}
}
}
#[derive(EnumSetType)]
pub enum Event {
ABRE,
ABRF,
CTS,
TXE,
TC,
RXNE,
IDLE,
ORE,
NE,
FE,
PE,
}
pub struct UsartRx<'d, T: Instance, M: Mode> {
_p: PhantomData<(T, M)>,
_rxd: Option<PeripheralRef<'d, AnyPin>>,
_rts: Option<PeripheralRef<'d, AnyPin>>,
rx_dma: Option<DmaChannel<'d, DMA, M>>,
}
pub struct UsartTx<'d, T: Instance, M: Mode> {
_p: PhantomData<(T, M)>,
_txd: Option<PeripheralRef<'d, AnyPin>>,
_cts: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<DmaChannel<'d, DMA, M>>,
}
pub struct AnyUsart<'d, T: Instance, M: Mode> {
pub rx: UsartRx<'d, T, M>,
pub tx: UsartTx<'d, T, M>,
}
impl<'d, T: Instance, M: Mode> AnyUsart<'d, T, M> {
pub fn split(self) -> (UsartRx<'d, T, M>, UsartTx<'d, T, M>) {
(self.rx, self.tx)
}
pub fn new(
usart: impl Peripheral<P = T> + 'd,
rxd: Option<impl Peripheral<P = impl RxPin<T>> + 'd>,
txd: Option<impl Peripheral<P = impl TxPin<T>> + 'd>,
rx_dma: Option<DmaChannel<'d, DMA, M>>,
tx_dma: Option<DmaChannel<'d, DMA, M>>,
config: Config,
) -> Self {
let rxd = rxd.map_or_else(
|| None,
|rxd| {
into_ref!(rxd);
rxd.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::OpenDrain);
Some(rxd.map_into())
},
);
let txd = txd.map_or_else(
|| None,
|txd| {
into_ref!(txd);
txd.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::OpenDrain);
Some(txd.map_into())
},
);
into_ref!(usart);
Self::new_inner(usart, rxd, txd, None, None, rx_dma, tx_dma, config)
}
#[allow(clippy::too_many_arguments)]
fn new_inner(
_usart: PeripheralRef<'d, T>,
rxd: Option<PeripheralRef<'d, AnyPin>>,
txd: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
rx_dma: Option<DmaChannel<'d, DMA, M>>,
tx_dma: Option<DmaChannel<'d, DMA, M>>,
config: Config,
) -> Self {
T::enable();
T::config(config);
if M::is_async() {
T::id().enable_interrupt();
}
Self {
rx: UsartRx::<T, M>::new(rxd, rts, rx_dma),
tx: UsartTx::<T, M>::new(txd, cts, tx_dma),
}
}
}
impl<'d, T: Instance> UsartRx<'d, T, Blocking> {
pub fn read_blocking(&self, buf: &mut [u8]) -> usize {
T::read_bytes_blocking(buf)
}
pub fn read_dma_idle_blocking(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let len = buf.len();
if let Some(dma) = &mut self.rx_dma {
let clear_events = Event::IDLE | Event::RXNE | Event::NE | Event::FE | Event::PE;
clear_events.iter().for_each(|e| T::event_clear(e));
let (rx_dma_map, _tx_dma_map) = T::id().dma_channel_map();
dma.clear_flag(EnumSet::all());
let _tx_dmp_close = DropGuard::new(|| T::tx_dma_enable(false));
dma.config(dma::Config::new_periph2mem(
T::block().dr.as_ptr() as u32, false,
dma::Burst::Single,
buf.as_ptr() as u32,
true,
dma::Burst::Single,
dma::Priorities::Medium,
dma::RepeatMode::OneTime(buf.len() as u16),
));
dma.bind(rx_dma_map);
dma.start();
T::rx_dma_enable(true);
let remain = loop {
if T::event_flag(Event::FE) {
return Err(Error::Frame);
}
if T::event_flag(Event::PE) {
return Err(Error::Parity);
}
if T::event_flag(Event::NE) {
return Err(Error::Noise);
}
if dma.is_error() {
return Err(Error::DMA);
}
if dma.is_finish() {
break 0;
}
if T::event_flag(Event::IDLE) {
break dma.remain() as usize;
}
};
Ok(len - remain)
} else {
Err(Error::DMA)
}
}
pub fn read_idle_blocking(&self, buf: &mut [u8]) -> usize {
T::read_bytes_idle_blocking(buf)
}
pub fn nb_read(&self) -> Result<u8, nb::Error<Error>> {
if T::rx_ready() {
Ok(T::read_byte_blocking())
} else {
Err(nb::Error::WouldBlock)
}
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> UsartRx<'d, T, Async> {
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let mut cnt = 0;
for v in buf {
let events = Event::RXNE | Event::PE | Event::NE | Event::FE | Event::ORE;
let event_future = poll_fn(move |cx| {
events.iter().for_each(|e| {
future::EVENT_WAKERS[T::id() as usize][e as usize].register(cx.waker());
T::event_config(e, true);
});
let mut events_happen = EnumSet::empty();
events.iter().for_each(|e| {
if T::event_flag(e) {
T::event_clear(e);
events_happen |= e;
}
});
if !events_happen.is_empty() {
events.iter().for_each(|e| {
T::event_config(e, false);
});
return Poll::Ready(events_happen);
}
Poll::Pending
});
let events_happen = event_future.await;
*v = T::read();
cnt += 1;
if events_happen != Event::RXNE {
return Err(Error::Others);
}
}
Ok(cnt)
}
pub async fn read_with_idle(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let mut cnt = 0;
let events = Event::RXNE | Event::PE | Event::NE | Event::FE | Event::ORE | Event::IDLE;
for v in buf {
let event = EventFuture::<T>::new(events).await;
if event == Event::RXNE {
*v = T::read();
cnt += 1;
} else if event.contains(Event::IDLE) {
return Ok(cnt);
} else {
return Err(Error::Others);
}
}
Ok(cnt)
}
}
impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> {
pub(crate) fn new(
rxd: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
rx_dma: Option<DmaChannel<'d, DMA, M>>,
) -> Self {
T::rx_enable(rxd.is_some());
T::rts_enable(rts.is_none());
Self {
_p: PhantomData,
_rxd: rxd,
_rts: rts,
rx_dma,
}
}
}
impl<'d, T: Instance> UsartTx<'d, T, Blocking> {
fn write_bytes_dma_blocking(&mut self, buf: &[u8]) -> Result<(), Error> {
if let Some(dma) = &mut self.tx_dma {
let (_rx_dma_map, tx_dma_map) = T::id().dma_channel_map();
let _tx_dmp_close = DropGuard::new(|| T::tx_dma_enable(false));
dma.clear_flag(EnumSet::all());
dma.config(dma::Config::new_mem2periph(
buf.as_ptr() as u32,
true,
dma::Burst::Single,
T::block().dr.as_ptr() as u32,
false,
dma::Burst::Single,
dma::Priorities::Medium,
dma::RepeatMode::OneTime(buf.len() as u16),
));
dma.bind(tx_dma_map);
dma.start();
T::tx_dma_enable(true);
dma.wait_complet().map_err(|_| Error::DMA)?;
Ok(())
} else {
Err(Error::DMA)
}
}
fn write_bytes_blocking(&mut self, buf: &[u8]) -> Result<(), Error> {
T::write_bytes_blocking(buf)
}
pub fn write(&mut self, buf: &[u8]) -> Result<(), Error> {
if self.tx_dma.is_none() {
self.write_bytes_blocking(buf)
} else {
self.write_bytes_dma_blocking(buf)
}
}
fn flush(&self) -> nb::Result<(), Error> {
T::tx_flush();
Ok(())
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> UsartTx<'d, T, Async> {
pub async fn write(&mut self, buf: &[u8]) -> Result<(), Error> {
if self.tx_dma.is_some() {
self.write_bytes_dma(buf).await
} else {
self.write_bytes(buf).await
}
}
async fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Error> {
let events = Event::TXE | Event::CTS;
for v in buf {
T::write(*v);
let rst = EventFuture::<T>::new(events).await;
if rst != Event::TXE {
return Err(Error::Others);
}
}
Ok(())
}
async fn write_bytes_dma(&mut self, buf: &[u8]) -> Result<(), Error> {
if let Some(dma) = &mut self.tx_dma {
let (_rx_dma_map, tx_dma_map) = T::id().dma_channel_map();
let _tx_dmp_close = DropGuard::new(|| T::tx_dma_enable(false));
dma.config(dma::Config::new_mem2periph(
buf.as_ptr() as u32,
true,
dma::Burst::Single,
T::block().dr.as_ptr() as u32,
false,
dma::Burst::Single,
dma::Priorities::Medium,
dma::RepeatMode::OneTime(buf.len() as u16),
));
dma.bind(tx_dma_map);
dma.start();
T::tx_dma_enable(true);
dma.wait_complet().await.map_err(|_| Error::DMA)?;
Ok(())
} else {
Err(Error::DMA)
}
}
pub async fn flush(&mut self) -> Result<(), Error> {
EventFuture::<T>::new(EnumSet::empty() | Event::TC).await;
Ok(())
}
}
impl<'d, T: Instance, M: Mode> UsartTx<'d, T, M> {
pub(crate) fn new(
txd: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<DmaChannel<'d, DMA, M>>,
) -> Self {
T::tx_enable(txd.is_some());
T::cts_enable(cts.is_some());
Self {
_p: PhantomData,
_txd: txd,
_cts: cts,
tx_dma,
}
}
}
impl<'d, T: Instance> embedded_hal::serial::Read<u8> for AnyUsart<'d, T, Blocking> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.rx.nb_read()
}
}
impl<'d, T: Instance> embedded_hal::serial::Write<u8> for AnyUsart<'d, T, Blocking> {
type Error = Error;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.tx.flush()
}
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.tx.write(&[word])?;
Ok(())
}
}
impl<'d, T: Instance> embedded_hal::serial::Read<u8> for UsartRx<'d, T, Blocking> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.nb_read()
}
}
impl<'d, T: Instance> embedded_hal::serial::Write<u8> for UsartTx<'d, T, Blocking> {
type Error = Error;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
T::tx_flush();
Ok(())
}
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.write(&[word])?;
Ok(())
}
}
impl embedded_io::Error for Error {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::Other
}
}
impl<'d, T: Instance> embedded_io::ErrorType for AnyUsart<'d, T, Blocking> {
type Error = Error;
}
impl<'d, T: Instance> embedded_io::ErrorType for UsartRx<'d, T, Blocking> {
type Error = Error;
}
impl<'d, T: Instance> embedded_io::Read for AnyUsart<'d, T, Blocking> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.rx.read(buf)
}
}
impl<'d, T: Instance> embedded_io::Read for UsartRx<'d, T, Blocking> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
Ok(T::read_bytes_blocking(buf))
}
}
impl<'d, T: Instance> embedded_io::ErrorType for UsartTx<'d, T, Blocking> {
type Error = Error;
}
impl<'d, T: Instance> embedded_io::Write for AnyUsart<'d, T, Blocking> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.tx.write(buf)?;
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
T::tx_flush();
Ok(())
}
}
impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf)?;
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
T::tx_flush();
Ok(())
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::ErrorType for AnyUsart<'d, T, Async> {
type Error = Error;
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::ErrorType for UsartRx<'d, T, Async> {
type Error = Error;
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::Read for AnyUsart<'d, T, Async> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.rx.read(buf).await
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::Read for UsartRx<'d, T, Async> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read_with_idle(buf).await
}
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::ErrorType for UsartTx<'d, T, Async> {
type Error = Error;
}
#[cfg(feature = "embassy")]
impl<'d, T: Instance> embedded_io_async::Write for UsartTx<'d, T, Async> {
async fn flush(&mut self) -> Result<(), Self::Error> {
EventFuture::<T>::new(EnumSet::empty() | Event::TC).await;
Ok(())
}
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf).await?;
Ok(buf.len())
}
}