stm32/dma: impl all variants

This commit is contained in:
Dario Nieuwenhuis
2021-07-15 05:42:06 +02:00
committed by Bob McWhirter
parent 69fb1b5418
commit 3d1391ef2d
19 changed files with 665 additions and 989 deletions

View File

@ -3,7 +3,7 @@
#[cfg_attr(usart_v1, path = "v1.rs")]
#[cfg_attr(usart_v2, path = "v2.rs")]
mod _version;
use crate::peripherals;
use crate::{dma, peripherals};
pub use _version::*;
use crate::gpio::Pin;
@ -72,9 +72,6 @@ pub enum Error {
pub(crate) mod sealed {
use super::*;
#[cfg(any(dma, bdma, dmamux))]
use crate::dma_traits::WriteDma;
pub trait Instance {
fn regs(&self) -> crate::pac::usart::Usart;
}
@ -94,11 +91,13 @@ pub(crate) mod sealed {
fn af_num(&self) -> u8;
}
#[cfg(any(bdma, dma, dmamux))]
pub trait RxDma<T: Instance> {}
pub trait RxDma<T: Instance> {
fn request(&self) -> dma::Request;
}
#[cfg(any(bdma, dma, dmamux))]
pub trait TxDma<T: Instance>: WriteDma<T> {}
pub trait TxDma<T: Instance> {
fn request(&self) -> dma::Request;
}
}
pub trait Instance: sealed::Instance + RccPeripheral {}
@ -107,12 +106,8 @@ pub trait TxPin<T: Instance>: sealed::TxPin<T> {}
pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {}
pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {}
pub trait CkPin<T: Instance>: sealed::CkPin<T> {}
#[cfg(any(bdma, dma, dmamux))]
pub trait RxDma<T: Instance>: sealed::RxDma<T> {}
#[cfg(any(bdma, dma, dmamux))]
pub trait TxDma<T: Instance>: sealed::TxDma<T> {}
pub trait RxDma<T: Instance>: sealed::RxDma<T> + dma::Channel {}
pub trait TxDma<T: Instance>: sealed::TxDma<T> + dma::Channel {}
crate::pac::peripherals!(
(usart, $inst:ident) => {
@ -141,46 +136,86 @@ macro_rules! impl_pin {
crate::pac::peripheral_pins!(
// USART
($inst:ident, usart, USART, $pin:ident, TX, $af:expr) => {
impl_pin!($inst, $pin, TxPin, $af);
};
($inst:ident, usart, USART, $pin:ident, RX, $af:expr) => {
impl_pin!($inst, $pin, RxPin, $af);
};
($inst:ident, usart, USART, $pin:ident, CTS, $af:expr) => {
impl_pin!($inst, $pin, CtsPin, $af);
};
($inst:ident, usart, USART, $pin:ident, RTS, $af:expr) => {
impl_pin!($inst, $pin, RtsPin, $af);
};
($inst:ident, usart, USART, $pin:ident, CK, $af:expr) => {
impl_pin!($inst, $pin, CkPin, $af);
};
// UART
($inst:ident, uart, UART, $pin:ident, TX, $af:expr) => {
impl_pin!($inst, $pin, TxPin, $af);
};
($inst:ident, uart, UART, $pin:ident, RX, $af:expr) => {
impl_pin!($inst, $pin, RxPin, $af);
};
($inst:ident, uart, UART, $pin:ident, CTS, $af:expr) => {
impl_pin!($inst, $pin, CtsPin, $af);
};
($inst:ident, uart, UART, $pin:ident, RTS, $af:expr) => {
impl_pin!($inst, $pin, RtsPin, $af);
};
($inst:ident, uart, UART, $pin:ident, CK, $af:expr) => {
impl_pin!($inst, $pin, CkPin, $af);
};
);
macro_rules! impl_dma {
($inst:ident, ALL, $signal:ident, $request:expr) => {
impl<T: crate::dma::Channel> sealed::$signal<peripherals::$inst> for T {
fn request(&self) -> dma::Request {
$request
}
}
impl<T: crate::dma::Channel> $signal<peripherals::$inst> for T {}
};
($inst:ident, $channel:ident, $signal:ident, $request:expr) => {
impl sealed::$signal<peripherals::$inst> for peripherals::$channel {
fn request(&self) -> dma::Request {
$request
}
}
impl $signal<peripherals::$inst> for peripherals::$channel {}
};
}
crate::pac::peripheral_dma_channels! {
($peri:ident, usart, $kind:ident, RX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
impl_dma!($peri, $channel, RxDma, $request);
};
($peri:ident, usart, $kind:ident, TX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
impl_dma!($peri, $channel, TxDma, $request);
};
($peri:ident, uart, $kind:ident, RX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
impl_dma!($peri, $channel, RxDma, $request);
};
($peri:ident, uart, $kind:ident, TX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
impl_dma!($peri, $channel, TxDma, $request);
};
}
crate::pac::dma_requests! {
(usart, $peri:ident, RX, $request:expr) => {
impl_dma!($peri, ALL, RxDma, $request);
};
(usart, $peri:ident, TX, $request:expr) => {
impl_dma!($peri, ALL, TxDma, $request);
};
(uart, $peri:ident, RX, $request:expr) => {
impl_dma!($peri, ALL, RxDma, $request);
};
(uart, $peri:ident, TX, $request:expr) => {
impl_dma!($peri, ALL, TxDma, $request);
};
}

View File

@ -1,25 +1,31 @@
use core::future::Future;
use core::marker::PhantomData;
use embassy::util::Unborrow;
use embassy_extras::unborrow;
use crate::pac::usart::{regs, vals};
use futures::TryFutureExt;
use super::*;
use crate::dma::NoDma;
use crate::pac::usart::{regs, vals};
pub struct Uart<'d, T: Instance> {
pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
inner: T,
phantom: PhantomData<&'d mut T>,
tx_dma: TxDma,
#[allow(dead_code)]
rx_dma: RxDma,
}
impl<'d, T: Instance> Uart<'d, T> {
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
pub fn new(
inner: impl Unborrow<Target = T>,
rx: impl Unborrow<Target = impl RxPin<T>>,
tx: impl Unborrow<Target = impl TxPin<T>>,
tx_dma: impl Unborrow<Target = TxDma>,
rx_dma: impl Unborrow<Target = RxDma>,
config: Config,
) -> Self {
unborrow!(inner, rx, tx);
unborrow!(inner, rx, tx, tx_dma, rx_dma);
T::enable();
let pclk_freq = T::frequency();
@ -53,11 +59,16 @@ impl<'d, T: Instance> Uart<'d, T> {
Self {
inner,
phantom: PhantomData,
tx_dma,
rx_dma,
}
}
#[cfg(dma)]
pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> {
async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error>
where
TxDma: crate::usart::TxDma<T>,
{
let ch = &mut self.tx_dma;
unsafe {
self.inner.regs().cr3().modify(|reg| {
reg.set_dmat(true);
@ -65,7 +76,7 @@ impl<'d, T: Instance> Uart<'d, T> {
}
let r = self.inner.regs();
let dst = r.dr().ptr() as *mut u8;
ch.transfer(buffer, dst).await;
ch.write(ch.request(), buffer, dst).await;
Ok(())
}
@ -98,7 +109,9 @@ impl<'d, T: Instance> Uart<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> {
impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8>
for Uart<'d, T, NoDma, RxDma>
{
type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
unsafe {
@ -118,3 +131,15 @@ impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T>
Ok(())
}
}
// rustfmt::skip because intellij removes the 'where' claus on the associated type.
#[rustfmt::skip]
impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma>
where TxDma: crate::usart::TxDma<T>
{
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>>;
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other)
}
}

View File

@ -1,21 +1,18 @@
use core::marker::PhantomData;
use core::future::Future;
use futures::TryFutureExt;
use embassy::util::Unborrow;
use embassy_extras::unborrow;
use crate::pac::usart::{regs, vals};
use super::*;
use core::future::Future;
use futures::TryFutureExt;
use crate::dma::NoDma;
use crate::dma_traits::NoDma;
#[allow(dead_code)]
pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
inner: T,
phantom: PhantomData<&'d mut T>,
tx_dma: TxDma,
#[allow(dead_code)]
rx_dma: RxDma,
}
@ -83,7 +80,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}
let r = self.inner.regs();
let dst = r.tdr().ptr() as *mut u8;
ch.transfer(buffer, dst).await;
ch.write(ch.request(), buffer, dst).await;
Ok(())
}