From f5e1c1607fa0dd1d1f7edf14e929c97ce8a9da06 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 12 Dec 2022 16:03:20 +0100 Subject: [PATCH 1/3] Add missing UART instances --- esp-hal-common/src/peripherals/esp32.rs | 1 + esp-hal-common/src/peripherals/esp32s3.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/esp-hal-common/src/peripherals/esp32.rs b/esp-hal-common/src/peripherals/esp32.rs index a785fa76fce..4ace77ecbb1 100644 --- a/esp-hal-common/src/peripherals/esp32.rs +++ b/esp-hal-common/src/peripherals/esp32.rs @@ -54,5 +54,6 @@ mod peripherals { crate::create_peripherals! { UART0, UART1, + UART2, } } diff --git a/esp-hal-common/src/peripherals/esp32s3.rs b/esp-hal-common/src/peripherals/esp32s3.rs index 8edfe1f417c..f852bb7869d 100644 --- a/esp-hal-common/src/peripherals/esp32s3.rs +++ b/esp-hal-common/src/peripherals/esp32s3.rs @@ -63,5 +63,6 @@ mod peripherals { crate::create_peripherals! { UART0, UART1, + UART2, } } From d1d6e0c9ec9e9f8170b8ac72fec7b2d24725dee6 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 12 Dec 2022 16:06:05 +0100 Subject: [PATCH 2/3] Add SPI to list of peripherals to be created --- esp-hal-common/src/peripherals/esp32.rs | 4 ++++ esp-hal-common/src/peripherals/esp32c2.rs | 3 +++ esp-hal-common/src/peripherals/esp32c3.rs | 3 +++ esp-hal-common/src/peripherals/esp32s2.rs | 5 +++++ esp-hal-common/src/peripherals/esp32s3.rs | 4 ++++ 5 files changed, 19 insertions(+) diff --git a/esp-hal-common/src/peripherals/esp32.rs b/esp-hal-common/src/peripherals/esp32.rs index 4ace77ecbb1..704d90415c9 100644 --- a/esp-hal-common/src/peripherals/esp32.rs +++ b/esp-hal-common/src/peripherals/esp32.rs @@ -55,5 +55,9 @@ mod peripherals { UART0, UART1, UART2, + SPI0, + SPI1, + SPI2, + SPI3, } } diff --git a/esp-hal-common/src/peripherals/esp32c2.rs b/esp-hal-common/src/peripherals/esp32c2.rs index 0ccff88a24a..b468890129b 100644 --- a/esp-hal-common/src/peripherals/esp32c2.rs +++ b/esp-hal-common/src/peripherals/esp32c2.rs @@ -36,5 +36,8 @@ mod peripherals { crate::create_peripherals! { UART0, UART1, + SPI0, + SPI1, + SPI2, } } diff --git a/esp-hal-common/src/peripherals/esp32c3.rs b/esp-hal-common/src/peripherals/esp32c3.rs index ed6181fc895..b6b69b2b645 100644 --- a/esp-hal-common/src/peripherals/esp32c3.rs +++ b/esp-hal-common/src/peripherals/esp32c3.rs @@ -47,5 +47,8 @@ mod peripherals { crate::create_peripherals! { UART0, UART1, + SPI0, + SPI1, + SPI2, } } diff --git a/esp-hal-common/src/peripherals/esp32s2.rs b/esp-hal-common/src/peripherals/esp32s2.rs index 7bccc792218..029b57db8db 100644 --- a/esp-hal-common/src/peripherals/esp32s2.rs +++ b/esp-hal-common/src/peripherals/esp32s2.rs @@ -52,5 +52,10 @@ mod peripherals { crate::create_peripherals! { UART0, UART1, + SPI0, + SPI1, + SPI2, + SPI3, + SPI4, } } diff --git a/esp-hal-common/src/peripherals/esp32s3.rs b/esp-hal-common/src/peripherals/esp32s3.rs index f852bb7869d..4f7373f987b 100644 --- a/esp-hal-common/src/peripherals/esp32s3.rs +++ b/esp-hal-common/src/peripherals/esp32s3.rs @@ -64,5 +64,9 @@ mod peripherals { UART0, UART1, UART2, + SPI0, + SPI1, + SPI2, + SPI3, } } From 2730e0aad8868d329d61cd78cb28020b55b0f732 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 12 Dec 2022 16:41:03 +0100 Subject: [PATCH 3/3] Refactor SPI driver to use PeripheralRef --- esp-hal-common/src/cpu_control/esp32.rs | 2 +- esp-hal-common/src/spi.rs | 172 ++++++++++++------------ 2 files changed, 86 insertions(+), 88 deletions(-) diff --git a/esp-hal-common/src/cpu_control/esp32.rs b/esp-hal-common/src/cpu_control/esp32.rs index 26a2f1865b7..83c2831cdc1 100644 --- a/esp-hal-common/src/cpu_control/esp32.rs +++ b/esp-hal-common/src/cpu_control/esp32.rs @@ -137,7 +137,7 @@ impl CpuControl { } fn enable_cache(&mut self, core: Cpu) { - let spi0 = unsafe { &(*crate::pac::SPI0::ptr()) }; + let spi0 = unsafe { &(*crate::peripherals::SPI0::ptr()) }; let dport_control = crate::pac::DPORT::PTR; let dport_control = unsafe { &*dport_control }; diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index 9ab50705e8f..e476eef36b2 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -58,6 +58,7 @@ use crate::{ DmaPeripheral, }, pac::spi2::RegisterBlock, + peripheral::{Peripheral, PeripheralRef}, system::PeripheralClockControl, types::{InputSignal, OutputSignal}, InputPin, @@ -103,17 +104,17 @@ pub enum SpiMode { Mode3, } -pub struct Spi { - spi: T, +pub struct Spi<'d, T> { + spi: PeripheralRef<'d, T>, } -impl Spi +impl<'d, T> Spi<'d, T> where T: Instance, { /// Constructs an SPI instance in 8bit dataframe mode. pub fn new( - spi: T, + spi: impl Peripheral

+ 'd, mut sck: SCK, mut mosi: MOSI, mut miso: MISO, @@ -123,6 +124,7 @@ where peripheral_clock_control: &mut PeripheralClockControl, clocks: &Clocks, ) -> Self { + crate::into_ref!(spi); sck.set_to_push_pull_output() .connect_peripheral_to_output(spi.sclk_signal()); @@ -140,7 +142,7 @@ where /// Constructs an SPI instance in 8bit dataframe mode without CS pin. pub fn new_no_cs( - spi: T, + spi: impl Peripheral

+ 'd, mut sck: SCK, mut mosi: MOSI, mut miso: MISO, @@ -149,6 +151,7 @@ where peripheral_clock_control: &mut PeripheralClockControl, clocks: &Clocks, ) -> Self { + crate::into_ref!(spi); sck.set_to_push_pull_output() .connect_peripheral_to_output(spi.sclk_signal()); @@ -164,7 +167,7 @@ where /// Constructs an SPI instance in 8bit dataframe mode without CS and MISO /// pin. pub fn new_no_cs_no_miso( - spi: T, + spi: impl Peripheral

+ 'd, mut sck: SCK, mut mosi: MOSI, frequency: HertzU32, @@ -172,6 +175,7 @@ where peripheral_clock_control: &mut PeripheralClockControl, clocks: &Clocks, ) -> Self { + crate::into_ref!(spi); sck.set_to_push_pull_output() .connect_peripheral_to_output(spi.sclk_signal()); @@ -186,13 +190,14 @@ where /// other protocols by bitbanging (WS2812B, onewire, generating arbitrary /// waveforms…) pub fn new_mosi_only( - spi: T, + spi: impl Peripheral

+ 'd, mut mosi: MOSI, frequency: HertzU32, mode: SpiMode, peripheral_clock_control: &mut PeripheralClockControl, clocks: &Clocks, ) -> Self { + crate::into_ref!(spi); mosi.set_to_push_pull_output() .connect_peripheral_to_output(spi.mosi_signal()); @@ -200,7 +205,7 @@ where } pub(crate) fn new_internal( - spi: T, + spi: PeripheralRef<'d, T>, frequency: HertzU32, mode: SpiMode, peripheral_clock_control: &mut PeripheralClockControl, @@ -219,14 +224,9 @@ where pub fn change_bus_frequency(&mut self, frequency: HertzU32, clocks: &Clocks) { self.spi.ch_bus_freq(frequency, clocks); } - - /// Return the raw interface to the underlying peripheral instance - pub fn free(self) -> T { - self.spi - } } -impl embedded_hal::spi::FullDuplex for Spi +impl embedded_hal::spi::FullDuplex for Spi<'_, T> where T: Instance, { @@ -241,7 +241,7 @@ where } } -impl embedded_hal::blocking::spi::Transfer for Spi +impl embedded_hal::blocking::spi::Transfer for Spi<'_, T> where T: Instance, { @@ -252,7 +252,7 @@ where } } -impl embedded_hal::blocking::spi::Write for Spi +impl embedded_hal::blocking::spi::Write for Spi<'_, T> where T: Instance, { @@ -275,42 +275,45 @@ pub mod dma { use super::{Instance, InstanceDma, Spi, Spi2Instance, MAX_DMA_SIZE}; #[cfg(any(esp32, esp32s2))] use crate::dma::private::Spi3Peripheral; - use crate::dma::{ - private::{Rx, Spi2Peripheral, SpiPeripheral, Tx}, - Channel, - DmaTransfer, - DmaTransferRxTx, + use crate::{ + dma::{ + private::{Rx, Spi2Peripheral, SpiPeripheral, Tx}, + Channel, + DmaTransfer, + DmaTransferRxTx, + }, + peripheral::PeripheralRef, }; - pub trait WithDmaSpi2 + pub trait WithDmaSpi2<'d, T, RX, TX, P> where T: Instance + Spi2Instance, TX: Tx, RX: Rx, P: SpiPeripheral, { - fn with_dma(self, channel: Channel) -> SpiDma; + fn with_dma(self, channel: Channel) -> SpiDma<'d, T, TX, RX, P>; } #[cfg(any(esp32, esp32s2))] - pub trait WithDmaSpi3 + pub trait WithDmaSpi3<'d, T, RX, TX, P> where T: Instance + Spi3Instance, TX: Tx, RX: Rx, P: SpiPeripheral, { - fn with_dma(self, channel: Channel) -> SpiDma; + fn with_dma(self, channel: Channel) -> SpiDma<'d, T, TX, RX, P>; } - impl WithDmaSpi2 for Spi + impl<'d, T, RX, TX, P> WithDmaSpi2<'d, T, RX, TX, P> for Spi<'d, T> where T: Instance + Spi2Instance, TX: Tx, RX: Rx, P: SpiPeripheral + Spi2Peripheral, { - fn with_dma(self, mut channel: Channel) -> SpiDma { + fn with_dma(self, mut channel: Channel) -> SpiDma<'d, T, TX, RX, P> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { @@ -321,14 +324,14 @@ pub mod dma { } #[cfg(any(esp32, esp32s2))] - impl WithDmaSpi3 for Spi + impl<'d, T, RX, TX, P> WithDmaSpi3<'d, T, RX, TX, P> for Spi<'d, T> where T: Instance + Spi3Instance, TX: Tx, RX: Rx, P: SpiPeripheral + Spi3Peripheral, { - fn with_dma(self, mut channel: Channel) -> SpiDma { + fn with_dma(self, mut channel: Channel) -> SpiDma<'d, T, TX, RX, P> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { @@ -338,20 +341,20 @@ pub mod dma { } } /// An in-progress DMA transfer - pub struct SpiDmaTransferRxTx + pub struct SpiDmaTransferRxTx<'d, T, TX, RX, P, RBUFFER, TBUFFER> where T: InstanceDma, TX: Tx, RX: Rx, P: SpiPeripheral, { - spi_dma: SpiDma, + spi_dma: SpiDma<'d, T, TX, RX, P>, rbuffer: RBUFFER, tbuffer: TBUFFER, } - impl DmaTransferRxTx> - for SpiDmaTransferRxTx + impl<'d, T, TX, RX, P, RXBUF, TXBUF> DmaTransferRxTx> + for SpiDmaTransferRxTx<'d, T, TX, RX, P, RXBUF, TXBUF> where T: InstanceDma, TX: Tx, @@ -360,7 +363,7 @@ pub mod dma { { /// Wait for the DMA transfer to complete and return the buffers and the /// SPI instance. - fn wait(mut self) -> (RXBUF, TXBUF, SpiDma) { + fn wait(mut self) -> (RXBUF, TXBUF, SpiDma<'d, T, TX, RX, P>) { self.spi_dma.spi.flush().ok(); // waiting for the DMA transfer is not enough // `DmaTransfer` needs to have a `Drop` implementation, because we accept @@ -380,7 +383,7 @@ pub mod dma { } } - impl Drop for SpiDmaTransferRxTx + impl<'d, T, TX, RX, P, RXBUF, TXBUF> Drop for SpiDmaTransferRxTx<'d, T, TX, RX, P, RXBUF, TXBUF> where T: InstanceDma, TX: Tx, @@ -393,19 +396,19 @@ pub mod dma { } /// An in-progress DMA transfer. - pub struct SpiDmaTransfer + pub struct SpiDmaTransfer<'d, T, TX, RX, P, BUFFER> where T: InstanceDma, TX: Tx, RX: Rx, P: SpiPeripheral, { - spi_dma: SpiDma, + spi_dma: SpiDma<'d, T, TX, RX, P>, buffer: BUFFER, } - impl DmaTransfer> - for SpiDmaTransfer + impl<'d, T, TX, RX, P, BUFFER> DmaTransfer> + for SpiDmaTransfer<'d, T, TX, RX, P, BUFFER> where T: InstanceDma, TX: Tx, @@ -414,7 +417,7 @@ pub mod dma { { /// Wait for the DMA transfer to complete and return the buffers and the /// SPI instance. - fn wait(mut self) -> (BUFFER, SpiDma) { + fn wait(mut self) -> (BUFFER, SpiDma<'d, T, TX, RX, P>) { self.spi_dma.spi.flush().ok(); // waiting for the DMA transfer is not enough // `DmaTransfer` needs to have a `Drop` implementation, because we accept @@ -433,7 +436,7 @@ pub mod dma { } } - impl Drop for SpiDmaTransfer + impl<'d, T, TX, RX, P, BUFFER> Drop for SpiDmaTransfer<'d, T, TX, RX, P, BUFFER> where T: InstanceDma, TX: Tx, @@ -446,28 +449,23 @@ pub mod dma { } /// A DMA capable SPI instance. - pub struct SpiDma + pub struct SpiDma<'d, T, TX, RX, P> where TX: Tx, RX: Rx, P: SpiPeripheral, { - pub(crate) spi: T, + pub(crate) spi: PeripheralRef<'d, T>, pub(crate) channel: Channel, } - impl SpiDma + impl<'d, T, TX, RX, P> SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, RX: Rx, P: SpiPeripheral, { - /// Return the raw interface to the underlying peripheral instance - pub fn free(self) -> T { - self.spi - } - /// Perform a DMA write. /// /// This will return a [SpiDmaTransfer] owning the buffer(s) and the SPI @@ -476,7 +474,7 @@ pub mod dma { pub fn dma_write( mut self, words: TXBUF, - ) -> Result, super::Error> + ) -> Result, super::Error> where TXBUF: ReadBuffer, { @@ -502,7 +500,7 @@ pub mod dma { pub fn dma_read( mut self, mut words: RXBUF, - ) -> Result, super::Error> + ) -> Result, super::Error> where RXBUF: WriteBuffer, { @@ -529,7 +527,7 @@ pub mod dma { mut self, words: TXBUF, mut read_buffer: RXBUF, - ) -> Result, super::Error> + ) -> Result, super::Error> where TXBUF: ReadBuffer, RXBUF: WriteBuffer, @@ -557,7 +555,7 @@ pub mod dma { } } - impl embedded_hal::blocking::spi::Transfer for SpiDma + impl<'d, T, TX, RX, P> embedded_hal::blocking::spi::Transfer for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -572,7 +570,7 @@ pub mod dma { } } - impl embedded_hal::blocking::spi::Write for SpiDma + impl<'d, T, TX, RX, P> embedded_hal::blocking::spi::Write for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -595,7 +593,7 @@ pub mod dma { use super::{super::InstanceDma, SpiDma, SpiPeripheral}; use crate::dma::private::{Rx, Tx}; - impl embedded_hal_1::spi::ErrorType for SpiDma + impl<'d, T, TX, RX, P> embedded_hal_1::spi::ErrorType for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -605,7 +603,7 @@ pub mod dma { type Error = super::super::Error; } - impl SpiBusWrite for SpiDma + impl<'d, T, TX, RX, P> SpiBusWrite for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -619,7 +617,7 @@ pub mod dma { } } - impl SpiBusRead for SpiDma + impl<'d, T, TX, RX, P> SpiBusRead for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -633,7 +631,7 @@ pub mod dma { } } - impl SpiBus for SpiDma + impl<'d, T, TX, RX, P> SpiBus for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -670,7 +668,7 @@ pub mod dma { } } - impl SpiBusFlush for SpiDma + impl<'d, T, TX, RX, P> SpiBusFlush for SpiDma<'d, T, TX, RX, P> where T: InstanceDma, TX: Tx, @@ -705,11 +703,11 @@ mod ehal1 { use super::*; use crate::OutputPin; - impl embedded_hal_1::spi::ErrorType for Spi { + impl embedded_hal_1::spi::ErrorType for Spi<'_, T> { type Error = super::Error; } - impl FullDuplex for Spi + impl FullDuplex for Spi<'_, T> where T: Instance, { @@ -722,7 +720,7 @@ mod ehal1 { } } - impl SpiBusWrite for Spi + impl SpiBusWrite for Spi<'_, T> where T: Instance, { @@ -732,7 +730,7 @@ mod ehal1 { } } - impl SpiBusRead for Spi + impl SpiBusRead for Spi<'_, T> where T: Instance, { @@ -742,7 +740,7 @@ mod ehal1 { } } - impl SpiBus for Spi + impl SpiBus for Spi<'_, T> where T: Instance, { @@ -815,7 +813,7 @@ mod ehal1 { } } - impl SpiBusFlush for Spi + impl SpiBusFlush for Spi<'_, T> where T: Instance, { @@ -829,27 +827,27 @@ mod ehal1 { /// Has exclusive access to an SPI bus, which is managed via a `Mutex`. Used /// as basis for the [`SpiBusDevice`] implementation. Note that the /// wrapped [`RefCell`] is used solely to achieve interior mutability. - pub struct SpiBusController { - lock: critical_section::Mutex>>, + pub struct SpiBusController<'d, I: Instance> { + lock: critical_section::Mutex>>, } - impl SpiBusController { + impl<'d, I: Instance> SpiBusController<'d, I> { /// Create a new controller from an SPI bus instance. /// /// Takes ownership of the SPI bus in the process. Afterwards, the SPI /// bus can only be accessed via instances of [`SpiBusDevice`]. - pub fn from_spi(bus: Spi) -> Self { + pub fn from_spi(bus: Spi<'d, I>) -> Self { SpiBusController { lock: critical_section::Mutex::new(RefCell::new(bus)), } } - pub fn add_device<'a, CS: OutputPin>(&'a self, cs: CS) -> SpiBusDevice<'a, I, CS> { + pub fn add_device<'a, CS: OutputPin>(&'a self, cs: CS) -> SpiBusDevice<'a, 'd, I, CS> { SpiBusDevice::new(self, cs) } } - impl ErrorType for SpiBusController { + impl<'d, I: Instance> ErrorType for SpiBusController<'d, I> { type Error = spi::ErrorKind; } @@ -858,27 +856,27 @@ mod ehal1 { /// Provides device specific access on a shared SPI bus. Enables attaching /// multiple SPI devices to the same bus, each with its own CS line, and /// performing safe transfers on them. - pub struct SpiBusDevice<'a, I, CS> + pub struct SpiBusDevice<'a, 'd, I, CS> where I: Instance, CS: OutputPin, { - bus: &'a SpiBusController, + bus: &'a SpiBusController<'d, I>, cs: CS, } - impl<'a, I, CS> SpiBusDevice<'a, I, CS> + impl<'a, 'd, I, CS> SpiBusDevice<'a, 'd, I, CS> where I: Instance, CS: OutputPin, { - pub fn new(bus: &'a SpiBusController, mut cs: CS) -> Self { + pub fn new(bus: &'a SpiBusController<'d, I>, mut cs: CS) -> Self { cs.set_to_push_pull_output().set_output_high(true); SpiBusDevice { bus, cs } } } - impl<'a, I, CS> ErrorType for SpiBusDevice<'a, I, CS> + impl<'a, 'd, I, CS> ErrorType for SpiBusDevice<'a, 'd, I, CS> where I: Instance, CS: OutputPin, @@ -886,12 +884,12 @@ mod ehal1 { type Error = spi::ErrorKind; } - impl SpiDevice for SpiBusDevice<'_, I, CS> + impl<'a, 'd, I, CS> SpiDevice for SpiBusDevice<'a, 'd, I, CS> where I: Instance, CS: OutputPin + crate::gpio::OutputPin, { - type Bus = Spi; + type Bus = Spi<'d, I>; fn transaction( &mut self, @@ -1137,7 +1135,7 @@ where } } -impl InstanceDma for crate::pac::SPI2 +impl InstanceDma for crate::peripherals::SPI2 where TX: Tx, RX: Rx, @@ -1145,7 +1143,7 @@ where } #[cfg(any(esp32, esp32s2, esp32s3))] -impl InstanceDma for crate::pac::SPI3 +impl InstanceDma for crate::peripherals::SPI3 where TX: Tx, RX: Rx, @@ -1552,7 +1550,7 @@ pub trait Instance { } #[cfg(any(esp32c2, esp32c3))] -impl Instance for crate::pac::SPI2 { +impl Instance for crate::peripherals::SPI2 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { self @@ -1590,7 +1588,7 @@ impl Instance for crate::pac::SPI2 { } #[cfg(any(esp32))] -impl Instance for crate::pac::SPI2 { +impl Instance for crate::peripherals::SPI2 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { self @@ -1628,7 +1626,7 @@ impl Instance for crate::pac::SPI2 { } #[cfg(any(esp32))] -impl Instance for crate::pac::SPI3 { +impl Instance for crate::peripherals::SPI3 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { self @@ -1666,7 +1664,7 @@ impl Instance for crate::pac::SPI3 { } #[cfg(any(esp32s2, esp32s3))] -impl Instance for crate::pac::SPI2 { +impl Instance for crate::peripherals::SPI2 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { self @@ -1704,7 +1702,7 @@ impl Instance for crate::pac::SPI2 { } #[cfg(any(esp32s2, esp32s3))] -impl Instance for crate::pac::SPI3 { +impl Instance for crate::peripherals::SPI3 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { self @@ -1746,7 +1744,7 @@ pub trait Spi2Instance {} #[cfg(any(esp32, esp32s2, esp32s3))] pub trait Spi3Instance {} -impl Spi2Instance for crate::pac::SPI2 {} +impl Spi2Instance for crate::peripherals::SPI2 {} #[cfg(any(esp32, esp32s2, esp32s3))] -impl Spi3Instance for crate::pac::SPI3 {} +impl Spi3Instance for crate::peripherals::SPI3 {}