From 259e84e68e32894a77b6050ee7cbdc9211865447 Mon Sep 17 00:00:00 2001 From: Tobias Pisani Date: Sat, 9 Oct 2021 22:04:25 +0200 Subject: [PATCH] Make miso/mosi optional when for unidirectional spi Only suported on v1 currently --- embassy-stm32/src/spi/mod.rs | 8 ++--- embassy-stm32/src/spi/v1.rs | 57 ++++++++++++++++++++++++++---------- embassy-stm32/src/spi/v2.rs | 40 ++++++++++++++++--------- embassy-stm32/src/spi/v3.rs | 44 ++++++++++++++++++---------- 4 files changed, 100 insertions(+), 49 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 492fc41c..e881a523 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -8,7 +8,7 @@ mod _version; use crate::{dma, peripherals, rcc::RccPeripheral}; pub use _version::*; -use crate::gpio::Pin; +use crate::gpio::OptionalPin; #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -53,15 +53,15 @@ pub(crate) mod sealed { fn regs() -> &'static crate::pac::spi::Spi; } - pub trait SckPin: Pin { + pub trait SckPin: OptionalPin { fn af_num(&self) -> u8; } - pub trait MosiPin: Pin { + pub trait MosiPin: OptionalPin { fn af_num(&self) -> u8; } - pub trait MisoPin: Pin { + pub trait MisoPin: OptionalPin { fn af_num(&self) -> u8; } diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs index 560d99a2..6f8f8afb 100644 --- a/embassy-stm32/src/spi/v1.rs +++ b/embassy-stm32/src/spi/v1.rs @@ -6,9 +6,10 @@ use crate::gpio::{ AFType::{OutputOpenDrain, OutputPushPull}, Pin, }, - AnyPin, + AnyPin, NoPin, }; use crate::pac::spi; +use crate::peripherals; use crate::spi::{ ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel, WordSize, @@ -20,6 +21,7 @@ use core::ptr; use embassy::util::Unborrow; use embassy_hal_common::unborrow; 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; @@ -32,10 +34,29 @@ impl WordSize { } } +macro_rules! impl_nopin { + ($inst:ident, $signal:ident) => { + impl $signal for NoPin {} + + impl super::sealed::$signal for NoPin { + fn af_num(&self) -> u8 { + 0 + } + } + }; +} +crate::pac::peripherals!( + (spi, $inst:ident) => { + impl_nopin!($inst, SckPin); + impl_nopin!($inst, MosiPin); + impl_nopin!($inst, MisoPin); + }; +); + pub struct Spi<'d, T: Instance, Tx, Rx> { - sck: AnyPin, - mosi: AnyPin, - miso: AnyPin, + sck: Option, + mosi: Option, + miso: Option, txdma: Tx, rxdma: Rx, current_word_size: WordSize, @@ -58,15 +79,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { { unborrow!(sck, mosi, miso, txdma, rxdma); - unsafe { - sck.set_as_af(sck.af_num(), OutputPushPull); - mosi.set_as_af(mosi.af_num(), OutputPushPull); - miso.set_as_af(miso.af_num(), OutputOpenDrain); - } + let sck_af = sck.af_num(); + let mosi_af = mosi.af_num(); + let miso_af = miso.af_num(); + let sck = sck.degrade_optional(); + let mosi = mosi.degrade_optional(); + let miso = miso.degrade_optional(); - let sck = sck.degrade(); - let mosi = mosi.degrade(); - let miso = miso.degrade(); + unsafe { + sck.as_ref().map(|x| x.set_as_af(sck_af, OutputPushPull)); + mosi.as_ref().map(|x| x.set_as_af(mosi_af, OutputPushPull)); + miso.as_ref().map(|x| x.set_as_af(miso_af, OutputOpenDrain)); + } unsafe { T::regs().cr2().modify(|w| { @@ -103,6 +127,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { w.set_ssm(true); w.set_crcen(false); w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); + if mosi.is_none() { + w.set_rxonly(spi::vals::Rxonly::OUTPUTDISABLED); + } w.set_dff(WordSize::EightBit.dff()) }); } @@ -294,9 +321,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { fn drop(&mut self) { unsafe { - self.sck.set_as_analog(); - self.mosi.set_as_analog(); - self.miso.set_as_analog(); + self.sck.as_ref().map(|x| x.set_as_analog()); + self.mosi.as_ref().map(|x| x.set_as_analog()); + self.miso.as_ref().map(|x| x.set_as_analog()); } } } diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index 9df71ef2..cb871a9a 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -36,9 +36,9 @@ impl WordSize { } pub struct Spi<'d, T: Instance, Tx, Rx> { - sck: AnyPin, - mosi: AnyPin, - miso: AnyPin, + sck: Option, + mosi: Option, + miso: Option, txdma: Tx, rxdma: Rx, phantom: PhantomData<&'d mut T>, @@ -60,15 +60,21 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { { unborrow!(sck, mosi, miso, txdma, rxdma); - unsafe { - Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num()); - Self::configure_pin(mosi.block(), mosi.pin() as _, mosi.af_num()); - Self::configure_pin(miso.block(), miso.pin() as _, miso.af_num()); - } + let sck_af = sck.af_num(); + let mosi_af = mosi.af_num(); + let miso_af = miso.af_num(); + let sck = sck.degrade_optional(); + let mosi = mosi.degrade_optional(); + let miso = miso.degrade_optional(); - let sck = sck.degrade(); - let mosi = mosi.degrade(); - let miso = miso.degrade(); + unsafe { + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, sck_af)); + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, mosi_af)); + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, miso_af)); + } let pclk = T::frequency(); let freq = freq.into(); @@ -307,9 +313,15 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { fn drop(&mut self) { unsafe { - Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _); - Self::unconfigure_pin(self.mosi.block(), self.mosi.pin() as _); - Self::unconfigure_pin(self.miso.block(), self.miso.pin() as _); + self.sck + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); + self.mosi + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); + self.miso + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); } } } diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs index b0e57254..ef0f123f 100644 --- a/embassy-stm32/src/spi/v3.rs +++ b/embassy-stm32/src/spi/v3.rs @@ -38,9 +38,9 @@ impl WordSize { #[allow(unused)] pub struct Spi<'d, T: Instance, Tx = NoDma, Rx = NoDma> { - sck: AnyPin, - mosi: AnyPin, - miso: AnyPin, + sck: Option, + mosi: Option, + miso: Option, txdma: Tx, rxdma: Rx, phantom: PhantomData<&'d mut T>, @@ -62,17 +62,23 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { { unborrow!(sck, mosi, miso, txdma, rxdma); - unsafe { - Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num()); - //sck.block().otyper().modify(|w| w.set_ot(sck.pin() as _, crate::pac::gpio::vals::Ot::PUSHPULL)); - Self::configure_pin(mosi.block(), mosi.pin() as _, mosi.af_num()); - //mosi.block().otyper().modify(|w| w.set_ot(mosi.pin() as _, crate::pac::gpio::vals::Ot::PUSHPULL)); - Self::configure_pin(miso.block(), miso.pin() as _, miso.af_num()); - } + let sck_af = sck.af_num(); + let mosi_af = mosi.af_num(); + let miso_af = miso.af_num(); + let sck = sck.degrade_optional(); + let mosi = mosi.degrade_optional(); + let miso = miso.degrade_optional(); - let sck = sck.degrade(); - let mosi = mosi.degrade(); - let miso = miso.degrade(); + unsafe { + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, sck_af)); + //sck.block().otyper().modify(|w| w.set_ot(Pin::pin(sck) as _, crate::pac::gpio::vals::Ot::PUSHPULL)); + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, mosi_af)); + //mosi.block().otyper().modify(|w| w.set_ot(Pin::pin(mosi) as _, crate::pac::gpio::vals::Ot::PUSHPULL)); + sck.as_ref() + .map(|x| Self::configure_pin(x.block(), x.pin() as _, miso_af)); + } let pclk = T::frequency(); let br = Self::compute_baud_rate(pclk, freq.into()); @@ -340,9 +346,15 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { fn drop(&mut self) { unsafe { - Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _); - Self::unconfigure_pin(self.mosi.block(), self.mosi.pin() as _); - Self::unconfigure_pin(self.miso.block(), self.miso.pin() as _); + self.sck + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); + self.mosi + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); + self.miso + .as_ref() + .map(|x| Self::unconfigure_pin(x.block(), x.pin() as _)); } } }