Skip to content

Commit

Permalink
Refactor the spi and spi_slave modules into a common spi module (
Browse files Browse the repository at this point in the history
…esp-rs#843)

* Refactor the `spi` and `spi_slave` modules into a single `spi` module

* Update import paths in examples as needed

* Extract some common types from `spi::master` into the root `spi` module

* Fix imports in examples (again)

* Documentation fixes/improvements

* Remove unnecessary re-exports

* Update `CHANGELOG.md`
  • Loading branch information
jessebraham authored and MabezDev committed Oct 20, 2023
1 parent 1ae132c commit 0c9c832
Show file tree
Hide file tree
Showing 60 changed files with 256 additions and 157 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adding async support for RSA peripheral(doesn't work properly for `esp32` chip - issue will be created)(#790)
- Added sleep support for ESP32-C3 with timer and GPIO wakeups (#795)
- Support for ULP-RISCV including Delay and GPIO (#840)
- Add bare-bones SPI slave support, DMA only (#580)
- Add bare-bones SPI slave support, DMA only (#580, #843)
- Embassy `#[main]` convenience macro

### Changed
Expand Down Expand Up @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Unify the system peripheral, `SYSTEM`, `DPORT` and `PCR` are now all exposed as `SYSTEM` (#832).
- Unified the ESP32's and ESP32-C2's xtal frequency features (#831)
- Replace any underscores in feature names with dashes (#833)
- The `spi` and `spi_slave` modules have been refactored into the `spi`, `spi::master`, and `spi::slave` modules (#843)

## [0.12.0]

Expand Down
6 changes: 1 addition & 5 deletions esp-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ pub use self::soc::peripherals;
pub use self::soc::psram;
#[cfg(ulp_riscv_core)]
pub use self::soc::ulp_core;
#[cfg(any(spi0, spi1, spi2, spi3))]
pub use self::spi::Spi;
#[cfg(any(timg0, timg1))]
pub use self::timer::Timer;
#[cfg(any(uart0, uart1, uart2))]
Expand Down Expand Up @@ -138,8 +136,6 @@ pub mod rtc_cntl;
pub mod sha;
#[cfg(any(spi0, spi1, spi2, spi3))]
pub mod spi;
#[cfg(all(any(spi0, spi1, spi2, spi3), not(pdma)))]
pub mod spi_slave;
#[cfg(any(dport, pcr, system))]
pub mod system;
#[cfg(systimer)]
Expand Down Expand Up @@ -402,7 +398,7 @@ mod critical_section_impl {
/// needs to transmit data from flash (ROM) via the embedded-hal traits. This is
/// often a `const` variable.
///
/// Example usage using [`spi::dma::SpiDma`]
/// Example usage using [`spi::master::dma::SpiDma`]
/// ```no_run
/// const ARRAY_IN_FLASH = [0xAA; 128]
///
Expand Down
6 changes: 3 additions & 3 deletions esp-hal-common/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ pub use crate::ledc::{
#[cfg(radio)]
pub use crate::radio::RadioExt as _esp_hal_RadioExt;
#[cfg(any(esp32, esp32s2, esp32s3))]
pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3;
pub use crate::spi::master::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3;
#[cfg(any(spi0, spi1, spi2, spi3))]
pub use crate::spi::{
pub use crate::spi::master::{
dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2,
Instance as _esp_hal_spi_Instance,
InstanceDma as _esp_hal_spi_InstanceDma,
};
#[cfg(all(any(spi0, spi1, spi2, spi3), not(pdma)))]
pub use crate::spi_slave::{
pub use crate::spi::slave::{
dma::WithDmaSpi2 as _esp_hal_spi_slave_dma_WithDmaSpi2,
Instance as _esp_hal_spi_slave_Instance,
InstanceDma as _esp_hal_spi_slave_InstanceDma,
Expand Down
101 changes: 28 additions & 73 deletions esp-hal-common/src/spi.rs → esp-hal-common/src/spi/master.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! # Serial Peripheral Interface
//! # Serial Peripheral Interface - Master Mode
//!
//! ## Overview
//!
//! There are multiple ways to use SPI, depending on your needs. Regardless of
//! which way you choose, you must first create an SPI instance with
//! [`Spi::new`].
Expand Down Expand Up @@ -53,9 +54,19 @@ use core::marker::PhantomData;

use fugit::HertzU32;

use super::{
DuplexMode,
Error,
FullDuplexMode,
HalfDuplexMode,
IsFullDuplex,
IsHalfDuplex,
SpiDataMode,
SpiMode,
};
use crate::{
clock::Clocks,
dma::{DmaError, DmaPeripheral, Rx, Tx},
dma::{DmaPeripheral, Rx, Tx},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
peripheral::{Peripheral, PeripheralRef},
peripherals::spi2::RegisterBlock,
Expand All @@ -67,69 +78,13 @@ use crate::{
const FIFO_SIZE: usize = 64;
#[cfg(esp32s2)]
const FIFO_SIZE: usize = 72;

/// Padding byte for empty write transfers
const EMPTY_WRITE_PAD: u8 = 0x00u8;

#[allow(unused)]
const MAX_DMA_SIZE: usize = 32736;

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
DmaError(DmaError),
MaxDmaTransferSizeExceeded,
FifoSizeExeeded,
Unsupported,
Unknown,
}

impl From<DmaError> for Error {
fn from(value: DmaError) -> Self {
Error::DmaError(value)
}
}

#[cfg(feature = "eh1")]
impl embedded_hal_1::spi::Error for Error {
fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
embedded_hal_1::spi::ErrorKind::Other
}
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiMode {
Mode0,
Mode1,
Mode2,
Mode3,
}

pub trait DuplexMode {}
pub trait IsFullDuplex: DuplexMode {}
pub trait IsHalfDuplex: DuplexMode {}

/// SPI data mode
///
/// Single = 1 bit, 2 wires
/// Dual = 2 bit, 2 wires
/// Quad = 4 bit, 4 wires
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiDataMode {
Single,
Dual,
Quad,
}

pub struct FullDuplexMode {}
impl DuplexMode for FullDuplexMode {}
impl IsFullDuplex for FullDuplexMode {}

pub struct HalfDuplexMode {}
impl DuplexMode for HalfDuplexMode {}
impl IsHalfDuplex for HalfDuplexMode {}

/// SPI command, 1 to 16 bits.
///
/// Can be [Command::None] if command phase should be suppressed.
Expand Down Expand Up @@ -754,7 +709,7 @@ pub mod dma {
use embedded_dma::{ReadBuffer, WriteBuffer};
use fugit::HertzU32;

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
use super::Spi3Instance;
use super::{
Address,
Expand All @@ -769,7 +724,7 @@ pub mod dma {
SpiDataMode,
MAX_DMA_SIZE,
};
#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
use crate::dma::Spi3Peripheral;
use crate::{
clock::Clocks,
Expand Down Expand Up @@ -798,7 +753,7 @@ pub mod dma {
fn with_dma(self, channel: Channel<'d, C>) -> SpiDma<'d, T, C, M>;
}

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
pub trait WithDmaSpi3<'d, T, C, M>
where
T: Instance + Spi3Instance,
Expand Down Expand Up @@ -827,7 +782,7 @@ pub mod dma {
}
}

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
impl<'d, T, C, M> WithDmaSpi3<'d, T, C, M> for Spi<'d, T, M>
where
T: Instance + Spi3Instance,
Expand Down Expand Up @@ -1510,8 +1465,8 @@ pub mod dma {
mod ehal1 {
use embedded_hal_1::spi::SpiBus;

use super::{super::InstanceDma, SpiDma, SpiPeripheral};
use crate::{dma::ChannelTypes, spi::IsFullDuplex, FlashSafeDma};
use super::{super::InstanceDma, *};
use crate::{dma::ChannelTypes, FlashSafeDma};

impl<'d, T, C, M> embedded_hal_1::spi::ErrorType for SpiDma<'d, T, C, M>
where
Expand Down Expand Up @@ -1990,7 +1945,7 @@ where
fn dma_peripheral(&self) -> DmaPeripheral {
match self.spi_num() {
2 => DmaPeripheral::Spi2,
#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
3 => DmaPeripheral::Spi3,
_ => panic!("Illegal SPI instance"),
}
Expand Down Expand Up @@ -2101,7 +2056,7 @@ where
{
}

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
impl<TX, RX> InstanceDma<TX, RX> for crate::peripherals::SPI3
where
TX: Tx,
Expand Down Expand Up @@ -2803,8 +2758,8 @@ pub trait Instance {

fn write_bytes_half_duplex(
&mut self,
cmd: crate::spi::Command,
address: crate::spi::Address,
cmd: Command,
address: Address,
dummy: u8,
buffer: &[u8],
) -> Result<(), Error> {
Expand Down Expand Up @@ -2866,8 +2821,8 @@ pub trait Instance {

fn read_bytes_half_duplex(
&mut self,
cmd: crate::spi::Command,
address: crate::spi::Address,
cmd: Command,
address: Address,
dummy: u8,
buffer: &mut [u8],
) -> Result<(), Error> {
Expand Down Expand Up @@ -3282,10 +3237,10 @@ impl ExtendedInstance for crate::peripherals::SPI3 {

pub trait Spi2Instance {}

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
pub trait Spi3Instance {}

impl Spi2Instance for crate::peripherals::SPI2 {}

#[cfg(any(esp32, esp32s2, esp32s3))]
#[cfg(spi3)]
impl Spi3Instance for crate::peripherals::SPI3 {}
72 changes: 72 additions & 0 deletions esp-hal-common/src/spi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Serial Peripheral Interface
//!
//! This peripheral is capable of operating in either master or slave mode. For
//! more information on these modes, please refer to the documentation in their
//! respective modules.
use crate::dma::DmaError;

pub mod master;
#[cfg(all(any(spi0, spi1, spi2, spi3), not(pdma)))]
pub mod slave;

/// SPI errors
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
DmaError(DmaError),
MaxDmaTransferSizeExceeded,
FifoSizeExeeded,
Unsupported,
Unknown,
}

impl From<DmaError> for Error {
fn from(value: DmaError) -> Self {
Error::DmaError(value)
}
}

#[cfg(feature = "eh1")]
impl embedded_hal_1::spi::Error for Error {
fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
embedded_hal_1::spi::ErrorKind::Other
}
}

/// SPI modes
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiMode {
Mode0,
Mode1,
Mode2,
Mode3,
}

pub trait DuplexMode {}
pub trait IsFullDuplex: DuplexMode {}
pub trait IsHalfDuplex: DuplexMode {}

/// SPI data mode
///
/// Single = 1 bit, 2 wires
/// Dual = 2 bit, 2 wires
/// Quad = 4 bit, 4 wires
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiDataMode {
Single,
Dual,
Quad,
}

/// Full-duplex operation
pub struct FullDuplexMode {}
impl DuplexMode for FullDuplexMode {}
impl IsFullDuplex for FullDuplexMode {}

/// Half-duplex operation
pub struct HalfDuplexMode {}
impl DuplexMode for HalfDuplexMode {}
impl IsHalfDuplex for HalfDuplexMode {}
Loading

0 comments on commit 0c9c832

Please sign in to comment.