Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the spi and spi_slave modules into a common spi module #843

Merged
merged 7 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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