Skip to content

Commit

Permalink
SPI slave with_pin functions
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 7, 2024
1 parent 4233bdd commit 553d90a
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 68 deletions.
2 changes: 2 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- `spi::master::Config` and `{Spi, SpiDma, SpiDmaBus}::apply_config` (#2448)
- `embassy_embedded_hal::SetConfig` is now implemented for `{Spi, SpiDma, SpiDmaBus}` (#2448)
- `slave::Spi::{with_mosi(), with_miso(), with_sclk(), with_cs()}` functions (#?)

### Changed

Expand All @@ -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)
- Peripheral interconnections via GPIO pins now use the GPIO matrix. (#2419)
- The I2S driver has been moved to `i2s::master` (#2472)
- `slave::Spi` constructors no longer take pins (#?)

### Fixed

Expand Down
23 changes: 22 additions & 1 deletion esp-hal/MIGRATING-0.21.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `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.
> TODO(danielb): this means they are currently only usable with GPIO pins, but upcoming GPIO changes should allow using any output signal.

```diff
- let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
Expand Down Expand Up @@ -131,6 +130,28 @@ The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::writ
.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

The following functions have been removed:
Expand Down
108 changes: 55 additions & 53 deletions esp-hal/src/spi/slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,20 @@
//! dma_buffers!(32000);
//! let mut spi = Spi::new(
//! peripherals.SPI2,
//! sclk,
//! mosi,
//! miso,
//! cs,
//! SpiMode::Mode0,
//! )
//! .with_dma(dma_channel.configure(
//! false,
//! DmaPriority::Priority0,
//! ), rx_descriptors, tx_descriptors);
//! .with_sclk(sclk)
//! .with_mosi(mosi)
//! .with_miso(miso)
//! .with_cs(cs)
//! .with_dma(
//! dma_channel.configure(
//! false,
//! DmaPriority::Priority0,
//! ),
//! rx_descriptors,
//! tx_descriptors,
//! );
//!
//! let mut receive = rx_buffer;
//! let mut send = tx_buffer;
Expand Down Expand Up @@ -110,13 +114,9 @@ impl<'d> Spi<'d, Blocking> {
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)
Self::new_typed(spi.map_into(), mode)
}
}

Expand All @@ -125,55 +125,57 @@ where
T: Instance,
{
/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new_typed<
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> {
pub fn new_typed(spi: impl Peripheral<P = T> + 'd, mode: SpiMode) -> Spi<'d, M, T> {
crate::into_ref!(spi);

let spi = Spi {
let this = Spi {
spi,
data_mode: mode,
_mode: PhantomData,
};

PeripheralClockControl::reset(spi.spi.info().peripheral);
PeripheralClockControl::enable(spi.spi.info().peripheral);
PeripheralClockControl::reset(this.spi.info().peripheral);
PeripheralClockControl::enable(this.spi.info().peripheral);

this.spi.info().init();
this.spi.info().set_data_mode(mode, false);

spi.spi.info().init();
spi.spi.info().set_data_mode(mode, false);
this.with_mosi(NoPin)
.with_miso(NoPin)
.with_sck(NoPin)
.with_cs(NoPin)
}

/// Assign the SCLK (Serial Clock) pin for the SPI instance.
pub fn with_sclk(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
}

spi
/// 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
}
}

Expand Down
23 changes: 10 additions & 13 deletions examples/src/bin/spi_slave_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,16 @@ fn main() -> ! {

let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);

let mut spi = Spi::new(
peripherals.SPI2,
slave_sclk,
slave_mosi,
slave_miso,
slave_cs,
SpiMode::Mode0,
)
.with_dma(
dma_channel.configure(false, DmaPriority::Priority0),
tx_descriptors,
rx_descriptors,
);
let mut spi = Spi::new(peripherals.SPI2, SpiMode::Mode0)
.with_sclk(slave_sclk)
.with_mosi(slave_mosi)
.with_miso(slave_miso)
.with_cs(slave_cs)
.with_dma(
dma_channel.configure(false, DmaPriority::Priority0),
tx_descriptors,
rx_descriptors,
);

let delay = Delay::new();

Expand Down
6 changes: 5 additions & 1 deletion hil-test/tests/spi_slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ mod tests {
let miso = unsafe { miso_gpio.clone_unchecked() }.into_peripheral_output();

Context {
spi: Spi::new(peripherals.SPI2, sclk, mosi, miso, cs, SpiMode::Mode1),
spi: Spi::new(peripherals.SPI2, SpiMode::Mode1)
.with_sclk(sclk)
.with_mosi(mosi)
.with_miso(miso)
.with_cs(cs),
bitbang_spi: BitbangSpi::new(sclk_gpio, mosi_gpio, miso_gpio, cs_gpio),
dma_channel,
}
Expand Down

0 comments on commit 553d90a

Please sign in to comment.