Make miso/mosi optional when for unidirectional spi

Only suported on v1 currently
This commit is contained in:
Tobias Pisani 2021-10-09 22:04:25 +02:00
parent c44bed300b
commit 259e84e68e
4 changed files with 100 additions and 49 deletions

View File

@ -8,7 +8,7 @@ mod _version;
use crate::{dma, peripherals, rcc::RccPeripheral}; use crate::{dma, peripherals, rcc::RccPeripheral};
pub use _version::*; pub use _version::*;
use crate::gpio::Pin; use crate::gpio::OptionalPin;
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -53,15 +53,15 @@ pub(crate) mod sealed {
fn regs() -> &'static crate::pac::spi::Spi; fn regs() -> &'static crate::pac::spi::Spi;
} }
pub trait SckPin<T: Instance>: Pin { pub trait SckPin<T: Instance>: OptionalPin {
fn af_num(&self) -> u8; fn af_num(&self) -> u8;
} }
pub trait MosiPin<T: Instance>: Pin { pub trait MosiPin<T: Instance>: OptionalPin {
fn af_num(&self) -> u8; fn af_num(&self) -> u8;
} }
pub trait MisoPin<T: Instance>: Pin { pub trait MisoPin<T: Instance>: OptionalPin {
fn af_num(&self) -> u8; fn af_num(&self) -> u8;
} }

View File

@ -6,9 +6,10 @@ use crate::gpio::{
AFType::{OutputOpenDrain, OutputPushPull}, AFType::{OutputOpenDrain, OutputPushPull},
Pin, Pin,
}, },
AnyPin, AnyPin, NoPin,
}; };
use crate::pac::spi; use crate::pac::spi;
use crate::peripherals;
use crate::spi::{ use crate::spi::{
ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel, ByteOrder, Config, Error, Instance, MisoPin, MosiPin, RxDmaChannel, SckPin, TxDmaChannel,
WordSize, WordSize,
@ -20,6 +21,7 @@ use core::ptr;
use embassy::util::Unborrow; use embassy::util::Unborrow;
use embassy_hal_common::unborrow; use embassy_hal_common::unborrow;
use embassy_traits::spi as traits; 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}; pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
use futures::future::join3; use futures::future::join3;
@ -32,10 +34,29 @@ impl WordSize {
} }
} }
macro_rules! impl_nopin {
($inst:ident, $signal:ident) => {
impl $signal<peripherals::$inst> for NoPin {}
impl super::sealed::$signal<peripherals::$inst> 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> { pub struct Spi<'d, T: Instance, Tx, Rx> {
sck: AnyPin, sck: Option<AnyPin>,
mosi: AnyPin, mosi: Option<AnyPin>,
miso: AnyPin, miso: Option<AnyPin>,
txdma: Tx, txdma: Tx,
rxdma: Rx, rxdma: Rx,
current_word_size: WordSize, 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); unborrow!(sck, mosi, miso, txdma, rxdma);
unsafe { let sck_af = sck.af_num();
sck.set_as_af(sck.af_num(), OutputPushPull); let mosi_af = mosi.af_num();
mosi.set_as_af(mosi.af_num(), OutputPushPull); let miso_af = miso.af_num();
miso.set_as_af(miso.af_num(), OutputOpenDrain); let sck = sck.degrade_optional();
} let mosi = mosi.degrade_optional();
let miso = miso.degrade_optional();
let sck = sck.degrade(); unsafe {
let mosi = mosi.degrade(); sck.as_ref().map(|x| x.set_as_af(sck_af, OutputPushPull));
let miso = miso.degrade(); 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 { unsafe {
T::regs().cr2().modify(|w| { 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_ssm(true);
w.set_crcen(false); w.set_crcen(false);
w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL); w.set_bidimode(spi::vals::Bidimode::UNIDIRECTIONAL);
if mosi.is_none() {
w.set_rxonly(spi::vals::Rxonly::OUTPUTDISABLED);
}
w.set_dff(WordSize::EightBit.dff()) 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> { impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
self.sck.set_as_analog(); self.sck.as_ref().map(|x| x.set_as_analog());
self.mosi.set_as_analog(); self.mosi.as_ref().map(|x| x.set_as_analog());
self.miso.set_as_analog(); self.miso.as_ref().map(|x| x.set_as_analog());
} }
} }
} }

View File

@ -36,9 +36,9 @@ impl WordSize {
} }
pub struct Spi<'d, T: Instance, Tx, Rx> { pub struct Spi<'d, T: Instance, Tx, Rx> {
sck: AnyPin, sck: Option<AnyPin>,
mosi: AnyPin, mosi: Option<AnyPin>,
miso: AnyPin, miso: Option<AnyPin>,
txdma: Tx, txdma: Tx,
rxdma: Rx, rxdma: Rx,
phantom: PhantomData<&'d mut T>, 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); unborrow!(sck, mosi, miso, txdma, rxdma);
unsafe { let sck_af = sck.af_num();
Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num()); let mosi_af = mosi.af_num();
Self::configure_pin(mosi.block(), mosi.pin() as _, mosi.af_num()); let miso_af = miso.af_num();
Self::configure_pin(miso.block(), miso.pin() as _, miso.af_num()); let sck = sck.degrade_optional();
} let mosi = mosi.degrade_optional();
let miso = miso.degrade_optional();
let sck = sck.degrade(); unsafe {
let mosi = mosi.degrade(); sck.as_ref()
let miso = miso.degrade(); .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 pclk = T::frequency();
let freq = freq.into(); 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> { 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.sck
Self::unconfigure_pin(self.mosi.block(), self.mosi.pin() as _); .as_ref()
Self::unconfigure_pin(self.miso.block(), self.miso.pin() as _); .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 _));
} }
} }
} }

View File

@ -38,9 +38,9 @@ impl WordSize {
#[allow(unused)] #[allow(unused)]
pub struct Spi<'d, T: Instance, Tx = NoDma, Rx = NoDma> { pub struct Spi<'d, T: Instance, Tx = NoDma, Rx = NoDma> {
sck: AnyPin, sck: Option<AnyPin>,
mosi: AnyPin, mosi: Option<AnyPin>,
miso: AnyPin, miso: Option<AnyPin>,
txdma: Tx, txdma: Tx,
rxdma: Rx, rxdma: Rx,
phantom: PhantomData<&'d mut T>, 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); unborrow!(sck, mosi, miso, txdma, rxdma);
unsafe { let sck_af = sck.af_num();
Self::configure_pin(sck.block(), sck.pin() as _, sck.af_num()); let mosi_af = mosi.af_num();
//sck.block().otyper().modify(|w| w.set_ot(sck.pin() as _, crate::pac::gpio::vals::Ot::PUSHPULL)); let miso_af = miso.af_num();
Self::configure_pin(mosi.block(), mosi.pin() as _, mosi.af_num()); let sck = sck.degrade_optional();
//mosi.block().otyper().modify(|w| w.set_ot(mosi.pin() as _, crate::pac::gpio::vals::Ot::PUSHPULL)); let mosi = mosi.degrade_optional();
Self::configure_pin(miso.block(), miso.pin() as _, miso.af_num()); let miso = miso.degrade_optional();
}
let sck = sck.degrade(); unsafe {
let mosi = mosi.degrade(); sck.as_ref()
let miso = miso.degrade(); .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 pclk = T::frequency();
let br = Self::compute_baud_rate(pclk, freq.into()); 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> { 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.sck
Self::unconfigure_pin(self.mosi.block(), self.mosi.pin() as _); .as_ref()
Self::unconfigure_pin(self.miso.block(), self.miso.pin() as _); .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 _));
} }
} }
} }