SPI slave with_pin functions (#2485)

This commit is contained in:
Dániel Buga 2024-11-08 08:29:37 +01:00 committed by GitHub
parent 4233bddf23
commit d5e6ba5ceb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 96 additions and 77 deletions

View File

@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- GPIO ETM tasks and events now accept `InputSignal` and `OutputSignal` (#2427) - GPIO ETM tasks and events now accept `InputSignal` and `OutputSignal` (#2427)
- `spi::master::Config` and `{Spi, SpiDma, SpiDmaBus}::apply_config` (#2448) - `spi::master::Config` and `{Spi, SpiDma, SpiDmaBus}::apply_config` (#2448)
- `embassy_embedded_hal::SetConfig` is now implemented for `{Spi, SpiDma, SpiDmaBus}` (#2448) - `embassy_embedded_hal::SetConfig` is now implemented for `{Spi, SpiDma, SpiDmaBus}` (#2448)
- `slave::Spi::{with_mosi(), with_miso(), with_sclk(), with_cs()}` functions (#2485)
### Changed ### Changed
@ -55,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `spi::master::Spi::new()` no longer takes `frequency` and `mode` as a parameter. (#2448) - `spi::master::Spi::new()` no longer takes `frequency` and `mode` as a parameter. (#2448)
- Peripheral interconnections via GPIO pins now use the GPIO matrix. (#2419) - Peripheral interconnections via GPIO pins now use the GPIO matrix. (#2419)
- The I2S driver has been moved to `i2s::master` (#2472) - The I2S driver has been moved to `i2s::master` (#2472)
- `slave::Spi` constructors no longer take pins (#2485)
### Fixed ### Fixed

View File

@ -84,7 +84,6 @@ drivers. It is now possible to execute half-duplex and full-duplex operations on
- The `Spi::new_half_duplex` constructor has been removed. Use `new` (or `new_typed`) instead. - The `Spi::new_half_duplex` constructor has been removed. Use `new` (or `new_typed`) instead.
- The `with_pins` methods have been removed. Use the individual `with_*` functions instead. - The `with_pins` methods have been removed. Use the individual `with_*` functions instead.
- The `with_mosi` and `with_miso` functions now take input-output peripheral signals to support half-duplex mode. - The `with_mosi` and `with_miso` functions now take input-output peripheral signals to support half-duplex mode.
> TODO(danielb): this means they are currently only usable with GPIO pins, but upcoming GPIO changes should allow using any output signal.
```diff ```diff
- let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
@ -131,6 +130,28 @@ The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::writ
.unwrap(); .unwrap();
``` ```
## Slave-mode SPI
### Driver construction
The constructors no longer accept pins. Use the `with_pin_name` setters instead.
```diff
let mut spi = Spi::new(
peripherals.SPI2,
- sclk,
- mosi,
- miso,
- cs,
SpiMode::Mode0,
-);
+)
+.with_sclk(sclk)
+.with_mosi(mosi)
+.with_miso(miso)
+.with_cs(cs);
```
## UART event listening ## UART event listening
The following functions have been removed: The following functions have been removed:

View File

@ -34,16 +34,20 @@
//! dma_buffers!(32000); //! dma_buffers!(32000);
//! let mut spi = Spi::new( //! let mut spi = Spi::new(
//! peripherals.SPI2, //! peripherals.SPI2,
//! sclk,
//! mosi,
//! miso,
//! cs,
//! SpiMode::Mode0, //! SpiMode::Mode0,
//! ) //! )
//! .with_dma(dma_channel.configure( //! .with_sck(sclk)
//! .with_mosi(mosi)
//! .with_miso(miso)
//! .with_cs(cs)
//! .with_dma(
//! dma_channel.configure(
//! false, //! false,
//! DmaPriority::Priority0, //! DmaPriority::Priority0,
//! ), rx_descriptors, tx_descriptors); //! ),
//! rx_descriptors,
//! tx_descriptors,
//! );
//! //!
//! let mut receive = rx_buffer; //! let mut receive = rx_buffer;
//! let mut send = tx_buffer; //! let mut send = tx_buffer;
@ -79,6 +83,7 @@ use crate::{
gpio::{ gpio::{
interconnect::{PeripheralInput, PeripheralOutput}, interconnect::{PeripheralInput, PeripheralOutput},
InputSignal, InputSignal,
NoPin,
OutputSignal, OutputSignal,
}, },
peripheral::{Peripheral, PeripheralRef}, peripheral::{Peripheral, PeripheralRef},
@ -103,20 +108,8 @@ pub struct Spi<'d, M, T = AnySpi> {
impl<'d> Spi<'d, Blocking> { impl<'d> Spi<'d, Blocking> {
/// Constructs an SPI instance in 8bit dataframe mode. /// Constructs an SPI instance in 8bit dataframe mode.
pub fn new< pub fn new(spi: impl Peripheral<P = impl Instance> + 'd, mode: SpiMode) -> Spi<'d, Blocking> {
SCK: PeripheralInput, Self::new_typed(spi.map_into(), mode)
MOSI: PeripheralInput,
MISO: PeripheralOutput,
CS: PeripheralInput,
>(
spi: impl Peripheral<P = impl Instance> + 'd,
sclk: impl Peripheral<P = SCK> + 'd,
mosi: impl Peripheral<P = MOSI> + 'd,
miso: impl Peripheral<P = MISO> + 'd,
cs: impl Peripheral<P = CS> + 'd,
mode: SpiMode,
) -> Spi<'d, Blocking> {
Self::new_typed(spi.map_into(), sclk, mosi, miso, cs, mode)
} }
} }
@ -125,55 +118,57 @@ where
T: Instance, T: Instance,
{ {
/// Constructs an SPI instance in 8bit dataframe mode. /// Constructs an SPI instance in 8bit dataframe mode.
pub fn new_typed< pub fn new_typed(spi: impl Peripheral<P = T> + 'd, mode: SpiMode) -> Spi<'d, M, T> {
SCK: PeripheralInput,
MOSI: PeripheralInput,
MISO: PeripheralOutput,
CS: PeripheralInput,
>(
spi: impl Peripheral<P = T> + 'd,
sclk: impl Peripheral<P = SCK> + 'd,
mosi: impl Peripheral<P = MOSI> + 'd,
miso: impl Peripheral<P = MISO> + 'd,
cs: impl Peripheral<P = CS> + 'd,
mode: SpiMode,
) -> Spi<'d, M, T> {
crate::into_mapped_ref!(sclk, mosi, miso, cs);
let this = Self::new_internal(spi, mode);
// TODO: with_pins et. al.
sclk.enable_input(true, private::Internal);
this.spi.info().sclk.connect_to(sclk);
mosi.enable_input(true, private::Internal);
this.spi.info().mosi.connect_to(mosi);
miso.set_to_push_pull_output(private::Internal);
this.spi.info().miso.connect_to(miso);
cs.enable_input(true, private::Internal);
this.spi.info().cs.connect_to(cs);
this
}
pub(crate) fn new_internal(spi: impl Peripheral<P = T> + 'd, mode: SpiMode) -> Spi<'d, M, T> {
crate::into_ref!(spi); crate::into_ref!(spi);
let spi = Spi { let this = Spi {
spi, spi,
data_mode: mode, data_mode: mode,
_mode: PhantomData, _mode: PhantomData,
}; };
PeripheralClockControl::reset(spi.spi.info().peripheral); PeripheralClockControl::reset(this.spi.info().peripheral);
PeripheralClockControl::enable(spi.spi.info().peripheral); PeripheralClockControl::enable(this.spi.info().peripheral);
spi.spi.info().init(); this.spi.info().init();
spi.spi.info().set_data_mode(mode, false); this.spi.info().set_data_mode(mode, false);
spi this.with_mosi(NoPin)
.with_miso(NoPin)
.with_sck(NoPin)
.with_cs(NoPin)
}
/// Assign the SCK (Serial Clock) pin for the SPI instance.
pub fn with_sck(self, sclk: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
crate::into_mapped_ref!(sclk);
sclk.enable_input(true, private::Internal);
self.spi.info().sclk.connect_to(sclk);
self
}
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
pub fn with_mosi(self, mosi: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
crate::into_mapped_ref!(mosi);
mosi.enable_input(true, private::Internal);
self.spi.info().mosi.connect_to(mosi);
self
}
/// Assign the MISO (Master In Slave Out) pin for the SPI instance.
pub fn with_miso(self, miso: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self {
crate::into_mapped_ref!(miso);
miso.set_to_push_pull_output(private::Internal);
self.spi.info().miso.connect_to(miso);
self
}
/// Assign the CS (Chip Select) pin for the SPI instance.
pub fn with_cs(self, cs: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self {
crate::into_mapped_ref!(cs);
cs.enable_input(true, private::Internal);
self.spi.info().cs.connect_to(cs);
self
} }
} }

View File

@ -67,18 +67,15 @@ fn main() -> ! {
let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000); let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
let mut spi = Spi::new( let mut spi = Spi::new(peripherals.SPI2, SpiMode::Mode0)
peripherals.SPI2, .with_sck(slave_sclk)
slave_sclk, .with_mosi(slave_mosi)
slave_mosi, .with_miso(slave_miso)
slave_miso, .with_cs(slave_cs)
slave_cs,
SpiMode::Mode0,
)
.with_dma( .with_dma(
dma_channel.configure(false, DmaPriority::Priority0), dma_channel.configure(false, DmaPriority::Priority0),
tx_descriptors,
rx_descriptors, rx_descriptors,
tx_descriptors,
); );
let delay = Delay::new(); let delay = Delay::new();

View File

@ -130,7 +130,11 @@ mod tests {
let miso = unsafe { miso_gpio.clone_unchecked() }.into_peripheral_output(); let miso = unsafe { miso_gpio.clone_unchecked() }.into_peripheral_output();
Context { Context {
spi: Spi::new(peripherals.SPI2, sclk, mosi, miso, cs, SpiMode::Mode1), spi: Spi::new(peripherals.SPI2, SpiMode::Mode1)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso)
.with_cs(cs),
bitbang_spi: BitbangSpi::new(sclk_gpio, mosi_gpio, miso_gpio, cs_gpio), bitbang_spi: BitbangSpi::new(sclk_gpio, mosi_gpio, miso_gpio, cs_gpio),
dma_channel, dma_channel,
} }