From 496579b48b985391be4191505de37228c0e74b5e Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Mon, 6 Dec 2021 18:16:15 -0600 Subject: [PATCH 1/5] Move Word trait to mod --- embassy-stm32/src/spi/mod.rs | 5 +++++ embassy-stm32/src/spi/v1.rs | 5 +---- embassy-stm32/src/spi/v2.rs | 5 +---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 80a05aac..be4061e0 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -374,6 +374,11 @@ impl RegsExt for crate::pac::spi::Spi { } } +trait Word {} + +impl Word for u8 {} +impl Word for u16 {} + pub(crate) mod sealed { use super::*; diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index 255bd950..c1a9cdbf 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -258,10 +258,7 @@ impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::FullDupl } } -trait Word {} - -impl Word for u8 {} -impl Word for u16 {} +use super::Word; fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { loop { diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index b1fae4bd..1ca90619 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -174,10 +174,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } } -trait Word {} - -impl Word for u8 {} -impl Word for u16 {} +use super::Word; /// Write a single word blocking. Assumes word size have already been set. fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { From 20d2151b1d59bb4a1ad2aa4f6697fcc2f259cbd7 Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Mon, 6 Dec 2021 19:12:34 -0600 Subject: [PATCH 2/5] check_error_flags function --- embassy-stm32/src/spi/mod.rs | 29 ++++++++++++++++++- embassy-stm32/src/spi/v1.rs | 36 ++++++----------------- embassy-stm32/src/spi/v2.rs | 28 ++++++------------ embassy-stm32/src/spi/v3.rs | 56 +++++++----------------------------- 4 files changed, 56 insertions(+), 93 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index be4061e0..76857ae6 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -3,7 +3,7 @@ use crate::dma; 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; @@ -374,6 +374,33 @@ 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(()) +} + trait Word {} impl Word for u8 {} diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index c1a9cdbf..3a7d948a 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -1,7 +1,9 @@ #![macro_use] use crate::dma::NoDma; -use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; +use crate::spi::{ + check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, +}; use core::future::Future; use core::ptr; use embassy_traits::spi as traits; @@ -263,19 +265,9 @@ use super::Word; fn write_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); - } + + check_error_flags(sr)?; + if sr.txe() { unsafe { ptr::write_volatile(regs.tx_ptr(), word); @@ -289,19 +281,9 @@ fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<( fn read_word(regs: &'static crate::pac::spi::Spi) -> Result { 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); - } + + check_error_flags(sr)?; + if sr.rxne() { unsafe { return Ok(ptr::read_volatile(regs.rx_ptr())); diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 1ca90619..2f02dc86 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -1,7 +1,7 @@ #![macro_use] use crate::dma::NoDma; -use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; +use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, check_error_flags}; use core::future::Future; use core::ptr; use embassy_traits::spi as traits; @@ -180,15 +180,10 @@ use super::Word; fn write_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() { + + check_error_flags(sr)?; + + if sr.txe() { unsafe { ptr::write_volatile(regs.tx_ptr(), word); } @@ -201,15 +196,10 @@ fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<( fn read_word(regs: &'static crate::pac::spi::Spi) -> Result { 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() { + + check_error_flags(sr)?; + + if sr.rxne() { unsafe { return Ok(ptr::read_volatile(regs.rx_ptr())); } diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index 052924db..e63dbcb2 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs @@ -1,7 +1,7 @@ #![macro_use] use crate::dma::NoDma; -use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; +use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, check_error_flags}; use core::future::Future; use core::ptr; use embassy_traits::spi as traits; @@ -249,29 +249,14 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, N 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); - } + + check_error_flags(sr)?; } 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); - } + check_error_flags(sr)?; } Ok(words) @@ -296,15 +281,9 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spi<'d, T, NoD } 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); - } + + check_error_flags(sr)?; + if !sr.txp() { // loop waiting for TXE continue; @@ -350,15 +329,8 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, 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); - } + + check_error_flags(sr)?; } unsafe { @@ -366,15 +338,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, *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); - } + check_error_flags(sr)?; } Ok(words) From 3a17e3a2a523773d5e025d99139385616aaebc87 Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Mon, 6 Dec 2021 22:06:58 -0600 Subject: [PATCH 3/5] Move async trait impls to mod --- embassy-stm32/src/spi/mod.rs | 41 +++++++++++++++++++++++++++ embassy-stm32/src/spi/v1.rs | 54 +++++------------------------------- embassy-stm32/src/spi/v2.rs | 54 ++++-------------------------------- embassy-stm32/src/spi/v3.rs | 54 ++++-------------------------------- 4 files changed, 60 insertions(+), 143 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 76857ae6..f39fc746 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -7,9 +7,11 @@ 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 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")] @@ -406,6 +408,45 @@ trait Word {} impl Word for u8 {} impl Word for u16 {} +impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { + type Error = Error; +} + +impl<'d, T: Instance, Tx: TxDmaChannel, Rx> traits::Write for Spi<'d, T, Tx, Rx> { + #[rustfmt::skip] + type WriteFuture<'a> where Self: 'a = impl Future> + 'a; + + fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { + self.write_dma_u8(data) + } +} + +impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::Read + for Spi<'d, T, Tx, Rx> +{ + #[rustfmt::skip] + type ReadFuture<'a> where Self: 'a = impl Future> + '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, Rx: RxDmaChannel> traits::FullDuplex + for Spi<'d, T, Tx, Rx> +{ + #[rustfmt::skip] + type WriteReadFuture<'a> where Self: 'a = impl Future> + '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::*; diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index 3a7d948a..efe7e468 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -4,9 +4,7 @@ use crate::dma::NoDma; use crate::spi::{ check_error_flags, 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; @@ -14,8 +12,7 @@ use futures::future::join3; use super::Spi; 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, { @@ -43,8 +40,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, Rx: RxDmaChannel, @@ -96,8 +92,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, Rx: RxDmaChannel, @@ -221,45 +220,6 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, } } -impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { - type Error = super::Error; -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx> traits::Write for Spi<'d, T, Tx, Rx> { - #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; - - fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { - self.write_dma_u8(data) - } -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::Read - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + '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, Rx: RxDmaChannel> traits::FullDuplex - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type WriteReadFuture<'a> where Self: 'a = impl Future> + '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) - } -} - use super::Word; fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 2f02dc86..e905a1b9 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -1,18 +1,17 @@ #![macro_use] use crate::dma::NoDma; -use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, check_error_flags}; -use core::future::Future; +use crate::spi::{ + check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, +}; 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; 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, { @@ -49,8 +48,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, Rx: RxDmaChannel, @@ -102,8 +100,7 @@ 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, Rx: RxDmaChannel, @@ -270,42 +267,3 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, Ok(words) } } - -impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { - type Error = super::Error; -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx> traits::Write for Spi<'d, T, Tx, Rx> { - #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; - - fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { - self.write_dma_u8(data) - } -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::Read - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + '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, Rx: RxDmaChannel> traits::FullDuplex - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type WriteReadFuture<'a> where Self: 'a = impl Future> + '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) - } -} diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index e63dbcb2..cbe2861e 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs @@ -1,10 +1,10 @@ #![macro_use] use crate::dma::NoDma; -use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, check_error_flags}; -use core::future::Future; +use crate::spi::{ + check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, +}; 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; @@ -12,8 +12,7 @@ use futures::future::join3; use super::Spi; 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, { @@ -53,8 +52,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, Rx: RxDmaChannel, @@ -107,8 +105,7 @@ 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, Rx: RxDmaChannel, @@ -344,42 +341,3 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer for Spi<'d, T, Ok(words) } } - -impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { - type Error = super::Error; -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx> traits::Write for Spi<'d, T, Tx, Rx> { - #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; - - fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { - self.write_dma_u8(data) - } -} - -impl<'d, T: Instance, Tx: TxDmaChannel, Rx: RxDmaChannel> traits::Read - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + '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, Rx: RxDmaChannel> traits::FullDuplex - for Spi<'d, T, Tx, Rx> -{ - #[rustfmt::skip] - type WriteReadFuture<'a> where Self: 'a = impl Future> + '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) - } -} From bf1f80afa1bde29963fb41008bb44349b5f464d7 Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Mon, 6 Dec 2021 22:45:40 -0600 Subject: [PATCH 4/5] Unify blocking trait impls --- embassy-stm32/src/spi/mod.rs | 112 +++++++++++++++++++++ embassy-stm32/src/spi/v1.rs | 103 +------------------- embassy-stm32/src/spi/v2.rs | 110 ++------------------- embassy-stm32/src/spi/v3.rs | 182 ++--------------------------------- 4 files changed, 125 insertions(+), 382 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index f39fc746..d3d78e2a 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -1,6 +1,7 @@ #![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::{regs, vals}; @@ -9,6 +10,7 @@ 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; @@ -403,11 +405,121 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> { 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 {} impl Word for u8 {} impl Word for u16 {} +fn transfer_word(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Result { + 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); +} + +impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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() { + let _ = transfer_word(regs, *word)?; + } + + Ok(()) + } +} + +impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer 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() { + *word = transfer_word(regs, *word)?; + } + + Ok(words) + } +} + +impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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() { + let _ = transfer_word(regs, *word)?; + } + + Ok(()) + } +} + +impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer 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() { + *word = transfer_word(regs, *word)?; + } + + Ok(words) + } +} + impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { type Error = Error; } diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index efe7e468..92449ea8 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -1,15 +1,10 @@ #![macro_use] -use crate::dma::NoDma; -use crate::spi::{ - check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, -}; -use core::ptr; 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> { pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> @@ -155,99 +150,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } } } - -impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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 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 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 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) - } -} - -use super::Word; - -fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { - loop { - let sr = unsafe { regs.sr().read() }; - - check_error_flags(sr)?; - - 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(regs: &'static crate::pac::spi::Spi) -> Result { - loop { - let sr = unsafe { regs.sr().read() }; - - check_error_flags(sr)?; - - if sr.rxne() { - unsafe { - return Ok(ptr::read_volatile(regs.rx_ptr())); - } - } - } -} diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index e905a1b9..de78676c 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -1,14 +1,9 @@ #![macro_use] -use crate::dma::NoDma; -use crate::spi::{ - check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, -}; -use core::ptr; 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> { pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> @@ -100,7 +95,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Ok(()) } - pub(super) 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, Rx: RxDmaChannel, @@ -170,100 +169,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } } } - -use super::Word; - -/// Write a single word blocking. Assumes word size have already been set. -fn write_word(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> { - loop { - let sr = unsafe { regs.sr().read() }; - - check_error_flags(sr)?; - - 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(regs: &'static crate::pac::spi::Spi) -> Result { - loop { - let sr = unsafe { regs.sr().read() }; - - check_error_flags(sr)?; - - if sr.rxne() { - unsafe { - return Ok(ptr::read_volatile(regs.rx_ptr())); - } - } - } -} - -impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write 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 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 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 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) - } -} diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index cbe2861e..ef0f2306 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs @@ -1,15 +1,9 @@ #![macro_use] -use crate::dma::NoDma; -use crate::spi::{ - check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize, -}; -use core::ptr; 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> { pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> @@ -105,7 +99,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Ok(()) } - pub(super) 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, Rx: RxDmaChannel, @@ -173,171 +171,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } } } - -impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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 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; - } - - check_error_flags(sr)?; - } - unsafe { - *word = ptr::read_volatile(T::regs().rx_ptr()); - } - let sr = unsafe { regs.sr().read() }; - check_error_flags(sr)?; - } - - Ok(words) - } -} - -impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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() }; - - check_error_flags(sr)?; - - 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 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; - } - - check_error_flags(sr)?; - } - - unsafe { - let rxdr = regs.rxdr().ptr() as *const u16; - *word = ptr::read_volatile(rxdr); - } - let sr = unsafe { regs.sr().read() }; - check_error_flags(sr)?; - } - - Ok(words) - } -} From 79baa041184d8837a26c9e4b07230b1cdd8cb5b3 Mon Sep 17 00:00:00 2001 From: Grant Miller Date: Mon, 6 Dec 2021 23:29:16 -0600 Subject: [PATCH 5/5] Implement blocking traits with a macro --- embassy-stm32/src/spi/mod.rs | 91 ++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index d3d78e2a..5d919f92 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -439,10 +439,16 @@ fn spin_until_rx_ready(regs: &'static crate::pac::spi::Spi) -> Result<(), Error> } } -trait Word {} +trait Word { + const WORDSIZE: WordSize; +} -impl Word for u8 {} -impl Word for u16 {} +impl Word for u8 { + const WORDSIZE: WordSize = WordSize::EightBit; +} +impl Word for u16 { + const WORDSIZE: WordSize = WordSize::SixteenBit; +} fn transfer_word(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Result { spin_until_tx_ready(regs)?; @@ -460,65 +466,46 @@ fn transfer_word(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Re return Ok(rx_word); } -impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spi<'d, T, NoDma, NoDma> { - type Error = Error; +// 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: &[u8]) -> Result<(), Self::Error> { - self.set_word_size(WordSize::EightBit); - let regs = T::regs(); + 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)?; + for word in words.iter() { + let _ = transfer_word(regs, *word)?; + } + + Ok(()) + } } - Ok(()) - } -} + impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<$w> + for Spi<'d, T, NoDma, NoDma> + { + type Error = Error; -impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer 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(); - 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() { + *word = transfer_word(regs, *word)?; + } - for word in words.iter_mut() { - *word = transfer_word(regs, *word)?; + Ok(words) + } } - - Ok(words) - } + }; } -impl<'d, T: Instance> embedded_hal::blocking::spi::Write 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() { - let _ = transfer_word(regs, *word)?; - } - - Ok(()) - } -} - -impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer 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() { - *word = transfer_word(regs, *word)?; - } - - Ok(words) - } -} +impl_blocking!(u8); +impl_blocking!(u16); impl<'d, T: Instance, Tx, Rx> traits::Spi for Spi<'d, T, Tx, Rx> { type Error = Error;