Merge #523
523: Incrementally merge STM32 SPI versions, Part 2 r=Dirbaio a=GrantM11235 Co-authored-by: Grant Miller <GrantM11235@gmail.com>
This commit is contained in:
commit
56bcc824e0
4 changed files with 197 additions and 588 deletions
|
@ -1,15 +1,19 @@
|
|||
#![macro_use]
|
||||
|
||||
use crate::dma;
|
||||
use crate::dma::NoDma;
|
||||
use crate::gpio::sealed::{AFType, Pin};
|
||||
use crate::gpio::{AnyPin, NoPin, OptionalPin};
|
||||
use crate::pac::spi::vals;
|
||||
use crate::pac::spi::{regs, vals};
|
||||
use crate::peripherals;
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::time::Hertz;
|
||||
use core::future::Future;
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr;
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::unborrow;
|
||||
use embassy_traits::spi as traits;
|
||||
|
||||
#[cfg_attr(spi_v1, path = "v1.rs")]
|
||||
#[cfg_attr(spi_f1, path = "v1.rs")]
|
||||
|
@ -374,6 +378,174 @@ impl RegsExt for crate::pac::spi::Spi {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
#[cfg(not(any(spi_f1, spi_v3)))]
|
||||
if sr.fre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
#[cfg(spi_v3)]
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.modf() {
|
||||
return Err(Error::ModeFault);
|
||||
}
|
||||
#[cfg(not(spi_v3))]
|
||||
if sr.crcerr() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
#[cfg(spi_v3)]
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spin_until_tx_ready(regs: &'static crate::pac::spi::Spi) -> Result<(), Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
|
||||
check_error_flags(sr)?;
|
||||
|
||||
#[cfg(not(spi_v3))]
|
||||
if sr.txe() {
|
||||
return Ok(());
|
||||
}
|
||||
#[cfg(spi_v3)]
|
||||
if sr.txp() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn spin_until_rx_ready(regs: &'static crate::pac::spi::Spi) -> Result<(), Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
|
||||
check_error_flags(sr)?;
|
||||
|
||||
#[cfg(not(spi_v3))]
|
||||
if sr.rxne() {
|
||||
return Ok(());
|
||||
}
|
||||
#[cfg(spi_v3)]
|
||||
if sr.rxp() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Word {
|
||||
const WORDSIZE: WordSize;
|
||||
}
|
||||
|
||||
impl Word for u8 {
|
||||
const WORDSIZE: WordSize = WordSize::EightBit;
|
||||
}
|
||||
impl Word for u16 {
|
||||
const WORDSIZE: WordSize = WordSize::SixteenBit;
|
||||
}
|
||||
|
||||
fn transfer_word<W: Word>(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Result<W, Error> {
|
||||
spin_until_tx_ready(regs)?;
|
||||
|
||||
unsafe {
|
||||
ptr::write_volatile(regs.tx_ptr(), tx_word);
|
||||
|
||||
#[cfg(spi_v3)]
|
||||
regs.cr1().modify(|reg| reg.set_cstart(true));
|
||||
}
|
||||
|
||||
spin_until_rx_ready(regs)?;
|
||||
|
||||
let rx_word = unsafe { ptr::read_volatile(regs.rx_ptr()) };
|
||||
return Ok(rx_word);
|
||||
}
|
||||
|
||||
// Note: It is not possible to impl these traits generically in embedded-hal 0.2 due to a conflict with
|
||||
// some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289
|
||||
macro_rules! impl_blocking {
|
||||
($w:ident) => {
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<$w> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
|
||||
self.set_word_size($w::WORDSIZE);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
let _ = transfer_word(regs, *word)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<$w>
|
||||
for Spi<'d, T, NoDma, NoDma>
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
|
||||
self.set_word_size($w::WORDSIZE);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(regs, *word)?;
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_blocking!(u8);
|
||||
impl_blocking!(u16);
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
|
||||
#[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> {
|
||||
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>(
|
||||
&'a mut self,
|
||||
read: &'a mut [u8],
|
||||
write: &'a [u8],
|
||||
) -> Self::WriteReadFuture<'a> {
|
||||
self.read_write_dma_u8(read, write)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
#![macro_use]
|
||||
|
||||
use crate::dma::NoDma;
|
||||
use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
|
||||
use core::future::Future;
|
||||
use core::ptr;
|
||||
use embassy_traits::spi as traits;
|
||||
pub use embedded_hal::blocking;
|
||||
pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||
use futures::future::join3;
|
||||
|
||||
use super::Spi;
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
#[allow(unused)]
|
||||
async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
{
|
||||
|
@ -41,8 +35,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -94,8 +87,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_write_dma_u8(
|
||||
&mut self,
|
||||
read: &mut [u8],
|
||||
write: &[u8],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -154,161 +150,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
write_word(regs, *word)?;
|
||||
let _: u8 = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
write_word(regs, *word)?;
|
||||
*word = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
write_word(regs, *word)?;
|
||||
let _: u8 = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
write_word(regs, *word)?;
|
||||
*word = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
|
||||
type Error = super::Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
|
||||
#[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> {
|
||||
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>(
|
||||
&'a mut self,
|
||||
read: &'a mut [u8],
|
||||
write: &'a [u8],
|
||||
) -> Self::WriteReadFuture<'a> {
|
||||
self.read_write_dma_u8(read, write)
|
||||
}
|
||||
}
|
||||
|
||||
trait Word {}
|
||||
|
||||
impl Word for u8 {}
|
||||
impl Word for u16 {}
|
||||
|
||||
fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
#[cfg(not(spi_f1))]
|
||||
if sr.fre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.modf() {
|
||||
return Err(Error::ModeFault);
|
||||
}
|
||||
if sr.crcerr() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
if sr.txe() {
|
||||
unsafe {
|
||||
ptr::write_volatile(regs.tx_ptr(), word);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a single word blocking. Assumes word size have already been set.
|
||||
fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
#[cfg(not(spi_f1))]
|
||||
if sr.fre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.modf() {
|
||||
return Err(Error::ModeFault);
|
||||
}
|
||||
if sr.crcerr() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
if sr.rxne() {
|
||||
unsafe {
|
||||
return Ok(ptr::read_volatile(regs.rx_ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
#![macro_use]
|
||||
|
||||
use crate::dma::NoDma;
|
||||
use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
|
||||
use core::future::Future;
|
||||
use core::ptr;
|
||||
use embassy_traits::spi as traits;
|
||||
pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||
use futures::future::{join, join3};
|
||||
|
||||
use super::Spi;
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
#[allow(unused)]
|
||||
async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
{
|
||||
|
@ -49,8 +43,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -102,8 +95,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_write_dma_u8(
|
||||
&mut self,
|
||||
read: &mut [u8],
|
||||
write: &[u8],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -173,152 +169,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Word {}
|
||||
|
||||
impl Word for u8 {}
|
||||
impl Word for u16 {}
|
||||
|
||||
/// Write a single word blocking. Assumes word size have already been set.
|
||||
fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
} else if sr.fre() {
|
||||
return Err(Error::Framing);
|
||||
} else if sr.modf() {
|
||||
return Err(Error::ModeFault);
|
||||
} else if sr.crcerr() {
|
||||
return Err(Error::Crc);
|
||||
} else if sr.txe() {
|
||||
unsafe {
|
||||
ptr::write_volatile(regs.tx_ptr(), word);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a single word blocking. Assumes word size have already been set.
|
||||
fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
} else if sr.modf() {
|
||||
return Err(Error::ModeFault);
|
||||
} else if sr.fre() {
|
||||
return Err(Error::Framing);
|
||||
} else if sr.crcerr() {
|
||||
return Err(Error::Crc);
|
||||
} else if sr.rxne() {
|
||||
unsafe {
|
||||
return Ok(ptr::read_volatile(regs.rx_ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, Rx> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
write_word(regs, *word)?;
|
||||
let _: u8 = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
write_word(regs, *word)?;
|
||||
*word = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, Rx> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
write_word(regs, *word)?;
|
||||
let _: u16 = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
write_word(regs, *word)?;
|
||||
*word = read_word(regs)?;
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
|
||||
type Error = super::Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
|
||||
#[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> {
|
||||
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>(
|
||||
&'a mut self,
|
||||
read: &'a mut [u8],
|
||||
write: &'a [u8],
|
||||
) -> Self::WriteReadFuture<'a> {
|
||||
self.read_write_dma_u8(read, write)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
#![macro_use]
|
||||
|
||||
use crate::dma::NoDma;
|
||||
use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
|
||||
use core::future::Future;
|
||||
use core::ptr;
|
||||
use embassy_traits::spi as traits;
|
||||
pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||
|
||||
use futures::future::join3;
|
||||
|
||||
use super::Spi;
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
#[allow(unused)]
|
||||
async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
{
|
||||
|
@ -53,8 +46,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -107,8 +99,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error>
|
||||
pub(super) async fn read_write_dma_u8(
|
||||
&mut self,
|
||||
read: &mut [u8],
|
||||
write: &[u8],
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Tx: TxDmaChannel<T>,
|
||||
Rx: RxDmaChannel<T>,
|
||||
|
@ -176,246 +171,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
while unsafe { !regs.sr().read().txp() } {
|
||||
// spin
|
||||
}
|
||||
unsafe {
|
||||
ptr::write_volatile(regs.tx_ptr(), *word);
|
||||
regs.cr1().modify(|reg| reg.set_cstart(true));
|
||||
}
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
if !sr.txp() {
|
||||
// loop waiting for TXE
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
unsafe {
|
||||
// discard read to prevent pverrun.
|
||||
let _: u8 = ptr::read_volatile(T::regs().rx_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
while unsafe { !regs.sr().read().txc() } {
|
||||
// spin
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
self.set_word_size(WordSize::EightBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
unsafe {
|
||||
regs.cr1().modify(|reg| {
|
||||
reg.set_ssi(false);
|
||||
});
|
||||
}
|
||||
while unsafe { !regs.sr().read().txp() } {
|
||||
// spin
|
||||
}
|
||||
unsafe {
|
||||
ptr::write_volatile(T::regs().tx_ptr(), *word);
|
||||
regs.cr1().modify(|reg| reg.set_cstart(true));
|
||||
}
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
|
||||
if sr.rxp() {
|
||||
break;
|
||||
}
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
*word = ptr::read_volatile(T::regs().rx_ptr());
|
||||
}
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter() {
|
||||
while unsafe { !regs.sr().read().txp() } {
|
||||
// spin
|
||||
}
|
||||
unsafe {
|
||||
let txdr = regs.txdr().ptr() as *mut u16;
|
||||
ptr::write_volatile(txdr, *word);
|
||||
regs.cr1().modify(|reg| reg.set_cstart(true));
|
||||
}
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
if !sr.txp() {
|
||||
// loop waiting for TXE
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let rxdr = regs.rxdr().ptr() as *const u8;
|
||||
// discard read to prevent pverrun.
|
||||
let _ = ptr::read_volatile(rxdr);
|
||||
}
|
||||
}
|
||||
|
||||
while unsafe { !regs.sr().read().txc() } {
|
||||
// spin
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
|
||||
type Error = Error;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
|
||||
self.set_word_size(WordSize::SixteenBit);
|
||||
let regs = T::regs();
|
||||
|
||||
for word in words.iter_mut() {
|
||||
while unsafe { !regs.sr().read().txp() } {
|
||||
// spin
|
||||
}
|
||||
unsafe {
|
||||
let txdr = regs.txdr().ptr() as *mut u16;
|
||||
ptr::write_volatile(txdr, *word);
|
||||
regs.cr1().modify(|reg| reg.set_cstart(true));
|
||||
}
|
||||
|
||||
loop {
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
|
||||
if sr.rxp() {
|
||||
break;
|
||||
}
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let rxdr = regs.rxdr().ptr() as *const u16;
|
||||
*word = ptr::read_volatile(rxdr);
|
||||
}
|
||||
let sr = unsafe { regs.sr().read() };
|
||||
if sr.tifre() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ovr() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
if sr.crce() {
|
||||
return Err(Error::Crc);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
|
||||
type Error = super::Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
|
||||
#[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> {
|
||||
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>(
|
||||
&'a mut self,
|
||||
read: &'a mut [u8],
|
||||
write: &'a [u8],
|
||||
) -> Self::WriteReadFuture<'a> {
|
||||
self.read_write_dma_u8(read, write)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue