esp_hal/spi/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! Serial Peripheral Interface (SPI)
//!
//! ## Overview
//! The Serial Peripheral Interface (SPI) is a synchronous serial interface
//! useful for communication with external peripherals.
//!
//! ## Configuration
//! 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::{DmaEligible, DmaError};

pub mod master;
pub mod slave;

/// SPI errors
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
    /// Error occurred due to a DMA-related issue.
    DmaError(DmaError),
    /// Error indicating that the maximum DMA transfer size was exceeded.
    MaxDmaTransferSizeExceeded,
    /// Error indicating that the FIFO size was exceeded during SPI
    /// communication.
    FifoSizeExeeded,
    /// Error indicating that the operation is unsupported by the current
    /// implementation.
    Unsupported,
    /// An unknown error occurred during SPI communication.
    Unknown,
}

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

impl embedded_hal::spi::Error for Error {
    fn kind(&self) -> embedded_hal::spi::ErrorKind {
        embedded_hal::spi::ErrorKind::Other
    }
}

/// SPI communication modes, defined by clock polarity (CPOL) and clock phase
/// (CPHA).
///
/// These modes control the clock signal's idle state and when data is sampled
/// and shifted.
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiMode {
    /// Mode 0 (CPOL = 0, CPHA = 0): Clock is low when idle, data is captured on
    /// the rising edge and propagated on the falling edge.
    Mode0,
    /// Mode 1 (CPOL = 0, CPHA = 1): Clock is low when idle, data is captured on
    /// the falling edge and propagated on the rising edge.
    Mode1,
    /// Mode 2 (CPOL = 1, CPHA = 0): Clock is high when idle, data is captured
    /// on the falling edge and propagated on the rising edge.
    Mode2,
    /// Mode 3 (CPOL = 1, CPHA = 1): Clock is high when idle, data is captured
    /// on the rising edge and propagated on the falling edge.
    Mode3,
}

/// SPI Bit Order
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SpiBitOrder {
    /// Most Significant Bit (MSB) is transmitted first.
    MSBFirst,
    /// Least Significant Bit (LSB) is transmitted first.
    LSBFirst,
}

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

crate::any_peripheral! {
    /// Any SPI peripheral.
    pub peripheral AnySpi {
        #[cfg(spi2)]
        Spi2(crate::peripherals::SPI2),
        #[cfg(spi3)]
        Spi3(crate::peripherals::SPI3),
    }
}

impl DmaEligible for AnySpi {
    #[cfg(gdma)]
    type Dma = crate::dma::AnyGdmaChannel;
    #[cfg(pdma)]
    type Dma = crate::dma::AnySpiDmaChannel;

    fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
        match &self.0 {
            #[cfg(spi2)]
            AnySpiInner::Spi2(_) => crate::dma::DmaPeripheral::Spi2,
            #[cfg(spi3)]
            AnySpiInner::Spi3(_) => crate::dma::DmaPeripheral::Spi3,
        }
    }
}