Skip to main content

esp_hal/spi/master/
mod.rs

1//! # Serial Peripheral Interface - Master Mode
2//!
3//! ## Overview
4//!
5//! In this mode, the SPI acts as master and initiates the SPI transactions.
6//!
7//! ## Configuration
8//!
9//! The peripheral can be used in full-duplex and half-duplex mode and can
10//! leverage DMA for data transfers. It can also be used in blocking or async.
11//!
12//! ### Exclusive access to the SPI bus
13//!
14//! If all you want to do is to communicate to a single device, and you initiate
15//! transactions yourself, there are a number of ways to achieve this:
16//!
17//! - Use the [`SpiBus`] or [`SpiBusAsync`] trait and its associated functions to initiate
18//!   transactions with simultaneous reads and writes, or
19//! - Use the `ExclusiveDevice` struct from [`embedded-hal-bus`] or `SpiDevice` from
20//!   [`embassy-embedded-hal`].
21//!
22//! ### Shared SPI access
23//!
24//! If you have multiple devices on the same SPI bus that each have their own CS
25//! line (and optionally, configuration), you may want to have a look at the
26//! implementations provided by [`embedded-hal-bus`] and
27//! [`embassy-embedded-hal`].
28//!
29//! ## Usage
30//!
31//! The module implements several third-party traits from embedded-hal@1.x.x
32//! and [`embassy-embedded-hal`].
33//!
34//! [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/spi/index.html
35//! [`embassy-embedded-hal`]: embassy_embedded_hal::shared_bus
36
37#[cfg(esp32)]
38use core::cell::Cell;
39use core::{
40    cell::UnsafeCell,
41    future::Future,
42    marker::PhantomData,
43    mem::MaybeUninit,
44    pin::Pin,
45    task::{Context, Poll},
46};
47
48#[cfg(spi_master_supports_dma)]
49mod dma;
50
51#[instability::unstable]
52#[cfg(spi_master_supports_dma)]
53pub use dma::*;
54use embedded_hal::spi::SpiBus;
55use embedded_hal_async::spi::SpiBus as SpiBusAsync;
56use enumset::{EnumSet, EnumSetType, enum_set};
57use procmacros::doc_replace;
58
59use super::{BitOrder, Error, Mode};
60use crate::{
61    Async,
62    Blocking,
63    DriverMode,
64    RegisterToggle,
65    asynch::AtomicWaker,
66    clock::Clocks,
67    gpio::{
68        InputConfig,
69        InputSignal,
70        NoPin,
71        OutputConfig,
72        OutputSignal,
73        PinGuard,
74        interconnect::{self, PeripheralInput, PeripheralOutput},
75    },
76    handler,
77    interrupt::InterruptHandler,
78    pac::spi2::RegisterBlock,
79    private::{self, DropGuard, Sealed},
80    ram,
81    system::PeripheralGuard,
82    time::Rate,
83};
84
85/// Enumeration of possible SPI interrupt events.
86#[derive(Debug, Hash, EnumSetType)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88#[non_exhaustive]
89#[instability::unstable]
90pub enum SpiInterrupt {
91    /// Indicates that the SPI transaction has completed successfully.
92    ///
93    /// This interrupt is triggered when an SPI transaction has finished
94    /// transmitting and receiving data.
95    TransferDone,
96
97    /// Triggered at the end of configurable segmented transfer.
98    #[cfg(spi_master_has_dma_segmented_transfer)]
99    DmaSegmentedTransferDone,
100
101    /// Used and triggered by software. Only used for user defined function.
102    #[cfg(spi_master_has_app_interrupts)]
103    App2,
104
105    /// Used and triggered by software. Only used for user defined function.
106    #[cfg(spi_master_has_app_interrupts)]
107    App1,
108}
109
110/// The size of the FIFO buffer for SPI
111const FIFO_SIZE: usize = if cfg!(esp32s2) { 72 } else { 64 };
112
113/// Padding byte for empty write transfers
114const EMPTY_WRITE_PAD: u8 = 0x00;
115
116/// SPI commands, each consisting of a 16-bit command value and a data mode.
117///
118/// Used to define specific commands sent over the SPI bus.
119/// Can be [Command::None] if command phase should be suppressed.
120#[non_exhaustive]
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122#[cfg_attr(feature = "defmt", derive(defmt::Format))]
123#[instability::unstable]
124pub enum Command {
125    /// No command is sent.
126    None,
127    /// A 1-bit command.
128    _1Bit(u16, DataMode),
129    /// A 2-bit command.
130    _2Bit(u16, DataMode),
131    /// A 3-bit command.
132    _3Bit(u16, DataMode),
133    /// A 4-bit command.
134    _4Bit(u16, DataMode),
135    /// A 5-bit command.
136    _5Bit(u16, DataMode),
137    /// A 6-bit command.
138    _6Bit(u16, DataMode),
139    /// A 7-bit command.
140    _7Bit(u16, DataMode),
141    /// A 8-bit command.
142    _8Bit(u16, DataMode),
143    /// A 9-bit command.
144    _9Bit(u16, DataMode),
145    /// A 10-bit command.
146    _10Bit(u16, DataMode),
147    /// A 11-bit command.
148    _11Bit(u16, DataMode),
149    /// A 12-bit command.
150    _12Bit(u16, DataMode),
151    /// A 13-bit command.
152    _13Bit(u16, DataMode),
153    /// A 14-bit command.
154    _14Bit(u16, DataMode),
155    /// A 15-bit command.
156    _15Bit(u16, DataMode),
157    /// A 16-bit command.
158    _16Bit(u16, DataMode),
159}
160
161impl Command {
162    fn width(&self) -> usize {
163        match self {
164            Command::None => 0,
165            Command::_1Bit(_, _) => 1,
166            Command::_2Bit(_, _) => 2,
167            Command::_3Bit(_, _) => 3,
168            Command::_4Bit(_, _) => 4,
169            Command::_5Bit(_, _) => 5,
170            Command::_6Bit(_, _) => 6,
171            Command::_7Bit(_, _) => 7,
172            Command::_8Bit(_, _) => 8,
173            Command::_9Bit(_, _) => 9,
174            Command::_10Bit(_, _) => 10,
175            Command::_11Bit(_, _) => 11,
176            Command::_12Bit(_, _) => 12,
177            Command::_13Bit(_, _) => 13,
178            Command::_14Bit(_, _) => 14,
179            Command::_15Bit(_, _) => 15,
180            Command::_16Bit(_, _) => 16,
181        }
182    }
183
184    fn value(&self) -> u16 {
185        match self {
186            Command::None => 0,
187            Command::_1Bit(value, _)
188            | Command::_2Bit(value, _)
189            | Command::_3Bit(value, _)
190            | Command::_4Bit(value, _)
191            | Command::_5Bit(value, _)
192            | Command::_6Bit(value, _)
193            | Command::_7Bit(value, _)
194            | Command::_8Bit(value, _)
195            | Command::_9Bit(value, _)
196            | Command::_10Bit(value, _)
197            | Command::_11Bit(value, _)
198            | Command::_12Bit(value, _)
199            | Command::_13Bit(value, _)
200            | Command::_14Bit(value, _)
201            | Command::_15Bit(value, _)
202            | Command::_16Bit(value, _) => *value,
203        }
204    }
205
206    fn mode(&self) -> DataMode {
207        match self {
208            Command::None => DataMode::SingleTwoDataLines,
209            Command::_1Bit(_, mode)
210            | Command::_2Bit(_, mode)
211            | Command::_3Bit(_, mode)
212            | Command::_4Bit(_, mode)
213            | Command::_5Bit(_, mode)
214            | Command::_6Bit(_, mode)
215            | Command::_7Bit(_, mode)
216            | Command::_8Bit(_, mode)
217            | Command::_9Bit(_, mode)
218            | Command::_10Bit(_, mode)
219            | Command::_11Bit(_, mode)
220            | Command::_12Bit(_, mode)
221            | Command::_13Bit(_, mode)
222            | Command::_14Bit(_, mode)
223            | Command::_15Bit(_, mode)
224            | Command::_16Bit(_, mode) => *mode,
225        }
226    }
227
228    fn is_none(&self) -> bool {
229        matches!(self, Command::None)
230    }
231}
232
233/// SPI address, ranging from 1 to 32 bits, paired with a data mode.
234///
235/// This can be used to specify the address phase of SPI transactions.
236/// Can be [Address::None] if address phase should be suppressed.
237#[non_exhaustive]
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
239#[cfg_attr(feature = "defmt", derive(defmt::Format))]
240#[instability::unstable]
241pub enum Address {
242    /// No address phase.
243    None,
244    /// A 1-bit address.
245    _1Bit(u32, DataMode),
246    /// A 2-bit address.
247    _2Bit(u32, DataMode),
248    /// A 3-bit address.
249    _3Bit(u32, DataMode),
250    /// A 4-bit address.
251    _4Bit(u32, DataMode),
252    /// A 5-bit address.
253    _5Bit(u32, DataMode),
254    /// A 6-bit address.
255    _6Bit(u32, DataMode),
256    /// A 7-bit address.
257    _7Bit(u32, DataMode),
258    /// A 8-bit address.
259    _8Bit(u32, DataMode),
260    /// A 9-bit address.
261    _9Bit(u32, DataMode),
262    /// A 10-bit address.
263    _10Bit(u32, DataMode),
264    /// A 11-bit address.
265    _11Bit(u32, DataMode),
266    /// A 12-bit address.
267    _12Bit(u32, DataMode),
268    /// A 13-bit address.
269    _13Bit(u32, DataMode),
270    /// A 14-bit address.
271    _14Bit(u32, DataMode),
272    /// A 15-bit address.
273    _15Bit(u32, DataMode),
274    /// A 16-bit address.
275    _16Bit(u32, DataMode),
276    /// A 17-bit address.
277    _17Bit(u32, DataMode),
278    /// A 18-bit address.
279    _18Bit(u32, DataMode),
280    /// A 19-bit address.
281    _19Bit(u32, DataMode),
282    /// A 20-bit address.
283    _20Bit(u32, DataMode),
284    /// A 21-bit address.
285    _21Bit(u32, DataMode),
286    /// A 22-bit address.
287    _22Bit(u32, DataMode),
288    /// A 23-bit address.
289    _23Bit(u32, DataMode),
290    /// A 24-bit address.
291    _24Bit(u32, DataMode),
292    /// A 25-bit address.
293    _25Bit(u32, DataMode),
294    /// A 26-bit address.
295    _26Bit(u32, DataMode),
296    /// A 27-bit address.
297    _27Bit(u32, DataMode),
298    /// A 28-bit address.
299    _28Bit(u32, DataMode),
300    /// A 29-bit address.
301    _29Bit(u32, DataMode),
302    /// A 30-bit address.
303    _30Bit(u32, DataMode),
304    /// A 31-bit address.
305    _31Bit(u32, DataMode),
306    /// A 32-bit address.
307    _32Bit(u32, DataMode),
308}
309
310impl Address {
311    fn width(&self) -> usize {
312        match self {
313            Address::None => 0,
314            Address::_1Bit(_, _) => 1,
315            Address::_2Bit(_, _) => 2,
316            Address::_3Bit(_, _) => 3,
317            Address::_4Bit(_, _) => 4,
318            Address::_5Bit(_, _) => 5,
319            Address::_6Bit(_, _) => 6,
320            Address::_7Bit(_, _) => 7,
321            Address::_8Bit(_, _) => 8,
322            Address::_9Bit(_, _) => 9,
323            Address::_10Bit(_, _) => 10,
324            Address::_11Bit(_, _) => 11,
325            Address::_12Bit(_, _) => 12,
326            Address::_13Bit(_, _) => 13,
327            Address::_14Bit(_, _) => 14,
328            Address::_15Bit(_, _) => 15,
329            Address::_16Bit(_, _) => 16,
330            Address::_17Bit(_, _) => 17,
331            Address::_18Bit(_, _) => 18,
332            Address::_19Bit(_, _) => 19,
333            Address::_20Bit(_, _) => 20,
334            Address::_21Bit(_, _) => 21,
335            Address::_22Bit(_, _) => 22,
336            Address::_23Bit(_, _) => 23,
337            Address::_24Bit(_, _) => 24,
338            Address::_25Bit(_, _) => 25,
339            Address::_26Bit(_, _) => 26,
340            Address::_27Bit(_, _) => 27,
341            Address::_28Bit(_, _) => 28,
342            Address::_29Bit(_, _) => 29,
343            Address::_30Bit(_, _) => 30,
344            Address::_31Bit(_, _) => 31,
345            Address::_32Bit(_, _) => 32,
346        }
347    }
348
349    fn value(&self) -> u32 {
350        match self {
351            Address::None => 0,
352            Address::_1Bit(value, _)
353            | Address::_2Bit(value, _)
354            | Address::_3Bit(value, _)
355            | Address::_4Bit(value, _)
356            | Address::_5Bit(value, _)
357            | Address::_6Bit(value, _)
358            | Address::_7Bit(value, _)
359            | Address::_8Bit(value, _)
360            | Address::_9Bit(value, _)
361            | Address::_10Bit(value, _)
362            | Address::_11Bit(value, _)
363            | Address::_12Bit(value, _)
364            | Address::_13Bit(value, _)
365            | Address::_14Bit(value, _)
366            | Address::_15Bit(value, _)
367            | Address::_16Bit(value, _)
368            | Address::_17Bit(value, _)
369            | Address::_18Bit(value, _)
370            | Address::_19Bit(value, _)
371            | Address::_20Bit(value, _)
372            | Address::_21Bit(value, _)
373            | Address::_22Bit(value, _)
374            | Address::_23Bit(value, _)
375            | Address::_24Bit(value, _)
376            | Address::_25Bit(value, _)
377            | Address::_26Bit(value, _)
378            | Address::_27Bit(value, _)
379            | Address::_28Bit(value, _)
380            | Address::_29Bit(value, _)
381            | Address::_30Bit(value, _)
382            | Address::_31Bit(value, _)
383            | Address::_32Bit(value, _) => *value,
384        }
385    }
386
387    fn is_none(&self) -> bool {
388        matches!(self, Address::None)
389    }
390
391    fn mode(&self) -> DataMode {
392        match self {
393            Address::None => DataMode::SingleTwoDataLines,
394            Address::_1Bit(_, mode)
395            | Address::_2Bit(_, mode)
396            | Address::_3Bit(_, mode)
397            | Address::_4Bit(_, mode)
398            | Address::_5Bit(_, mode)
399            | Address::_6Bit(_, mode)
400            | Address::_7Bit(_, mode)
401            | Address::_8Bit(_, mode)
402            | Address::_9Bit(_, mode)
403            | Address::_10Bit(_, mode)
404            | Address::_11Bit(_, mode)
405            | Address::_12Bit(_, mode)
406            | Address::_13Bit(_, mode)
407            | Address::_14Bit(_, mode)
408            | Address::_15Bit(_, mode)
409            | Address::_16Bit(_, mode)
410            | Address::_17Bit(_, mode)
411            | Address::_18Bit(_, mode)
412            | Address::_19Bit(_, mode)
413            | Address::_20Bit(_, mode)
414            | Address::_21Bit(_, mode)
415            | Address::_22Bit(_, mode)
416            | Address::_23Bit(_, mode)
417            | Address::_24Bit(_, mode)
418            | Address::_25Bit(_, mode)
419            | Address::_26Bit(_, mode)
420            | Address::_27Bit(_, mode)
421            | Address::_28Bit(_, mode)
422            | Address::_29Bit(_, mode)
423            | Address::_30Bit(_, mode)
424            | Address::_31Bit(_, mode)
425            | Address::_32Bit(_, mode) => *mode,
426        }
427    }
428}
429
430/// SPI clock source.
431#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
432#[cfg_attr(feature = "defmt", derive(defmt::Format))]
433#[instability::unstable]
434pub enum ClockSource {
435    /// Use the APB clock.
436    Apb,
437    // #[cfg(any(esp32c2, esp32c3, esp32s3))]
438    // Xtal,
439}
440
441/// SPI peripheral configuration
442#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, procmacros::BuilderLite)]
443#[cfg_attr(feature = "defmt", derive(defmt::Format))]
444#[non_exhaustive]
445pub struct Config {
446    /// The precomputed clock configuration register value.
447    ///
448    /// Clock divider calculations are relatively expensive, and the SPI
449    /// peripheral is commonly expected to be used in a shared bus
450    /// configuration, where different devices may need different bus clock
451    /// frequencies. To reduce the time required to reconfigure the bus, we
452    /// cache clock register's value here, for each configuration.
453    ///
454    /// This field is not intended to be set by the user, and is only used
455    /// internally.
456    #[builder_lite(skip)]
457    reg: Result<u32, ConfigError>,
458
459    /// The target frequency
460    #[builder_lite(skip_setter)]
461    frequency: Rate,
462
463    /// The clock source
464    #[builder_lite(unstable)]
465    #[builder_lite(skip_setter)]
466    clock_source: ClockSource,
467
468    /// SPI sample/shift mode.
469    mode: Mode,
470
471    /// Bit order of the read data.
472    read_bit_order: BitOrder,
473
474    /// Bit order of the written data.
475    write_bit_order: BitOrder,
476}
477
478impl Default for Config {
479    fn default() -> Self {
480        let mut this = Config {
481            reg: Ok(0),
482            frequency: Rate::from_mhz(1),
483            clock_source: ClockSource::Apb,
484            mode: Mode::_0,
485            read_bit_order: BitOrder::MsbFirst,
486            write_bit_order: BitOrder::MsbFirst,
487        };
488
489        this.reg = this.recalculate();
490
491        this
492    }
493}
494
495impl Config {
496    /// Set the frequency of the SPI bus clock.
497    pub fn with_frequency(mut self, frequency: Rate) -> Self {
498        self.frequency = frequency;
499        self.reg = self.recalculate();
500
501        self
502    }
503
504    /// Set the clock source of the SPI bus.
505    #[instability::unstable]
506    pub fn with_clock_source(mut self, clock_source: ClockSource) -> Self {
507        self.clock_source = clock_source;
508        self.reg = self.recalculate();
509
510        self
511    }
512
513    fn clock_source_freq_hz(&self) -> Rate {
514        let clocks = Clocks::get();
515
516        // FIXME: take clock source into account
517        cfg_if::cfg_if! {
518            if #[cfg(esp32h2)] {
519                // ESP32-H2 is using PLL_48M_CLK source instead of APB_CLK
520                let _clocks = clocks;
521                Rate::from_mhz(48)
522            } else if #[cfg(any(esp32c5, esp32c61))] {
523                // We select the 160MHz PLL as the clock source in the driver. There is a by-2 divider
524                // configured between the PLL and the SPI clock (spi2_clkm_div_num).
525                let _clocks = clocks;
526                Rate::from_mhz(80) // clk_spi2_mst must be <= 80MHz
527            } else if #[cfg(esp32c6)] {
528                // We select the 80MHz PLL as the clock source in the driver
529                // FIXME we state that the default clock source is APB, which just isn't true
530                let _clocks = clocks;
531                Rate::from_mhz(80)
532            } else {
533                clocks.apb_clock
534            }
535        }
536    }
537
538    fn recalculate(&self) -> Result<u32, ConfigError> {
539        // taken from https://github.com/apache/incubator-nuttx/blob/8267a7618629838231256edfa666e44b5313348e/arch/risc-v/src/esp32c3/esp32c3_spi.c#L496
540        let source_freq = self.clock_source_freq_hz();
541
542        let reg_val: u32;
543        let duty_cycle = 128;
544
545        // In HW, n, h and l fields range from 1 to 64, pre ranges from 1 to 8K.
546        // The value written to register is one lower than the used value.
547
548        if self.frequency > ((source_freq / 4) * 3) {
549            // Using APB frequency directly will give us the best result here.
550            reg_val = 1 << 31;
551        } else {
552            // For best duty cycle resolution, we want n to be as close to 32 as
553            // possible, but we also need a pre/n combo that gets us as close as
554            // possible to the intended frequency. To do this, we bruteforce n and
555            // calculate the best pre to go along with that. If there's a choice
556            // between pre/n combos that give the same result, use the one with the
557            // higher n.
558
559            let mut pre: i32;
560            let mut bestn: i32 = -1;
561            let mut bestpre: i32 = -1;
562            let mut besterr: i32 = 0;
563            let mut errval: i32;
564
565            let target_freq_hz = self.frequency.as_hz() as i32;
566            let source_freq_hz = source_freq.as_hz() as i32;
567
568            // Start at n = 2. We need to be able to set h/l so we have at least
569            // one high and one low pulse.
570
571            for n in 2..=64 {
572                // Effectively, this does:
573                // pre = round((APB_CLK_FREQ / n) / frequency)
574
575                pre = ((source_freq_hz / n) + (target_freq_hz / 2)) / target_freq_hz;
576
577                if pre <= 0 {
578                    pre = 1;
579                }
580
581                if pre > 16 {
582                    pre = 16;
583                }
584
585                errval = (source_freq_hz / (pre * n) - target_freq_hz).abs();
586                if bestn == -1 || errval <= besterr {
587                    besterr = errval;
588                    bestn = n;
589                    bestpre = pre;
590                }
591            }
592
593            let n: i32 = bestn;
594            pre = bestpre;
595            let l: i32 = n;
596
597            // Effectively, this does:
598            // h = round((duty_cycle * n) / 256)
599
600            let mut h: i32 = (duty_cycle * n + 127) / 256;
601            if h <= 0 {
602                h = 1;
603            }
604
605            reg_val = (l as u32 - 1)
606                | ((h as u32 - 1) << 6)
607                | ((n as u32 - 1) << 12)
608                | ((pre as u32 - 1) << 18);
609        }
610
611        Ok(reg_val)
612    }
613
614    fn raw_clock_reg_value(&self) -> Result<u32, ConfigError> {
615        self.reg
616    }
617
618    fn validate(&self) -> Result<(), ConfigError> {
619        let source_freq = self.clock_source_freq_hz();
620        let min_divider = 1;
621        // FIXME: while ESP32 and S2 support pre dividers as large as 8192,
622        // those values are not currently supported by the divider calculation.
623        let max_divider = 16 * 64; // n * pre
624
625        if self.frequency < source_freq / max_divider || self.frequency > source_freq / min_divider
626        {
627            return Err(ConfigError::FrequencyOutOfRange);
628        }
629
630        Ok(())
631    }
632}
633
634const SIO_PIN_COUNT: usize = 4 + cfg!(spi_master_has_octal) as usize * 4;
635
636#[derive(Debug)]
637#[cfg_attr(feature = "defmt", derive(defmt::Format))]
638struct SpiPinGuard {
639    sclk_pin: PinGuard,
640    cs_pin: PinGuard,
641    sio_pins: [PinGuard; SIO_PIN_COUNT],
642}
643
644impl SpiPinGuard {
645    const fn new_unconnected() -> Self {
646        Self {
647            sclk_pin: PinGuard::new_unconnected(),
648            cs_pin: PinGuard::new_unconnected(),
649            sio_pins: [const { PinGuard::new_unconnected() }; SIO_PIN_COUNT],
650        }
651    }
652}
653
654/// Configuration errors.
655#[non_exhaustive]
656#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
657#[cfg_attr(feature = "defmt", derive(defmt::Format))]
658pub enum ConfigError {
659    /// The requested frequency is not in the supported range.
660    FrequencyOutOfRange,
661}
662
663impl core::error::Error for ConfigError {}
664
665impl core::fmt::Display for ConfigError {
666    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
667        match self {
668            ConfigError::FrequencyOutOfRange => {
669                write!(f, "The requested frequency is not in the supported range")
670            }
671        }
672    }
673}
674
675#[derive(Debug)]
676#[cfg_attr(feature = "defmt", derive(defmt::Format))]
677struct SpiWrapper<'d> {
678    spi: AnySpi<'d>,
679    _guard: PeripheralGuard,
680}
681
682impl<'d> SpiWrapper<'d> {
683    fn new(spi: impl Instance + 'd) -> Self {
684        let p = spi.info().peripheral;
685        let this = Self {
686            spi: spi.degrade(),
687            _guard: PeripheralGuard::new(p),
688        };
689
690        // Initialize state
691        unsafe {
692            this.state()
693                .pins
694                .get()
695                .write(MaybeUninit::new(SpiPinGuard::new_unconnected()))
696        }
697
698        this
699    }
700
701    fn info(&self) -> &'static Info {
702        self.spi.info()
703    }
704
705    fn state(&self) -> &'static State {
706        self.spi.state()
707    }
708
709    fn disable_peri_interrupt_on_all_cores(&self) {
710        self.spi.disable_peri_interrupt_on_all_cores();
711    }
712
713    fn set_interrupt_handler(&self, handler: InterruptHandler) {
714        self.spi.set_interrupt_handler(handler);
715    }
716
717    fn pins(&mut self) -> &mut SpiPinGuard {
718        unsafe {
719            // SAFETY: we "own" the state, we are allowed to borrow it mutably
720            self.state().pins()
721        }
722    }
723}
724
725impl Drop for SpiWrapper<'_> {
726    fn drop(&mut self) {
727        unsafe {
728            // SAFETY: we "own" the state, we are allowed to deinit it
729            self.spi.state().deinit();
730        }
731    }
732}
733
734#[procmacros::doc_replace]
735/// SPI peripheral driver
736///
737/// ## Example
738///
739/// ```rust, no_run
740/// # {before_snippet}
741/// use esp_hal::spi::{
742///     Mode,
743///     master::{Config, Spi},
744/// };
745/// let mut spi = Spi::new(
746///     peripherals.SPI2,
747///     Config::default()
748///         .with_frequency(Rate::from_khz(100))
749///         .with_mode(Mode::_0),
750/// )?
751/// .with_sck(peripherals.GPIO0)
752/// .with_mosi(peripherals.GPIO1)
753/// .with_miso(peripherals.GPIO2);
754/// # {after_snippet}
755/// ```
756#[derive(Debug)]
757#[cfg_attr(feature = "defmt", derive(defmt::Format))]
758pub struct Spi<'d, Dm: DriverMode> {
759    spi: SpiWrapper<'d>,
760    _mode: PhantomData<Dm>,
761}
762
763impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
764
765impl<'d> Spi<'d, Blocking> {
766    #[procmacros::doc_replace]
767    /// Constructs an SPI instance in 8bit dataframe mode.
768    ///
769    /// ## Errors
770    ///
771    /// See [`Spi::apply_config`].
772    ///
773    /// ## Example
774    ///
775    /// ```rust, no_run
776    /// # {before_snippet}
777    /// use esp_hal::spi::{
778    ///     Mode,
779    ///     master::{Config, Spi},
780    /// };
781    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
782    ///     .with_sck(peripherals.GPIO0)
783    ///     .with_mosi(peripherals.GPIO1)
784    ///     .with_miso(peripherals.GPIO2);
785    /// # {after_snippet}
786    /// ```
787    pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
788        let mut this = Spi {
789            _mode: PhantomData,
790            spi: SpiWrapper::new(spi),
791        };
792
793        this.driver().init();
794        this.apply_config(&config)?;
795
796        let this = this.with_sck(NoPin).with_cs(NoPin);
797
798        for sio in 0..8 {
799            if let Some(signal) = this.driver().info.opt_sio_input(sio) {
800                signal.connect_to(&NoPin);
801            }
802            if let Some(signal) = this.driver().info.opt_sio_output(sio) {
803                signal.connect_to(&NoPin);
804            }
805        }
806
807        Ok(this)
808    }
809
810    /// Reconfigures the driver to operate in [`Async`] mode.
811    ///
812    /// See the [`Async`] documentation for an example on how to use this
813    /// method.
814    pub fn into_async(mut self) -> Spi<'d, Async> {
815        self.set_interrupt_handler(self.spi.info().async_handler);
816        Spi {
817            spi: self.spi,
818            _mode: PhantomData,
819        }
820    }
821
822    #[doc_replace(
823        "peripheral_on" => {
824            cfg(multi_core) => "peripheral on the current core",
825            _ => "peripheral",
826        }
827    )]
828    /// # Registers an interrupt handler for the __peripheral_on__.
829    ///
830    /// Note that this will replace any previously registered interrupt
831    /// handlers.
832    ///
833    /// You can restore the default/unhandled interrupt handler by using
834    /// [crate::interrupt::DEFAULT_INTERRUPT_HANDLER]
835    ///
836    /// # Panics
837    ///
838    /// Panics if passed interrupt handler is invalid (e.g. has priority
839    /// `None`)
840    #[instability::unstable]
841    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
842        self.spi.set_interrupt_handler(handler);
843    }
844}
845
846#[instability::unstable]
847impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
848    /// Sets the interrupt handler
849    ///
850    /// Interrupts are not enabled at the peripheral level here.
851    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
852        self.set_interrupt_handler(handler);
853    }
854}
855
856impl<'d> Spi<'d, Async> {
857    /// Reconfigures the driver to operate in [`Blocking`] mode.
858    ///
859    /// See the [`Blocking`] documentation for an example on how to use this
860    /// method.
861    pub fn into_blocking(self) -> Spi<'d, Blocking> {
862        self.spi.disable_peri_interrupt_on_all_cores();
863        Spi {
864            spi: self.spi,
865            _mode: PhantomData,
866        }
867    }
868
869    #[procmacros::doc_replace]
870    /// Waits for the completion of previous operations.
871    ///
872    /// ## Example
873    ///
874    /// ```rust, no_run
875    /// # {before_snippet}
876    /// use esp_hal::spi::{
877    ///     Mode,
878    ///     master::{Config, Spi},
879    /// };
880    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
881    ///     .with_sck(peripherals.GPIO0)
882    ///     .with_mosi(peripherals.GPIO1)
883    ///     .with_miso(peripherals.GPIO2)
884    ///     .into_async();
885    ///
886    /// let mut buffer = [0; 10];
887    /// spi.transfer_in_place_async(&mut buffer).await?;
888    /// spi.flush_async().await?;
889    ///
890    /// # {after_snippet}
891    /// ```
892    pub async fn flush_async(&mut self) -> Result<(), Error> {
893        self.driver().flush_async().await;
894        Ok(())
895    }
896
897    #[procmacros::doc_replace]
898    /// Sends `words` to the slave. Returns the `words` received from the slave.
899    ///
900    /// This function aborts the transfer when its Future is dropped. Some
901    /// amount of data may have been transferred before the Future is
902    /// dropped. Dropping the future may block for a short while to ensure
903    /// the transfer is aborted.
904    ///
905    /// ## Example
906    ///
907    /// ```rust, no_run
908    /// # {before_snippet}
909    /// use esp_hal::spi::{
910    ///     Mode,
911    ///     master::{Config, Spi},
912    /// };
913    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
914    ///     .with_sck(peripherals.GPIO0)
915    ///     .with_mosi(peripherals.GPIO1)
916    ///     .with_miso(peripherals.GPIO2)
917    ///     .into_async();
918    ///
919    /// let mut buffer = [0; 10];
920    /// spi.transfer_in_place_async(&mut buffer).await?;
921    ///
922    /// # {after_snippet}
923    /// ```
924    pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
925        // We need to flush because the blocking transfer functions may return while a
926        // transfer is still in progress.
927        self.driver().flush_async().await;
928        self.driver().setup_full_duplex()?;
929
930        self.driver().transfer_in_place_async(words).await
931    }
932
933    // TODO: These inherent methods should be public
934
935    async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
936        // We need to flush because the blocking transfer functions may return while a
937        // transfer is still in progress.
938        self.driver().flush_async().await;
939        self.driver().setup_full_duplex()?;
940
941        self.driver().read_async(words).await
942    }
943
944    async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
945        // We need to flush because the blocking transfer functions may return while a
946        // transfer is still in progress.
947        self.driver().flush_async().await;
948        self.driver().setup_full_duplex()?;
949
950        self.driver().write_async(words).await
951    }
952}
953
954macro_rules! def_with_sio_pin {
955    ($fn:ident, $n:literal) => {
956        #[doc = concat!(" Assign the SIO", stringify!($n), " pin for the SPI instance.")]
957        #[doc = " "]
958        #[doc = " Enables both input and output functionality for the pin, and connects it"]
959        #[doc = concat!(" to the SIO", stringify!($n), " output and input signals.")]
960        #[instability::unstable]
961        pub fn $fn(mut self, sio: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
962            self.spi.pins().sio_pins[$n] = self.connect_sio_pin(sio.into(), $n);
963
964            self
965        }
966    };
967}
968
969impl<'d, Dm> Spi<'d, Dm>
970where
971    Dm: DriverMode,
972{
973    fn connect_sio_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
974        let in_signal = self.spi.info().sio_input(n);
975        let out_signal = self.spi.info().sio_output(n);
976
977        pin.apply_input_config(&InputConfig::default());
978        pin.apply_output_config(&OutputConfig::default());
979
980        pin.set_input_enable(true);
981        pin.set_output_enable(false);
982
983        in_signal.connect_to(&pin);
984        pin.connect_with_guard(out_signal)
985    }
986
987    fn connect_sio_output_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
988        let out_signal = self.spi.info().sio_output(n);
989
990        self.connect_output_pin(pin, out_signal)
991    }
992
993    fn connect_output_pin(
994        &self,
995        pin: interconnect::OutputSignal<'d>,
996        signal: OutputSignal,
997    ) -> PinGuard {
998        pin.apply_output_config(&OutputConfig::default());
999        pin.set_output_enable(true); // TODO turn this bool into a Yes/No/PeripheralControl trio
1000
1001        pin.connect_with_guard(signal)
1002    }
1003
1004    #[procmacros::doc_replace]
1005    /// Assign the SCK (Serial Clock) pin for the SPI instance.
1006    ///
1007    /// Configures the specified pin to push-pull output and connects it to the
1008    /// SPI clock signal.
1009    ///
1010    /// Disconnects the previous pin that was assigned with `with_sck`.
1011    ///
1012    /// ## Example
1013    ///
1014    /// ```rust, no_run
1015    /// # {before_snippet}
1016    /// use esp_hal::spi::{
1017    ///     Mode,
1018    ///     master::{Config, Spi},
1019    /// };
1020    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_sck(peripherals.GPIO0);
1021    ///
1022    /// # {after_snippet}
1023    /// ```
1024    pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
1025        let info = self.spi.info();
1026        self.spi.pins().sclk_pin = self.connect_output_pin(sclk.into(), info.sclk);
1027
1028        self
1029    }
1030
1031    #[procmacros::doc_replace]
1032    /// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
1033    ///
1034    /// Enables output functionality for the pin, and connects it as the MOSI
1035    /// signal. You want to use this for full-duplex SPI or
1036    /// if you intend to use [DataMode::SingleTwoDataLines].
1037    ///
1038    /// Disconnects the previous pin that was assigned with `with_mosi` or
1039    /// `with_sio0`.
1040    ///
1041    /// ## Example
1042    ///
1043    /// ```rust, no_run
1044    /// # {before_snippet}
1045    /// use esp_hal::spi::{
1046    ///     Mode,
1047    ///     master::{Config, Spi},
1048    /// };
1049    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_mosi(peripherals.GPIO1);
1050    ///
1051    /// # {after_snippet}
1052    /// ```
1053    pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
1054        self.spi.pins().sio_pins[0] = self.connect_sio_output_pin(mosi.into(), 0);
1055        self
1056    }
1057
1058    #[procmacros::doc_replace]
1059    /// Assign the MISO (Master In Slave Out) pin for the SPI instance.
1060    ///
1061    /// Enables input functionality for the pin, and connects it to the MISO
1062    /// signal.
1063    ///
1064    /// You want to use this for full-duplex SPI or
1065    /// [DataMode::SingleTwoDataLines]
1066    ///
1067    /// ## Example
1068    ///
1069    /// ```rust, no_run
1070    /// # {before_snippet}
1071    /// use esp_hal::spi::{
1072    ///     Mode,
1073    ///     master::{Config, Spi},
1074    /// };
1075    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_miso(peripherals.GPIO2);
1076    ///
1077    /// # {after_snippet}
1078    /// ```
1079    pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
1080        let miso = miso.into();
1081
1082        miso.apply_input_config(&InputConfig::default());
1083        miso.set_input_enable(true);
1084
1085        self.driver().info.sio_input(1).connect_to(&miso);
1086
1087        self
1088    }
1089
1090    /// Assign the SIO0 pin for the SPI instance.
1091    ///
1092    /// Enables both input and output functionality for the pin, and connects it
1093    /// to the MOSI output signal and SIO0 input signal.
1094    ///
1095    /// Disconnects the previous pin that was assigned with `with_sio0` or
1096    /// `with_mosi`.
1097    ///
1098    /// Use this if any of the devices on the bus use half-duplex SPI.
1099    ///
1100    /// See also [Self::with_mosi] when you only need a one-directional MOSI
1101    /// signal.
1102    #[instability::unstable]
1103    pub fn with_sio0(mut self, mosi: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1104        self.spi.pins().sio_pins[0] = self.connect_sio_pin(mosi.into(), 0);
1105
1106        self
1107    }
1108
1109    /// Assign the SIO1/MISO pin for the SPI instance.
1110    ///
1111    /// Enables both input and output functionality for the pin, and connects it
1112    /// to the MISO input signal and SIO1 output signal.
1113    ///
1114    /// Disconnects the previous pin that was assigned with `with_sio1`.
1115    ///
1116    /// Use this if any of the devices on the bus use half-duplex SPI.
1117    ///
1118    /// See also [Self::with_miso] when you only need a one-directional MISO
1119    /// signal.
1120    #[instability::unstable]
1121    pub fn with_sio1(mut self, sio1: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1122        self.spi.pins().sio_pins[1] = self.connect_sio_pin(sio1.into(), 1);
1123
1124        self
1125    }
1126
1127    def_with_sio_pin!(with_sio2, 2);
1128    def_with_sio_pin!(with_sio3, 3);
1129
1130    #[cfg(spi_master_has_octal)]
1131    def_with_sio_pin!(with_sio4, 4);
1132
1133    #[cfg(spi_master_has_octal)]
1134    def_with_sio_pin!(with_sio5, 5);
1135
1136    #[cfg(spi_master_has_octal)]
1137    def_with_sio_pin!(with_sio6, 6);
1138
1139    #[cfg(spi_master_has_octal)]
1140    def_with_sio_pin!(with_sio7, 7);
1141
1142    /// Assign the CS (Chip Select) pin for the SPI instance.
1143    ///
1144    /// Configures the specified pin to push-pull output and connects it to the
1145    /// SPI CS signal.
1146    ///
1147    /// Disconnects the previous pin that was assigned with `with_cs`.
1148    ///
1149    /// # Current Stability Limitations
1150    /// The hardware chip select functionality is limited; only one CS line can
1151    /// be set, regardless of the total number available. There is no
1152    /// mechanism to select which CS line to use.
1153    #[instability::unstable]
1154    pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
1155        let info = self.spi.info();
1156        self.spi.pins().cs_pin = self.connect_output_pin(cs.into(), info.cs(0));
1157
1158        self
1159    }
1160
1161    #[doc_replace(
1162        "max_frequency" => {
1163            cfg(esp32h2) => "48MHz",
1164            _ => "80MHz",
1165        }
1166    )]
1167    /// Change the bus configuration.
1168    ///
1169    /// # Errors
1170    ///
1171    /// If frequency passed in config exceeds __max_frequency__ or is below 70kHz,
1172    /// [`ConfigError::FrequencyOutOfRange`] error will be returned.
1173    ///
1174    /// ## Example
1175    ///
1176    /// ```rust, no_run
1177    /// # {before_snippet}
1178    /// use esp_hal::spi::{
1179    ///     Mode,
1180    ///     master::{Config, Spi},
1181    /// };
1182    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?;
1183    ///
1184    /// spi.apply_config(&Config::default().with_frequency(Rate::from_khz(100)));
1185    /// #
1186    /// # {after_snippet}
1187    /// ```
1188    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1189        self.driver().apply_config(config)
1190    }
1191
1192    #[procmacros::doc_replace]
1193    /// Write bytes to SPI. After writing, flush is called to ensure all data
1194    /// has been transmitted.
1195    ///
1196    /// ## Example
1197    ///
1198    /// ```rust, no_run
1199    /// # {before_snippet}
1200    /// use esp_hal::spi::{
1201    ///     Mode,
1202    ///     master::{Config, Spi},
1203    /// };
1204    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1205    ///     .with_sck(peripherals.GPIO0)
1206    ///     .with_mosi(peripherals.GPIO1)
1207    ///     .with_miso(peripherals.GPIO2)
1208    ///     .into_async();
1209    ///
1210    /// let buffer = [0; 10];
1211    /// spi.write(&buffer)?;
1212    ///
1213    /// # {after_snippet}
1214    /// ```
1215    pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
1216        self.driver().flush()?;
1217        self.driver().setup_full_duplex()?;
1218
1219        for chunk in words.chunks(FIFO_SIZE) {
1220            self.driver().write_one(chunk)?;
1221            // NOTE: While we don't need to flush after the last chunk, changing
1222            // that would change the behavior of the function.
1223            // https://github.com/esp-rs/esp-hal/issues/5257
1224            self.driver().flush()?;
1225        }
1226
1227        Ok(())
1228    }
1229
1230    #[procmacros::doc_replace]
1231    /// Read bytes from SPI. The provided slice is filled with data received
1232    /// from the slave.
1233    ///
1234    /// ## Example
1235    ///
1236    /// ```rust, no_run
1237    /// # {before_snippet}
1238    /// use esp_hal::spi::{
1239    ///     Mode,
1240    ///     master::{Config, Spi},
1241    /// };
1242    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1243    ///     .with_sck(peripherals.GPIO0)
1244    ///     .with_mosi(peripherals.GPIO1)
1245    ///     .with_miso(peripherals.GPIO2)
1246    ///     .into_async();
1247    ///
1248    /// let mut buffer = [0; 10];
1249    /// spi.read(&mut buffer)?;
1250    ///
1251    /// # {after_snippet}
1252    /// ```
1253    pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
1254        self.driver().flush()?;
1255        self.driver().setup_full_duplex()?;
1256        self.driver().read(words)
1257    }
1258
1259    #[procmacros::doc_replace]
1260    /// Sends `words` to the slave. The received data will be written to
1261    /// `words`, overwriting its contents.
1262    ///
1263    /// ## Example
1264    ///
1265    /// ```rust, no_run
1266    /// # {before_snippet}
1267    /// use esp_hal::spi::{
1268    ///     Mode,
1269    ///     master::{Config, Spi},
1270    /// };
1271    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1272    ///     .with_sck(peripherals.GPIO0)
1273    ///     .with_mosi(peripherals.GPIO1)
1274    ///     .with_miso(peripherals.GPIO2)
1275    ///     .into_async();
1276    ///
1277    /// let mut buffer = [0; 10];
1278    /// spi.transfer(&mut buffer)?;
1279    ///
1280    /// # {after_snippet}
1281    /// ```
1282    pub fn transfer(&mut self, words: &mut [u8]) -> Result<(), Error> {
1283        self.driver().flush()?;
1284        self.driver().setup_full_duplex()?;
1285        self.driver().transfer_in_place(words)
1286    }
1287
1288    /// Half-duplex read.
1289    ///
1290    /// # Errors
1291    ///
1292    /// [`Error::FifoSizeExeeded`] or [`Error::Unsupported`] will be returned if
1293    /// passed buffer is bigger than FIFO size or if buffer is empty (currently
1294    /// unsupported). `DataMode::Single` cannot be combined with any other
1295    /// [`DataMode`], otherwise [`Error::Unsupported`] will be returned.
1296    #[instability::unstable]
1297    pub fn half_duplex_read(
1298        &mut self,
1299        data_mode: DataMode,
1300        cmd: Command,
1301        address: Address,
1302        dummy: u8,
1303        buffer: &mut [u8],
1304    ) -> Result<(), Error> {
1305        if buffer.len() > FIFO_SIZE {
1306            return Err(Error::FifoSizeExeeded);
1307        }
1308
1309        if buffer.is_empty() {
1310            error!("Half-duplex mode does not support empty buffer");
1311            return Err(Error::Unsupported);
1312        }
1313
1314        self.flush()?;
1315        self.driver().setup_half_duplex(
1316            false,
1317            cmd,
1318            address,
1319            false,
1320            dummy,
1321            buffer.is_empty(),
1322            data_mode,
1323        )?;
1324
1325        self.driver().configure_datalen(buffer.len(), 0);
1326        self.driver().start_operation();
1327        self.driver().flush()?;
1328        self.driver().read_from_fifo(buffer)
1329    }
1330
1331    /// Half-duplex write.
1332    ///
1333    /// # Errors
1334    ///
1335    /// [`Error::FifoSizeExeeded`] will be returned if
1336    /// passed buffer is bigger than FIFO size.
1337    #[cfg_attr(
1338        esp32,
1339        doc = "Dummy phase configuration is currently not supported, only value `0` is valid (see issue [#2240](https://github.com/esp-rs/esp-hal/issues/2240))."
1340    )]
1341    #[instability::unstable]
1342    pub fn half_duplex_write(
1343        &mut self,
1344        data_mode: DataMode,
1345        cmd: Command,
1346        address: Address,
1347        dummy: u8,
1348        buffer: &[u8],
1349    ) -> Result<(), Error> {
1350        if buffer.len() > FIFO_SIZE {
1351            return Err(Error::FifoSizeExeeded);
1352        }
1353
1354        self.flush()?;
1355
1356        cfg_if::cfg_if! {
1357            if #[cfg(all(esp32, spi_address_workaround))] {
1358                let mut buffer = buffer;
1359                let mut data_mode = data_mode;
1360                let mut address = address;
1361                let addr_bytes;
1362                if buffer.is_empty() && !address.is_none() {
1363                    // If the buffer is empty, we need to send a dummy byte
1364                    // to trigger the address phase.
1365                    let bytes_to_write = address.width().div_ceil(8);
1366                    // The address register is read in big-endian order,
1367                    // we have to prepare the emulated write in the same way.
1368                    addr_bytes = address.value().to_be_bytes();
1369                    buffer = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1370                    data_mode = address.mode();
1371                    address = Address::None;
1372                }
1373
1374                if dummy > 0 {
1375                    // FIXME: https://github.com/esp-rs/esp-hal/issues/2240
1376                    error!("Dummy bits are not supported without data");
1377                    return Err(Error::Unsupported);
1378                }
1379            }
1380        }
1381
1382        self.driver().setup_half_duplex(
1383            true,
1384            cmd,
1385            address,
1386            false,
1387            dummy,
1388            buffer.is_empty(),
1389            data_mode,
1390        )?;
1391
1392        if !buffer.is_empty() {
1393            self.driver().configure_datalen(0, buffer.len());
1394            self.driver().fill_fifo(buffer);
1395        }
1396
1397        self.driver().start_operation();
1398
1399        self.driver().flush()
1400    }
1401
1402    fn driver(&self) -> Driver {
1403        Driver {
1404            info: self.spi.info(),
1405            state: self.spi.state(),
1406        }
1407    }
1408}
1409
1410#[instability::unstable]
1411impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
1412where
1413    Dm: DriverMode,
1414{
1415    type Config = Config;
1416    type ConfigError = ConfigError;
1417
1418    fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1419        self.apply_config(config)
1420    }
1421}
1422
1423impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
1424where
1425    Dm: DriverMode,
1426{
1427    type Error = Error;
1428}
1429
1430impl<Dm> SpiBus for Spi<'_, Dm>
1431where
1432    Dm: DriverMode,
1433{
1434    fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
1435        self.read(words)
1436    }
1437
1438    fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
1439        // Do not call the inherent `write` method. The trait impl does not flush after.
1440        // Flush before starting to ensure the bus is clear before we reconfigure to full duplex.
1441        self.driver().flush()?;
1442        self.driver().setup_full_duplex()?;
1443        for chunk in words.chunks(FIFO_SIZE) {
1444            self.driver().flush()?;
1445            self.driver().write_one(chunk)?;
1446        }
1447        Ok(())
1448    }
1449
1450    fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
1451        self.driver().flush()?;
1452        self.driver().setup_full_duplex()?;
1453
1454        if read.is_empty() {
1455            self.driver().write(write)
1456        } else if write.is_empty() {
1457            self.driver().read(read)
1458        } else {
1459            self.driver().transfer(read, write)
1460        }
1461    }
1462
1463    fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
1464        self.driver().flush()?;
1465        self.driver().setup_full_duplex()?;
1466        self.driver().transfer_in_place(words)
1467    }
1468
1469    fn flush(&mut self) -> Result<(), Self::Error> {
1470        self.driver().flush()
1471    }
1472}
1473
1474impl SpiBusAsync for Spi<'_, Async> {
1475    async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
1476        self.read_async(words).await
1477    }
1478
1479    async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
1480        self.write_async(words).await
1481    }
1482
1483    async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
1484        self.driver().flush_async().await;
1485        self.driver().setup_full_duplex()?;
1486
1487        if read.is_empty() {
1488            self.driver().write_async(write).await
1489        } else if write.is_empty() {
1490            self.driver().read_async(read).await
1491        } else {
1492            self.driver().transfer_async(read, write).await
1493        }
1494    }
1495
1496    async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
1497        self.transfer_in_place_async(words).await
1498    }
1499
1500    async fn flush(&mut self) -> Result<(), Self::Error> {
1501        self.flush_async().await
1502    }
1503}
1504
1505/// SPI peripheral instance.
1506pub trait Instance: private::Sealed + any::Degrade {
1507    #[doc(hidden)]
1508    /// Returns the peripheral data and state describing this instance.
1509    fn parts(&self) -> (&'static Info, &'static State);
1510
1511    /// Returns the peripheral data describing this instance.
1512    #[doc(hidden)]
1513    #[inline(always)]
1514    fn info(&self) -> &'static Info {
1515        self.parts().0
1516    }
1517
1518    /// Returns the peripheral state for this instance.
1519    #[doc(hidden)]
1520    #[inline(always)]
1521    fn state(&self) -> &'static State {
1522        self.parts().1
1523    }
1524}
1525
1526/// Marker trait for QSPI-capable SPI peripherals.
1527#[doc(hidden)]
1528pub trait QspiInstance: Instance {}
1529
1530/// Peripheral data describing a particular SPI instance.
1531#[doc(hidden)]
1532#[non_exhaustive]
1533#[allow(private_interfaces, reason = "Unstable details")]
1534pub struct Info {
1535    /// Pointer to the register block for this SPI instance.
1536    ///
1537    /// Use [Self::register_block] to access the register block.
1538    pub register_block: *const RegisterBlock,
1539
1540    /// The system peripheral marker.
1541    pub peripheral: crate::system::Peripheral,
1542
1543    /// Interrupt handler for the asynchronous operations.
1544    pub async_handler: InterruptHandler,
1545
1546    /// SCLK signal.
1547    pub sclk: OutputSignal,
1548
1549    /// Chip select signals.
1550    pub cs: &'static [OutputSignal],
1551
1552    pub sio_inputs: &'static [InputSignal],
1553    pub sio_outputs: &'static [OutputSignal],
1554}
1555
1556impl Info {
1557    fn cs(&self, n: usize) -> OutputSignal {
1558        *unwrap!(self.cs.get(n), "CS{} is not defined", n)
1559    }
1560
1561    fn opt_sio_input(&self, n: usize) -> Option<InputSignal> {
1562        self.sio_inputs.get(n).copied()
1563    }
1564
1565    fn opt_sio_output(&self, n: usize) -> Option<OutputSignal> {
1566        self.sio_outputs.get(n).copied()
1567    }
1568
1569    fn sio_input(&self, n: usize) -> InputSignal {
1570        unwrap!(self.opt_sio_input(n), "SIO{} is not defined", n)
1571    }
1572
1573    fn sio_output(&self, n: usize) -> OutputSignal {
1574        unwrap!(self.opt_sio_output(n), "SIO{} is not defined", n)
1575    }
1576}
1577
1578struct Driver {
1579    info: &'static Info,
1580    state: &'static State,
1581}
1582
1583// private implementation bits
1584// FIXME: split this up into peripheral versions
1585impl Driver {
1586    /// Returns the register block for this SPI instance.
1587    pub fn regs(&self) -> &RegisterBlock {
1588        unsafe { &*self.info.register_block }
1589    }
1590
1591    fn abort_transfer(&self) {
1592        // Note(danielb): This method came later than DmaDriver::abort_transfer. That
1593        // function works for DMA so I have left it unchanged, but does not work
1594        // for CPU-controlled transfers on the ESP32. Toggling slave mode works on
1595        // ESP32, but not on later chips.
1596        cfg_if::cfg_if! {
1597            if #[cfg(esp32)] {
1598                self.regs().slave().toggle(|w, en| w.mode().bit(en));
1599            } else {
1600                self.configure_datalen(1, 1);
1601            }
1602        }
1603        self.update();
1604    }
1605
1606    /// Initialize for full-duplex 1 bit mode
1607    fn init(&self) {
1608        self.regs().user().modify(|_, w| {
1609            w.usr_miso_highpart().clear_bit();
1610            w.usr_mosi_highpart().clear_bit();
1611            w.doutdin().set_bit();
1612            w.usr_miso().set_bit();
1613            w.usr_mosi().set_bit();
1614            w.cs_hold().set_bit();
1615            w.usr_dummy_idle().set_bit();
1616            w.usr_addr().clear_bit();
1617            w.usr_command().clear_bit()
1618        });
1619
1620        #[cfg(not(any(esp32, esp32s2)))]
1621        self.regs().clk_gate().modify(|_, w| {
1622            w.clk_en().set_bit();
1623            w.mst_clk_active().set_bit();
1624            w.mst_clk_sel().set_bit()
1625        });
1626
1627        #[cfg(soc_has_pcr)]
1628        unsafe {
1629            // use default clock source
1630            crate::peripherals::PCR::regs()
1631                .spi2_clkm_conf()
1632                .modify(|_, w| {
1633                    #[cfg(spi_master_has_clk_pre_div)]
1634                    w.spi2_clkm_div_num().bits(1);
1635                    w.spi2_clkm_sel().bits(1);
1636                    w.spi2_clkm_en().set_bit()
1637                });
1638        }
1639
1640        cfg_if::cfg_if! {
1641            if #[cfg(esp32)] {
1642                self.regs().ctrl().modify(|_, w| w.wp().clear_bit());
1643            } else {
1644                self.regs().ctrl().modify(|_, w| {
1645                    w.q_pol().clear_bit();
1646                    w.d_pol().clear_bit();
1647                    #[cfg(esp32s2)]
1648                    w.wp().clear_bit();
1649                    #[cfg(not(esp32s2))]
1650                    w.hold_pol().clear_bit();
1651                    w
1652                });
1653                self.regs().misc().write(|w| unsafe { w.bits(0) });
1654            }
1655        }
1656
1657        self.regs().slave().write(|w| unsafe { w.bits(0) });
1658    }
1659
1660    #[cfg(not(esp32))]
1661    fn init_spi_data_mode(
1662        &self,
1663        cmd_mode: DataMode,
1664        address_mode: DataMode,
1665        data_mode: DataMode,
1666    ) -> Result<(), Error> {
1667        self.regs().ctrl().modify(|_, w| {
1668            w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
1669            w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
1670            w.faddr_dual().bit(address_mode == DataMode::Dual);
1671            w.faddr_quad().bit(address_mode == DataMode::Quad);
1672            w.fread_dual().bit(data_mode == DataMode::Dual);
1673            w.fread_quad().bit(data_mode == DataMode::Quad)
1674        });
1675        self.regs().user().modify(|_, w| {
1676            w.fwrite_dual().bit(data_mode == DataMode::Dual);
1677            w.fwrite_quad().bit(data_mode == DataMode::Quad)
1678        });
1679        Ok(())
1680    }
1681
1682    #[cfg(esp32)]
1683    fn init_spi_data_mode(
1684        &self,
1685        cmd_mode: DataMode,
1686        address_mode: DataMode,
1687        data_mode: DataMode,
1688    ) -> Result<(), Error> {
1689        match cmd_mode {
1690            DataMode::Single => (),
1691            DataMode::SingleTwoDataLines => (),
1692            // FIXME: more detailed error - Only 1-bit commands are supported.
1693            _ => {
1694                error!("Commands must be single bit wide");
1695                return Err(Error::Unsupported);
1696            }
1697        }
1698
1699        match address_mode {
1700            DataMode::Single | DataMode::SingleTwoDataLines => {
1701                self.regs().ctrl().modify(|_, w| {
1702                    w.fastrd_mode()
1703                        .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
1704                    w.fread_dio().clear_bit();
1705                    w.fread_qio().clear_bit();
1706                    w.fread_dual().bit(data_mode == DataMode::Dual);
1707                    w.fread_quad().bit(data_mode == DataMode::Quad)
1708                });
1709
1710                self.regs().user().modify(|_, w| {
1711                    w.fwrite_dio().clear_bit();
1712                    w.fwrite_qio().clear_bit();
1713                    w.fwrite_dual().bit(data_mode == DataMode::Dual);
1714                    w.fwrite_quad().bit(data_mode == DataMode::Quad)
1715                });
1716            }
1717            address_mode if address_mode == data_mode => {
1718                self.regs().ctrl().modify(|_, w| {
1719                    w.fastrd_mode()
1720                        .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
1721                    w.fread_dio().bit(address_mode == DataMode::Dual);
1722                    w.fread_qio().bit(address_mode == DataMode::Quad);
1723                    w.fread_dual().clear_bit();
1724                    w.fread_quad().clear_bit()
1725                });
1726
1727                self.regs().user().modify(|_, w| {
1728                    w.fwrite_dio().bit(address_mode == DataMode::Dual);
1729                    w.fwrite_qio().bit(address_mode == DataMode::Quad);
1730                    w.fwrite_dual().clear_bit();
1731                    w.fwrite_quad().clear_bit()
1732                });
1733            }
1734            _ => {
1735                // FIXME: more detailed error - Unsupported combination of data-modes
1736                error!("Address mode must be single bit wide or equal to the data mode");
1737                return Err(Error::Unsupported);
1738            }
1739        }
1740
1741        Ok(())
1742    }
1743
1744    /// Enable or disable listening for the given interrupts.
1745    #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
1746    fn enable_listen(&self, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
1747        cfg_if::cfg_if! {
1748            if #[cfg(esp32)] {
1749                self.regs().slave().modify(|_, w| {
1750                    for interrupt in interrupts {
1751                        match interrupt {
1752                            SpiInterrupt::TransferDone => w.trans_inten().bit(enable),
1753                        };
1754                    }
1755                    w
1756                });
1757            } else if #[cfg(esp32s2)] {
1758                self.regs().slave().modify(|_, w| {
1759                    for interrupt in interrupts {
1760                        match interrupt {
1761                            SpiInterrupt::TransferDone => w.int_trans_done_en().bit(enable),
1762                            SpiInterrupt::DmaSegmentedTransferDone => w.int_dma_seg_trans_en().bit(enable),
1763                        };
1764                    }
1765                    w
1766                });
1767            } else {
1768                self.regs().dma_int_ena().modify(|_, w| {
1769                    for interrupt in interrupts {
1770                        match interrupt {
1771                            SpiInterrupt::TransferDone => w.trans_done().bit(enable),
1772                            #[cfg(spi_master_has_dma_segmented_transfer)]
1773                            SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
1774                            #[cfg(spi_master_has_app_interrupts)]
1775                            SpiInterrupt::App2 => w.app2().bit(enable),
1776                            #[cfg(spi_master_has_app_interrupts)]
1777                            SpiInterrupt::App1 => w.app1().bit(enable),
1778                        };
1779                    }
1780                    w
1781                });
1782            }
1783        }
1784    }
1785
1786    /// Gets asserted interrupts
1787    #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
1788    fn interrupts(&self) -> EnumSet<SpiInterrupt> {
1789        let mut res = EnumSet::new();
1790
1791        cfg_if::cfg_if! {
1792            if #[cfg(esp32)] {
1793                if self.regs().slave().read().trans_done().bit() {
1794                    res.insert(SpiInterrupt::TransferDone);
1795                }
1796            } else if #[cfg(esp32s2)] {
1797                if self.regs().slave().read().trans_done().bit() {
1798                    res.insert(SpiInterrupt::TransferDone);
1799                }
1800                if self.regs().hold().read().dma_seg_trans_done().bit() {
1801                    res.insert(SpiInterrupt::DmaSegmentedTransferDone);
1802                }
1803            } else {
1804                let ints = self.regs().dma_int_raw().read();
1805
1806                if ints.trans_done().bit() {
1807                    res.insert(SpiInterrupt::TransferDone);
1808                }
1809                #[cfg(spi_master_has_dma_segmented_transfer)]
1810                if ints.dma_seg_trans_done().bit() {
1811                    res.insert(SpiInterrupt::DmaSegmentedTransferDone);
1812                }
1813                #[cfg(spi_master_has_app_interrupts)]
1814                if ints.app2().bit() {
1815                    res.insert(SpiInterrupt::App2);
1816                }
1817                #[cfg(spi_master_has_app_interrupts)]
1818                if ints.app1().bit() {
1819                    res.insert(SpiInterrupt::App1);
1820                }
1821            }
1822        }
1823
1824        res
1825    }
1826
1827    /// Resets asserted interrupts
1828    fn clear_interrupts(&self, interrupts: EnumSet<SpiInterrupt>) {
1829        cfg_if::cfg_if! {
1830            if #[cfg(esp32)] {
1831                for interrupt in interrupts {
1832                    match interrupt {
1833                        SpiInterrupt::TransferDone => {
1834                            self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
1835                        }
1836                    }
1837                }
1838            } else if #[cfg(esp32s2)] {
1839                for interrupt in interrupts {
1840                    match interrupt {
1841                        SpiInterrupt::TransferDone => {
1842                            self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
1843                        }
1844
1845                        SpiInterrupt::DmaSegmentedTransferDone => {
1846                            self.regs()
1847                                .hold()
1848                                .modify(|_, w| w.dma_seg_trans_done().clear_bit());
1849                        }
1850                    }
1851                }
1852            } else {
1853                self.regs().dma_int_clr().write(|w| {
1854                    for interrupt in interrupts {
1855                        match interrupt {
1856                            SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
1857                            #[cfg(spi_master_has_dma_segmented_transfer)]
1858                            SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
1859                            #[cfg(spi_master_has_app_interrupts)]
1860                            SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
1861                            #[cfg(spi_master_has_app_interrupts)]
1862                            SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
1863                        };
1864                    }
1865                    w
1866                });
1867            }
1868        }
1869    }
1870
1871    fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
1872        config.validate()?;
1873        self.ch_bus_freq(config)?;
1874        self.set_bit_order(config.read_bit_order, config.write_bit_order);
1875        self.set_data_mode(config.mode);
1876
1877        #[cfg(esp32)]
1878        self.calculate_half_duplex_values(config);
1879
1880        Ok(())
1881    }
1882
1883    #[cfg(esp32)]
1884    fn calculate_half_duplex_values(&self, config: &Config) {
1885        let f_apb = 80_000_000;
1886        let source_freq_hz = match config.clock_source {
1887            ClockSource::Apb => f_apb,
1888        };
1889
1890        let clock_reg = self.regs().clock().read();
1891        let eff_clk = if clock_reg.clk_equ_sysclk().bit_is_set() {
1892            f_apb
1893        } else {
1894            let pre = clock_reg.clkdiv_pre().bits() as i32 + 1;
1895            let n = clock_reg.clkcnt_n().bits() as i32 + 1;
1896            f_apb / (pre * n)
1897        };
1898
1899        let apbclk_khz = source_freq_hz / 1000;
1900        // how many apb clocks a period has
1901        let spiclk_apb_n = source_freq_hz / eff_clk;
1902
1903        // How many apb clocks the delay is, the 1 is to compensate in case
1904        // ``input_delay_ns`` is rounded off. Change from esp-idf: we use
1905        // `input_delay_ns` to also represent the GPIO matrix delay.
1906        let input_delay_ns = 25; // TODO: allow configuring input delay.
1907        let delay_apb_n = (1 + input_delay_ns) * apbclk_khz / 1000 / 1000;
1908
1909        let dummy_required = delay_apb_n / spiclk_apb_n;
1910        let timing_miso_delay = if dummy_required > 0 {
1911            // due to the clock delay between master and slave, there's a range in which
1912            // data is random give MISO a delay if needed to make sure we
1913            // sample at the time MISO is stable
1914            Some(((dummy_required + 1) * spiclk_apb_n - delay_apb_n - 1) as u8)
1915        } else if delay_apb_n * 4 <= spiclk_apb_n {
1916            // if the dummy is not required, maybe we should also delay half a SPI clock if
1917            // the data comes too early
1918            None
1919        } else {
1920            Some(0)
1921        };
1922
1923        self.state.esp32_hack.extra_dummy.set(dummy_required as u8);
1924        self.state
1925            .esp32_hack
1926            .timing_miso_delay
1927            .set(timing_miso_delay);
1928    }
1929
1930    fn set_data_mode(&self, data_mode: Mode) {
1931        cfg_if::cfg_if! {
1932            if #[cfg(esp32)] {
1933                let pin_reg = self.regs().pin();
1934            } else {
1935                let pin_reg = self.regs().misc();
1936            }
1937        };
1938
1939        pin_reg.modify(|_, w| {
1940            w.ck_idle_edge()
1941                .bit(matches!(data_mode, Mode::_2 | Mode::_3))
1942        });
1943        self.regs().user().modify(|_, w| {
1944            w.ck_out_edge()
1945                .bit(matches!(data_mode, Mode::_1 | Mode::_2))
1946        });
1947    }
1948
1949    fn ch_bus_freq(&self, bus_clock_config: &Config) -> Result<(), ConfigError> {
1950        fn enable_clocks(_reg_block: &RegisterBlock, _enable: bool) {
1951            #[cfg(not(any(esp32, esp32s2)))]
1952            _reg_block.clk_gate().modify(|_, w| {
1953                w.clk_en().bit(_enable);
1954                w.mst_clk_active().bit(_enable);
1955                w.mst_clk_sel().bit(true) // TODO: support XTAL clock source
1956            });
1957        }
1958
1959        // Change clock frequency
1960        let raw = bus_clock_config.raw_clock_reg_value()?;
1961
1962        enable_clocks(self.regs(), false);
1963        self.regs().clock().write(|w| unsafe { w.bits(raw) });
1964        enable_clocks(self.regs(), true);
1965
1966        Ok(())
1967    }
1968
1969    #[cfg(not(any(esp32, esp32c3, esp32s2)))]
1970    fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
1971        let read_value = match read_order {
1972            BitOrder::MsbFirst => 0,
1973            BitOrder::LsbFirst => 1,
1974        };
1975        let write_value = match write_order {
1976            BitOrder::MsbFirst => 0,
1977            BitOrder::LsbFirst => 1,
1978        };
1979        self.regs().ctrl().modify(|_, w| unsafe {
1980            w.rd_bit_order().bits(read_value);
1981            w.wr_bit_order().bits(write_value);
1982            w
1983        });
1984    }
1985
1986    #[cfg(any(esp32, esp32c3, esp32s2))]
1987    fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
1988        let read_value = match read_order {
1989            BitOrder::MsbFirst => false,
1990            BitOrder::LsbFirst => true,
1991        };
1992        let write_value = match write_order {
1993            BitOrder::MsbFirst => false,
1994            BitOrder::LsbFirst => true,
1995        };
1996        self.regs().ctrl().modify(|_, w| {
1997            w.rd_bit_order().bit(read_value);
1998            w.wr_bit_order().bit(write_value);
1999            w
2000        });
2001    }
2002
2003    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2004    fn fill_fifo(&self, chunk: &[u8]) {
2005        // TODO: replace with `array_chunks` and `from_le_bytes`
2006        let mut c_iter = chunk.chunks_exact(4);
2007        let mut w_iter = self.regs().w_iter();
2008        for c in c_iter.by_ref() {
2009            if let Some(w_reg) = w_iter.next() {
2010                let word = (c[0] as u32)
2011                    | ((c[1] as u32) << 8)
2012                    | ((c[2] as u32) << 16)
2013                    | ((c[3] as u32) << 24);
2014                w_reg.write(|w| w.buf().set(word));
2015            }
2016        }
2017        let rem = c_iter.remainder();
2018        if !rem.is_empty()
2019            && let Some(w_reg) = w_iter.next()
2020        {
2021            let word = match rem.len() {
2022                3 => (rem[0] as u32) | ((rem[1] as u32) << 8) | ((rem[2] as u32) << 16),
2023                2 => (rem[0] as u32) | ((rem[1] as u32) << 8),
2024                1 => rem[0] as u32,
2025                _ => unreachable!(),
2026            };
2027            w_reg.write(|w| w.buf().set(word));
2028        }
2029    }
2030
2031    /// Write bytes to SPI.
2032    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2033    fn write_one(&self, words: &[u8]) -> Result<(), Error> {
2034        if words.len() > FIFO_SIZE {
2035            return Err(Error::FifoSizeExeeded);
2036        }
2037        self.configure_datalen(0, words.len());
2038        self.fill_fifo(words);
2039        self.start_operation();
2040        Ok(())
2041    }
2042
2043    /// Write bytes to SPI.
2044    ///
2045    /// This function will return before all bytes of the last chunk to transmit
2046    /// have been sent to the wire. If you must ensure that the whole
2047    /// messages was written correctly, use [`Self::flush`].
2048    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2049    fn write(&self, words: &[u8]) -> Result<(), Error> {
2050        for chunk in words.chunks(FIFO_SIZE) {
2051            self.flush()?;
2052            self.write_one(chunk)?;
2053        }
2054        Ok(())
2055    }
2056
2057    /// Write bytes to SPI.
2058    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2059    async fn write_async(&self, words: &[u8]) -> Result<(), Error> {
2060        for chunk in words.chunks(FIFO_SIZE) {
2061            self.write_one(chunk)?;
2062            self.flush_async().await;
2063        }
2064        Ok(())
2065    }
2066
2067    /// Read bytes from SPI.
2068    ///
2069    /// Sends out a stuffing byte for every byte to read. This function doesn't
2070    /// perform flushing. If you want to read the response to something you
2071    /// have written before, consider using [`Self::transfer`] instead.
2072    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2073    fn read(&self, words: &mut [u8]) -> Result<(), Error> {
2074        let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
2075
2076        for chunk in words.chunks_mut(FIFO_SIZE) {
2077            self.write_one(&empty_array[0..chunk.len()])?;
2078            self.flush()?;
2079            self.read_from_fifo(chunk)?;
2080        }
2081        Ok(())
2082    }
2083
2084    /// Read bytes from SPI.
2085    ///
2086    /// Sends out a stuffing byte for every byte to read. If you want to read
2087    /// the response to something you have written before, consider using
2088    /// [`Self::transfer`] instead.
2089    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2090    async fn read_async(&self, words: &mut [u8]) -> Result<(), Error> {
2091        let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
2092
2093        for chunk in words.chunks_mut(FIFO_SIZE) {
2094            self.write_one(&empty_array[0..chunk.len()])?;
2095            self.flush_async().await;
2096            self.read_from_fifo(chunk)?;
2097        }
2098        Ok(())
2099    }
2100
2101    /// Read received bytes from SPI FIFO.
2102    ///
2103    /// Copies the contents of the SPI receive FIFO into `words`. This function
2104    /// doesn't perform any data transfer. If you want to read the response to
2105    /// something you have written before, consider using [`Self::transfer`]
2106    /// instead.
2107    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2108    fn read_from_fifo(&self, words: &mut [u8]) -> Result<(), Error> {
2109        if words.len() > FIFO_SIZE {
2110            return Err(Error::FifoSizeExeeded);
2111        }
2112
2113        for (chunk, w_reg) in words.chunks_mut(4).zip(self.regs().w_iter()) {
2114            let reg_val = w_reg.read().bits();
2115            let bytes = reg_val.to_le_bytes();
2116
2117            let len = chunk.len();
2118            chunk.copy_from_slice(&bytes[..len]);
2119        }
2120
2121        Ok(())
2122    }
2123
2124    fn busy(&self) -> bool {
2125        self.regs().cmd().read().usr().bit_is_set()
2126    }
2127
2128    // Check if the bus is busy and if it is wait for it to be idle
2129    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2130    fn flush_async(&self) -> impl Future<Output = ()> {
2131        SpiFuture { driver: self }
2132    }
2133
2134    // Check if the bus is busy and if it is wait for it to be idle
2135    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2136    fn flush(&self) -> Result<(), Error> {
2137        while self.busy() {
2138            // wait for bus to be clear
2139        }
2140        Ok(())
2141    }
2142
2143    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2144    fn transfer_in_place(&self, words: &mut [u8]) -> Result<(), Error> {
2145        for chunk in words.chunks_mut(FIFO_SIZE) {
2146            self.write_one(chunk)?;
2147            self.flush()?;
2148            self.read_from_fifo(chunk)?;
2149        }
2150
2151        Ok(())
2152    }
2153
2154    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2155    fn transfer(&self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2156        let mut write_from = 0;
2157        let mut read_from = 0;
2158
2159        loop {
2160            // How many bytes we write in this chunk
2161            let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2162            // How many bytes we read in this chunk
2163            let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2164
2165            if (write_inc == 0) && (read_inc == 0) {
2166                break;
2167            }
2168
2169            self.flush()?;
2170
2171            if write_inc < read_inc {
2172                // Read more than we write, must pad writing part with zeros
2173                let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2174                empty[0..write_inc].copy_from_slice(&write[write_from..][..write_inc]);
2175                self.write_one(&empty[..read_inc])?;
2176            } else {
2177                self.write_one(&write[write_from..][..write_inc])?;
2178            }
2179
2180            if read_inc > 0 {
2181                self.flush()?;
2182                self.read_from_fifo(&mut read[read_from..][..read_inc])?;
2183            }
2184
2185            write_from += write_inc;
2186            read_from += read_inc;
2187        }
2188        Ok(())
2189    }
2190
2191    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2192    async fn transfer_in_place_async(&self, words: &mut [u8]) -> Result<(), Error> {
2193        for chunk in words.chunks_mut(FIFO_SIZE) {
2194            // Cut the transfer short if the future is dropped. We'll block for a short
2195            // while to ensure the peripheral is idle.
2196            let cancel_on_drop = DropGuard::new((), |_| {
2197                self.abort_transfer();
2198                while self.busy() {}
2199            });
2200            let res = self.write_one(chunk);
2201            self.flush_async().await;
2202            cancel_on_drop.defuse();
2203            res?;
2204
2205            self.read_from_fifo(chunk)?;
2206        }
2207
2208        Ok(())
2209    }
2210
2211    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2212    async fn transfer_async(&self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2213        let mut write_from = 0;
2214        let mut read_from = 0;
2215
2216        loop {
2217            // How many bytes we write in this chunk
2218            let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2219            // How many bytes we read in this chunk
2220            let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2221
2222            if (write_inc == 0) && (read_inc == 0) {
2223                break;
2224            }
2225
2226            self.flush_async().await;
2227
2228            if write_inc < read_inc {
2229                // Read more than we write, must pad writing part with zeros
2230                let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2231                empty[0..write_inc].copy_from_slice(&write[write_from..][..write_inc]);
2232                self.write_one(&empty[..read_inc])?;
2233            } else {
2234                self.write_one(&write[write_from..][..write_inc])?;
2235            }
2236
2237            // Preserve previous semantics - see https://github.com/esp-rs/esp-hal/issues/5257
2238            self.flush_async().await;
2239            if read_inc > 0 {
2240                self.read_from_fifo(&mut read[read_from..][..read_inc])?;
2241            }
2242
2243            write_from += write_inc;
2244            read_from += read_inc;
2245        }
2246        Ok(())
2247    }
2248
2249    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2250    fn start_operation(&self) {
2251        self.update();
2252        self.clear_interrupts(SpiInterrupt::TransferDone.into());
2253        self.regs().cmd().modify(|_, w| w.usr().set_bit());
2254    }
2255
2256    fn setup_full_duplex(&self) -> Result<(), Error> {
2257        self.regs().user().modify(|_, w| {
2258            w.usr_miso().set_bit();
2259            w.usr_mosi().set_bit();
2260            w.doutdin().set_bit();
2261            w.usr_dummy().clear_bit();
2262            w.sio().clear_bit()
2263        });
2264
2265        self.init_spi_data_mode(
2266            DataMode::SingleTwoDataLines,
2267            DataMode::SingleTwoDataLines,
2268            DataMode::SingleTwoDataLines,
2269        )?;
2270
2271        // For full-duplex, we don't need compensation according to esp-idf.
2272        #[cfg(esp32)]
2273        self.regs().ctrl2().modify(|_, w| unsafe {
2274            w.miso_delay_mode().bits(0);
2275            w.miso_delay_num().bits(0)
2276        });
2277
2278        Ok(())
2279    }
2280
2281    #[expect(clippy::too_many_arguments)]
2282    fn setup_half_duplex(
2283        &self,
2284        is_write: bool,
2285        cmd: Command,
2286        address: Address,
2287        dummy_idle: bool,
2288        dummy: u8,
2289        no_mosi_miso: bool,
2290        data_mode: DataMode,
2291    ) -> Result<(), Error> {
2292        self.init_spi_data_mode(cmd.mode(), address.mode(), data_mode)?;
2293
2294        #[cfg(esp32)]
2295        let mut dummy = dummy;
2296
2297        #[cfg(esp32)]
2298        self.regs().ctrl2().modify(|_, w| {
2299            let mut delay_mode = 0;
2300            let mut delay_num = 0;
2301
2302            if !is_write {
2303                // Values are set up in apply_config
2304                let timing_miso_delay = self.state.esp32_hack.timing_miso_delay.get();
2305                let extra_dummy = self.state.esp32_hack.extra_dummy.get();
2306                dummy += extra_dummy;
2307
2308                if let Some(delay) = timing_miso_delay {
2309                    delay_num = if extra_dummy > 0 { delay } else { 0 };
2310                } else {
2311                    let out_edge = self.regs().user().read().ck_out_edge().bit_is_set();
2312                    // SPI modes 1 and 2 need delay mode 1 according to esp-idf.
2313                    delay_mode = if out_edge { 1 } else { 2 };
2314                }
2315            }
2316
2317            unsafe {
2318                w.miso_delay_mode().bits(delay_mode);
2319                w.miso_delay_num().bits(delay_num)
2320            }
2321        });
2322
2323        let reg_block = self.regs();
2324        reg_block.user().modify(|_, w| {
2325            w.usr_miso_highpart().clear_bit();
2326            w.usr_mosi_highpart().clear_bit();
2327            // This bit tells the hardware whether we use Single or SingleTwoDataLines
2328            w.sio().bit(data_mode == DataMode::Single);
2329            w.doutdin().clear_bit();
2330            w.usr_miso().bit(!is_write && !no_mosi_miso);
2331            w.usr_mosi().bit(is_write && !no_mosi_miso);
2332            w.cs_hold().set_bit();
2333            w.usr_dummy_idle().bit(dummy_idle);
2334            w.usr_dummy().bit(dummy != 0);
2335            w.usr_addr().bit(!address.is_none());
2336            w.usr_command().bit(!cmd.is_none())
2337        });
2338
2339        // FIXME why is clock config even here?
2340        #[cfg(not(any(esp32, esp32s2)))]
2341        reg_block.clk_gate().modify(|_, w| {
2342            w.clk_en().set_bit();
2343            w.mst_clk_active().set_bit();
2344            w.mst_clk_sel().set_bit()
2345        });
2346
2347        #[cfg(soc_has_pcr)]
2348        // use default clock source
2349        crate::peripherals::PCR::regs()
2350            .spi2_clkm_conf()
2351            .modify(|_, w| unsafe { w.spi2_clkm_sel().bits(1) });
2352
2353        #[cfg(not(esp32))]
2354        reg_block.misc().write(|w| unsafe { w.bits(0) });
2355
2356        reg_block.slave().write(|w| unsafe { w.bits(0) });
2357
2358        self.update();
2359
2360        // set cmd, address, dummy cycles
2361        self.set_up_common_phases(cmd, address, dummy);
2362
2363        Ok(())
2364    }
2365
2366    fn set_up_common_phases(&self, cmd: Command, address: Address, dummy: u8) {
2367        let reg_block = self.regs();
2368        if !cmd.is_none() {
2369            reg_block.user2().modify(|_, w| unsafe {
2370                w.usr_command_bitlen().bits((cmd.width() - 1) as u8);
2371                w.usr_command_value().bits(cmd.value())
2372            });
2373        }
2374
2375        if !address.is_none() {
2376            reg_block
2377                .user1()
2378                .modify(|_, w| unsafe { w.usr_addr_bitlen().bits((address.width() - 1) as u8) });
2379
2380            let addr = address.value() << (32 - address.width());
2381            #[cfg(not(esp32))]
2382            reg_block
2383                .addr()
2384                .write(|w| unsafe { w.usr_addr_value().bits(addr) });
2385            #[cfg(esp32)]
2386            reg_block.addr().write(|w| unsafe { w.bits(addr) });
2387        }
2388
2389        if dummy > 0 {
2390            reg_block
2391                .user1()
2392                .modify(|_, w| unsafe { w.usr_dummy_cyclelen().bits(dummy - 1) });
2393        }
2394    }
2395
2396    fn update(&self) {
2397        cfg_if::cfg_if! {
2398            if #[cfg(not(any(esp32, esp32s2)))] {
2399                let reg_block = self.regs();
2400
2401                reg_block.cmd().modify(|_, w| w.update().set_bit());
2402
2403                while reg_block.cmd().read().update().bit_is_set() {
2404                    // wait
2405                }
2406            } else {
2407                // Doesn't seem to be needed for ESP32 and ESP32-S2
2408            }
2409        }
2410    }
2411
2412    fn configure_datalen(&self, rx_len_bytes: usize, tx_len_bytes: usize) {
2413        let reg_block = self.regs();
2414
2415        let rx_len = rx_len_bytes as u32 * 8;
2416        let tx_len = tx_len_bytes as u32 * 8;
2417
2418        let rx_len = rx_len.saturating_sub(1);
2419        let tx_len = tx_len.saturating_sub(1);
2420
2421        cfg_if::cfg_if! {
2422            if #[cfg(esp32)] {
2423                let len = rx_len.max(tx_len);
2424                reg_block
2425                    .mosi_dlen()
2426                    .write(|w| unsafe { w.usr_mosi_dbitlen().bits(len) });
2427
2428                reg_block
2429                    .miso_dlen()
2430                    .write(|w| unsafe { w.usr_miso_dbitlen().bits(len) });
2431            } else if #[cfg(esp32s2)] {
2432                reg_block
2433                    .mosi_dlen()
2434                    .write(|w| unsafe { w.usr_mosi_dbitlen().bits(tx_len) });
2435
2436                reg_block
2437                    .miso_dlen()
2438                    .write(|w| unsafe { w.usr_miso_dbitlen().bits(rx_len) });
2439            } else {
2440                reg_block
2441                    .ms_dlen()
2442                    .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
2443            }
2444
2445        }
2446    }
2447}
2448
2449impl PartialEq for Info {
2450    fn eq(&self, other: &Self) -> bool {
2451        core::ptr::eq(self.register_block, other.register_block)
2452    }
2453}
2454
2455unsafe impl Sync for Info {}
2456
2457for_each_spi_master! {
2458    ($peri:ident, $sys:ident, $sclk:ident [$($cs:ident),+] [$($sio:ident),*] $(, $is_qspi:tt)?) => {
2459        impl Instance for crate::peripherals::$peri<'_> {
2460            #[inline(always)]
2461            fn parts(&self) -> (&'static Info, &'static State) {
2462                #[handler]
2463                #[ram]
2464                fn irq_handler() {
2465                    handle_async(&INFO, &STATE)
2466                }
2467
2468                static INFO: Info = Info {
2469                    register_block: crate::peripherals::$peri::regs(),
2470                    peripheral: crate::system::Peripheral::$sys,
2471                    async_handler: irq_handler,
2472                    sclk: OutputSignal::$sclk,
2473                    cs: &[$(OutputSignal::$cs),+],
2474                    sio_inputs: &[$(InputSignal::$sio),*],
2475                    sio_outputs: &[$(OutputSignal::$sio),*],
2476                };
2477
2478                static STATE: State = State {
2479                    waker: AtomicWaker::new(),
2480                    pins: UnsafeCell::new(MaybeUninit::uninit()),
2481
2482                    #[cfg(esp32)]
2483                    esp32_hack: Esp32Hack {
2484                        timing_miso_delay: Cell::new(None),
2485                        extra_dummy: Cell::new(0),
2486                    },
2487                };
2488
2489                (&INFO, &STATE)
2490            }
2491        }
2492
2493        $(
2494            // If the extra pins are set, implement QspiInstance
2495            $crate::ignore!($is_qspi);
2496            impl QspiInstance for crate::peripherals::$peri<'_> {}
2497        )?
2498    };
2499}
2500
2501impl QspiInstance for AnySpi<'_> {}
2502
2503#[doc(hidden)]
2504pub struct State {
2505    waker: AtomicWaker,
2506    pins: UnsafeCell<MaybeUninit<SpiPinGuard>>,
2507
2508    #[cfg(esp32)]
2509    esp32_hack: Esp32Hack,
2510}
2511
2512impl State {
2513    // Syntactic helper to get a mutable reference to the pin guard.
2514    //
2515    // Intended to be called in `SpiWrapper::pins` only
2516    //
2517    // # Safety
2518    //
2519    // The caller must ensure that Rust's aliasing rules are upheld.
2520    #[allow(
2521        clippy::mut_from_ref,
2522        reason = "Safety requirements ensure this is okay"
2523    )]
2524    unsafe fn pins(&self) -> &mut SpiPinGuard {
2525        unsafe { (&mut *self.pins.get()).assume_init_mut() }
2526    }
2527
2528    unsafe fn deinit(&self) {
2529        unsafe {
2530            let mut old = self.pins.get().replace(MaybeUninit::uninit());
2531            old.assume_init_drop();
2532        }
2533    }
2534}
2535
2536#[cfg(esp32)]
2537struct Esp32Hack {
2538    timing_miso_delay: Cell<Option<u8>>,
2539    extra_dummy: Cell<u8>,
2540}
2541
2542unsafe impl Sync for State {}
2543
2544#[ram]
2545fn handle_async(info: &'static Info, state: &'static State) {
2546    let driver = Driver { info, state };
2547    if driver.interrupts().contains(SpiInterrupt::TransferDone) {
2548        driver.enable_listen(SpiInterrupt::TransferDone.into(), false);
2549        state.waker.wake();
2550    }
2551}
2552
2553/// SPI data mode
2554#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2555#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2556#[instability::unstable]
2557pub enum DataMode {
2558    /// 1 bit, two data lines. (MOSI, MISO)
2559    SingleTwoDataLines,
2560    /// 1 bit, 1 data line (SIO0)
2561    Single,
2562    /// 2 bits, two data lines. (SIO0, SIO1)
2563    Dual,
2564    /// 4 bit, 4 data lines. (SIO0 .. SIO3)
2565    Quad,
2566    #[cfg(spi_master_has_octal)]
2567    /// 8 bit, 8 data lines. (SIO0 .. SIO7)
2568    Octal,
2569}
2570
2571crate::any_peripheral! {
2572    /// Any SPI peripheral.
2573    pub peripheral AnySpi<'d> {
2574        #[cfg(spi_master_spi2)]
2575        Spi2(crate::peripherals::SPI2<'d>),
2576        #[cfg(spi_master_spi3)]
2577        Spi3(crate::peripherals::SPI3<'d>),
2578    }
2579}
2580
2581impl Instance for AnySpi<'_> {
2582    #[inline]
2583    fn parts(&self) -> (&'static Info, &'static State) {
2584        any::delegate!(self, spi => { spi.parts() })
2585    }
2586}
2587
2588impl AnySpi<'_> {
2589    fn bind_peri_interrupt(&self, handler: InterruptHandler) {
2590        any::delegate!(self, spi => { spi.bind_peri_interrupt(handler) })
2591    }
2592
2593    fn disable_peri_interrupt_on_all_cores(&self) {
2594        any::delegate!(self, spi => { spi.disable_peri_interrupt_on_all_cores() })
2595    }
2596
2597    fn set_interrupt_handler(&self, handler: InterruptHandler) {
2598        self.disable_peri_interrupt_on_all_cores();
2599        self.bind_peri_interrupt(handler);
2600    }
2601}
2602
2603struct SpiFuture<'a> {
2604    driver: &'a Driver,
2605}
2606
2607impl SpiFuture<'_> {
2608    const EVENTS: EnumSet<SpiInterrupt> = enum_set!(SpiInterrupt::TransferDone);
2609}
2610
2611impl Future for SpiFuture<'_> {
2612    type Output = ();
2613
2614    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2615    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2616        if self.driver.busy() {
2617            self.driver.state.waker.register(cx.waker());
2618            self.driver.enable_listen(Self::EVENTS, true);
2619
2620            Poll::Pending
2621        } else {
2622            self.driver.clear_interrupts(Self::EVENTS);
2623            Poll::Ready(())
2624        }
2625    }
2626}
2627
2628impl Drop for SpiFuture<'_> {
2629    fn drop(&mut self) {
2630        self.driver.enable_listen(Self::EVENTS, false);
2631    }
2632}