From 9f9b63609914efa28d8c6b39a3134c856115ab2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 19 Oct 2024 11:47:59 +0200 Subject: [PATCH] Remove duplex type param --- esp-hal/CHANGELOG.md | 6 + esp-hal/MIGRATING-0.21.md | 57 ++ esp-hal/src/spi/master.rs | 930 +++++------------- esp-hal/src/spi/mod.rs | 13 - esp-hal/src/spi/slave.rs | 19 +- examples/src/bin/embassy_spi.rs | 5 +- examples/src/bin/qspi_flash.rs | 19 +- .../spi_halfduplex_read_manufacturer_id.rs | 17 +- examples/src/bin/spi_loopback.rs | 11 +- examples/src/bin/spi_loopback_dma.rs | 5 +- examples/src/bin/spi_loopback_dma_psram.rs | 5 +- hil-test/tests/embassy_interrupt_spi_dma.rs | 3 +- hil-test/tests/qspi.rs | 60 +- hil-test/tests/spi_full_duplex.rs | 10 +- hil-test/tests/spi_half_duplex_read.rs | 15 +- hil-test/tests/spi_half_duplex_write.rs | 15 +- hil-test/tests/spi_half_duplex_write_psram.rs | 15 +- hil-test/tests/spi_slave.rs | 4 +- 18 files changed, 445 insertions(+), 764 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index b620a9a49bb..eb3d25f3a6d 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -15,16 +15,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AnyPin` now implements `From>`. (#2326) - Added `AnySpi` and `AnySpiDmaChannel`. (#2334) - `Pins::steal()` to unsafely obtain GPIO. (#2335) +- `Spi::half_duplex_read` and `Spi::half_duplex_write` (#2373) ### Changed - Peripheral type erasure for SPI (#2334) +- The SPI driver has been rewritten to allow using half-duplex and full-duplex functionality on the same bus. See the migration guide for details. (#2373) ### Fixed ### Removed - The `i2s::{I2sWrite, I2sWriteDma, I2sRead, I2sReadDma, I2sWriteDmaAsync, I2sReadDmaAsync}` traits have been removed. (#2316) +- The `spi::master::HalfDuplexReadWrite` trait has been removed. (#2373) +- The `Spi::with_pins` methods have been removed. (#2373) +- The `Spi::new_half_duplex` constructor have been removed. (#2373) +- The `HalfDuplexMode` and `FullDuplexMode` parameters have been removed from `Spi`. (#2373) ## [0.21.1] diff --git a/esp-hal/MIGRATING-0.21.md b/esp-hal/MIGRATING-0.21.md index 5eeb638dea2..839f83a6ed5 100644 --- a/esp-hal/MIGRATING-0.21.md +++ b/esp-hal/MIGRATING-0.21.md @@ -45,3 +45,60 @@ the peripheral instance has been moved to the last generic parameter position. ```rust let spi: Spi<'static, FullDuplexMode, SPI2> = Spi::new_typed(peripherals.SPI2, 1.MHz(), SpiMode::Mode0); ``` + +## Changes to half-duplex SPI + +The `HalfDuplexMode` and `FullDuplexMode` type parameters have been removed from SPI master and slave +drivers. It is now possible to execute half-duplex and full-duplex operations on the same SPI bus. + +### Driver construction + +- 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) +- .with_pins(sck, mosi, miso, sio2, sio3, cs); ++ let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) ++ .with_sck(sck) ++ .with_cs(cs) ++ .with_mosi(mosi) ++ .with_miso(miso) ++ .with_sio2(sio2) ++ .with_sio3(sio3); +``` + +### Transfer functions + +The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::write` functions have been replaced by +`half_duplex_read` and `half_duplex_write`. + +```diff + let mut data = [0u8; 2]; + let transfer = spi +- .read( ++ .half_duplex_read( + SpiDataMode::Single, + Command::Command8(0x90, SpiDataMode::Single), + Address::Address24(0x000000, SpiDataMode::Single), + 0, + &mut data, + ) + .unwrap(); + + let transfer = spi +- .write( ++ .half_duplex_write( + SpiDataMode::Quad, + Command::Command8(write as u16, command_data_mode), + Address::Address24( + write as u32 | (write as u32) << 8 | (write as u32) << 16, + SpiDataMode::Quad, + ), + 0, + dma_tx_buf, + ) + .unwrap(); +``` \ No newline at end of file diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 40cd6677194..83dc0b11d19 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -58,8 +58,6 @@ //! [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/spi/index.html //! [`embassy-embedded-hal`]: https://docs.embassy.dev/embassy-embedded-hal/git/default/shared_bus/index.html -use core::marker::PhantomData; - pub use dma::*; #[cfg(gdma)] use enumset::EnumSet; @@ -69,16 +67,7 @@ use fugit::HertzU32; #[cfg(place_spi_driver_in_ram)] use procmacros::ram; -use super::{ - DmaError, - DuplexMode, - Error, - FullDuplexMode, - HalfDuplexMode, - SpiBitOrder, - SpiDataMode, - SpiMode, -}; +use super::{DmaError, Error, SpiBitOrder, SpiDataMode, SpiMode}; use crate::{ clock::Clocks, dma::{DmaChannelConvert, DmaEligible, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, @@ -425,92 +414,14 @@ impl Address { } } -/// Read and Write in half duplex mode. -pub trait HalfDuplexReadWrite { - /// The associated error type that will be returned in the event of a - /// failure. - type Error; - - /// Half-duplex read. - fn read( - &mut self, - data_mode: SpiDataMode, - cmd: Command, - address: Address, - dummy: u8, - buffer: &mut [u8], - ) -> Result<(), Self::Error>; - - /// Half-duplex write. - fn write( - &mut self, - data_mode: SpiDataMode, - cmd: Command, - address: Address, - dummy: u8, - buffer: &[u8], - ) -> Result<(), Self::Error>; -} - /// SPI peripheral driver -pub struct Spi<'d, M, T = AnySpi> { +pub struct Spi<'d, T = AnySpi> { spi: PeripheralRef<'d, T>, - _mode: PhantomData, } -impl<'d, M, T> Spi<'d, M, T> -where - T: Instance, -{ - fn new_internal( - spi: impl Peripheral

+ 'd> + 'd, - frequency: HertzU32, - mode: SpiMode, - ) -> Spi<'d, M, T> { - crate::into_ref!(spi); - - let mut spi = Spi { - spi: spi.map_into(), - _mode: PhantomData, - }; - spi.spi.reset_peripheral(); - spi.spi.enable_peripheral(); - spi.spi.setup(frequency); - spi.spi.init(); - spi.spi.set_data_mode(mode); - - spi - } - - /// Assign the SCK (Serial Clock) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI - /// clock signal. - pub fn with_sck(self, sclk: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(sclk); - sclk.set_to_push_pull_output(private::Internal); - sclk.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); - - self - } - - /// Assign the CS (Chip Select) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI CS - /// signal. - pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(cs); - cs.set_to_push_pull_output(private::Internal); - cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); - - self - } -} - -impl<'d, M, T> Spi<'d, M, T> +impl<'d, T> Spi<'d, T> where T: InstanceDma, - M: DuplexMode, { /// Configures the SPI instance to use DMA with the specified channel. /// @@ -520,7 +431,7 @@ where pub fn with_dma( self, channel: crate::dma::Channel<'d, CH, DmaMode>, - ) -> SpiDma<'d, M, DmaMode, T> + ) -> SpiDma<'d, DmaMode, T> where CH: DmaChannelConvert, DmaMode: Mode, @@ -529,7 +440,7 @@ where } } -impl<'d, T> Spi<'d, FullDuplexMode, T> +impl<'d, T> Spi<'d, T> where T: Instance, { @@ -565,7 +476,7 @@ where } } -impl<'d> Spi<'d, FullDuplexMode> { +impl<'d> Spi<'d> { /// Constructs an SPI instance in 8bit dataframe mode. /// /// All pins are optional. Setup these pins using @@ -574,12 +485,12 @@ impl<'d> Spi<'d, FullDuplexMode> { spi: impl Peripheral

+ 'd> + 'd, frequency: HertzU32, mode: SpiMode, - ) -> Spi<'d, FullDuplexMode> { + ) -> Spi<'d> { Self::new_typed(spi, frequency, mode) } } -impl<'d, T> Spi<'d, FullDuplexMode, T> +impl<'d, T> Spi<'d, T> where T: Instance, { @@ -591,146 +502,130 @@ where spi: impl Peripheral

+ 'd> + 'd, frequency: HertzU32, mode: SpiMode, - ) -> Spi<'d, FullDuplexMode, T> { - let spi = Spi::::new_internal(spi, frequency, mode); + ) -> Spi<'d, T> { + crate::into_ref!(spi); - // Disconnect any lingering connections - spi.with_pins(NoPin, NoPin, NoPin, NoPin) + let mut spi = Spi { + spi: spi.map_into(), + }; + spi.spi.reset_peripheral(); + spi.spi.enable_peripheral(); + spi.spi.setup(frequency); + spi.spi.init(); + spi.spi.set_data_mode(mode); + + let spi = spi + .with_mosi(NoPin) + .with_miso(NoPin) + .with_sck(NoPin) + .with_cs(NoPin); + + let is_qspi = spi.spi.sio2_input_signal().is_some(); + if is_qspi { + NoPin.connect_input_to_peripheral( + unwrap!(spi.spi.sio2_input_signal()), + private::Internal, + ); + NoPin.connect_peripheral_to_output( + unwrap!(spi.spi.sio2_output_signal()), + private::Internal, + ); + NoPin.connect_input_to_peripheral( + unwrap!(spi.spi.sio3_input_signal()), + private::Internal, + ); + NoPin.connect_peripheral_to_output( + unwrap!(spi.spi.sio3_output_signal()), + private::Internal, + ); + } + + spi } /// Assign the MOSI (Master Out Slave In) pin for the SPI instance. /// - /// Sets the specified pin to push-pull output and connects it to the SPI - /// MOSI signal. - pub fn with_mosi(self, mosi: impl Peripheral

+ 'd) -> Self { + /// Enables both input and output functionality for the pin, and connects it + /// to the MOSI signal and SIO0 input signal. + pub fn with_mosi( + self, + mosi: impl Peripheral

+ 'd, + ) -> Self { crate::into_ref!(mosi); - mosi.set_to_push_pull_output(private::Internal); + + mosi.enable_output(true, private::Internal); mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); + mosi.enable_input(true, private::Internal); + mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); + self } /// Assign the MISO (Master In Slave Out) pin for the SPI instance. /// - /// Sets the specified pin to input and connects it to the SPI MISO signal. - pub fn with_miso(self, miso: impl Peripheral

+ 'd) -> Self { + /// Enables both input and output functionality for the pin, and connects it + /// to the MISO signal and SIO1 input signal. + pub fn with_miso( + self, + miso: impl Peripheral

+ 'd, + ) -> Self { crate::into_ref!(miso); - miso.init_input(crate::gpio::Pull::None, private::Internal); + + miso.enable_input(true, private::Internal); miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); + miso.enable_output(true, private::Internal); + miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); + self } - /// Set the bit order for the SPI instance. + /// Assign the SCK (Serial Clock) pin for the SPI instance. /// - /// The default is MSB first for both read and write. - pub fn with_bit_order(mut self, read_order: SpiBitOrder, write_order: SpiBitOrder) -> Self { - self.spi.set_bit_order(read_order, write_order); + /// Sets the specified pin to push-pull output and connects it to the SPI + /// clock signal. + pub fn with_sck(self, sclk: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(sclk); + sclk.set_to_push_pull_output(private::Internal); + sclk.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); + self } - /// Setup pins for this SPI instance. + /// Assign the CS (Chip Select) pin for the SPI instance. /// - /// All pins are optional. Pass [crate::gpio::NoPin] if you don't need the - /// given pin. - pub fn with_pins< - SCK: PeripheralOutput, - MOSI: PeripheralOutput, - MISO: PeripheralInput, - CS: PeripheralOutput, - >( - self, - sck: impl Peripheral

+ 'd, - mosi: impl Peripheral

+ 'd, - miso: impl Peripheral

+ 'd, - cs: impl Peripheral

+ 'd, - ) -> Self { - self.with_sck(sck) - .with_mosi(mosi) - .with_miso(miso) - .with_cs(cs) + /// Sets the specified pin to push-pull output and connects it to the SPI CS + /// signal. + pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(cs); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); + + self } - /// Change the bus frequency of the SPI instance. + /// Change the bus frequency of the SPI instance in half-duplex mode. /// - /// This method allows user to update the bus frequency for the SPI + /// This method allows you to update the bus frequency for the SPI /// communication after the instance has been created. pub fn change_bus_frequency(&mut self, frequency: HertzU32) { self.spi.ch_bus_freq(frequency); } -} -impl<'d> Spi<'d, HalfDuplexMode> { - /// Constructs an SPI instance in half-duplex mode. + /// Set the bit order for the SPI instance. /// - /// All pins are optional. Setup these pins using - /// [with_pins](Self::with_pins) or individual methods for each pin. - pub fn new_half_duplex( - spi: impl Peripheral

+ 'd> + 'd, - frequency: HertzU32, - mode: SpiMode, - ) -> Spi<'d, HalfDuplexMode> { - Self::new_half_duplex_typed(spi, frequency, mode) + /// The default is MSB first for both read and write. + pub fn with_bit_order(mut self, read_order: SpiBitOrder, write_order: SpiBitOrder) -> Self { + self.spi.set_bit_order(read_order, write_order); + self } } -impl<'d, T> Spi<'d, HalfDuplexMode, T> +impl<'d, T> Spi<'d, T> where - T: ExtendedInstance, + T: QspiInstance, { - /// Constructs an SPI instance in half-duplex mode. - /// - /// All pins are optional. Setup these pins using - /// [with_pins](Self::with_pins) or individual methods for each pin. - pub fn new_half_duplex_typed( - spi: impl Peripheral

+ 'd> + 'd, - frequency: HertzU32, - mode: SpiMode, - ) -> Spi<'d, HalfDuplexMode, T> { - let spi = Spi::::new_internal(spi, frequency, mode); - - // Disconnect any lingering connections - spi.with_pins(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin) - } - - /// Assign the MOSI (Master Out Slave In) pin for the SPI instance in - /// half-duplex mode. - /// - /// Enables both input and output functionality for the pin, and connects it - /// to the MOSI signal and SIO0 input signal. - pub fn with_mosi( - self, - mosi: impl Peripheral

+ 'd, - ) -> Self { - crate::into_ref!(mosi); - mosi.enable_input(true, private::Internal); - mosi.enable_output(true, private::Internal); - - mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); - mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); - - self - } - - /// Assign the MISO (Master In Slave Out) pin for the SPI instance in - /// half-duplex mode. - /// - /// Enables both input and output functionality for the pin, and connects it - /// to the MISO signal and SIO1 input signal. - pub fn with_miso( - self, - miso: impl Peripheral

+ 'd, - ) -> Self { - crate::into_ref!(miso); - miso.enable_input(true, private::Internal); - miso.enable_output(true, private::Internal); - - miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); - miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); - - self - } - /// Assign the SIO2 pin for the SPI instance. /// /// Enables both input and output functionality for the pin, and connects it @@ -738,13 +633,19 @@ where pub fn with_sio2( self, sio2: impl Peripheral

+ 'd, - ) -> Self { + ) -> Self + where + T: QspiInstance, + { crate::into_ref!(sio2); sio2.enable_input(true, private::Internal); sio2.enable_output(true, private::Internal); - sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal); - sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); + sio2.connect_input_to_peripheral(unwrap!(self.spi.sio2_input_signal()), private::Internal); + sio2.connect_peripheral_to_output( + unwrap!(self.spi.sio2_output_signal()), + private::Internal, + ); self } @@ -756,75 +657,37 @@ where pub fn with_sio3( self, sio3: impl Peripheral

+ 'd, - ) -> Self { + ) -> Self + where + T: QspiInstance, + { crate::into_ref!(sio3); sio3.enable_input(true, private::Internal); sio3.enable_output(true, private::Internal); - sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); - sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); - - self - } - - /// Setup pins for this SPI instance. - /// - /// All pins are optional. Pass [crate::gpio::NoPin] if you don't need the - /// given pin. - pub fn with_pins< - SCK: PeripheralOutput, - MOSI: PeripheralOutput + PeripheralInput, - MISO: PeripheralOutput + PeripheralInput, - SIO2: PeripheralOutput + PeripheralInput, - SIO3: PeripheralOutput + PeripheralInput, - CS: PeripheralOutput, - >( - self, - sck: impl Peripheral

+ 'd, - mosi: impl Peripheral

+ 'd, - miso: impl Peripheral

+ 'd, - sio2: impl Peripheral

+ 'd, - sio3: impl Peripheral

+ 'd, - cs: impl Peripheral

+ 'd, - ) -> Self { - self.with_sck(sck) - .with_mosi(mosi) - .with_miso(miso) - .with_sio2(sio2) - .with_sio3(sio3) - .with_cs(cs) - } - /// Change the bus frequency of the SPI instance in half-duplex mode. - /// - /// This method allows you to update the bus frequency for the SPI - /// communication after the instance has been created. - pub fn change_bus_frequency(&mut self, frequency: HertzU32) { - self.spi.ch_bus_freq(frequency); - } + sio3.connect_input_to_peripheral(unwrap!(self.spi.sio3_input_signal()), private::Internal); + sio3.connect_peripheral_to_output( + unwrap!(self.spi.sio3_output_signal()), + private::Internal, + ); - /// Set the bit order for the SPI instance. - /// - /// The default is MSB first for both read and write. - pub fn with_bit_order(mut self, read_order: SpiBitOrder, write_order: SpiBitOrder) -> Self { - self.spi.set_bit_order(read_order, write_order); self } } -impl HalfDuplexReadWrite for Spi<'_, HalfDuplexMode, T> +impl Spi<'_, T> where T: Instance, { - type Error = Error; - - fn read( + /// Half-duplex read. + pub fn half_duplex_read( &mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, buffer: &mut [u8], - ) -> Result<(), Self::Error> { + ) -> Result<(), Error> { if buffer.len() > FIFO_SIZE { return Err(Error::FifoSizeExeeded); } @@ -849,14 +712,15 @@ where self.spi.read_bytes_from_fifo(buffer) } - fn write( + /// Half-duplex write. + pub fn half_duplex_write( &mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, buffer: &[u8], - ) -> Result<(), Self::Error> { + ) -> Result<(), Error> { if buffer.len() > FIFO_SIZE { return Err(Error::FifoSizeExeeded); } @@ -902,7 +766,7 @@ where } } -impl embedded_hal_02::spi::FullDuplex for Spi<'_, FullDuplexMode, T> +impl embedded_hal_02::spi::FullDuplex for Spi<'_, T> where T: Instance, { @@ -917,7 +781,7 @@ where } } -impl embedded_hal_02::blocking::spi::Transfer for Spi<'_, FullDuplexMode, T> +impl embedded_hal_02::blocking::spi::Transfer for Spi<'_, T> where T: Instance, { @@ -928,7 +792,7 @@ where } } -impl embedded_hal_02::blocking::spi::Write for Spi<'_, FullDuplexMode, T> +impl embedded_hal_02::blocking::spi::Write for Spi<'_, T> where T: Instance, { @@ -971,10 +835,9 @@ mod dma { /// [`SpiDmaBus`] via `with_buffers` to get access /// to a DMA capable SPI bus that implements the /// embedded-hal traits. - pub struct SpiDma<'d, D, M, T = AnySpi> + pub struct SpiDma<'d, M, T = AnySpi> where T: InstanceDma, - D: DuplexMode, M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, @@ -983,22 +846,19 @@ mod dma { rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] address_buffer: DmaTxBuf, - _mode: PhantomData, } #[cfg(all(esp32, spi_address_workaround))] - unsafe impl<'d, D, M, T> Send for SpiDma<'d, D, M, T> + unsafe impl<'d, M, T> Send for SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { } - impl<'d, D, M, T> core::fmt::Debug for SpiDma<'d, D, M, T> + impl<'d, M, T> core::fmt::Debug for SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { /// Formats the `SpiDma` instance for debugging purposes. @@ -1010,10 +870,9 @@ mod dma { } } - impl<'d, D, M, T> SpiDma<'d, D, M, T> + impl<'d, M, T> SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self @@ -1044,7 +903,6 @@ mod dma { address_buffer, tx_transfer_in_progress: false, rx_transfer_in_progress: false, - _mode: PhantomData, } } @@ -1218,18 +1076,16 @@ mod dma { } } - impl<'d, D, M, T> crate::private::Sealed for SpiDma<'d, D, M, T> + impl<'d, M, T> crate::private::Sealed for SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { } - impl<'d, D, M, T> InterruptConfigurable for SpiDma<'d, D, M, T> + impl<'d, M, T> InterruptConfigurable for SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { /// Configures the interrupt handler for the DMA-enabled SPI instance. @@ -1238,10 +1094,9 @@ mod dma { } } - impl<'d, D, M, T> SpiDma<'d, D, M, T> + impl<'d, M, T> SpiDma<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { /// Changes the SPI bus frequency for the DMA-enabled SPI instance. @@ -1258,7 +1113,7 @@ mod dma { self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf, - ) -> SpiDmaBus<'d, D, M, T> { + ) -> SpiDmaBus<'d, M, T> { SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf) } } @@ -1267,23 +1122,21 @@ mod dma { /// /// This structure holds references to the SPI instance, DMA buffers, and /// transfer status. - pub struct SpiDmaTransfer<'d, D, M, Buf, T = AnySpi> + pub struct SpiDmaTransfer<'d, M, Buf, T = AnySpi> where T: InstanceDma, - D: DuplexMode, M: Mode, { - spi_dma: ManuallyDrop>, + spi_dma: ManuallyDrop>, dma_buf: ManuallyDrop, } - impl<'d, D, M, T, Buf> SpiDmaTransfer<'d, D, M, Buf, T> + impl<'d, M, T, Buf> SpiDmaTransfer<'d, M, Buf, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { - fn new(spi_dma: SpiDma<'d, D, M, T>, dma_buf: Buf) -> Self { + fn new(spi_dma: SpiDma<'d, M, T>, dma_buf: Buf) -> Self { Self { spi_dma: ManuallyDrop::new(spi_dma), dma_buf: ManuallyDrop::new(dma_buf), @@ -1302,7 +1155,7 @@ mod dma { /// /// This method blocks until the transfer is finished and returns the /// `SpiDma` instance and the associated buffer. - pub fn wait(mut self) -> (SpiDma<'d, D, M, T>, Buf) { + pub fn wait(mut self) -> (SpiDma<'d, M, T>, Buf) { self.spi_dma.wait_for_idle(); let retval = unsafe { ( @@ -1322,10 +1175,9 @@ mod dma { } } - impl<'d, D, M, T, Buf> Drop for SpiDmaTransfer<'d, D, M, Buf, T> + impl<'d, M, T, Buf> Drop for SpiDmaTransfer<'d, M, Buf, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { fn drop(&mut self) { @@ -1341,10 +1193,9 @@ mod dma { } } - impl<'d, T, D, Buf> SpiDmaTransfer<'d, D, crate::Async, Buf, T> + impl<'d, T, Buf> SpiDmaTransfer<'d, crate::Async, Buf, T> where T: InstanceDma, - D: DuplexMode, { /// Waits for the DMA transfer to complete asynchronously. /// @@ -1354,7 +1205,7 @@ mod dma { } } - impl<'d, M, T> SpiDma<'d, FullDuplexMode, M, T> + impl<'d, M, T> SpiDma<'d, M, T> where T: InstanceDma, M: Mode, @@ -1389,7 +1240,7 @@ mod dma { pub fn dma_write( mut self, mut buffer: TX, - ) -> Result, (Error, Self, TX)> { + ) -> Result, (Error, Self, TX)> { self.wait_for_idle(); match unsafe { self.start_dma_write(&mut buffer) } { @@ -1428,7 +1279,7 @@ mod dma { pub fn dma_read( mut self, mut buffer: RX, - ) -> Result, (Error, Self, RX)> { + ) -> Result, (Error, Self, RX)> { self.wait_for_idle(); match unsafe { self.start_dma_read(&mut buffer) } { Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)), @@ -1467,8 +1318,7 @@ mod dma { mut self, mut rx_buffer: RX, mut tx_buffer: TX, - ) -> Result, (Error, Self, RX, TX)> - { + ) -> Result, (Error, Self, RX, TX)> { self.wait_for_idle(); match unsafe { self.start_dma_transfer(&mut rx_buffer, &mut tx_buffer) } { Ok(_) => Ok(SpiDmaTransfer::new(self, (rx_buffer, tx_buffer))), @@ -1477,7 +1327,7 @@ mod dma { } } - impl<'d, M, T> SpiDma<'d, HalfDuplexMode, M, T> + impl<'d, M, T> SpiDma<'d, M, T> where T: InstanceDma, M: Mode, @@ -1522,14 +1372,14 @@ mod dma { /// Perform a half-duplex read operation using DMA. #[allow(clippy::type_complexity)] #[cfg_attr(place_spi_driver_in_ram, ram)] - pub fn read( + pub fn half_duplex_read( mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, mut buffer: RX, - ) -> Result, (Error, Self, RX)> { + ) -> Result, (Error, Self, RX)> { self.wait_for_idle(); match unsafe { @@ -1589,14 +1439,14 @@ mod dma { /// Perform a half-duplex write operation using DMA. #[allow(clippy::type_complexity)] #[cfg_attr(place_spi_driver_in_ram, ram)] - pub fn write( + pub fn half_duplex_write( mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, mut buffer: TX, - ) -> Result, (Error, Self, TX)> { + ) -> Result, (Error, Self, TX)> { self.wait_for_idle(); match unsafe { @@ -1612,26 +1462,25 @@ mod dma { /// /// This structure is responsible for managing SPI transfers using DMA /// buffers. - pub struct SpiDmaBus<'d, D, M, T = AnySpi> + pub struct SpiDmaBus<'d, M, T = AnySpi> where T: InstanceDma, - D: DuplexMode, + M: Mode, { - spi_dma: SpiDma<'d, D, M, T>, + spi_dma: SpiDma<'d, M, T>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf, } - impl<'d, D, M, T> SpiDmaBus<'d, D, M, T> + impl<'d, M, T> SpiDmaBus<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { /// Creates a new `SpiDmaBus` with the specified SPI instance and DMA /// buffers. - pub fn new(spi_dma: SpiDma<'d, D, M, T>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self { + pub fn new(spi_dma: SpiDma<'d, M, T>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self { Self { spi_dma, rx_buf, @@ -1680,10 +1529,9 @@ mod dma { } } - impl<'d, D, M, T> InterruptConfigurable for SpiDmaBus<'d, D, M, T> + impl<'d, M, T> InterruptConfigurable for SpiDmaBus<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { /// Configures the interrupt handler for the DMA-enabled SPI instance. @@ -1692,15 +1540,14 @@ mod dma { } } - impl<'d, D, M, T> crate::private::Sealed for SpiDmaBus<'d, D, M, T> + impl<'d, M, T> crate::private::Sealed for SpiDmaBus<'d, M, T> where T: InstanceDma, - D: DuplexMode, M: Mode, { } - impl<'d, M, T> SpiDmaBus<'d, FullDuplexMode, M, T> + impl<'d, M, T> SpiDmaBus<'d, M, T> where T: InstanceDma, M: Mode, @@ -1800,22 +1647,20 @@ mod dma { } } - impl<'d, M, T> HalfDuplexReadWrite for SpiDmaBus<'d, HalfDuplexMode, M, T> + impl<'d, M, T> SpiDmaBus<'d, M, T> where T: InstanceDma, M: Mode, { - type Error = Error; - /// Half-duplex read. - fn read( + pub fn half_duplex_read( &mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, buffer: &mut [u8], - ) -> Result<(), Self::Error> { + ) -> Result<(), Error> { if buffer.len() > self.rx_buf.capacity() { return Err(Error::DmaError(DmaError::Overflow)); } @@ -1841,14 +1686,14 @@ mod dma { } /// Half-duplex write. - fn write( + pub fn half_duplex_write( &mut self, data_mode: SpiDataMode, cmd: Command, address: Address, dummy: u8, buffer: &[u8], - ) -> Result<(), Self::Error> { + ) -> Result<(), Error> { if buffer.len() > self.tx_buf.capacity() { return Err(Error::DmaError(DmaError::Overflow)); } @@ -1871,8 +1716,7 @@ mod dma { } } - impl<'d, T> embedded_hal_02::blocking::spi::Transfer - for SpiDmaBus<'d, FullDuplexMode, crate::Blocking, T> + impl<'d, T> embedded_hal_02::blocking::spi::Transfer for SpiDmaBus<'d, crate::Blocking, T> where T: InstanceDma, { @@ -1884,8 +1728,7 @@ mod dma { } } - impl<'d, T> embedded_hal_02::blocking::spi::Write - for SpiDmaBus<'d, FullDuplexMode, crate::Blocking, T> + impl<'d, T> embedded_hal_02::blocking::spi::Write for SpiDmaBus<'d, crate::Blocking, T> where T: InstanceDma, { @@ -1944,7 +1787,7 @@ mod dma { } } - impl<'d, T> SpiDmaBus<'d, FullDuplexMode, crate::Async, T> + impl<'d, T> SpiDmaBus<'d, crate::Async, T> where T: InstanceDma, { @@ -2058,7 +1901,7 @@ mod dma { } } - impl<'d, T> embedded_hal_async::spi::SpiBus for SpiDmaBus<'d, FullDuplexMode, crate::Async, T> + impl<'d, T> embedded_hal_async::spi::SpiBus for SpiDmaBus<'d, crate::Async, T> where T: InstanceDma, { @@ -2090,7 +1933,7 @@ mod dma { use super::*; - impl<'d, M, T> ErrorType for SpiDmaBus<'d, FullDuplexMode, M, T> + impl<'d, M, T> ErrorType for SpiDmaBus<'d, M, T> where T: InstanceDma, M: Mode, @@ -2098,7 +1941,7 @@ mod dma { type Error = Error; } - impl<'d, M, T> SpiBus for SpiDmaBus<'d, FullDuplexMode, M, T> + impl<'d, M, T> SpiBus for SpiDmaBus<'d, M, T> where T: InstanceDma, M: Mode, @@ -2133,11 +1976,11 @@ mod ehal1 { use super::*; - impl embedded_hal::spi::ErrorType for Spi<'_, M, T> { + impl embedded_hal::spi::ErrorType for Spi<'_, T> { type Error = Error; } - impl FullDuplex for Spi<'_, FullDuplexMode, T> + impl FullDuplex for Spi<'_, T> where T: Instance, { @@ -2150,7 +1993,7 @@ mod ehal1 { } } - impl SpiBus for Spi<'_, FullDuplexMode, T> + impl SpiBus for Spi<'_, T> where T: Instance, { @@ -2356,33 +2199,22 @@ impl InstanceDma for crate::peripherals::SPI2 {} #[cfg(spi3)] impl InstanceDma for crate::peripherals::SPI3 {} -#[doc(hidden)] -pub trait ExtendedInstance: Instance { - fn sio0_input_signal(&self) -> InputSignal; - - fn sio1_output_signal(&self) -> OutputSignal; - - fn sio2_output_signal(&self) -> OutputSignal; - - fn sio2_input_signal(&self) -> InputSignal; - - fn sio3_output_signal(&self) -> OutputSignal; - - fn sio3_input_signal(&self) -> InputSignal; -} - #[doc(hidden)] pub trait Instance: private::Sealed + PeripheralMarker { fn register_block(&self) -> &RegisterBlock; fn sclk_signal(&self) -> OutputSignal; - fn mosi_signal(&self) -> OutputSignal; - fn miso_signal(&self) -> InputSignal; - fn cs_signal(&self) -> OutputSignal; + fn sio0_input_signal(&self) -> InputSignal; + fn sio1_output_signal(&self) -> OutputSignal; + fn sio2_output_signal(&self) -> Option; + fn sio2_input_signal(&self) -> Option; + fn sio3_output_signal(&self) -> Option; + fn sio3_input_signal(&self) -> Option; + #[inline(always)] fn enable_peripheral(&self) { PeripheralClockControl::enable(self.peripheral()); @@ -3011,6 +2843,9 @@ pub trait Instance: private::Sealed + PeripheralMarker { } } +#[doc(hidden)] +pub trait QspiInstance: Instance {} + fn set_up_common_phases(reg_block: &RegisterBlock, cmd: Command, address: Address, dummy: u8) { if !cmd.is_none() { reg_block.user2().modify(|_, w| unsafe { @@ -3040,269 +2875,113 @@ fn set_up_common_phases(reg_block: &RegisterBlock, cmd: Command, address: Addres } } -#[cfg(spi2)] -impl Instance for crate::peripherals::SPI2 { - #[inline(always)] - fn register_block(&self) -> &RegisterBlock { - self - } +macro_rules! spi_instance { + ($num:literal, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident, $sio0:ident, $sio1:ident $(, $sio2:ident, $sio3:ident)?) => { + paste::paste! { + impl Instance for crate::peripherals::[] { + #[inline(always)] + fn register_block(&self) -> &RegisterBlock { + self + } - #[inline(always)] - fn spi_num(&self) -> u8 { - 2 - } + #[inline(always)] + fn spi_num(&self) -> u8 { + $num + } - #[inline(always)] - fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - self.bind_spi2_interrupt(handler.handler()); - crate::interrupt::enable(crate::peripherals::Interrupt::SPI2, handler.priority()).unwrap(); - } + #[inline(always)] + fn set_interrupt_handler(&mut self, handler: InterruptHandler) { + self.[](handler.handler()); + crate::interrupt::enable(crate::peripherals::Interrupt::[], handler.priority()).unwrap(); + } - #[inline(always)] - fn sclk_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPICLK - } else if #[cfg(any(esp32s2, esp32s3))] { - OutputSignal::FSPICLK - } else { - OutputSignal::FSPICLK_MUX - } - } - } + #[inline(always)] + fn sclk_signal(&self) -> OutputSignal { + OutputSignal::$sclk + } - #[inline(always)] - fn mosi_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPID - } else { - OutputSignal::FSPID - } - } - } + #[inline(always)] + fn mosi_signal(&self) -> OutputSignal { + OutputSignal::$mosi + } - #[inline(always)] - fn miso_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPIQ - } else { - InputSignal::FSPIQ - } - } - } + #[inline(always)] + fn miso_signal(&self) -> InputSignal { + InputSignal::$miso + } - #[inline(always)] - fn cs_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPICS0 - } else { - OutputSignal::FSPICS0 - } - } - } -} + #[inline(always)] + fn cs_signal(&self) -> OutputSignal { + OutputSignal::$cs + } -#[cfg(spi2)] -impl ExtendedInstance for crate::peripherals::SPI2 { - #[inline(always)] - fn sio0_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPID - } else { - InputSignal::FSPID - } - } - } + #[inline(always)] + fn sio0_input_signal(&self) -> InputSignal { + InputSignal::$sio0 + } - #[inline(always)] - fn sio1_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIQ - } else { - OutputSignal::FSPIQ - } - } - } + #[inline(always)] + fn sio1_output_signal(&self) -> OutputSignal { + OutputSignal::$sio1 + } - #[inline(always)] - fn sio2_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIWP - } else { - OutputSignal::FSPIWP - } - } - } + #[inline(always)] + fn sio2_output_signal(&self) -> Option { + if_set!($(Some(OutputSignal::$sio2))?, None) + } - #[inline(always)] - fn sio2_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPIWP - } else { - InputSignal::FSPIWP - } - } - } + #[inline(always)] + fn sio2_input_signal(&self) -> Option { + if_set!($(Some(InputSignal::$sio2))?, None) + } - #[inline(always)] - fn sio3_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIHD - } else { - OutputSignal::FSPIHD - } - } - } + #[inline(always)] + fn sio3_output_signal(&self) -> Option { + if_set!($(Some(OutputSignal::$sio3))?, None) + } - #[inline(always)] - fn sio3_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPIHD - } else { - InputSignal::FSPIHD + #[inline(always)] + fn sio3_input_signal(&self) -> Option { + if_set!($(Some(InputSignal::$sio3))?, None) + } } } } } -#[cfg(spi3)] -impl Instance for crate::peripherals::SPI3 { - #[inline(always)] - fn register_block(&self) -> &RegisterBlock { - self - } - - #[inline(always)] - fn spi_num(&self) -> u8 { - 3 - } - - #[inline(always)] - fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - self.bind_spi3_interrupt(handler.handler()); - crate::interrupt::enable(crate::peripherals::Interrupt::SPI3, handler.priority()).unwrap(); - } - - #[inline(always)] - fn sclk_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::VSPICLK - } else { - OutputSignal::SPI3_CLK - } - } - } - - #[inline(always)] - fn mosi_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::VSPID - } else { - OutputSignal::SPI3_D - } - } - } - - #[inline(always)] - fn miso_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::VSPIQ - } else { - InputSignal::SPI3_Q - } - } - } - - #[inline(always)] - fn cs_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::VSPICS0 - } else { - OutputSignal::SPI3_CS0 - } - } - } +macro_rules! if_set { + (, $not_set:expr) => { + $not_set + }; + ($set:expr, $not_set:expr) => { + $set + }; } -#[cfg(all(spi3, any(esp32, esp32s3)))] -impl ExtendedInstance for crate::peripherals::SPI3 { - #[inline(always)] - fn sio0_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPID - } else { - InputSignal::SPI3_D - } - } - } - - #[inline(always)] - fn sio1_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIQ - } else { - OutputSignal::SPI3_Q - } - } - } - - #[inline(always)] - fn sio2_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIWP - } else { - OutputSignal::SPI3_WP - } - } - } - - #[inline(always)] - fn sio2_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPIWP - } else { - InputSignal::SPI3_WP - } - } - } - - #[inline(always)] - fn sio3_output_signal(&self) -> OutputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - OutputSignal::HSPIHD - } else { - OutputSignal::SPI3_HD - } - } +#[cfg(spi2)] +cfg_if::cfg_if! { + if #[cfg(esp32)] { + spi_instance!(2, HSPICLK, HSPID, HSPIQ, HSPICS0, HSPID, HSPIQ, HSPIWP, HSPIHD); + impl QspiInstance for crate::peripherals::SPI2 {} + } else if #[cfg(any(esp32s2, esp32s3))] { + spi_instance!(2, FSPICLK, FSPID, FSPIQ, FSPICS0, FSPID, FSPIQ, FSPIWP, FSPIHD); + impl QspiInstance for crate::peripherals::SPI2 {} + } else { + spi_instance!(2, FSPICLK_MUX, FSPID, FSPIQ, FSPICS0, FSPID, FSPIQ, FSPIWP, FSPIHD); + impl QspiInstance for crate::peripherals::SPI2 {} } +} - #[inline(always)] - fn sio3_input_signal(&self) -> InputSignal { - cfg_if::cfg_if! { - if #[cfg(esp32)] { - InputSignal::HSPIHD - } else { - InputSignal::SPI3_HD - } - } +#[cfg(spi3)] +cfg_if::cfg_if! { + if #[cfg(esp32)] { + spi_instance!(3, VSPICLK, VSPID, VSPIQ, VSPICS0, HSPID, HSPIQ, HSPIWP, HSPIHD); + impl QspiInstance for crate::peripherals::SPI3 {} + } else if #[cfg(esp32s3)] { + spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, SPI3_CS0, SPI3_D, SPI3_Q, SPI3_WP, SPI3_HD); + impl QspiInstance for crate::peripherals::SPI3 {} + } else { + spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, SPI3_CS0, SPI3_D, SPI3_Q); } } @@ -3319,6 +2998,13 @@ impl Instance for super::AnySpi { fn mosi_signal(&self) -> OutputSignal; fn miso_signal(&self) -> InputSignal; fn cs_signal(&self) -> OutputSignal; + + fn sio0_input_signal(&self) -> InputSignal; + fn sio1_output_signal(&self) -> OutputSignal; + fn sio2_output_signal(&self) -> Option; + fn sio2_input_signal(&self) -> Option; + fn sio3_output_signal(&self) -> Option; + fn sio3_input_signal(&self) -> Option; } } delegate::delegate! { @@ -3332,79 +3018,7 @@ impl Instance for super::AnySpi { } } -impl ExtendedInstance for super::AnySpi { - fn sio0_input_signal(&self) -> InputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio0_input_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio0_input_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } - - fn sio1_output_signal(&self) -> OutputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio1_output_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio1_output_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } - - fn sio2_output_signal(&self) -> OutputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio2_output_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio2_output_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } - - fn sio2_input_signal(&self) -> InputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio2_input_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio2_input_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } - - fn sio3_output_signal(&self) -> OutputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio3_output_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio3_output_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } - - fn sio3_input_signal(&self) -> InputSignal { - match &self.0 { - super::AnySpiInner::Spi2(spi) => spi.sio3_input_signal(), - - #[cfg(all(spi3, any(esp32, esp32s3)))] - super::AnySpiInner::Spi3(spi) => spi.sio3_input_signal(), - - #[cfg(all(spi3, not(any(esp32, esp32s3))))] - super::AnySpiInner::Spi3(_) => unimplemented!("SPI3 is does not support QSPI"), - } - } -} +impl QspiInstance for super::AnySpi {} impl InstanceDma for super::AnySpi { delegate::delegate! { diff --git a/esp-hal/src/spi/mod.rs b/esp-hal/src/spi/mod.rs index ff530590116..7ac8b313ae1 100644 --- a/esp-hal/src/spi/mod.rs +++ b/esp-hal/src/spi/mod.rs @@ -76,9 +76,6 @@ pub enum SpiBitOrder { LSBFirst, } -/// Trait marker for defining SPI duplex modes. -pub trait DuplexMode: crate::private::Sealed {} - /// SPI data mode #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -91,16 +88,6 @@ pub enum SpiDataMode { Quad, } -/// Full-duplex operation -pub struct FullDuplexMode {} -impl DuplexMode for FullDuplexMode {} -impl crate::private::Sealed for FullDuplexMode {} - -/// Half-duplex operation -pub struct HalfDuplexMode {} -impl DuplexMode for HalfDuplexMode {} -impl crate::private::Sealed for HalfDuplexMode {} - crate::any_peripheral! { /// Any SPI peripheral. pub peripheral AnySpi { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index bd0bc183b4c..c9ee481b292 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -69,9 +69,8 @@ //! `is_done()`. //! //! See [tracking issue](https://github.com/esp-rs/esp-hal/issues/469) for more information. -use core::marker::PhantomData; -use super::{Error, FullDuplexMode, SpiMode}; +use super::{Error, SpiMode}; use crate::{ dma::{DescriptorChain, DmaChannelConvert, DmaEligible, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, @@ -87,14 +86,13 @@ const MAX_DMA_SIZE: usize = 32768 - 32; /// SPI peripheral driver. /// /// See the [module-level documentation][self] for more details. -pub struct Spi<'d, M, T = AnySpi> { +pub struct Spi<'d, T = AnySpi> { spi: PeripheralRef<'d, T>, #[allow(dead_code)] data_mode: SpiMode, - _mode: PhantomData, } -impl<'d> Spi<'d, FullDuplexMode> { +impl<'d> Spi<'d> { /// Constructs an SPI instance in 8bit dataframe mode. pub fn new< SCK: PeripheralInput, @@ -108,12 +106,12 @@ impl<'d> Spi<'d, FullDuplexMode> { miso: impl Peripheral

+ 'd, cs: impl Peripheral

+ 'd, mode: SpiMode, - ) -> Spi<'d, FullDuplexMode> { + ) -> Spi<'d> { Self::new_typed(spi, sclk, mosi, miso, cs, mode) } } -impl<'d, T> Spi<'d, FullDuplexMode, T> +impl<'d, T> Spi<'d, T> where T: Instance, { @@ -130,7 +128,7 @@ where miso: impl Peripheral

+ 'd, cs: impl Peripheral

+ 'd, mode: SpiMode, - ) -> Spi<'d, FullDuplexMode, T> { + ) -> Spi<'d, T> { crate::into_ref!(sclk, mosi, miso, cs); let this = Self::new_internal(spi, mode); @@ -154,13 +152,12 @@ where pub(crate) fn new_internal( spi: impl Peripheral

+ 'd> + 'd, mode: SpiMode, - ) -> Spi<'d, FullDuplexMode, T> { + ) -> Spi<'d, T> { crate::into_ref!(spi); let mut spi = Spi { spi: spi.map_into(), data_mode: mode, - _mode: PhantomData, }; spi.spi.reset_peripheral(); spi.spi.enable_peripheral(); @@ -193,7 +190,7 @@ pub mod dma { Mode, }; - impl<'d, T> Spi<'d, FullDuplexMode, T> + impl<'d, T> Spi<'d, T> where T: InstanceDma, { diff --git a/examples/src/bin/embassy_spi.rs b/examples/src/bin/embassy_spi.rs index 4187226feaf..334cd713764 100644 --- a/examples/src/bin/embassy_spi.rs +++ b/examples/src/bin/embassy_spi.rs @@ -59,7 +59,10 @@ async fn main(_spawner: Spawner) { let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - .with_pins(sclk, mosi, miso, cs) + .with_sck(sclk) + .with_mosi(mosi) + .with_miso(miso) + .with_cs(cs) .with_dma(dma_channel.configure_for_async(false, DmaPriority::Priority0)) .with_buffers(dma_rx_buf, dma_tx_buf); diff --git a/examples/src/bin/qspi_flash.rs b/examples/src/bin/qspi_flash.rs index 036a17d3998..687b28ba18f 100644 --- a/examples/src/bin/qspi_flash.rs +++ b/examples/src/bin/qspi_flash.rs @@ -79,8 +79,13 @@ fn main() -> ! { let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - .with_pins(sclk, mosi, miso, sio2, sio3, cs) + let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + .with_sck(sclk) + .with_mosi(mosi) + .with_miso(miso) + .with_sio2(sio2) + .with_sio3(sio3) + .with_cs(cs) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); let delay = Delay::new(); @@ -88,7 +93,7 @@ fn main() -> ! { // write enable dma_tx_buf.set_length(0); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::Command8(0x06, SpiDataMode::Single), Address::None, @@ -102,7 +107,7 @@ fn main() -> ! { // erase sector let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::Command8(0x20, SpiDataMode::Single), Address::Address24(0x000000, SpiDataMode::Single), @@ -116,7 +121,7 @@ fn main() -> ! { // write enable let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::Command8(0x06, SpiDataMode::Single), Address::None, @@ -133,7 +138,7 @@ fn main() -> ! { dma_tx_buf.as_mut_slice().fill(b'!'); dma_tx_buf.as_mut_slice()[0..][..5].copy_from_slice(&b"Hello"[..]); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Quad, Command::Command8(0x32, SpiDataMode::Single), Address::Address24(0x000000, SpiDataMode::Single), @@ -148,7 +153,7 @@ fn main() -> ! { loop { // quad fast read let transfer = spi - .read( + .half_duplex_read( SpiDataMode::Quad, Command::Command8(0xeb, SpiDataMode::Single), Address::Address32(0x000000 << 8, SpiDataMode::Quad), diff --git a/examples/src/bin/spi_halfduplex_read_manufacturer_id.rs b/examples/src/bin/spi_halfduplex_read_manufacturer_id.rs index 4bd36151707..c6dba002afc 100644 --- a/examples/src/bin/spi_halfduplex_read_manufacturer_id.rs +++ b/examples/src/bin/spi_halfduplex_read_manufacturer_id.rs @@ -33,7 +33,7 @@ use esp_hal::{ gpio::Io, prelude::*, spi::{ - master::{Address, Command, HalfDuplexReadWrite, Spi}, + master::{Address, Command, Spi}, SpiDataMode, SpiMode, }, @@ -63,15 +63,20 @@ fn main() -> ! { } } - let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - .with_pins(sclk, mosi, miso, sio2, sio3, cs); + let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + .with_sck(sclk) + .with_mosi(mosi) + .with_miso(miso) + .with_sio2(sio2) + .with_sio3(sio3) + .with_cs(cs); let delay = Delay::new(); loop { // READ MANUFACTURER ID FROM FLASH CHIP let mut data = [0u8; 2]; - spi.read( + spi.half_duplex_read( SpiDataMode::Single, Command::Command8(0x90, SpiDataMode::Single), Address::Address24(0x000000, SpiDataMode::Single), @@ -84,7 +89,7 @@ fn main() -> ! { // READ MANUFACTURER ID FROM FLASH CHIP let mut data = [0u8; 2]; - spi.read( + spi.half_duplex_read( SpiDataMode::Dual, Command::Command8(0x92, SpiDataMode::Single), Address::Address32(0x000000_00, SpiDataMode::Dual), @@ -97,7 +102,7 @@ fn main() -> ! { // READ MANUFACTURER ID FROM FLASH CHIP let mut data = [0u8; 2]; - spi.read( + spi.half_duplex_read( SpiDataMode::Quad, Command::Command8(0x94, SpiDataMode::Single), Address::Address32(0x000000_00, SpiDataMode::Quad), diff --git a/examples/src/bin/spi_loopback.rs b/examples/src/bin/spi_loopback.rs index 613cbaceca8..0900d031d9f 100644 --- a/examples/src/bin/spi_loopback.rs +++ b/examples/src/bin/spi_loopback.rs @@ -19,6 +19,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, gpio::Io, + peripheral::Peripheral, prelude::*, spi::{master::Spi, SpiMode}, }; @@ -33,11 +34,13 @@ fn main() -> ! { let miso_mosi = io.pins.gpio2; let cs = io.pins.gpio5; - let miso = miso_mosi.peripheral_input(); - let mosi = miso_mosi.into_peripheral_output(); + let miso = unsafe { miso_mosi.clone_unchecked() }; - let mut spi = - Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0).with_pins(sclk, mosi, miso, cs); + let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + .with_sck(sclk) + .with_mosi(miso_mosi) + .with_miso(miso) + .with_cs(cs); let delay = Delay::new(); diff --git a/examples/src/bin/spi_loopback_dma.rs b/examples/src/bin/spi_loopback_dma.rs index 50faea72910..00e321a1ebc 100644 --- a/examples/src/bin/spi_loopback_dma.rs +++ b/examples/src/bin/spi_loopback_dma.rs @@ -54,7 +54,10 @@ fn main() -> ! { let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - .with_pins(sclk, mosi, miso, cs) + .with_sck(sclk) + .with_mosi(mosi) + .with_miso(miso) + .with_cs(cs) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); let delay = Delay::new(); diff --git a/examples/src/bin/spi_loopback_dma_psram.rs b/examples/src/bin/spi_loopback_dma_psram.rs index 250123752d5..942609f4234 100644 --- a/examples/src/bin/spi_loopback_dma_psram.rs +++ b/examples/src/bin/spi_loopback_dma_psram.rs @@ -88,7 +88,10 @@ fn main() -> ! { ); let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) - .with_pins(sclk, mosi, miso, cs) + .with_sck(sclk) + .with_mosi(mosi) + .with_miso(miso) + .with_cs(cs) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); delay.delay_millis(100); // delay to let the above messages display diff --git a/hil-test/tests/embassy_interrupt_spi_dma.rs b/hil-test/tests/embassy_interrupt_spi_dma.rs index 9c8c40a4a30..f5b3ea6cba5 100644 --- a/hil-test/tests/embassy_interrupt_spi_dma.rs +++ b/hil-test/tests/embassy_interrupt_spi_dma.rs @@ -15,7 +15,6 @@ use esp_hal::{ prelude::*, spi::{ master::{Spi, SpiDma}, - FullDuplexMode, SpiMode, }, timer::{timg::TimerGroup, AnyTimer}, @@ -34,7 +33,7 @@ macro_rules! mk_static { } #[embassy_executor::task] -async fn interrupt_driven_task(spi: SpiDma<'static, FullDuplexMode, Async>) { +async fn interrupt_driven_task(spi: SpiDma<'static, Async>) { let mut ticker = Ticker::every(Duration::from_millis(1)); let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(128); diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index fa0d1819600..641098f1a62 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -10,11 +10,10 @@ use esp_hal::pcnt::{channel::EdgeMode, unit::Unit, Pcnt}; use esp_hal::{ dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{AnyPin, Input, Io, Level, NoPin, Output, Pull}, + gpio::{AnyPin, Input, Io, Level, Output, Pull}, prelude::*, spi::{ master::{Address, Command, Spi, SpiDma}, - HalfDuplexMode, SpiDataMode, SpiMode, }, @@ -38,7 +37,7 @@ cfg_if::cfg_if! { } } -type SpiUnderTest = SpiDma<'static, HalfDuplexMode, Blocking>; +type SpiUnderTest = SpiDma<'static, Blocking>; struct Context { spi: esp_hal::peripherals::SPI2, @@ -54,7 +53,7 @@ fn transfer_read( command: Command, ) -> (SpiUnderTest, DmaRxBuf) { let transfer = spi - .read(SpiDataMode::Quad, command, Address::None, 0, dma_rx_buf) + .half_duplex_read(SpiDataMode::Quad, command, Address::None, 0, dma_rx_buf) .map_err(|e| e.0) .unwrap(); transfer.wait() @@ -67,7 +66,7 @@ fn transfer_write( command_data_mode: SpiDataMode, ) -> (SpiUnderTest, DmaTxBuf) { let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Quad, Command::Command8(write as u16, command_data_mode), Address::Address24( @@ -226,8 +225,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, pin, NoPin, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(pin) .with_dma(ctx.dma_channel); super::execute_read(spi, pin_mirror, 0b0001_0001); @@ -239,8 +238,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, pin, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_miso(pin) .with_dma(ctx.dma_channel); super::execute_read(spi, pin_mirror, 0b0010_0010); @@ -252,8 +251,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, NoPin, pin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_sio2(pin) .with_dma(ctx.dma_channel); super::execute_read(spi, pin_mirror, 0b0100_0100); @@ -265,8 +264,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, NoPin, NoPin, pin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_sio3(pin) .with_dma(ctx.dma_channel); super::execute_read(spi, pin_mirror, 0b1000_1000); @@ -278,8 +277,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, pin, NoPin, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(pin) .with_dma(ctx.dma_channel); super::execute_write_read(spi, pin_mirror, 0b0001_0001); @@ -291,8 +290,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, pin, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_miso(pin) .with_dma(ctx.dma_channel); super::execute_write_read(spi, pin_mirror, 0b0010_0010); @@ -304,8 +303,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, NoPin, pin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_sio2(pin) .with_dma(ctx.dma_channel); super::execute_write_read(spi, pin_mirror, 0b0100_0100); @@ -317,8 +316,8 @@ mod tests { let [pin, pin_mirror, _] = ctx.gpios; let pin_mirror = Output::new(pin_mirror, Level::High); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, NoPin, NoPin, NoPin, pin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_sio3(pin) .with_dma(ctx.dma_channel); super::execute_write_read(spi, pin_mirror, 0b1000_1000); @@ -341,8 +340,8 @@ mod tests { .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, mosi, NoPin, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(mosi) .with_dma(ctx.dma_channel); super::execute_write(unit0, unit1, spi, 0b0000_0001, false); @@ -370,8 +369,9 @@ mod tests { .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, mosi, gpio, NoPin, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(mosi) + .with_miso(gpio) .with_dma(ctx.dma_channel); super::execute_write(unit0, unit1, spi, 0b0000_0010, true); @@ -399,8 +399,9 @@ mod tests { .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, mosi, NoPin, gpio, NoPin, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(mosi) + .with_sio2(gpio) .with_dma(ctx.dma_channel); super::execute_write(unit0, unit1, spi, 0b0000_0100, true); @@ -428,8 +429,9 @@ mod tests { .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0) - .with_pins(NoPin, mosi, NoPin, NoPin, gpio, NoPin) + let spi = Spi::new(ctx.spi, 100.kHz(), SpiMode::Mode0) + .with_mosi(mosi) + .with_sio3(gpio) .with_dma(ctx.dma_channel); super::execute_write(unit0, unit1, spi, 0b0000_1000, true); diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index b8ab6153b3a..a70b0d8312c 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -15,8 +15,9 @@ use esp_hal::{ dma::{Dma, DmaDescriptor, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{Io, Level, NoPin}, + peripheral::Peripheral, prelude::*, - spi::{master::Spi, FullDuplexMode, SpiMode}, + spi::{master::Spi, SpiMode}, }; #[cfg(pcnt)] use esp_hal::{ @@ -34,7 +35,7 @@ cfg_if::cfg_if! { } struct Context { - spi: Spi<'static, FullDuplexMode>, + spi: Spi<'static>, dma_channel: DmaChannelCreator, // Reuse the really large buffer so we don't run out of DRAM with many tests rx_buffer: &'static mut [u8], @@ -72,11 +73,10 @@ mod tests { #[cfg(pcnt)] let mosi_loopback_pcnt = mosi.peripheral_input(); - let mosi_loopback = mosi.peripheral_input(); let spi = Spi::new(peripherals.SPI2, 10000.kHz(), SpiMode::Mode0) .with_sck(sclk) - .with_mosi(mosi) - .with_miso(mosi_loopback); + .with_mosi(unsafe { mosi.clone_unchecked() }) + .with_miso(mosi); let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000); diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index 63d786a9cd6..a50fa0dc807 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -11,8 +11,7 @@ use esp_hal::{ gpio::{Io, Level, Output}, prelude::*, spi::{ - master::{Address, Command, HalfDuplexReadWrite, Spi, SpiDma}, - HalfDuplexMode, + master::{Address, Command, Spi, SpiDma}, SpiDataMode, SpiMode, }, @@ -21,7 +20,7 @@ use esp_hal::{ use hil_test as _; struct Context { - spi: SpiDma<'static, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, Blocking>, miso_mirror: Output<'static>, } @@ -50,7 +49,7 @@ mod tests { } } - let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_miso(miso) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); @@ -72,7 +71,7 @@ mod tests { let mut spi = ctx.spi; let transfer = spi - .read( + .half_duplex_read( SpiDataMode::Single, Command::None, Address::None, @@ -89,7 +88,7 @@ mod tests { ctx.miso_mirror.set_high(); let transfer = spi - .read( + .half_duplex_read( SpiDataMode::Single, Command::None, Address::None, @@ -120,7 +119,7 @@ mod tests { ctx.miso_mirror.set_low(); let mut buffer = [0xAA; DMA_BUFFER_SIZE]; - spi.read( + spi.half_duplex_read( SpiDataMode::Single, Command::None, Address::None, @@ -134,7 +133,7 @@ mod tests { // SPI should read '1's from the MISO pin ctx.miso_mirror.set_high(); - spi.read( + spi.half_duplex_read( SpiDataMode::Single, Command::None, Address::None, diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index 75b8a89574c..a44dda26070 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -12,8 +12,7 @@ use esp_hal::{ pcnt::{channel::EdgeMode, unit::Unit, Pcnt}, prelude::*, spi::{ - master::{Address, Command, HalfDuplexReadWrite, Spi, SpiDma}, - HalfDuplexMode, + master::{Address, Command, Spi, SpiDma}, SpiDataMode, SpiMode, }, @@ -22,7 +21,7 @@ use esp_hal::{ use hil_test as _; struct Context { - spi: SpiDma<'static, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, Blocking>, pcnt_unit: Unit<'static, 0>, pcnt_source: InputSignal, } @@ -53,7 +52,7 @@ mod tests { let mosi_loopback = mosi.peripheral_input(); - let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); @@ -84,7 +83,7 @@ mod tests { dma_tx_buf.fill(&[0b0110_1010; DMA_BUFFER_SIZE]); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -98,7 +97,7 @@ mod tests { assert_eq!(unit.get_value(), (3 * DMA_BUFFER_SIZE) as _); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -130,7 +129,7 @@ mod tests { let buffer = [0b0110_1010; DMA_BUFFER_SIZE]; // Write the buffer where each byte has 3 pos edges. - spi.write( + spi.half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -141,7 +140,7 @@ mod tests { assert_eq!(unit.get_value(), (3 * DMA_BUFFER_SIZE) as _); - spi.write( + spi.half_duplex_write( SpiDataMode::Single, Command::None, Address::None, diff --git a/hil-test/tests/spi_half_duplex_write_psram.rs b/hil-test/tests/spi_half_duplex_write_psram.rs index d0f9e3cdc09..eea6b6254a6 100644 --- a/hil-test/tests/spi_half_duplex_write_psram.rs +++ b/hil-test/tests/spi_half_duplex_write_psram.rs @@ -14,8 +14,7 @@ use esp_hal::{ pcnt::{channel::EdgeMode, unit::Unit, Pcnt}, prelude::*, spi::{ - master::{Address, Command, HalfDuplexReadWrite, Spi, SpiDma}, - HalfDuplexMode, + master::{Address, Command, Spi, SpiDma}, SpiDataMode, SpiMode, }, @@ -39,7 +38,7 @@ macro_rules! dma_alloc_buffer { } struct Context { - spi: SpiDma<'static, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, Blocking>, pcnt_unit: Unit<'static, 0>, pcnt_source: InputSignal, } @@ -65,7 +64,7 @@ mod tests { let mosi_loopback = mosi.peripheral_input(); - let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) + let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); @@ -99,7 +98,7 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. dma_tx_buf.fill(&[0b0110_1010; DMA_BUFFER_SIZE]); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -113,7 +112,7 @@ mod tests { assert_eq!(unit.get_value(), (3 * DMA_BUFFER_SIZE) as _); let transfer = spi - .write( + .half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -151,7 +150,7 @@ mod tests { let buffer = [0b0110_1010; DMA_BUFFER_SIZE]; // Write the buffer where each byte has 3 pos edges. - spi.write( + spi.half_duplex_write( SpiDataMode::Single, Command::None, Address::None, @@ -162,7 +161,7 @@ mod tests { assert_eq!(unit.get_value(), (3 * DMA_BUFFER_SIZE) as _); - spi.write( + spi.half_duplex_write( SpiDataMode::Single, Command::None, Address::None, diff --git a/hil-test/tests/spi_slave.rs b/hil-test/tests/spi_slave.rs index 08870aea108..c52839167a0 100644 --- a/hil-test/tests/spi_slave.rs +++ b/hil-test/tests/spi_slave.rs @@ -12,7 +12,7 @@ use esp_hal::{ dma::{Dma, DmaPriority}, dma_buffers, gpio::{interconnect::InputSignal, Io, Level, Output, PeripheralInput}, - spi::{slave::Spi, FullDuplexMode, SpiMode}, + spi::{slave::Spi, SpiMode}, }; use hil_test as _; @@ -25,7 +25,7 @@ cfg_if::cfg_if! { } struct Context { - spi: Spi<'static, FullDuplexMode>, + spi: Spi<'static>, dma_channel: DmaChannelCreator, bitbang_spi: BitbangSpi, }