Begin reworking SPI to add DMA for stm32.

This commit is contained in:
Bob McWhirter 2021-07-20 13:38:44 -04:00
parent fe66f0f8f8
commit 3f379e06b0
3 changed files with 59 additions and 46 deletions

View File

@ -8,7 +8,6 @@ use crate::{dma, peripherals, rcc::RccPeripheral};
pub use _version::*; pub use _version::*;
use crate::gpio::Pin; use crate::gpio::Pin;
use core::marker::PhantomData;
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error { pub enum Error {
@ -73,27 +72,12 @@ pub(crate) mod sealed {
} }
} }
pub trait Instance: sealed::Instance + RccPeripheral + 'static {} pub trait Instance: sealed::Instance + RccPeripheral {}
pub trait SckPin<T: Instance>: sealed::SckPin<T> {}
pub trait SckPin<T: Instance>: sealed::SckPin<T> + 'static {} pub trait MosiPin<T: Instance>: sealed::MosiPin<T> {}
pub trait MisoPin<T: Instance>: sealed::MisoPin<T> {}
pub trait MosiPin<T: Instance>: sealed::MosiPin<T> + 'static {} pub trait TxDmaChannel<T: Instance>: sealed::TxDmaChannel<T> + dma::Channel {}
pub trait RxDmaChannel<T: Instance>: sealed::RxDmaChannel<T> + dma::Channel {}
pub trait MisoPin<T: Instance>: sealed::MisoPin<T> + 'static {}
pub trait TxDmaChannel<T: Instance>: sealed::TxDmaChannel<T> + 'static {}
pub trait RxDmaChannel<T: Instance>: sealed::RxDmaChannel<T> + 'static {}
pub trait SpiDma {}
pub struct DmaPair<T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> {
tx: Tx,
rx: Rx,
_phantom: PhantomData<T>,
}
impl<T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> SpiDma for DmaPair<T, Tx, Rx> {}
crate::pac::peripherals!( crate::pac::peripherals!(
(spi, $inst:ident) => { (spi, $inst:ident) => {

View File

@ -1,18 +1,21 @@
#![macro_use] #![macro_use]
use crate::dma::NoDma;
use crate::gpio::{AnyPin, Pin}; use crate::gpio::{AnyPin, Pin};
use crate::pac::gpio::vals::{Afr, Moder}; use crate::pac::gpio::vals::{Afr, Moder};
use crate::pac::gpio::Gpio; use crate::pac::gpio::Gpio;
use crate::pac::spi; use crate::pac::spi;
use crate::spi::{ use crate::spi::{
ByteOrder, Config, DmaPair, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, SpiDma, ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel,
TxDmaChannel, WordSize, WordSize,
}; };
use crate::time::Hertz; use crate::time::Hertz;
use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ptr; use core::ptr;
use embassy::util::Unborrow; use embassy::util::Unborrow;
use embassy_extras::unborrow; use embassy_extras::unborrow;
use embassy_traits::spi as traits;
pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
impl WordSize { impl WordSize {
@ -31,28 +34,30 @@ impl WordSize {
} }
} }
pub struct Spi<'d, T: Instance, D = NoDma> { pub struct Spi<'d, T: Instance, Tx = NoDma, Rx = NoDma> {
sck: AnyPin, sck: AnyPin,
mosi: AnyPin, mosi: AnyPin,
miso: AnyPin, miso: AnyPin,
dma: D, txdma: Tx,
rxdma: Rx,
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
} }
impl<'d, T: Instance, D> Spi<'d, T, D> { impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
pub fn new<F>( pub fn new<F>(
_peri: impl Unborrow<Target = T> + 'd, _peri: impl Unborrow<Target = T> + 'd,
sck: impl Unborrow<Target = impl SckPin<T>>, sck: impl Unborrow<Target = impl SckPin<T>>,
mosi: impl Unborrow<Target = impl MosiPin<T>>, mosi: impl Unborrow<Target = impl MosiPin<T>>,
miso: impl Unborrow<Target = impl MisoPin<T>>, miso: impl Unborrow<Target = impl MisoPin<T>>,
dma: impl Unborrow<Target = D>, txdma: impl Unborrow<Target = Tx>,
rxdma: impl Unborrow<Target = Rx>,
freq: F, freq: F,
config: Config, config: Config,
) -> Self ) -> Self
where where
F: Into<Hertz>, F: Into<Hertz>,
{ {
unborrow!(sck, mosi, miso, dma); unborrow!(sck, mosi, miso, txdma, rxdma);
unsafe { unsafe {
Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num()); Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num());
@ -118,7 +123,8 @@ impl<'d, T: Instance, D> Spi<'d, T, D> {
sck, sck,
mosi, mosi,
miso, miso,
dma, txdma,
rxdma,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -167,9 +173,21 @@ impl<'d, T: Instance, D> Spi<'d, T, D> {
}); });
} }
} }
async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> {
unimplemented!()
}
async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error> {
unimplemented!()
}
async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
unimplemented!()
}
} }
impl<'d, T: Instance> Drop for Spi<'d, T> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _); Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _);
@ -364,30 +382,41 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T,
} }
} }
use crate::dma::NoDma; impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
use core::future::Future;
use embassy_traits::spi::FullDuplex;
#[rustfmt::skip]
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> FullDuplex<u8> for Spi<'d, T, DmaPair<T, Tx, Rx>> {
type Error = super::Error; type Error = super::Error;
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; }
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
unimplemented!() #[rustfmt::skip]
} type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
unimplemented!() self.write_dma_u8(data)
} }
}
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
for Spi<'d, T, Tx, Rx>
{
#[rustfmt::skip]
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
self.read_dma_u8(data)
}
}
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDuplex<u8>
for Spi<'d, T, Tx, Rx>
{
#[rustfmt::skip]
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
fn read_write<'a>( fn read_write<'a>(
&'a mut self, &'a mut self,
read: &'a mut [u8], read: &'a mut [u8],
write: &'a [u8], write: &'a [u8],
) -> Self::WriteReadFuture<'a> { ) -> Self::WriteReadFuture<'a> {
unimplemented!() self.read_write_dma_u8(read, write)
} }
} }

View File

@ -44,7 +44,7 @@ pub trait Write<Word>: Spi<Word> {
fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a>; fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a>;
} }
pub trait Read<Word>: Spi<Word> { pub trait Read<Word>: Write<Word> {
type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
where where
Self: 'a; Self: 'a;