esp_hal/spi/
mod.rs

1//! Serial Peripheral Interface (SPI)
2//!
3//! ## Overview
4//! The Serial Peripheral Interface (SPI) is a synchronous serial interface
5//! useful for communication with external peripherals.
6//!
7//! ## Configuration
8//! This peripheral is capable of operating in either master or slave mode. For
9//! more information on these modes, please refer to the documentation in their
10//! respective modules.
11
12use crate::dma::{DmaEligible, DmaError};
13
14pub mod master;
15
16crate::unstable_module! {
17    pub mod slave;
18}
19
20/// SPI errors
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23#[non_exhaustive]
24pub enum Error {
25    /// Error occurred due to a DMA-related issue.
26    #[cfg(any(doc, feature = "unstable"))]
27    #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
28    #[allow(clippy::enum_variant_names, reason = "DMA is unstable")]
29    DmaError(DmaError),
30    /// Error indicating that the maximum DMA transfer size was exceeded.
31    MaxDmaTransferSizeExceeded,
32    /// Error indicating that the FIFO size was exceeded during SPI
33    /// communication.
34    FifoSizeExeeded,
35    /// Error indicating that the operation is unsupported by the current
36    /// implementation or for the given arguments.
37    Unsupported,
38    /// An unknown error occurred during SPI communication.
39    Unknown,
40}
41
42#[doc(hidden)]
43#[cfg(feature = "unstable")]
44impl From<DmaError> for Error {
45    fn from(value: DmaError) -> Self {
46        Error::DmaError(value)
47    }
48}
49
50#[doc(hidden)]
51#[cfg(not(any(doc, feature = "unstable")))]
52impl From<DmaError> for Error {
53    fn from(_value: DmaError) -> Self {
54        Error::Unknown
55    }
56}
57
58impl embedded_hal::spi::Error for Error {
59    fn kind(&self) -> embedded_hal::spi::ErrorKind {
60        embedded_hal::spi::ErrorKind::Other
61    }
62}
63
64/// SPI communication modes, defined by clock polarity (CPOL) and clock phase
65/// (CPHA).
66///
67/// These modes control the clock signal's idle state and when data is sampled
68/// and shifted.
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
70#[cfg_attr(feature = "defmt", derive(defmt::Format))]
71pub enum Mode {
72    /// Mode 0 (CPOL = 0, CPHA = 0): Clock is low when idle, data is captured on
73    /// the rising edge and propagated on the falling edge.
74    _0,
75    /// Mode 1 (CPOL = 0, CPHA = 1): Clock is low when idle, data is captured on
76    /// the falling edge and propagated on the rising edge.
77    _1,
78    /// Mode 2 (CPOL = 1, CPHA = 0): Clock is high when idle, data is captured
79    /// on the falling edge and propagated on the rising edge.
80    _2,
81    /// Mode 3 (CPOL = 1, CPHA = 1): Clock is high when idle, data is captured
82    /// on the rising edge and propagated on the falling edge.
83    _3,
84}
85
86/// SPI Bit Order
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89pub enum BitOrder {
90    /// Most Significant Bit (MSB) is transmitted first.
91    MsbFirst,
92    /// Least Significant Bit (LSB) is transmitted first.
93    LsbFirst,
94}
95
96/// SPI data mode
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98#[cfg_attr(feature = "defmt", derive(defmt::Format))]
99#[instability::unstable]
100pub enum DataMode {
101    /// 1 bit, two data lines. (MOSI, MISO)
102    SingleTwoDataLines,
103    /// 1 bit, 1 data line (SIO0)
104    Single,
105    /// 2 bits, two data lines. (SIO0, SIO1)
106    Dual,
107    /// 4 bit, 4 data lines. (SIO0 .. SIO3)
108    Quad,
109    #[cfg(spi_octal)]
110    /// 8 bit, 8 data lines. (SIO0 .. SIO7)
111    Octal,
112}
113
114crate::any_peripheral! {
115    /// Any SPI peripheral.
116    pub peripheral AnySpi {
117        #[cfg(spi2)]
118        Spi2(crate::peripherals::SPI2),
119        #[cfg(spi3)]
120        Spi3(crate::peripherals::SPI3),
121    }
122}
123
124impl DmaEligible for AnySpi {
125    #[cfg(gdma)]
126    type Dma = crate::dma::AnyGdmaChannel;
127    #[cfg(pdma)]
128    type Dma = crate::dma::AnySpiDmaChannel;
129
130    fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
131        match &self.0 {
132            #[cfg(spi2)]
133            AnySpiInner::Spi2(_) => crate::dma::DmaPeripheral::Spi2,
134            #[cfg(spi3)]
135            AnySpiInner::Spi3(_) => crate::dma::DmaPeripheral::Spi3,
136        }
137    }
138}