esp_hal/spi/
master.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`](embedded_hal::spi::SpiBus) 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::marker::PhantomData;
40
41#[instability::unstable]
42pub use dma::*;
43use enumset::{EnumSet, EnumSetType};
44use procmacros::doc_replace;
45#[cfg(place_spi_master_driver_in_ram)]
46use procmacros::ram;
47
48use super::{BitOrder, DmaError, Error, Mode};
49use crate::{
50    Async,
51    Blocking,
52    DriverMode,
53    asynch::AtomicWaker,
54    clock::Clocks,
55    dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer},
56    gpio::{
57        InputConfig,
58        InputSignal,
59        NoPin,
60        OutputConfig,
61        OutputSignal,
62        PinGuard,
63        interconnect::{self, PeripheralInput, PeripheralOutput},
64    },
65    interrupt::InterruptHandler,
66    pac::spi2::RegisterBlock,
67    private::{self, OnDrop, Sealed},
68    system::PeripheralGuard,
69    time::Rate,
70};
71
72/// Enumeration of possible SPI interrupt events.
73#[derive(Debug, Hash, EnumSetType)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75#[non_exhaustive]
76#[instability::unstable]
77pub enum SpiInterrupt {
78    /// Indicates that the SPI transaction has completed successfully.
79    ///
80    /// This interrupt is triggered when an SPI transaction has finished
81    /// transmitting and receiving data.
82    TransferDone,
83
84    /// Triggered at the end of configurable segmented transfer.
85    #[cfg(any(esp32s2, gdma))]
86    DmaSegmentedTransferDone,
87
88    /// Used and triggered by software. Only used for user defined function.
89    #[cfg(gdma)]
90    App2,
91
92    /// Used and triggered by software. Only used for user defined function.
93    #[cfg(gdma)]
94    App1,
95}
96
97/// The size of the FIFO buffer for SPI
98const FIFO_SIZE: usize = if cfg!(esp32s2) { 72 } else { 64 };
99
100/// Padding byte for empty write transfers
101const EMPTY_WRITE_PAD: u8 = 0x00;
102
103const MAX_DMA_SIZE: usize = 32736;
104
105/// SPI commands, each consisting of a 16-bit command value and a data mode.
106///
107/// Used to define specific commands sent over the SPI bus.
108/// Can be [Command::None] if command phase should be suppressed.
109#[non_exhaustive]
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
112#[instability::unstable]
113pub enum Command {
114    /// No command is sent.
115    None,
116    /// A 1-bit command.
117    _1Bit(u16, DataMode),
118    /// A 2-bit command.
119    _2Bit(u16, DataMode),
120    /// A 3-bit command.
121    _3Bit(u16, DataMode),
122    /// A 4-bit command.
123    _4Bit(u16, DataMode),
124    /// A 5-bit command.
125    _5Bit(u16, DataMode),
126    /// A 6-bit command.
127    _6Bit(u16, DataMode),
128    /// A 7-bit command.
129    _7Bit(u16, DataMode),
130    /// A 8-bit command.
131    _8Bit(u16, DataMode),
132    /// A 9-bit command.
133    _9Bit(u16, DataMode),
134    /// A 10-bit command.
135    _10Bit(u16, DataMode),
136    /// A 11-bit command.
137    _11Bit(u16, DataMode),
138    /// A 12-bit command.
139    _12Bit(u16, DataMode),
140    /// A 13-bit command.
141    _13Bit(u16, DataMode),
142    /// A 14-bit command.
143    _14Bit(u16, DataMode),
144    /// A 15-bit command.
145    _15Bit(u16, DataMode),
146    /// A 16-bit command.
147    _16Bit(u16, DataMode),
148}
149
150impl Command {
151    fn width(&self) -> usize {
152        match self {
153            Command::None => 0,
154            Command::_1Bit(_, _) => 1,
155            Command::_2Bit(_, _) => 2,
156            Command::_3Bit(_, _) => 3,
157            Command::_4Bit(_, _) => 4,
158            Command::_5Bit(_, _) => 5,
159            Command::_6Bit(_, _) => 6,
160            Command::_7Bit(_, _) => 7,
161            Command::_8Bit(_, _) => 8,
162            Command::_9Bit(_, _) => 9,
163            Command::_10Bit(_, _) => 10,
164            Command::_11Bit(_, _) => 11,
165            Command::_12Bit(_, _) => 12,
166            Command::_13Bit(_, _) => 13,
167            Command::_14Bit(_, _) => 14,
168            Command::_15Bit(_, _) => 15,
169            Command::_16Bit(_, _) => 16,
170        }
171    }
172
173    fn value(&self) -> u16 {
174        match self {
175            Command::None => 0,
176            Command::_1Bit(value, _)
177            | Command::_2Bit(value, _)
178            | Command::_3Bit(value, _)
179            | Command::_4Bit(value, _)
180            | Command::_5Bit(value, _)
181            | Command::_6Bit(value, _)
182            | Command::_7Bit(value, _)
183            | Command::_8Bit(value, _)
184            | Command::_9Bit(value, _)
185            | Command::_10Bit(value, _)
186            | Command::_11Bit(value, _)
187            | Command::_12Bit(value, _)
188            | Command::_13Bit(value, _)
189            | Command::_14Bit(value, _)
190            | Command::_15Bit(value, _)
191            | Command::_16Bit(value, _) => *value,
192        }
193    }
194
195    fn mode(&self) -> DataMode {
196        match self {
197            Command::None => DataMode::SingleTwoDataLines,
198            Command::_1Bit(_, mode)
199            | Command::_2Bit(_, mode)
200            | Command::_3Bit(_, mode)
201            | Command::_4Bit(_, mode)
202            | Command::_5Bit(_, mode)
203            | Command::_6Bit(_, mode)
204            | Command::_7Bit(_, mode)
205            | Command::_8Bit(_, mode)
206            | Command::_9Bit(_, mode)
207            | Command::_10Bit(_, mode)
208            | Command::_11Bit(_, mode)
209            | Command::_12Bit(_, mode)
210            | Command::_13Bit(_, mode)
211            | Command::_14Bit(_, mode)
212            | Command::_15Bit(_, mode)
213            | Command::_16Bit(_, mode) => *mode,
214        }
215    }
216
217    fn is_none(&self) -> bool {
218        matches!(self, Command::None)
219    }
220}
221
222/// SPI address, ranging from 1 to 32 bits, paired with a data mode.
223///
224/// This can be used to specify the address phase of SPI transactions.
225/// Can be [Address::None] if address phase should be suppressed.
226#[non_exhaustive]
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
229#[instability::unstable]
230pub enum Address {
231    /// No address phase.
232    None,
233    /// A 1-bit address.
234    _1Bit(u32, DataMode),
235    /// A 2-bit address.
236    _2Bit(u32, DataMode),
237    /// A 3-bit address.
238    _3Bit(u32, DataMode),
239    /// A 4-bit address.
240    _4Bit(u32, DataMode),
241    /// A 5-bit address.
242    _5Bit(u32, DataMode),
243    /// A 6-bit address.
244    _6Bit(u32, DataMode),
245    /// A 7-bit address.
246    _7Bit(u32, DataMode),
247    /// A 8-bit address.
248    _8Bit(u32, DataMode),
249    /// A 9-bit address.
250    _9Bit(u32, DataMode),
251    /// A 10-bit address.
252    _10Bit(u32, DataMode),
253    /// A 11-bit address.
254    _11Bit(u32, DataMode),
255    /// A 12-bit address.
256    _12Bit(u32, DataMode),
257    /// A 13-bit address.
258    _13Bit(u32, DataMode),
259    /// A 14-bit address.
260    _14Bit(u32, DataMode),
261    /// A 15-bit address.
262    _15Bit(u32, DataMode),
263    /// A 16-bit address.
264    _16Bit(u32, DataMode),
265    /// A 17-bit address.
266    _17Bit(u32, DataMode),
267    /// A 18-bit address.
268    _18Bit(u32, DataMode),
269    /// A 19-bit address.
270    _19Bit(u32, DataMode),
271    /// A 20-bit address.
272    _20Bit(u32, DataMode),
273    /// A 21-bit address.
274    _21Bit(u32, DataMode),
275    /// A 22-bit address.
276    _22Bit(u32, DataMode),
277    /// A 23-bit address.
278    _23Bit(u32, DataMode),
279    /// A 24-bit address.
280    _24Bit(u32, DataMode),
281    /// A 25-bit address.
282    _25Bit(u32, DataMode),
283    /// A 26-bit address.
284    _26Bit(u32, DataMode),
285    /// A 27-bit address.
286    _27Bit(u32, DataMode),
287    /// A 28-bit address.
288    _28Bit(u32, DataMode),
289    /// A 29-bit address.
290    _29Bit(u32, DataMode),
291    /// A 30-bit address.
292    _30Bit(u32, DataMode),
293    /// A 31-bit address.
294    _31Bit(u32, DataMode),
295    /// A 32-bit address.
296    _32Bit(u32, DataMode),
297}
298
299impl Address {
300    fn width(&self) -> usize {
301        match self {
302            Address::None => 0,
303            Address::_1Bit(_, _) => 1,
304            Address::_2Bit(_, _) => 2,
305            Address::_3Bit(_, _) => 3,
306            Address::_4Bit(_, _) => 4,
307            Address::_5Bit(_, _) => 5,
308            Address::_6Bit(_, _) => 6,
309            Address::_7Bit(_, _) => 7,
310            Address::_8Bit(_, _) => 8,
311            Address::_9Bit(_, _) => 9,
312            Address::_10Bit(_, _) => 10,
313            Address::_11Bit(_, _) => 11,
314            Address::_12Bit(_, _) => 12,
315            Address::_13Bit(_, _) => 13,
316            Address::_14Bit(_, _) => 14,
317            Address::_15Bit(_, _) => 15,
318            Address::_16Bit(_, _) => 16,
319            Address::_17Bit(_, _) => 17,
320            Address::_18Bit(_, _) => 18,
321            Address::_19Bit(_, _) => 19,
322            Address::_20Bit(_, _) => 20,
323            Address::_21Bit(_, _) => 21,
324            Address::_22Bit(_, _) => 22,
325            Address::_23Bit(_, _) => 23,
326            Address::_24Bit(_, _) => 24,
327            Address::_25Bit(_, _) => 25,
328            Address::_26Bit(_, _) => 26,
329            Address::_27Bit(_, _) => 27,
330            Address::_28Bit(_, _) => 28,
331            Address::_29Bit(_, _) => 29,
332            Address::_30Bit(_, _) => 30,
333            Address::_31Bit(_, _) => 31,
334            Address::_32Bit(_, _) => 32,
335        }
336    }
337
338    fn value(&self) -> u32 {
339        match self {
340            Address::None => 0,
341            Address::_1Bit(value, _)
342            | Address::_2Bit(value, _)
343            | Address::_3Bit(value, _)
344            | Address::_4Bit(value, _)
345            | Address::_5Bit(value, _)
346            | Address::_6Bit(value, _)
347            | Address::_7Bit(value, _)
348            | Address::_8Bit(value, _)
349            | Address::_9Bit(value, _)
350            | Address::_10Bit(value, _)
351            | Address::_11Bit(value, _)
352            | Address::_12Bit(value, _)
353            | Address::_13Bit(value, _)
354            | Address::_14Bit(value, _)
355            | Address::_15Bit(value, _)
356            | Address::_16Bit(value, _)
357            | Address::_17Bit(value, _)
358            | Address::_18Bit(value, _)
359            | Address::_19Bit(value, _)
360            | Address::_20Bit(value, _)
361            | Address::_21Bit(value, _)
362            | Address::_22Bit(value, _)
363            | Address::_23Bit(value, _)
364            | Address::_24Bit(value, _)
365            | Address::_25Bit(value, _)
366            | Address::_26Bit(value, _)
367            | Address::_27Bit(value, _)
368            | Address::_28Bit(value, _)
369            | Address::_29Bit(value, _)
370            | Address::_30Bit(value, _)
371            | Address::_31Bit(value, _)
372            | Address::_32Bit(value, _) => *value,
373        }
374    }
375
376    fn is_none(&self) -> bool {
377        matches!(self, Address::None)
378    }
379
380    fn mode(&self) -> DataMode {
381        match self {
382            Address::None => DataMode::SingleTwoDataLines,
383            Address::_1Bit(_, mode)
384            | Address::_2Bit(_, mode)
385            | Address::_3Bit(_, mode)
386            | Address::_4Bit(_, mode)
387            | Address::_5Bit(_, mode)
388            | Address::_6Bit(_, mode)
389            | Address::_7Bit(_, mode)
390            | Address::_8Bit(_, mode)
391            | Address::_9Bit(_, mode)
392            | Address::_10Bit(_, mode)
393            | Address::_11Bit(_, mode)
394            | Address::_12Bit(_, mode)
395            | Address::_13Bit(_, mode)
396            | Address::_14Bit(_, mode)
397            | Address::_15Bit(_, mode)
398            | Address::_16Bit(_, mode)
399            | Address::_17Bit(_, mode)
400            | Address::_18Bit(_, mode)
401            | Address::_19Bit(_, mode)
402            | Address::_20Bit(_, mode)
403            | Address::_21Bit(_, mode)
404            | Address::_22Bit(_, mode)
405            | Address::_23Bit(_, mode)
406            | Address::_24Bit(_, mode)
407            | Address::_25Bit(_, mode)
408            | Address::_26Bit(_, mode)
409            | Address::_27Bit(_, mode)
410            | Address::_28Bit(_, mode)
411            | Address::_29Bit(_, mode)
412            | Address::_30Bit(_, mode)
413            | Address::_31Bit(_, mode)
414            | Address::_32Bit(_, mode) => *mode,
415        }
416    }
417}
418
419/// SPI clock source.
420#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
421#[cfg_attr(feature = "defmt", derive(defmt::Format))]
422#[instability::unstable]
423pub enum ClockSource {
424    /// Use the APB clock.
425    Apb,
426    // #[cfg(any(esp32c2, esp32c3, esp32s3))]
427    // Xtal,
428}
429
430/// SPI peripheral configuration
431#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, procmacros::BuilderLite)]
432#[cfg_attr(feature = "defmt", derive(defmt::Format))]
433#[non_exhaustive]
434pub struct Config {
435    /// The precomputed clock configuration register value.
436    ///
437    /// Clock divider calculations are relatively expensive, and the SPI
438    /// peripheral is commonly expected to be used in a shared bus
439    /// configuration, where different devices may need different bus clock
440    /// frequencies. To reduce the time required to reconfigure the bus, we
441    /// cache clock register's value here, for each configuration.
442    ///
443    /// This field is not intended to be set by the user, and is only used
444    /// internally.
445    #[builder_lite(skip)]
446    reg: Result<u32, ConfigError>,
447
448    /// The target frequency
449    #[builder_lite(skip_setter)]
450    frequency: Rate,
451
452    /// The clock source
453    #[builder_lite(unstable)]
454    #[builder_lite(skip_setter)]
455    clock_source: ClockSource,
456
457    /// SPI sample/shift mode.
458    mode: Mode,
459
460    /// Bit order of the read data.
461    read_bit_order: BitOrder,
462
463    /// Bit order of the written data.
464    write_bit_order: BitOrder,
465}
466
467impl Default for Config {
468    fn default() -> Self {
469        let mut this = Config {
470            reg: Ok(0),
471            frequency: Rate::from_mhz(1),
472            clock_source: ClockSource::Apb,
473            mode: Mode::_0,
474            read_bit_order: BitOrder::MsbFirst,
475            write_bit_order: BitOrder::MsbFirst,
476        };
477
478        this.reg = this.recalculate();
479
480        this
481    }
482}
483
484impl Config {
485    /// Set the frequency of the SPI bus clock.
486    pub fn with_frequency(mut self, frequency: Rate) -> Self {
487        self.frequency = frequency;
488        self.reg = self.recalculate();
489
490        self
491    }
492
493    /// Set the clock source of the SPI bus.
494    #[instability::unstable]
495    pub fn with_clock_source(mut self, clock_source: ClockSource) -> Self {
496        self.clock_source = clock_source;
497        self.reg = self.recalculate();
498
499        self
500    }
501
502    fn clock_source_freq_hz(&self) -> Rate {
503        let clocks = Clocks::get();
504
505        // FIXME: take clock source into account
506        cfg_if::cfg_if! {
507            if #[cfg(esp32h2)] {
508                // ESP32-H2 is using PLL_48M_CLK source instead of APB_CLK
509                clocks.pll_48m_clock
510            } else {
511                clocks.apb_clock
512            }
513        }
514    }
515
516    fn recalculate(&self) -> Result<u32, ConfigError> {
517        // taken from https://github.com/apache/incubator-nuttx/blob/8267a7618629838231256edfa666e44b5313348e/arch/risc-v/src/esp32c3/esp32c3_spi.c#L496
518        let source_freq = self.clock_source_freq_hz();
519
520        let reg_val: u32;
521        let duty_cycle = 128;
522
523        // In HW, n, h and l fields range from 1 to 64, pre ranges from 1 to 8K.
524        // The value written to register is one lower than the used value.
525
526        if self.frequency > ((source_freq / 4) * 3) {
527            // Using APB frequency directly will give us the best result here.
528            reg_val = 1 << 31;
529        } else {
530            // For best duty cycle resolution, we want n to be as close to 32 as
531            // possible, but we also need a pre/n combo that gets us as close as
532            // possible to the intended frequency. To do this, we bruteforce n and
533            // calculate the best pre to go along with that. If there's a choice
534            // between pre/n combos that give the same result, use the one with the
535            // higher n.
536
537            let mut pre: i32;
538            let mut bestn: i32 = -1;
539            let mut bestpre: i32 = -1;
540            let mut besterr: i32 = 0;
541            let mut errval: i32;
542
543            let target_freq_hz = self.frequency.as_hz() as i32;
544            let source_freq_hz = source_freq.as_hz() as i32;
545
546            // Start at n = 2. We need to be able to set h/l so we have at least
547            // one high and one low pulse.
548
549            for n in 2..=64 {
550                // Effectively, this does:
551                // pre = round((APB_CLK_FREQ / n) / frequency)
552
553                pre = ((source_freq_hz / n) + (target_freq_hz / 2)) / target_freq_hz;
554
555                if pre <= 0 {
556                    pre = 1;
557                }
558
559                if pre > 16 {
560                    pre = 16;
561                }
562
563                errval = (source_freq_hz / (pre * n) - target_freq_hz).abs();
564                if bestn == -1 || errval <= besterr {
565                    besterr = errval;
566                    bestn = n;
567                    bestpre = pre;
568                }
569            }
570
571            let n: i32 = bestn;
572            pre = bestpre;
573            let l: i32 = n;
574
575            // Effectively, this does:
576            // h = round((duty_cycle * n) / 256)
577
578            let mut h: i32 = (duty_cycle * n + 127) / 256;
579            if h <= 0 {
580                h = 1;
581            }
582
583            reg_val = (l as u32 - 1)
584                | ((h as u32 - 1) << 6)
585                | ((n as u32 - 1) << 12)
586                | ((pre as u32 - 1) << 18);
587        }
588
589        Ok(reg_val)
590    }
591
592    fn raw_clock_reg_value(&self) -> Result<u32, ConfigError> {
593        self.reg
594    }
595
596    fn validate(&self) -> Result<(), ConfigError> {
597        let source_freq = self.clock_source_freq_hz();
598        let min_divider = 1;
599        // FIXME: while ESP32 and S2 support pre dividers as large as 8192,
600        // those values are not currently supported by the divider calculation.
601        let max_divider = 16 * 64; // n * pre
602
603        if self.frequency < source_freq / max_divider || self.frequency > source_freq / min_divider
604        {
605            return Err(ConfigError::FrequencyOutOfRange);
606        }
607
608        Ok(())
609    }
610}
611
612#[derive(Debug)]
613#[cfg_attr(feature = "defmt", derive(defmt::Format))]
614struct SpiPinGuard {
615    sclk_pin: PinGuard,
616    cs_pin: PinGuard,
617    sio0_pin: PinGuard,
618    sio1_pin: PinGuard,
619    sio2_pin: Option<PinGuard>,
620    sio3_pin: Option<PinGuard>,
621    #[cfg(spi_master_has_octal)]
622    sio4_pin: Option<PinGuard>,
623    #[cfg(spi_master_has_octal)]
624    sio5_pin: Option<PinGuard>,
625    #[cfg(spi_master_has_octal)]
626    sio6_pin: Option<PinGuard>,
627    #[cfg(spi_master_has_octal)]
628    sio7_pin: Option<PinGuard>,
629}
630
631/// Configuration errors.
632#[non_exhaustive]
633#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
634#[cfg_attr(feature = "defmt", derive(defmt::Format))]
635pub enum ConfigError {
636    /// The requested frequency is not in the supported range.
637    FrequencyOutOfRange,
638}
639
640impl core::error::Error for ConfigError {}
641
642impl core::fmt::Display for ConfigError {
643    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
644        match self {
645            ConfigError::FrequencyOutOfRange => {
646                write!(f, "The requested frequency is not in the supported range")
647            }
648        }
649    }
650}
651#[procmacros::doc_replace]
652/// SPI peripheral driver
653///
654/// ## Example
655///
656/// ```rust, no_run
657/// # {before_snippet}
658/// use esp_hal::spi::{
659///     Mode,
660///     master::{Config, Spi},
661/// };
662/// let mut spi = Spi::new(
663///     peripherals.SPI2,
664///     Config::default()
665///         .with_frequency(Rate::from_khz(100))
666///         .with_mode(Mode::_0),
667/// )?
668/// .with_sck(peripherals.GPIO0)
669/// .with_mosi(peripherals.GPIO1)
670/// .with_miso(peripherals.GPIO2);
671/// # {after_snippet}
672/// ```
673#[derive(Debug)]
674#[cfg_attr(feature = "defmt", derive(defmt::Format))]
675pub struct Spi<'d, Dm: DriverMode> {
676    spi: AnySpi<'d>,
677    _mode: PhantomData<Dm>,
678    guard: PeripheralGuard,
679    pins: SpiPinGuard,
680}
681
682impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
683
684impl<'d> Spi<'d, Blocking> {
685    #[procmacros::doc_replace]
686    /// Constructs an SPI instance in 8bit dataframe mode.
687    ///
688    /// ## Errors
689    ///
690    /// See [`Spi::apply_config`].
691    ///
692    /// ## Example
693    ///
694    /// ```rust, no_run
695    /// # {before_snippet}
696    /// use esp_hal::spi::{
697    ///     Mode,
698    ///     master::{Config, Spi},
699    /// };
700    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
701    ///     .with_sck(peripherals.GPIO0)
702    ///     .with_mosi(peripherals.GPIO1)
703    ///     .with_miso(peripherals.GPIO2);
704    /// # {after_snippet}
705    /// ```
706    pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
707        let guard = PeripheralGuard::new(spi.info().peripheral);
708
709        let mut this = Spi {
710            _mode: PhantomData,
711            guard,
712            pins: SpiPinGuard {
713                sclk_pin: PinGuard::new_unconnected(spi.info().sclk),
714                cs_pin: PinGuard::new_unconnected(spi.info().cs(0)),
715                sio0_pin: PinGuard::new_unconnected(spi.info().sio_output(0)),
716                sio1_pin: PinGuard::new_unconnected(spi.info().sio_output(1)),
717                sio2_pin: spi.info().opt_sio_output(2).map(PinGuard::new_unconnected),
718                sio3_pin: spi.info().opt_sio_output(3).map(PinGuard::new_unconnected),
719                #[cfg(spi_master_has_octal)]
720                sio4_pin: spi.info().opt_sio_output(4).map(PinGuard::new_unconnected),
721                #[cfg(spi_master_has_octal)]
722                sio5_pin: spi.info().opt_sio_output(5).map(PinGuard::new_unconnected),
723                #[cfg(spi_master_has_octal)]
724                sio6_pin: spi.info().opt_sio_output(6).map(PinGuard::new_unconnected),
725                #[cfg(spi_master_has_octal)]
726                sio7_pin: spi.info().opt_sio_output(7).map(PinGuard::new_unconnected),
727            },
728            spi: spi.degrade(),
729        };
730
731        this.driver().init();
732        this.apply_config(&config)?;
733
734        let this = this.with_sck(NoPin).with_cs(NoPin);
735
736        for sio in 0..8 {
737            if let Some(signal) = this.driver().info.opt_sio_input(sio) {
738                signal.connect_to(&NoPin);
739            }
740            if let Some(signal) = this.driver().info.opt_sio_output(sio) {
741                signal.connect_to(&NoPin);
742            }
743        }
744
745        Ok(this)
746    }
747
748    /// Reconfigures the driver to operate in [`Async`] mode.
749    ///
750    /// See the [`Async`] documentation for an example on how to use this
751    /// method.
752    pub fn into_async(mut self) -> Spi<'d, Async> {
753        self.set_interrupt_handler(self.spi.info().async_handler);
754        Spi {
755            spi: self.spi,
756            _mode: PhantomData,
757            guard: self.guard,
758            pins: self.pins,
759        }
760    }
761
762    #[doc_replace(
763        "dma_channel" => {
764            cfg(any(esp32, esp32s2)) => "let dma_channel = peripherals.DMA_SPI2;",
765            _ => "let dma_channel = peripherals.DMA_CH0;",
766        }
767    )]
768    /// Configures the SPI instance to use DMA with the specified channel.
769    ///
770    /// This method prepares the SPI instance for DMA transfers using SPI
771    /// and returns an instance of `SpiDma` that supports DMA
772    /// operations.
773    /// ```rust, no_run
774    /// # {before_snippet}
775    /// use esp_hal::{
776    ///     dma::{DmaRxBuf, DmaTxBuf},
777    ///     dma_buffers,
778    ///     spi::{
779    ///         Mode,
780    ///         master::{Config, Spi},
781    ///     },
782    /// };
783    /// # {dma_channel}
784    /// let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
785    ///
786    /// let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer)?;
787    ///
788    /// let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer)?;
789    ///
790    /// let mut spi = Spi::new(
791    ///     peripherals.SPI2,
792    ///     Config::default()
793    ///         .with_frequency(Rate::from_khz(100))
794    ///         .with_mode(Mode::_0),
795    /// )?
796    /// .with_dma(dma_channel)
797    /// .with_buffers(dma_rx_buf, dma_tx_buf);
798    /// # {after_snippet}
799    /// ```
800    #[instability::unstable]
801    pub fn with_dma(self, channel: impl DmaChannelFor<AnySpi<'d>>) -> SpiDma<'d, Blocking> {
802        SpiDma::new(self.spi, self.pins, channel.degrade())
803    }
804
805    #[doc_replace(
806        "header" => {
807            cfg(multi_core) => "Registers an interrupt handler for the peripheral on the current core.",
808            _ => "Registers an interrupt handler for the peripheral.",
809        }
810    )]
811    /// # {header}
812    ///
813    /// Note that this will replace any previously registered interrupt
814    /// handlers.
815    ///
816    /// You can restore the default/unhandled interrupt handler by using
817    /// [crate::interrupt::DEFAULT_INTERRUPT_HANDLER]
818    ///
819    /// # Panics
820    ///
821    /// Panics if passed interrupt handler is invalid (e.g. has priority
822    /// `None`)
823    #[instability::unstable]
824    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
825        self.spi.set_interrupt_handler(handler);
826    }
827}
828
829#[instability::unstable]
830impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
831    /// Sets the interrupt handler
832    ///
833    /// Interrupts are not enabled at the peripheral level here.
834    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
835        self.set_interrupt_handler(handler);
836    }
837}
838
839impl<'d> Spi<'d, Async> {
840    /// Reconfigures the driver to operate in [`Blocking`] mode.
841    ///
842    /// See the [`Blocking`] documentation for an example on how to use this
843    /// method.
844    pub fn into_blocking(self) -> Spi<'d, Blocking> {
845        self.spi.disable_peri_interrupt();
846        Spi {
847            spi: self.spi,
848            _mode: PhantomData,
849            guard: self.guard,
850            pins: self.pins,
851        }
852    }
853
854    #[procmacros::doc_replace]
855    /// Waits for the completion of previous operations.
856    ///
857    /// ## Example
858    ///
859    /// ```rust, no_run
860    /// # {before_snippet}
861    /// use esp_hal::spi::{
862    ///     Mode,
863    ///     master::{Config, Spi},
864    /// };
865    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
866    ///     .with_sck(peripherals.GPIO0)
867    ///     .with_mosi(peripherals.GPIO1)
868    ///     .with_miso(peripherals.GPIO2)
869    ///     .into_async();
870    ///
871    /// let mut buffer = [0; 10];
872    /// spi.transfer_in_place_async(&mut buffer).await?;
873    /// spi.flush_async().await?;
874    ///
875    /// # {after_snippet}
876    /// ```
877    pub async fn flush_async(&mut self) -> Result<(), Error> {
878        self.driver().flush_async().await
879    }
880
881    #[procmacros::doc_replace]
882    /// Sends `words` to the slave. Returns the `words` received from the slave.
883    ///
884    /// This function aborts the transfer when its Future is dropped. Some
885    /// amount of data may have been transferred before the Future is
886    /// dropped. Dropping the future may block for a short while to ensure
887    /// the transfer is aborted.
888    ///
889    /// ## Example
890    ///
891    /// ```rust, no_run
892    /// # {before_snippet}
893    /// use esp_hal::spi::{
894    ///     Mode,
895    ///     master::{Config, Spi},
896    /// };
897    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
898    ///     .with_sck(peripherals.GPIO0)
899    ///     .with_mosi(peripherals.GPIO1)
900    ///     .with_miso(peripherals.GPIO2)
901    ///     .into_async();
902    ///
903    /// let mut buffer = [0; 10];
904    /// spi.transfer_in_place_async(&mut buffer).await?;
905    ///
906    /// # {after_snippet}
907    /// ```
908    pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
909        // We need to flush because the blocking transfer functions may return while a
910        // transfer is still in progress.
911        self.driver().flush_async().await?;
912        self.driver().setup_full_duplex()?;
913        self.driver().transfer_in_place_async(words).await
914    }
915}
916
917macro_rules! def_with_sio_pin {
918    ($fn:ident, $field:ident, $n:literal) => {
919        #[doc = concat!(" Assign the SIO", stringify!($n), " pin for the SPI instance.")]
920        #[doc = " "]
921        #[doc = " Enables both input and output functionality for the pin, and connects it"]
922        #[doc = concat!(" to the SIO", stringify!($n), " output and input signals.")]
923        #[instability::unstable]
924        pub fn $fn(mut self, sio: impl PeripheralOutput<'d>) -> Self {
925            self.pins.$field = Some(self.connect_sio_pin(sio.into(), $n));
926
927            self
928        }
929    };
930}
931
932impl<'d, Dm> Spi<'d, Dm>
933where
934    Dm: DriverMode,
935{
936    fn connect_sio_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
937        let in_signal = self.spi.info().sio_input(n);
938        let out_signal = self.spi.info().sio_output(n);
939
940        pin.apply_input_config(&InputConfig::default());
941        pin.apply_output_config(&OutputConfig::default());
942
943        pin.set_input_enable(true);
944        pin.set_output_enable(false);
945
946        in_signal.connect_to(&pin);
947        pin.connect_with_guard(out_signal)
948    }
949
950    fn connect_sio_output_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
951        let out_signal = self.spi.info().sio_output(n);
952
953        self.connect_output_pin(pin, out_signal)
954    }
955
956    fn connect_output_pin(
957        &self,
958        pin: interconnect::OutputSignal<'d>,
959        signal: OutputSignal,
960    ) -> PinGuard {
961        pin.apply_output_config(&OutputConfig::default());
962        pin.set_output_enable(true); // TODO turn this bool into a Yes/No/PeripheralControl trio
963
964        pin.connect_with_guard(signal)
965    }
966
967    #[procmacros::doc_replace]
968    /// Assign the SCK (Serial Clock) pin for the SPI instance.
969    ///
970    /// Configures the specified pin to push-pull output and connects it to the
971    /// SPI clock signal.
972    ///
973    /// Disconnects the previous pin that was assigned with `with_sck`.
974    ///
975    /// ## Example
976    ///
977    /// ```rust, no_run
978    /// # {before_snippet}
979    /// use esp_hal::spi::{
980    ///     Mode,
981    ///     master::{Config, Spi},
982    /// };
983    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_sck(peripherals.GPIO0);
984    ///
985    /// # {after_snippet}
986    /// ```
987    pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
988        self.pins.sclk_pin = self.connect_output_pin(sclk.into(), self.driver().info.sclk);
989
990        self
991    }
992
993    #[procmacros::doc_replace]
994    /// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
995    ///
996    /// Enables output functionality for the pin, and connects it as the MOSI
997    /// signal. You want to use this for full-duplex SPI or
998    /// if you intend to use [DataMode::SingleTwoDataLines].
999    ///
1000    /// Disconnects the previous pin that was assigned with `with_mosi` or
1001    /// `with_sio0`.
1002    ///
1003    /// ## Example
1004    ///
1005    /// ```rust, no_run
1006    /// # {before_snippet}
1007    /// use esp_hal::spi::{
1008    ///     Mode,
1009    ///     master::{Config, Spi},
1010    /// };
1011    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_mosi(peripherals.GPIO1);
1012    ///
1013    /// # {after_snippet}
1014    /// ```
1015    pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
1016        self.pins.sio0_pin = self.connect_sio_output_pin(mosi.into(), 0);
1017
1018        self
1019    }
1020
1021    #[procmacros::doc_replace]
1022    /// Assign the MISO (Master In Slave Out) pin for the SPI instance.
1023    ///
1024    /// Enables input functionality for the pin, and connects it to the MISO
1025    /// signal.
1026    ///
1027    /// You want to use this for full-duplex SPI or
1028    /// [DataMode::SingleTwoDataLines]
1029    ///
1030    /// ## Example
1031    ///
1032    /// ```rust, no_run
1033    /// # {before_snippet}
1034    /// use esp_hal::spi::{
1035    ///     Mode,
1036    ///     master::{Config, Spi},
1037    /// };
1038    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_miso(peripherals.GPIO2);
1039    ///
1040    /// # {after_snippet}
1041    /// ```
1042    pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
1043        let miso = miso.into();
1044
1045        miso.apply_input_config(&InputConfig::default());
1046        miso.set_input_enable(true);
1047
1048        self.driver().info.sio_input(1).connect_to(&miso);
1049
1050        self
1051    }
1052
1053    /// Assign the SIO0 pin for the SPI instance.
1054    ///
1055    /// Enables both input and output functionality for the pin, and connects it
1056    /// to the MOSI output signal and SIO0 input signal.
1057    ///
1058    /// Disconnects the previous pin that was assigned with `with_sio0` or
1059    /// `with_mosi`.
1060    ///
1061    /// Use this if any of the devices on the bus use half-duplex SPI.
1062    ///
1063    /// See also [Self::with_mosi] when you only need a one-directional MOSI
1064    /// signal.
1065    #[instability::unstable]
1066    pub fn with_sio0(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
1067        self.pins.sio0_pin = self.connect_sio_pin(mosi.into(), 0);
1068
1069        self
1070    }
1071
1072    /// Assign the SIO1/MISO pin for the SPI instance.
1073    ///
1074    /// Enables both input and output functionality for the pin, and connects it
1075    /// to the MISO input signal and SIO1 output signal.
1076    ///
1077    /// Disconnects the previous pin that was assigned with `with_sio1`.
1078    ///
1079    /// Use this if any of the devices on the bus use half-duplex SPI.
1080    ///
1081    /// See also [Self::with_miso] when you only need a one-directional MISO
1082    /// signal.
1083    #[instability::unstable]
1084    pub fn with_sio1(mut self, sio1: impl PeripheralOutput<'d>) -> Self {
1085        self.pins.sio1_pin = self.connect_sio_pin(sio1.into(), 1);
1086
1087        self
1088    }
1089
1090    def_with_sio_pin!(with_sio2, sio2_pin, 2);
1091    def_with_sio_pin!(with_sio3, sio3_pin, 3);
1092
1093    #[cfg(spi_master_has_octal)]
1094    def_with_sio_pin!(with_sio4, sio4_pin, 4);
1095
1096    #[cfg(spi_master_has_octal)]
1097    def_with_sio_pin!(with_sio5, sio5_pin, 5);
1098
1099    #[cfg(spi_master_has_octal)]
1100    def_with_sio_pin!(with_sio6, sio6_pin, 6);
1101
1102    #[cfg(spi_master_has_octal)]
1103    def_with_sio_pin!(with_sio7, sio7_pin, 7);
1104
1105    /// Assign the CS (Chip Select) pin for the SPI instance.
1106    ///
1107    /// Configures the specified pin to push-pull output and connects it to the
1108    /// SPI CS signal.
1109    ///
1110    /// Disconnects the previous pin that was assigned with `with_cs`.
1111    ///
1112    /// # Current Stability Limitations
1113    /// The hardware chip select functionality is limited; only one CS line can
1114    /// be set, regardless of the total number available. There is no
1115    /// mechanism to select which CS line to use.
1116    #[instability::unstable]
1117    pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
1118        self.pins.cs_pin = self.connect_output_pin(cs.into(), self.driver().info.cs(0));
1119        self
1120    }
1121
1122    #[doc_replace(
1123        "max_frequency" => {
1124            cfg(esp32h2) => " 48MHz",
1125            _ => " 80MHz",
1126        }
1127    )]
1128    /// Change the bus configuration.
1129    ///
1130    /// # Errors
1131    ///
1132    /// If frequency passed in config exceeds
1133    /// # {max_frequency}
1134    /// or is below 70kHz, [`ConfigError::FrequencyOutOfRange`] error will be returned.
1135    ///
1136    /// ## Example
1137    ///
1138    /// ```rust, no_run
1139    /// # {before_snippet}
1140    /// use esp_hal::spi::{
1141    ///     Mode,
1142    ///     master::{Config, Spi},
1143    /// };
1144    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?;
1145    ///
1146    /// spi.apply_config(&Config::default().with_frequency(Rate::from_khz(100)));
1147    /// #
1148    /// # {after_snippet}
1149    /// ```
1150    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1151        self.driver().apply_config(config)
1152    }
1153
1154    #[procmacros::doc_replace]
1155    /// Write bytes to SPI. After writing, flush is called to ensure all data
1156    /// has been transmitted.
1157    ///
1158    /// ## Example
1159    ///
1160    /// ```rust, no_run
1161    /// # {before_snippet}
1162    /// use esp_hal::spi::{
1163    ///     Mode,
1164    ///     master::{Config, Spi},
1165    /// };
1166    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1167    ///     .with_sck(peripherals.GPIO0)
1168    ///     .with_mosi(peripherals.GPIO1)
1169    ///     .with_miso(peripherals.GPIO2)
1170    ///     .into_async();
1171    ///
1172    /// let buffer = [0; 10];
1173    /// spi.write(&buffer)?;
1174    ///
1175    /// # {after_snippet}
1176    /// ```
1177    pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
1178        self.driver().setup_full_duplex()?;
1179        self.driver().write(words)?;
1180        self.driver().flush()?;
1181
1182        Ok(())
1183    }
1184
1185    #[procmacros::doc_replace]
1186    /// Read bytes from SPI. The provided slice is filled with data received
1187    /// from the slave.
1188    ///
1189    /// ## Example
1190    ///
1191    /// ```rust, no_run
1192    /// # {before_snippet}
1193    /// use esp_hal::spi::{
1194    ///     Mode,
1195    ///     master::{Config, Spi},
1196    /// };
1197    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1198    ///     .with_sck(peripherals.GPIO0)
1199    ///     .with_mosi(peripherals.GPIO1)
1200    ///     .with_miso(peripherals.GPIO2)
1201    ///     .into_async();
1202    ///
1203    /// let mut buffer = [0; 10];
1204    /// spi.read(&mut buffer)?;
1205    ///
1206    /// # {after_snippet}
1207    /// ```
1208    pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
1209        self.driver().setup_full_duplex()?;
1210        self.driver().read(words)
1211    }
1212
1213    #[procmacros::doc_replace]
1214    /// Sends `words` to the slave. The received data will be written to
1215    /// `words`, overwriting its contents.
1216    ///
1217    /// ## Example
1218    ///
1219    /// ```rust, no_run
1220    /// # {before_snippet}
1221    /// use esp_hal::spi::{
1222    ///     Mode,
1223    ///     master::{Config, Spi},
1224    /// };
1225    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
1226    ///     .with_sck(peripherals.GPIO0)
1227    ///     .with_mosi(peripherals.GPIO1)
1228    ///     .with_miso(peripherals.GPIO2)
1229    ///     .into_async();
1230    ///
1231    /// let mut buffer = [0; 10];
1232    /// spi.transfer(&mut buffer)?;
1233    ///
1234    /// # {after_snippet}
1235    /// ```
1236    pub fn transfer(&mut self, words: &mut [u8]) -> Result<(), Error> {
1237        self.driver().setup_full_duplex()?;
1238        self.driver().transfer(words)
1239    }
1240
1241    /// Half-duplex read.
1242    ///
1243    /// # Errors
1244    ///
1245    /// [`Error::FifoSizeExeeded`] or [`Error::Unsupported`] will be returned if
1246    /// passed buffer is bigger than FIFO size or if buffer is empty (currently
1247    /// unsupported). `DataMode::Single` cannot be combined with any other
1248    /// [`DataMode`], otherwise [`Error::Unsupported`] will be returned.
1249    #[instability::unstable]
1250    pub fn half_duplex_read(
1251        &mut self,
1252        data_mode: DataMode,
1253        cmd: Command,
1254        address: Address,
1255        dummy: u8,
1256        buffer: &mut [u8],
1257    ) -> Result<(), Error> {
1258        if buffer.len() > FIFO_SIZE {
1259            return Err(Error::FifoSizeExeeded);
1260        }
1261
1262        if buffer.is_empty() {
1263            error!("Half-duplex mode does not support empty buffer");
1264            return Err(Error::Unsupported);
1265        }
1266
1267        self.driver().setup_half_duplex(
1268            false,
1269            cmd,
1270            address,
1271            false,
1272            dummy,
1273            buffer.is_empty(),
1274            data_mode,
1275        )?;
1276
1277        self.driver().configure_datalen(buffer.len(), 0);
1278        self.driver().start_operation();
1279        self.driver().flush()?;
1280        self.driver().read_from_fifo(buffer)
1281    }
1282
1283    /// Half-duplex write.
1284    ///
1285    /// # Errors
1286    ///
1287    /// [`Error::FifoSizeExeeded`] will be returned if
1288    /// passed buffer is bigger than FIFO size.
1289    #[cfg_attr(
1290        esp32,
1291        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))."
1292    )]
1293    #[instability::unstable]
1294    pub fn half_duplex_write(
1295        &mut self,
1296        data_mode: DataMode,
1297        cmd: Command,
1298        address: Address,
1299        dummy: u8,
1300        buffer: &[u8],
1301    ) -> Result<(), Error> {
1302        if buffer.len() > FIFO_SIZE {
1303            return Err(Error::FifoSizeExeeded);
1304        }
1305
1306        cfg_if::cfg_if! {
1307            if #[cfg(all(esp32, spi_address_workaround))] {
1308                let mut buffer = buffer;
1309                let mut data_mode = data_mode;
1310                let mut address = address;
1311                let addr_bytes;
1312                if buffer.is_empty() && !address.is_none() {
1313                    // If the buffer is empty, we need to send a dummy byte
1314                    // to trigger the address phase.
1315                    let bytes_to_write = address.width().div_ceil(8);
1316                    // The address register is read in big-endian order,
1317                    // we have to prepare the emulated write in the same way.
1318                    addr_bytes = address.value().to_be_bytes();
1319                    buffer = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1320                    data_mode = address.mode();
1321                    address = Address::None;
1322                }
1323
1324                if dummy > 0 {
1325                    // FIXME: https://github.com/esp-rs/esp-hal/issues/2240
1326                    error!("Dummy bits are not supported without data");
1327                    return Err(Error::Unsupported);
1328                }
1329            }
1330        }
1331
1332        self.driver().setup_half_duplex(
1333            true,
1334            cmd,
1335            address,
1336            false,
1337            dummy,
1338            buffer.is_empty(),
1339            data_mode,
1340        )?;
1341
1342        if !buffer.is_empty() {
1343            // re-using the full-duplex write here
1344            self.driver().write(buffer)?;
1345        } else {
1346            self.driver().start_operation();
1347        }
1348
1349        self.driver().flush()
1350    }
1351
1352    fn driver(&self) -> Driver {
1353        Driver {
1354            info: self.spi.info(),
1355            state: self.spi.state(),
1356        }
1357    }
1358}
1359
1360#[instability::unstable]
1361impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
1362where
1363    Dm: DriverMode,
1364{
1365    type Config = Config;
1366    type ConfigError = ConfigError;
1367
1368    fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1369        self.apply_config(config)
1370    }
1371}
1372
1373mod dma {
1374    use core::{
1375        cmp::min,
1376        mem::ManuallyDrop,
1377        sync::atomic::{Ordering, fence},
1378    };
1379
1380    use super::*;
1381    use crate::{
1382        dma::{Channel, DmaRxBuf, DmaTxBuf, EmptyBuf, PeripheralDmaChannel, asynch::DmaRxFuture},
1383        spi::master::dma::asynch::DropGuard,
1384    };
1385
1386    #[doc_replace(
1387        "dma_channel" => {
1388            cfg(any(esp32, esp32s2)) => "let dma_channel = peripherals.DMA_SPI2;",
1389            _ => "let dma_channel = peripherals.DMA_CH0;",
1390        }
1391    )]
1392    /// A DMA capable SPI instance.
1393    ///
1394    /// Using `SpiDma` is not recommended unless you wish
1395    /// to manage buffers yourself. It's recommended to use
1396    /// [`SpiDmaBus`] via `with_buffers` to get access
1397    /// to a DMA capable SPI bus that implements the
1398    /// embedded-hal traits.
1399    /// ```rust, no_run
1400    /// # {before_snippet}
1401    /// use esp_hal::{
1402    ///     dma::{DmaRxBuf, DmaTxBuf},
1403    ///     dma_buffers,
1404    ///     spi::{
1405    ///         Mode,
1406    ///         master::{Config, Spi},
1407    ///     },
1408    /// };
1409    /// # {dma_channel}
1410    /// let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
1411    ///
1412    /// let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer)?;
1413    ///
1414    /// let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer)?;
1415    ///
1416    /// let mut spi = Spi::new(
1417    ///     peripherals.SPI2,
1418    ///     Config::default()
1419    ///         .with_frequency(Rate::from_khz(100))
1420    ///         .with_mode(Mode::_0),
1421    /// )?
1422    /// .with_dma(dma_channel)
1423    /// .with_buffers(dma_rx_buf, dma_tx_buf);
1424    /// #
1425    /// # {after_snippet}
1426    /// ```
1427    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1428    pub struct SpiDma<'d, Dm>
1429    where
1430        Dm: DriverMode,
1431    {
1432        pub(crate) spi: AnySpi<'d>,
1433        pub(crate) channel: Channel<Dm, PeripheralDmaChannel<AnySpi<'d>>>,
1434        tx_transfer_in_progress: bool,
1435        rx_transfer_in_progress: bool,
1436        #[cfg(all(esp32, spi_address_workaround))]
1437        address_buffer: DmaTxBuf,
1438        guard: PeripheralGuard,
1439        pins: SpiPinGuard,
1440    }
1441
1442    impl<Dm> crate::private::Sealed for SpiDma<'_, Dm> where Dm: DriverMode {}
1443
1444    impl<'d> SpiDma<'d, Blocking> {
1445        /// Converts the SPI instance into async mode.
1446        #[instability::unstable]
1447        pub fn into_async(mut self) -> SpiDma<'d, Async> {
1448            self.set_interrupt_handler(self.spi.info().async_handler);
1449            SpiDma {
1450                spi: self.spi,
1451                channel: self.channel.into_async(),
1452                tx_transfer_in_progress: self.tx_transfer_in_progress,
1453                rx_transfer_in_progress: self.rx_transfer_in_progress,
1454                #[cfg(all(esp32, spi_address_workaround))]
1455                address_buffer: self.address_buffer,
1456                guard: self.guard,
1457                pins: self.pins,
1458            }
1459        }
1460
1461        pub(super) fn new(
1462            spi: AnySpi<'d>,
1463            pins: SpiPinGuard,
1464            channel: PeripheralDmaChannel<AnySpi<'d>>,
1465        ) -> Self {
1466            let channel = Channel::new(channel);
1467            channel.runtime_ensure_compatible(&spi);
1468            #[cfg(all(esp32, spi_address_workaround))]
1469            let address_buffer = {
1470                use crate::dma::DmaDescriptor;
1471                const SPI_NUM: usize = 2;
1472                static mut DESCRIPTORS: [[DmaDescriptor; 1]; SPI_NUM] =
1473                    [[DmaDescriptor::EMPTY]; SPI_NUM];
1474                static mut BUFFERS: [[u32; 1]; SPI_NUM] = [[0; 1]; SPI_NUM];
1475
1476                let id = if spi.info() == unsafe { crate::peripherals::SPI2::steal().info() } {
1477                    0
1478                } else {
1479                    1
1480                };
1481
1482                unwrap!(DmaTxBuf::new(
1483                    unsafe { &mut DESCRIPTORS[id] },
1484                    crate::dma::as_mut_byte_array!(BUFFERS[id], 4)
1485                ))
1486            };
1487
1488            let guard = PeripheralGuard::new(spi.info().peripheral);
1489
1490            Self {
1491                spi,
1492                channel,
1493                #[cfg(all(esp32, spi_address_workaround))]
1494                address_buffer,
1495                tx_transfer_in_progress: false,
1496                rx_transfer_in_progress: false,
1497                guard,
1498                pins,
1499            }
1500        }
1501
1502        /// Listen for the given interrupts
1503        #[instability::unstable]
1504        pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1505            self.driver().enable_listen(interrupts.into(), true);
1506        }
1507
1508        /// Unlisten the given interrupts
1509        #[instability::unstable]
1510        pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1511            self.driver().enable_listen(interrupts.into(), false);
1512        }
1513
1514        /// Gets asserted interrupts
1515        #[instability::unstable]
1516        pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
1517            self.driver().interrupts()
1518        }
1519
1520        /// Resets asserted interrupts
1521        #[instability::unstable]
1522        pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1523            self.driver().clear_interrupts(interrupts.into());
1524        }
1525
1526        #[cfg_attr(
1527            not(multi_core),
1528            doc = "Registers an interrupt handler for the peripheral."
1529        )]
1530        #[cfg_attr(
1531            multi_core,
1532            doc = "Registers an interrupt handler for the peripheral on the current core."
1533        )]
1534        #[doc = ""]
1535        /// Note that this will replace any previously registered interrupt
1536        /// handlers.
1537        ///
1538        /// You can restore the default/unhandled interrupt handler by using
1539        /// [crate::interrupt::DEFAULT_INTERRUPT_HANDLER]
1540        ///
1541        /// # Panics
1542        ///
1543        /// Panics if passed interrupt handler is invalid (e.g. has priority
1544        /// `None`)
1545        #[instability::unstable]
1546        pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1547            self.spi.set_interrupt_handler(handler);
1548        }
1549    }
1550
1551    impl<'d> SpiDma<'d, Async> {
1552        /// Converts the SPI instance into async mode.
1553        #[instability::unstable]
1554        pub fn into_blocking(self) -> SpiDma<'d, Blocking> {
1555            self.spi.disable_peri_interrupt();
1556            SpiDma {
1557                spi: self.spi,
1558                channel: self.channel.into_blocking(),
1559                tx_transfer_in_progress: self.tx_transfer_in_progress,
1560                rx_transfer_in_progress: self.rx_transfer_in_progress,
1561                #[cfg(all(esp32, spi_address_workaround))]
1562                address_buffer: self.address_buffer,
1563                guard: self.guard,
1564                pins: self.pins,
1565            }
1566        }
1567
1568        async fn wait_for_idle_async(&mut self) {
1569            if self.rx_transfer_in_progress {
1570                _ = DmaRxFuture::new(&mut self.channel.rx).await;
1571                self.rx_transfer_in_progress = false;
1572            }
1573
1574            struct Fut(Driver);
1575            impl Future for Fut {
1576                type Output = ();
1577
1578                fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1579                    if self.0.interrupts().contains(SpiInterrupt::TransferDone) {
1580                        #[cfg(any(esp32, esp32s2))]
1581                        // Need to poll for done-ness even after interrupt fires.
1582                        if self.0.busy() {
1583                            cx.waker().wake_by_ref();
1584                            return Poll::Pending;
1585                        }
1586
1587                        self.0.clear_interrupts(SpiInterrupt::TransferDone.into());
1588                        return Poll::Ready(());
1589                    }
1590
1591                    self.0.state.waker.register(cx.waker());
1592                    self.0
1593                        .enable_listen(SpiInterrupt::TransferDone.into(), true);
1594                    Poll::Pending
1595                }
1596            }
1597            impl Drop for Fut {
1598                fn drop(&mut self) {
1599                    self.0
1600                        .enable_listen(SpiInterrupt::TransferDone.into(), false);
1601                }
1602            }
1603
1604            if !self.is_done() {
1605                Fut(self.driver()).await;
1606            }
1607
1608            if self.tx_transfer_in_progress {
1609                // In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA.
1610                if !self.channel.tx.is_done() {
1611                    self.channel.tx.stop_transfer();
1612                }
1613                self.tx_transfer_in_progress = false;
1614            }
1615        }
1616    }
1617
1618    impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
1619    where
1620        Dm: DriverMode,
1621    {
1622        /// Formats the `SpiDma` instance for debugging purposes.
1623        ///
1624        /// This method returns a debug struct with the name "SpiDma" without
1625        /// exposing internal details.
1626        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1627            f.debug_struct("SpiDma").field("spi", &self.spi).finish()
1628        }
1629    }
1630
1631    #[instability::unstable]
1632    impl crate::interrupt::InterruptConfigurable for SpiDma<'_, Blocking> {
1633        /// Sets the interrupt handler
1634        ///
1635        /// Interrupts are not enabled at the peripheral level here.
1636        fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1637            self.set_interrupt_handler(handler);
1638        }
1639    }
1640
1641    impl<Dm> SpiDma<'_, Dm>
1642    where
1643        Dm: DriverMode,
1644    {
1645        fn driver(&self) -> Driver {
1646            Driver {
1647                info: self.spi.info(),
1648                state: self.spi.state(),
1649            }
1650        }
1651
1652        fn dma_driver(&self) -> DmaDriver {
1653            DmaDriver {
1654                driver: self.driver(),
1655                dma_peripheral: self.spi.dma_peripheral(),
1656            }
1657        }
1658
1659        fn is_done(&self) -> bool {
1660            if self.driver().busy() {
1661                return false;
1662            }
1663            if self.rx_transfer_in_progress {
1664                // If this is an asymmetric transfer and the RX side is smaller, the RX channel
1665                // will never be "done" as it won't have enough descriptors/buffer to receive
1666                // the EOF bit from the SPI. So instead the RX channel will hit
1667                // a "descriptor empty" which means the DMA is written as much
1668                // of the received data as possible into the buffer and
1669                // discarded the rest. The user doesn't care about this discarded data.
1670
1671                if !self.channel.rx.is_done() && !self.channel.rx.has_dscr_empty_error() {
1672                    return false;
1673                }
1674            }
1675            true
1676        }
1677
1678        fn wait_for_idle(&mut self) {
1679            while !self.is_done() {
1680                // Wait for the SPI to become idle
1681            }
1682            self.rx_transfer_in_progress = false;
1683            self.tx_transfer_in_progress = false;
1684            fence(Ordering::Acquire);
1685        }
1686
1687        /// # Safety:
1688        ///
1689        /// The caller must ensure to not access the buffer contents while the
1690        /// transfer is in progress. Moving the buffer itself is allowed.
1691        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1692        unsafe fn start_transfer_dma<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1693            &mut self,
1694            full_duplex: bool,
1695            bytes_to_read: usize,
1696            bytes_to_write: usize,
1697            rx_buffer: &mut RX,
1698            tx_buffer: &mut TX,
1699        ) -> Result<(), Error> {
1700            if bytes_to_read > MAX_DMA_SIZE || bytes_to_write > MAX_DMA_SIZE {
1701                return Err(Error::MaxDmaTransferSizeExceeded);
1702            }
1703
1704            self.rx_transfer_in_progress = bytes_to_read > 0;
1705            self.tx_transfer_in_progress = bytes_to_write > 0;
1706            unsafe {
1707                self.dma_driver().start_transfer_dma(
1708                    full_duplex,
1709                    bytes_to_read,
1710                    bytes_to_write,
1711                    rx_buffer,
1712                    tx_buffer,
1713                    &mut self.channel,
1714                )
1715            }
1716        }
1717
1718        #[cfg(all(esp32, spi_address_workaround))]
1719        fn set_up_address_workaround(
1720            &mut self,
1721            cmd: Command,
1722            address: Address,
1723            dummy: u8,
1724        ) -> Result<(), Error> {
1725            if dummy > 0 {
1726                // FIXME: https://github.com/esp-rs/esp-hal/issues/2240
1727                error!("Dummy bits are not supported when there is no data to write");
1728                return Err(Error::Unsupported);
1729            }
1730
1731            let bytes_to_write = address.width().div_ceil(8);
1732            // The address register is read in big-endian order,
1733            // we have to prepare the emulated write in the same way.
1734            let addr_bytes = address.value().to_be_bytes();
1735            let addr_bytes = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1736            self.address_buffer.fill(addr_bytes);
1737
1738            self.driver().setup_half_duplex(
1739                true,
1740                cmd,
1741                Address::None,
1742                false,
1743                dummy,
1744                bytes_to_write == 0,
1745                address.mode(),
1746            )?;
1747
1748            // FIXME: we could use self.start_transfer_dma if the address buffer was part of
1749            // the (yet-to-be-created) State struct.
1750            self.tx_transfer_in_progress = true;
1751            unsafe {
1752                self.dma_driver().start_transfer_dma(
1753                    false,
1754                    0,
1755                    bytes_to_write,
1756                    &mut EmptyBuf,
1757                    &mut self.address_buffer,
1758                    &mut self.channel,
1759                )
1760            }
1761        }
1762
1763        fn cancel_transfer(&mut self) {
1764            // The SPI peripheral is controlling how much data we transfer, so let's
1765            // update its counter.
1766            // 0 doesn't take effect on ESP32 and cuts the currently transmitted byte
1767            // immediately.
1768            // 1 seems to stop after transmitting the current byte which is somewhat less
1769            // impolite.
1770            if self.tx_transfer_in_progress || self.rx_transfer_in_progress {
1771                self.dma_driver().abort_transfer();
1772
1773                // We need to stop the DMA transfer, too.
1774                if self.tx_transfer_in_progress {
1775                    self.channel.tx.stop_transfer();
1776                    self.tx_transfer_in_progress = false;
1777                }
1778                if self.rx_transfer_in_progress {
1779                    self.channel.rx.stop_transfer();
1780                    self.rx_transfer_in_progress = false;
1781                }
1782            }
1783        }
1784    }
1785
1786    #[instability::unstable]
1787    impl<Dm> embassy_embedded_hal::SetConfig for SpiDma<'_, Dm>
1788    where
1789        Dm: DriverMode,
1790    {
1791        type Config = Config;
1792        type ConfigError = ConfigError;
1793
1794        fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1795            self.apply_config(config)
1796        }
1797    }
1798
1799    /// A structure representing a DMA transfer for SPI.
1800    ///
1801    /// This structure holds references to the SPI instance, DMA buffers, and
1802    /// transfer status.
1803    #[instability::unstable]
1804    pub struct SpiDmaTransfer<'d, Dm, Buf>
1805    where
1806        Dm: DriverMode,
1807    {
1808        spi_dma: ManuallyDrop<SpiDma<'d, Dm>>,
1809        dma_buf: ManuallyDrop<Buf>,
1810    }
1811
1812    impl<Buf> SpiDmaTransfer<'_, Async, Buf> {
1813        /// Waits for the DMA transfer to complete asynchronously.
1814        ///
1815        /// This method awaits the completion of both RX and TX operations.
1816        #[instability::unstable]
1817        pub async fn wait_for_done(&mut self) {
1818            self.spi_dma.wait_for_idle_async().await;
1819        }
1820    }
1821
1822    impl<'d, Dm, Buf> SpiDmaTransfer<'d, Dm, Buf>
1823    where
1824        Dm: DriverMode,
1825    {
1826        fn new(spi_dma: SpiDma<'d, Dm>, dma_buf: Buf) -> Self {
1827            Self {
1828                spi_dma: ManuallyDrop::new(spi_dma),
1829                dma_buf: ManuallyDrop::new(dma_buf),
1830            }
1831        }
1832
1833        /// Checks if the transfer is complete.
1834        ///
1835        /// This method returns `true` if both RX and TX operations are done,
1836        /// and the SPI instance is no longer busy.
1837        pub fn is_done(&self) -> bool {
1838            self.spi_dma.is_done()
1839        }
1840
1841        /// Waits for the DMA transfer to complete.
1842        ///
1843        /// This method blocks until the transfer is finished and returns the
1844        /// `SpiDma` instance and the associated buffer.
1845        #[instability::unstable]
1846        pub fn wait(mut self) -> (SpiDma<'d, Dm>, Buf) {
1847            self.spi_dma.wait_for_idle();
1848            let retval = unsafe {
1849                (
1850                    ManuallyDrop::take(&mut self.spi_dma),
1851                    ManuallyDrop::take(&mut self.dma_buf),
1852                )
1853            };
1854            core::mem::forget(self);
1855            retval
1856        }
1857
1858        /// Cancels the DMA transfer.
1859        #[instability::unstable]
1860        pub fn cancel(&mut self) {
1861            if !self.spi_dma.is_done() {
1862                self.spi_dma.cancel_transfer();
1863            }
1864        }
1865    }
1866
1867    impl<Dm, Buf> Drop for SpiDmaTransfer<'_, Dm, Buf>
1868    where
1869        Dm: DriverMode,
1870    {
1871        fn drop(&mut self) {
1872            if !self.is_done() {
1873                self.spi_dma.cancel_transfer();
1874                self.spi_dma.wait_for_idle();
1875
1876                unsafe {
1877                    ManuallyDrop::drop(&mut self.spi_dma);
1878                    ManuallyDrop::drop(&mut self.dma_buf);
1879                }
1880            }
1881        }
1882    }
1883
1884    impl<'d, Dm> SpiDma<'d, Dm>
1885    where
1886        Dm: DriverMode,
1887    {
1888        /// # Safety:
1889        ///
1890        /// The caller must ensure that the buffers are not accessed while the
1891        /// transfer is in progress. Moving the buffers is allowed.
1892        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1893        unsafe fn start_dma_write(
1894            &mut self,
1895            bytes_to_write: usize,
1896            buffer: &mut impl DmaTxBuffer,
1897        ) -> Result<(), Error> {
1898            unsafe { self.start_dma_transfer(0, bytes_to_write, &mut EmptyBuf, buffer) }
1899        }
1900
1901        /// Configures the DMA buffers for the SPI instance.
1902        ///
1903        /// This method sets up both RX and TX buffers for DMA transfers.
1904        /// It returns an instance of `SpiDmaBus` that can be used for SPI
1905        /// communication.
1906        #[instability::unstable]
1907        pub fn with_buffers(self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf) -> SpiDmaBus<'d, Dm> {
1908            SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf)
1909        }
1910
1911        /// Perform a DMA write.
1912        ///
1913        /// This will return a [SpiDmaTransfer] owning the buffer and the
1914        /// SPI instance. The maximum amount of data to be sent is 32736
1915        /// bytes.
1916        #[allow(clippy::type_complexity)]
1917        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1918        #[instability::unstable]
1919        pub fn write<TX: DmaTxBuffer>(
1920            mut self,
1921            bytes_to_write: usize,
1922            mut buffer: TX,
1923        ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1924            self.wait_for_idle();
1925            if let Err(e) = self.driver().setup_full_duplex() {
1926                return Err((e, self, buffer));
1927            };
1928            match unsafe { self.start_dma_write(bytes_to_write, &mut buffer) } {
1929                Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1930                Err(e) => Err((e, self, buffer)),
1931            }
1932        }
1933
1934        /// # Safety:
1935        ///
1936        /// The caller must ensure that the buffers are not accessed while the
1937        /// transfer is in progress. Moving the buffers is allowed.
1938        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1939        unsafe fn start_dma_read(
1940            &mut self,
1941            bytes_to_read: usize,
1942            buffer: &mut impl DmaRxBuffer,
1943        ) -> Result<(), Error> {
1944            unsafe { self.start_dma_transfer(bytes_to_read, 0, buffer, &mut EmptyBuf) }
1945        }
1946
1947        /// Perform a DMA read.
1948        ///
1949        /// This will return a [SpiDmaTransfer] owning the buffer and
1950        /// the SPI instance. The maximum amount of data to be
1951        /// received is 32736 bytes.
1952        #[allow(clippy::type_complexity)]
1953        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1954        #[instability::unstable]
1955        pub fn read<RX: DmaRxBuffer>(
1956            mut self,
1957            bytes_to_read: usize,
1958            mut buffer: RX,
1959        ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1960            self.wait_for_idle();
1961            if let Err(e) = self.driver().setup_full_duplex() {
1962                return Err((e, self, buffer));
1963            };
1964            match unsafe { self.start_dma_read(bytes_to_read, &mut buffer) } {
1965                Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1966                Err(e) => Err((e, self, buffer)),
1967            }
1968        }
1969
1970        /// # Safety:
1971        ///
1972        /// The caller must ensure that the buffers are not accessed while the
1973        /// transfer is in progress. Moving the buffers is allowed.
1974        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1975        unsafe fn start_dma_transfer(
1976            &mut self,
1977            bytes_to_read: usize,
1978            bytes_to_write: usize,
1979            rx_buffer: &mut impl DmaRxBuffer,
1980            tx_buffer: &mut impl DmaTxBuffer,
1981        ) -> Result<(), Error> {
1982            unsafe {
1983                self.start_transfer_dma(true, bytes_to_read, bytes_to_write, rx_buffer, tx_buffer)
1984            }
1985        }
1986
1987        /// Perform a DMA transfer
1988        ///
1989        /// This will return a [SpiDmaTransfer] owning the buffers and
1990        /// the SPI instance. The maximum amount of data to be
1991        /// sent/received is 32736 bytes.
1992        #[allow(clippy::type_complexity)]
1993        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1994        #[instability::unstable]
1995        pub fn transfer<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1996            mut self,
1997            bytes_to_read: usize,
1998            mut rx_buffer: RX,
1999            bytes_to_write: usize,
2000            mut tx_buffer: TX,
2001        ) -> Result<SpiDmaTransfer<'d, Dm, (RX, TX)>, (Error, Self, RX, TX)> {
2002            self.wait_for_idle();
2003            if let Err(e) = self.driver().setup_full_duplex() {
2004                return Err((e, self, rx_buffer, tx_buffer));
2005            };
2006            match unsafe {
2007                self.start_dma_transfer(
2008                    bytes_to_read,
2009                    bytes_to_write,
2010                    &mut rx_buffer,
2011                    &mut tx_buffer,
2012                )
2013            } {
2014                Ok(_) => Ok(SpiDmaTransfer::new(self, (rx_buffer, tx_buffer))),
2015                Err(e) => Err((e, self, rx_buffer, tx_buffer)),
2016            }
2017        }
2018
2019        /// # Safety:
2020        ///
2021        /// The caller must ensure that the buffers are not accessed while the
2022        /// transfer is in progress. Moving the buffers is allowed.
2023        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2024        unsafe fn start_half_duplex_read(
2025            &mut self,
2026            data_mode: DataMode,
2027            cmd: Command,
2028            address: Address,
2029            dummy: u8,
2030            bytes_to_read: usize,
2031            buffer: &mut impl DmaRxBuffer,
2032        ) -> Result<(), Error> {
2033            self.driver().setup_half_duplex(
2034                false,
2035                cmd,
2036                address,
2037                false,
2038                dummy,
2039                bytes_to_read == 0,
2040                data_mode,
2041            )?;
2042
2043            unsafe { self.start_transfer_dma(false, bytes_to_read, 0, buffer, &mut EmptyBuf) }
2044        }
2045
2046        /// Perform a half-duplex read operation using DMA.
2047        #[allow(clippy::type_complexity)]
2048        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2049        #[instability::unstable]
2050        pub fn half_duplex_read<RX: DmaRxBuffer>(
2051            mut self,
2052            data_mode: DataMode,
2053            cmd: Command,
2054            address: Address,
2055            dummy: u8,
2056            bytes_to_read: usize,
2057            mut buffer: RX,
2058        ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
2059            self.wait_for_idle();
2060
2061            match unsafe {
2062                self.start_half_duplex_read(
2063                    data_mode,
2064                    cmd,
2065                    address,
2066                    dummy,
2067                    bytes_to_read,
2068                    &mut buffer,
2069                )
2070            } {
2071                Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
2072                Err(e) => Err((e, self, buffer)),
2073            }
2074        }
2075
2076        /// # Safety:
2077        ///
2078        /// The caller must ensure that the buffers are not accessed while the
2079        /// transfer is in progress. Moving the buffers is allowed.
2080        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2081        unsafe fn start_half_duplex_write(
2082            &mut self,
2083            data_mode: DataMode,
2084            cmd: Command,
2085            address: Address,
2086            dummy: u8,
2087            bytes_to_write: usize,
2088            buffer: &mut impl DmaTxBuffer,
2089        ) -> Result<(), Error> {
2090            #[cfg(all(esp32, spi_address_workaround))]
2091            {
2092                // On the ESP32, if we don't have data, the address is always sent
2093                // on a single line, regardless of its data mode.
2094                if bytes_to_write == 0 && address.mode() != DataMode::SingleTwoDataLines {
2095                    return self.set_up_address_workaround(cmd, address, dummy);
2096                }
2097            }
2098
2099            self.driver().setup_half_duplex(
2100                true,
2101                cmd,
2102                address,
2103                false,
2104                dummy,
2105                bytes_to_write == 0,
2106                data_mode,
2107            )?;
2108
2109            unsafe { self.start_transfer_dma(false, 0, bytes_to_write, &mut EmptyBuf, buffer) }
2110        }
2111
2112        /// Perform a half-duplex write operation using DMA.
2113        #[allow(clippy::type_complexity)]
2114        #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2115        #[instability::unstable]
2116        pub fn half_duplex_write<TX: DmaTxBuffer>(
2117            mut self,
2118            data_mode: DataMode,
2119            cmd: Command,
2120            address: Address,
2121            dummy: u8,
2122            bytes_to_write: usize,
2123            mut buffer: TX,
2124        ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
2125            self.wait_for_idle();
2126
2127            match unsafe {
2128                self.start_half_duplex_write(
2129                    data_mode,
2130                    cmd,
2131                    address,
2132                    dummy,
2133                    bytes_to_write,
2134                    &mut buffer,
2135                )
2136            } {
2137                Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
2138                Err(e) => Err((e, self, buffer)),
2139            }
2140        }
2141
2142        /// Change the bus configuration.
2143        ///
2144        /// # Errors
2145        ///
2146        /// If frequency passed in config exceeds
2147        #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2148        #[cfg_attr(esp32h2, doc = " 48MHz")]
2149        /// or is below 70kHz,
2150        /// [`ConfigError::UnsupportedFrequency`] error will be returned.
2151        #[instability::unstable]
2152        pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2153            self.driver().apply_config(config)
2154        }
2155    }
2156
2157    /// A DMA-capable SPI bus.
2158    ///
2159    /// This structure is responsible for managing SPI transfers using DMA
2160    /// buffers.
2161    #[derive(Debug)]
2162    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
2163    #[instability::unstable]
2164    pub struct SpiDmaBus<'d, Dm>
2165    where
2166        Dm: DriverMode,
2167    {
2168        spi_dma: SpiDma<'d, Dm>,
2169        rx_buf: DmaRxBuf,
2170        tx_buf: DmaTxBuf,
2171    }
2172
2173    impl<Dm> crate::private::Sealed for SpiDmaBus<'_, Dm> where Dm: DriverMode {}
2174
2175    impl<'d> SpiDmaBus<'d, Blocking> {
2176        /// Converts the SPI instance into async mode.
2177        #[instability::unstable]
2178        pub fn into_async(self) -> SpiDmaBus<'d, Async> {
2179            SpiDmaBus {
2180                spi_dma: self.spi_dma.into_async(),
2181                rx_buf: self.rx_buf,
2182                tx_buf: self.tx_buf,
2183            }
2184        }
2185
2186        /// Listen for the given interrupts
2187        #[instability::unstable]
2188        pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2189            self.spi_dma.listen(interrupts.into());
2190        }
2191
2192        /// Unlisten the given interrupts
2193        #[instability::unstable]
2194        pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2195            self.spi_dma.unlisten(interrupts.into());
2196        }
2197
2198        /// Gets asserted interrupts
2199        #[instability::unstable]
2200        pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
2201            self.spi_dma.interrupts()
2202        }
2203
2204        /// Resets asserted interrupts
2205        #[instability::unstable]
2206        pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2207            self.spi_dma.clear_interrupts(interrupts.into());
2208        }
2209    }
2210
2211    impl<'d> SpiDmaBus<'d, Async> {
2212        /// Converts the SPI instance into async mode.
2213        #[instability::unstable]
2214        pub fn into_blocking(self) -> SpiDmaBus<'d, Blocking> {
2215            SpiDmaBus {
2216                spi_dma: self.spi_dma.into_blocking(),
2217                rx_buf: self.rx_buf,
2218                tx_buf: self.tx_buf,
2219            }
2220        }
2221
2222        /// Fill the given buffer with data from the bus.
2223        #[instability::unstable]
2224        pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2225            self.spi_dma.wait_for_idle_async().await;
2226            self.spi_dma.driver().setup_full_duplex()?;
2227            let chunk_size = self.rx_buf.capacity();
2228
2229            for chunk in words.chunks_mut(chunk_size) {
2230                let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2231
2232                unsafe { spi.start_dma_transfer(chunk.len(), 0, &mut self.rx_buf, &mut EmptyBuf)? };
2233
2234                spi.wait_for_idle_async().await;
2235
2236                chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2237
2238                spi.defuse();
2239            }
2240
2241            Ok(())
2242        }
2243
2244        /// Transmit the given buffer to the bus.
2245        #[instability::unstable]
2246        pub async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
2247            self.spi_dma.wait_for_idle_async().await;
2248            self.spi_dma.driver().setup_full_duplex()?;
2249
2250            let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2251            let chunk_size = self.tx_buf.capacity();
2252
2253            for chunk in words.chunks(chunk_size) {
2254                self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2255
2256                unsafe { spi.start_dma_transfer(0, chunk.len(), &mut EmptyBuf, &mut self.tx_buf)? };
2257
2258                spi.wait_for_idle_async().await;
2259            }
2260            spi.defuse();
2261
2262            Ok(())
2263        }
2264
2265        /// Transfer by writing out a buffer and reading the response from
2266        /// the bus into another buffer.
2267        #[instability::unstable]
2268        pub async fn transfer_async(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2269            self.spi_dma.wait_for_idle_async().await;
2270            self.spi_dma.driver().setup_full_duplex()?;
2271
2272            let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2273            let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2274
2275            let common_length = min(read.len(), write.len());
2276            let (read_common, read_remainder) = read.split_at_mut(common_length);
2277            let (write_common, write_remainder) = write.split_at(common_length);
2278
2279            for (read_chunk, write_chunk) in read_common
2280                .chunks_mut(chunk_size)
2281                .zip(write_common.chunks(chunk_size))
2282            {
2283                self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2284
2285                unsafe {
2286                    spi.start_dma_transfer(
2287                        read_chunk.len(),
2288                        write_chunk.len(),
2289                        &mut self.rx_buf,
2290                        &mut self.tx_buf,
2291                    )?;
2292                }
2293                spi.wait_for_idle_async().await;
2294
2295                read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2296            }
2297
2298            spi.defuse();
2299
2300            if !read_remainder.is_empty() {
2301                self.read_async(read_remainder).await
2302            } else if !write_remainder.is_empty() {
2303                self.write_async(write_remainder).await
2304            } else {
2305                Ok(())
2306            }
2307        }
2308
2309        /// Transfer by writing out a buffer and reading the response from
2310        /// the bus into the same buffer.
2311        #[instability::unstable]
2312        pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2313            self.spi_dma.wait_for_idle_async().await;
2314            self.spi_dma.driver().setup_full_duplex()?;
2315
2316            let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2317            for chunk in words.chunks_mut(self.tx_buf.capacity()) {
2318                self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2319
2320                unsafe {
2321                    spi.start_dma_transfer(
2322                        chunk.len(),
2323                        chunk.len(),
2324                        &mut self.rx_buf,
2325                        &mut self.tx_buf,
2326                    )?;
2327                }
2328                spi.wait_for_idle_async().await;
2329                chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2330            }
2331
2332            spi.defuse();
2333
2334            Ok(())
2335        }
2336    }
2337
2338    impl<'d, Dm> SpiDmaBus<'d, Dm>
2339    where
2340        Dm: DriverMode,
2341    {
2342        /// Creates a new `SpiDmaBus` with the specified SPI instance and DMA
2343        /// buffers.
2344        pub fn new(spi_dma: SpiDma<'d, Dm>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self {
2345            Self {
2346                spi_dma,
2347                rx_buf,
2348                tx_buf,
2349            }
2350        }
2351
2352        /// Splits [SpiDmaBus] back into [SpiDma], [DmaRxBuf] and [DmaTxBuf].
2353        #[instability::unstable]
2354        pub fn split(mut self) -> (SpiDma<'d, Dm>, DmaRxBuf, DmaTxBuf) {
2355            self.wait_for_idle();
2356            (self.spi_dma, self.rx_buf, self.tx_buf)
2357        }
2358
2359        fn wait_for_idle(&mut self) {
2360            self.spi_dma.wait_for_idle();
2361        }
2362
2363        /// Change the bus configuration.
2364        ///
2365        /// # Errors
2366        ///
2367        /// If frequency passed in config exceeds
2368        #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2369        #[cfg_attr(esp32h2, doc = " 48MHz")]
2370        /// or is below 70kHz,
2371        /// [`ConfigError::UnsupportedFrequency`] error will be returned.
2372        #[instability::unstable]
2373        pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2374            self.spi_dma.apply_config(config)
2375        }
2376
2377        /// Reads data from the SPI bus using DMA.
2378        #[instability::unstable]
2379        pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
2380            self.wait_for_idle();
2381            self.spi_dma.driver().setup_full_duplex()?;
2382            for chunk in words.chunks_mut(self.rx_buf.capacity()) {
2383                unsafe {
2384                    self.spi_dma.start_dma_transfer(
2385                        chunk.len(),
2386                        0,
2387                        &mut self.rx_buf,
2388                        &mut EmptyBuf,
2389                    )?;
2390                }
2391
2392                self.wait_for_idle();
2393                chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2394            }
2395
2396            Ok(())
2397        }
2398
2399        /// Writes data to the SPI bus using DMA.
2400        #[instability::unstable]
2401        pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
2402            self.wait_for_idle();
2403            self.spi_dma.driver().setup_full_duplex()?;
2404            for chunk in words.chunks(self.tx_buf.capacity()) {
2405                self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2406
2407                unsafe {
2408                    self.spi_dma.start_dma_transfer(
2409                        0,
2410                        chunk.len(),
2411                        &mut EmptyBuf,
2412                        &mut self.tx_buf,
2413                    )?;
2414                }
2415
2416                self.wait_for_idle();
2417            }
2418
2419            Ok(())
2420        }
2421
2422        /// Transfers data to and from the SPI bus simultaneously using DMA.
2423        #[instability::unstable]
2424        pub fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2425            self.wait_for_idle();
2426            self.spi_dma.driver().setup_full_duplex()?;
2427            let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2428
2429            let common_length = min(read.len(), write.len());
2430            let (read_common, read_remainder) = read.split_at_mut(common_length);
2431            let (write_common, write_remainder) = write.split_at(common_length);
2432
2433            for (read_chunk, write_chunk) in read_common
2434                .chunks_mut(chunk_size)
2435                .zip(write_common.chunks(chunk_size))
2436            {
2437                self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2438
2439                unsafe {
2440                    self.spi_dma.start_dma_transfer(
2441                        read_chunk.len(),
2442                        write_chunk.len(),
2443                        &mut self.rx_buf,
2444                        &mut self.tx_buf,
2445                    )?;
2446                }
2447                self.wait_for_idle();
2448
2449                read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2450            }
2451
2452            if !read_remainder.is_empty() {
2453                self.read(read_remainder)
2454            } else if !write_remainder.is_empty() {
2455                self.write(write_remainder)
2456            } else {
2457                Ok(())
2458            }
2459        }
2460
2461        /// Transfers data in place on the SPI bus using DMA.
2462        #[instability::unstable]
2463        pub fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
2464            self.wait_for_idle();
2465            self.spi_dma.driver().setup_full_duplex()?;
2466            let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2467
2468            for chunk in words.chunks_mut(chunk_size) {
2469                self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2470
2471                unsafe {
2472                    self.spi_dma.start_dma_transfer(
2473                        chunk.len(),
2474                        chunk.len(),
2475                        &mut self.rx_buf,
2476                        &mut self.tx_buf,
2477                    )?;
2478                }
2479                self.wait_for_idle();
2480                chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2481            }
2482
2483            Ok(())
2484        }
2485
2486        /// Half-duplex read.
2487        #[instability::unstable]
2488        pub fn half_duplex_read(
2489            &mut self,
2490            data_mode: DataMode,
2491            cmd: Command,
2492            address: Address,
2493            dummy: u8,
2494            buffer: &mut [u8],
2495        ) -> Result<(), Error> {
2496            if buffer.len() > self.rx_buf.capacity() {
2497                return Err(Error::from(DmaError::Overflow));
2498            }
2499            self.wait_for_idle();
2500
2501            unsafe {
2502                self.spi_dma.start_half_duplex_read(
2503                    data_mode,
2504                    cmd,
2505                    address,
2506                    dummy,
2507                    buffer.len(),
2508                    &mut self.rx_buf,
2509                )?;
2510            }
2511
2512            self.wait_for_idle();
2513
2514            buffer.copy_from_slice(&self.rx_buf.as_slice()[..buffer.len()]);
2515
2516            Ok(())
2517        }
2518
2519        /// Half-duplex write.
2520        #[instability::unstable]
2521        pub fn half_duplex_write(
2522            &mut self,
2523            data_mode: DataMode,
2524            cmd: Command,
2525            address: Address,
2526            dummy: u8,
2527            buffer: &[u8],
2528        ) -> Result<(), Error> {
2529            if buffer.len() > self.tx_buf.capacity() {
2530                return Err(Error::from(DmaError::Overflow));
2531            }
2532            self.wait_for_idle();
2533            self.tx_buf.as_mut_slice()[..buffer.len()].copy_from_slice(buffer);
2534
2535            unsafe {
2536                self.spi_dma.start_half_duplex_write(
2537                    data_mode,
2538                    cmd,
2539                    address,
2540                    dummy,
2541                    buffer.len(),
2542                    &mut self.tx_buf,
2543                )?;
2544            }
2545
2546            self.wait_for_idle();
2547
2548            Ok(())
2549        }
2550    }
2551
2552    #[instability::unstable]
2553    impl crate::interrupt::InterruptConfigurable for SpiDmaBus<'_, Blocking> {
2554        /// Sets the interrupt handler
2555        ///
2556        /// Interrupts are not enabled at the peripheral level here.
2557        fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
2558            self.spi_dma.set_interrupt_handler(handler);
2559        }
2560    }
2561
2562    #[instability::unstable]
2563    impl<Dm> embassy_embedded_hal::SetConfig for SpiDmaBus<'_, Dm>
2564    where
2565        Dm: DriverMode,
2566    {
2567        type Config = Config;
2568        type ConfigError = ConfigError;
2569
2570        fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
2571            self.apply_config(config)
2572        }
2573    }
2574
2575    /// Async functionality
2576    mod asynch {
2577        use core::ops::{Deref, DerefMut};
2578
2579        use super::*;
2580
2581        #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2582        pub(crate) struct DropGuard<I, F: FnOnce(I)> {
2583            inner: ManuallyDrop<I>,
2584            on_drop: ManuallyDrop<F>,
2585        }
2586
2587        #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2588        impl<I, F: FnOnce(I)> DropGuard<I, F> {
2589            pub(crate) fn new(inner: I, on_drop: F) -> Self {
2590                Self {
2591                    inner: ManuallyDrop::new(inner),
2592                    on_drop: ManuallyDrop::new(on_drop),
2593                }
2594            }
2595
2596            pub(crate) fn defuse(self) {}
2597        }
2598
2599        impl<I, F: FnOnce(I)> Drop for DropGuard<I, F> {
2600            fn drop(&mut self) {
2601                let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
2602                let on_drop = unsafe { ManuallyDrop::take(&mut self.on_drop) };
2603                (on_drop)(inner)
2604            }
2605        }
2606
2607        impl<I, F: FnOnce(I)> Deref for DropGuard<I, F> {
2608            type Target = I;
2609
2610            fn deref(&self) -> &I {
2611                &self.inner
2612            }
2613        }
2614
2615        impl<I, F: FnOnce(I)> DerefMut for DropGuard<I, F> {
2616            fn deref_mut(&mut self) -> &mut I {
2617                &mut self.inner
2618            }
2619        }
2620
2621        #[instability::unstable]
2622        impl embedded_hal_async::spi::SpiBus for SpiDmaBus<'_, Async> {
2623            async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2624                self.read_async(words).await
2625            }
2626
2627            async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2628                self.write_async(words).await
2629            }
2630
2631            async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2632                self.transfer_async(read, write).await
2633            }
2634
2635            async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2636                self.transfer_in_place_async(words).await
2637            }
2638
2639            async fn flush(&mut self) -> Result<(), Self::Error> {
2640                // All operations currently flush so this is no-op.
2641                Ok(())
2642            }
2643        }
2644    }
2645
2646    mod ehal1 {
2647        #[cfg(feature = "unstable")]
2648        use embedded_hal::spi::{ErrorType, SpiBus};
2649
2650        #[cfg(feature = "unstable")]
2651        use super::*;
2652
2653        #[instability::unstable]
2654        impl<Dm> ErrorType for SpiDmaBus<'_, Dm>
2655        where
2656            Dm: DriverMode,
2657        {
2658            type Error = Error;
2659        }
2660
2661        #[instability::unstable]
2662        impl<Dm> SpiBus for SpiDmaBus<'_, Dm>
2663        where
2664            Dm: DriverMode,
2665        {
2666            fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2667                self.read(words)
2668            }
2669
2670            fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2671                self.write(words)
2672            }
2673
2674            fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2675                self.transfer(read, write)
2676            }
2677
2678            fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2679                self.transfer_in_place(words)
2680            }
2681
2682            fn flush(&mut self) -> Result<(), Self::Error> {
2683                // All operations currently flush so this is no-op.
2684                Ok(())
2685            }
2686        }
2687    }
2688}
2689
2690mod ehal1 {
2691    use embedded_hal::spi::SpiBus;
2692    use embedded_hal_async::spi::SpiBus as SpiBusAsync;
2693
2694    use super::*;
2695
2696    impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
2697    where
2698        Dm: DriverMode,
2699    {
2700        type Error = Error;
2701    }
2702
2703    impl<Dm> SpiBus for Spi<'_, Dm>
2704    where
2705        Dm: DriverMode,
2706    {
2707        fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2708            self.driver().read(words)
2709        }
2710
2711        fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2712            self.driver().write(words)
2713        }
2714
2715        fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2716            // Optimizations
2717            if read.is_empty() {
2718                return SpiBus::write(self, write);
2719            } else if write.is_empty() {
2720                return SpiBus::read(self, read);
2721            }
2722
2723            let mut write_from = 0;
2724            let mut read_from = 0;
2725
2726            loop {
2727                // How many bytes we write in this chunk
2728                let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2729                let write_to = write_from + write_inc;
2730                // How many bytes we read in this chunk
2731                let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2732                let read_to = read_from + read_inc;
2733
2734                if (write_inc == 0) && (read_inc == 0) {
2735                    break;
2736                }
2737
2738                // No need to flush here, `SpiBus::write` will do it for us
2739
2740                if write_to < read_to {
2741                    // Read more than we write, must pad writing part with zeros
2742                    let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2743                    empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2744                    SpiBus::write(self, &empty)?;
2745                } else {
2746                    SpiBus::write(self, &write[write_from..write_to])?;
2747                }
2748
2749                if read_inc > 0 {
2750                    SpiBus::flush(self)?;
2751                    self.driver()
2752                        .read_from_fifo(&mut read[read_from..read_to])?;
2753                }
2754
2755                write_from = write_to;
2756                read_from = read_to;
2757            }
2758            Ok(())
2759        }
2760
2761        fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2762            self.driver().transfer(words)
2763        }
2764
2765        fn flush(&mut self) -> Result<(), Self::Error> {
2766            self.driver().flush()
2767        }
2768    }
2769
2770    impl SpiBusAsync for Spi<'_, Async> {
2771        async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2772            // We need to flush because the blocking transfer functions may return while a
2773            // transfer is still in progress.
2774            self.flush_async().await?;
2775            self.driver().setup_full_duplex()?;
2776            self.driver().read_async(words).await
2777        }
2778
2779        async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2780            // We need to flush because the blocking transfer functions may return while a
2781            // transfer is still in progress.
2782            self.flush_async().await?;
2783            self.driver().setup_full_duplex()?;
2784            self.driver().write_async(words).await
2785        }
2786
2787        async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2788            // Optimizations
2789            if read.is_empty() {
2790                return SpiBusAsync::write(self, write).await;
2791            } else if write.is_empty() {
2792                return SpiBusAsync::read(self, read).await;
2793            }
2794
2795            let mut write_from = 0;
2796            let mut read_from = 0;
2797
2798            loop {
2799                // How many bytes we write in this chunk
2800                let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2801                let write_to = write_from + write_inc;
2802                // How many bytes we read in this chunk
2803                let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2804                let read_to = read_from + read_inc;
2805
2806                if (write_inc == 0) && (read_inc == 0) {
2807                    break;
2808                }
2809
2810                // No need to flush here, `SpiBusAsync::write` will do it for us
2811
2812                if write_to < read_to {
2813                    // Read more than we write, must pad writing part with zeros
2814                    let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2815                    empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2816                    SpiBusAsync::write(self, &empty).await?;
2817                } else {
2818                    SpiBusAsync::write(self, &write[write_from..write_to]).await?;
2819                }
2820
2821                if read_inc > 0 {
2822                    self.driver()
2823                        .read_from_fifo(&mut read[read_from..read_to])?;
2824                }
2825
2826                write_from = write_to;
2827                read_from = read_to;
2828            }
2829            Ok(())
2830        }
2831
2832        async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2833            self.transfer_in_place_async(words).await
2834        }
2835
2836        async fn flush(&mut self) -> Result<(), Self::Error> {
2837            self.flush_async().await
2838        }
2839    }
2840}
2841
2842/// SPI peripheral instance.
2843#[cfg_attr(not(feature = "unstable"), expect(private_bounds))] // DmaEligible
2844pub trait Instance: private::Sealed + any::Degrade + DmaEligible {
2845    #[doc(hidden)]
2846    /// Returns the peripheral data and state describing this instance.
2847    fn parts(&self) -> (&'static Info, &'static State);
2848
2849    /// Returns the peripheral data describing this instance.
2850    #[doc(hidden)]
2851    #[inline(always)]
2852    fn info(&self) -> &'static Info {
2853        self.parts().0
2854    }
2855
2856    /// Returns the peripheral state for this instance.
2857    #[doc(hidden)]
2858    #[inline(always)]
2859    fn state(&self) -> &'static State {
2860        self.parts().1
2861    }
2862}
2863
2864/// Marker trait for QSPI-capable SPI peripherals.
2865#[doc(hidden)]
2866pub trait QspiInstance: Instance {}
2867
2868/// Peripheral data describing a particular SPI instance.
2869#[doc(hidden)]
2870#[non_exhaustive]
2871pub struct Info {
2872    /// Pointer to the register block for this SPI instance.
2873    ///
2874    /// Use [Self::register_block] to access the register block.
2875    pub register_block: *const RegisterBlock,
2876
2877    /// The system peripheral marker.
2878    pub peripheral: crate::system::Peripheral,
2879
2880    /// Interrupt handler for the asynchronous operations.
2881    pub async_handler: InterruptHandler,
2882
2883    /// SCLK signal.
2884    pub sclk: OutputSignal,
2885
2886    /// Chip select signals.
2887    pub cs: &'static [OutputSignal],
2888
2889    pub sio_inputs: &'static [InputSignal],
2890    pub sio_outputs: &'static [OutputSignal],
2891}
2892
2893impl Info {
2894    fn cs(&self, n: usize) -> OutputSignal {
2895        *unwrap!(self.cs.get(n), "CS{} is not defined", n)
2896    }
2897
2898    fn opt_sio_input(&self, n: usize) -> Option<InputSignal> {
2899        self.sio_inputs.get(n).copied()
2900    }
2901
2902    fn opt_sio_output(&self, n: usize) -> Option<OutputSignal> {
2903        self.sio_outputs.get(n).copied()
2904    }
2905
2906    fn sio_input(&self, n: usize) -> InputSignal {
2907        unwrap!(self.opt_sio_input(n), "SIO{} is not defined", n)
2908    }
2909
2910    fn sio_output(&self, n: usize) -> OutputSignal {
2911        unwrap!(self.opt_sio_output(n), "SIO{} is not defined", n)
2912    }
2913}
2914
2915struct DmaDriver {
2916    driver: Driver,
2917    dma_peripheral: crate::dma::DmaPeripheral,
2918}
2919
2920impl DmaDriver {
2921    fn abort_transfer(&self) {
2922        self.driver.configure_datalen(1, 1);
2923        self.driver.update();
2924    }
2925
2926    fn regs(&self) -> &RegisterBlock {
2927        self.driver.regs()
2928    }
2929
2930    #[allow(clippy::too_many_arguments)]
2931    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2932    unsafe fn start_transfer_dma<Dm: DriverMode>(
2933        &self,
2934        _full_duplex: bool,
2935        rx_len: usize,
2936        tx_len: usize,
2937        rx_buffer: &mut impl DmaRxBuffer,
2938        tx_buffer: &mut impl DmaTxBuffer,
2939        channel: &mut Channel<Dm, PeripheralDmaChannel<AnySpi<'_>>>,
2940    ) -> Result<(), Error> {
2941        #[cfg(esp32s2)]
2942        {
2943            // without this a transfer after a write will fail
2944            self.regs().dma_out_link().write(|w| unsafe { w.bits(0) });
2945            self.regs().dma_in_link().write(|w| unsafe { w.bits(0) });
2946        }
2947
2948        self.driver.configure_datalen(rx_len, tx_len);
2949
2950        // enable the MISO and MOSI if needed
2951        self.regs()
2952            .user()
2953            .modify(|_, w| w.usr_miso().bit(rx_len > 0).usr_mosi().bit(tx_len > 0));
2954
2955        self.enable_dma();
2956
2957        if rx_len > 0 {
2958            unsafe {
2959                channel
2960                    .rx
2961                    .prepare_transfer(self.dma_peripheral, rx_buffer)
2962                    .and_then(|_| channel.rx.start_transfer())?;
2963            }
2964        } else {
2965            #[cfg(esp32)]
2966            {
2967                // see https://github.com/espressif/esp-idf/commit/366e4397e9dae9d93fe69ea9d389b5743295886f
2968                // see https://github.com/espressif/esp-idf/commit/0c3653b1fd7151001143451d4aa95dbf15ee8506
2969                if _full_duplex {
2970                    self.regs()
2971                        .dma_in_link()
2972                        .modify(|_, w| unsafe { w.inlink_addr().bits(0) });
2973                    self.regs()
2974                        .dma_in_link()
2975                        .modify(|_, w| w.inlink_start().set_bit());
2976                }
2977            }
2978        }
2979        if tx_len > 0 {
2980            unsafe {
2981                channel
2982                    .tx
2983                    .prepare_transfer(self.dma_peripheral, tx_buffer)
2984                    .and_then(|_| channel.tx.start_transfer())?;
2985            }
2986        }
2987
2988        #[cfg(gdma)]
2989        self.reset_dma();
2990
2991        self.driver.start_operation();
2992
2993        Ok(())
2994    }
2995
2996    fn enable_dma(&self) {
2997        #[cfg(gdma)]
2998        // for non GDMA this is done in `assign_tx_device` / `assign_rx_device`
2999        self.regs().dma_conf().modify(|_, w| {
3000            w.dma_tx_ena().set_bit();
3001            w.dma_rx_ena().set_bit()
3002        });
3003
3004        #[cfg(pdma)]
3005        self.reset_dma();
3006    }
3007
3008    fn reset_dma(&self) {
3009        fn set_reset_bit(reg_block: &RegisterBlock, bit: bool) {
3010            #[cfg(pdma)]
3011            reg_block.dma_conf().modify(|_, w| {
3012                w.out_rst().bit(bit);
3013                w.in_rst().bit(bit);
3014                w.ahbm_fifo_rst().bit(bit);
3015                w.ahbm_rst().bit(bit)
3016            });
3017            #[cfg(gdma)]
3018            reg_block.dma_conf().modify(|_, w| {
3019                w.rx_afifo_rst().bit(bit);
3020                w.buf_afifo_rst().bit(bit);
3021                w.dma_afifo_rst().bit(bit)
3022            });
3023        }
3024
3025        set_reset_bit(self.regs(), true);
3026        set_reset_bit(self.regs(), false);
3027        self.clear_dma_interrupts();
3028    }
3029
3030    #[cfg(gdma)]
3031    fn clear_dma_interrupts(&self) {
3032        self.regs().dma_int_clr().write(|w| {
3033            w.dma_infifo_full_err().clear_bit_by_one();
3034            w.dma_outfifo_empty_err().clear_bit_by_one();
3035            w.trans_done().clear_bit_by_one();
3036            w.mst_rx_afifo_wfull_err().clear_bit_by_one();
3037            w.mst_tx_afifo_rempty_err().clear_bit_by_one()
3038        });
3039    }
3040
3041    #[cfg(pdma)]
3042    fn clear_dma_interrupts(&self) {
3043        self.regs().dma_int_clr().write(|w| {
3044            w.inlink_dscr_empty().clear_bit_by_one();
3045            w.outlink_dscr_error().clear_bit_by_one();
3046            w.inlink_dscr_error().clear_bit_by_one();
3047            w.in_done().clear_bit_by_one();
3048            w.in_err_eof().clear_bit_by_one();
3049            w.in_suc_eof().clear_bit_by_one();
3050            w.out_done().clear_bit_by_one();
3051            w.out_eof().clear_bit_by_one();
3052            w.out_total_eof().clear_bit_by_one()
3053        });
3054    }
3055}
3056
3057struct Driver {
3058    info: &'static Info,
3059    state: &'static State,
3060}
3061
3062// private implementation bits
3063// FIXME: split this up into peripheral versions
3064impl Driver {
3065    /// Returns the register block for this SPI instance.
3066    pub fn regs(&self) -> &RegisterBlock {
3067        unsafe { &*self.info.register_block }
3068    }
3069
3070    fn abort_transfer(&self) {
3071        // Note(danielb): This method came later than DmaDriver::abort_transfer. That
3072        // function works for DMA so I have left it unchanged, but does not work
3073        // for CPU-controlled transfers on the ESP32. Toggling slave mode works on
3074        // ESP32, but not on later chips.
3075        cfg_if::cfg_if! {
3076            if #[cfg(esp32)] {
3077                self.regs().slave().modify(|_, w| w.mode().set_bit());
3078                self.regs().slave().modify(|_, w| w.mode().clear_bit());
3079            } else {
3080                self.configure_datalen(1, 1);
3081            }
3082        }
3083        self.update();
3084    }
3085
3086    /// Initialize for full-duplex 1 bit mode
3087    fn init(&self) {
3088        self.regs().user().modify(|_, w| {
3089            w.usr_miso_highpart().clear_bit();
3090            w.usr_mosi_highpart().clear_bit();
3091            w.doutdin().set_bit();
3092            w.usr_miso().set_bit();
3093            w.usr_mosi().set_bit();
3094            w.cs_hold().set_bit();
3095            w.usr_dummy_idle().set_bit();
3096            w.usr_addr().clear_bit();
3097            w.usr_command().clear_bit()
3098        });
3099
3100        #[cfg(gdma)]
3101        self.regs().clk_gate().modify(|_, w| {
3102            w.clk_en().set_bit();
3103            w.mst_clk_active().set_bit();
3104            w.mst_clk_sel().set_bit()
3105        });
3106
3107        #[cfg(any(esp32c6, esp32h2))]
3108        unsafe {
3109            // use default clock source PLL_F80M_CLK (ESP32-C6) and
3110            // PLL_F48M_CLK (ESP32-H2)
3111            crate::peripherals::PCR::regs()
3112                .spi2_clkm_conf()
3113                .modify(|_, w| w.spi2_clkm_sel().bits(1));
3114        }
3115
3116        #[cfg(gdma)]
3117        self.regs().ctrl().modify(|_, w| {
3118            w.q_pol().clear_bit();
3119            w.d_pol().clear_bit();
3120            w.hold_pol().clear_bit()
3121        });
3122
3123        #[cfg(esp32s2)]
3124        self.regs().ctrl().modify(|_, w| {
3125            w.q_pol().clear_bit();
3126            w.d_pol().clear_bit();
3127            w.wp().clear_bit()
3128        });
3129
3130        #[cfg(esp32)]
3131        self.regs().ctrl().modify(|_, w| w.wp().clear_bit());
3132
3133        #[cfg(not(esp32))]
3134        self.regs().misc().write(|w| unsafe { w.bits(0) });
3135
3136        self.regs().slave().write(|w| unsafe { w.bits(0) });
3137    }
3138
3139    #[cfg(not(esp32))]
3140    fn init_spi_data_mode(
3141        &self,
3142        cmd_mode: DataMode,
3143        address_mode: DataMode,
3144        data_mode: DataMode,
3145    ) -> Result<(), Error> {
3146        self.regs().ctrl().modify(|_, w| {
3147            w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
3148            w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
3149            w.faddr_dual().bit(address_mode == DataMode::Dual);
3150            w.faddr_quad().bit(address_mode == DataMode::Quad);
3151            w.fread_dual().bit(data_mode == DataMode::Dual);
3152            w.fread_quad().bit(data_mode == DataMode::Quad)
3153        });
3154        self.regs().user().modify(|_, w| {
3155            w.fwrite_dual().bit(data_mode == DataMode::Dual);
3156            w.fwrite_quad().bit(data_mode == DataMode::Quad)
3157        });
3158        Ok(())
3159    }
3160
3161    #[cfg(esp32)]
3162    fn init_spi_data_mode(
3163        &self,
3164        cmd_mode: DataMode,
3165        address_mode: DataMode,
3166        data_mode: DataMode,
3167    ) -> Result<(), Error> {
3168        match cmd_mode {
3169            DataMode::Single => (),
3170            DataMode::SingleTwoDataLines => (),
3171            // FIXME: more detailed error - Only 1-bit commands are supported.
3172            _ => {
3173                error!("Commands must be single bit wide");
3174                return Err(Error::Unsupported);
3175            }
3176        }
3177
3178        match address_mode {
3179            DataMode::Single | DataMode::SingleTwoDataLines => {
3180                self.regs().ctrl().modify(|_, w| {
3181                    w.fastrd_mode()
3182                        .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3183                    w.fread_dio().clear_bit();
3184                    w.fread_qio().clear_bit();
3185                    w.fread_dual().bit(data_mode == DataMode::Dual);
3186                    w.fread_quad().bit(data_mode == DataMode::Quad)
3187                });
3188
3189                self.regs().user().modify(|_, w| {
3190                    w.fwrite_dio().clear_bit();
3191                    w.fwrite_qio().clear_bit();
3192                    w.fwrite_dual().bit(data_mode == DataMode::Dual);
3193                    w.fwrite_quad().bit(data_mode == DataMode::Quad)
3194                });
3195            }
3196            address_mode if address_mode == data_mode => {
3197                self.regs().ctrl().modify(|_, w| {
3198                    w.fastrd_mode()
3199                        .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3200                    w.fread_dio().bit(address_mode == DataMode::Dual);
3201                    w.fread_qio().bit(address_mode == DataMode::Quad);
3202                    w.fread_dual().clear_bit();
3203                    w.fread_quad().clear_bit()
3204                });
3205
3206                self.regs().user().modify(|_, w| {
3207                    w.fwrite_dio().bit(address_mode == DataMode::Dual);
3208                    w.fwrite_qio().bit(address_mode == DataMode::Quad);
3209                    w.fwrite_dual().clear_bit();
3210                    w.fwrite_quad().clear_bit()
3211                });
3212            }
3213            _ => {
3214                // FIXME: more detailed error - Unsupported combination of data-modes
3215                error!("Address mode must be single bit wide or equal to the data mode");
3216                return Err(Error::Unsupported);
3217            }
3218        }
3219
3220        Ok(())
3221    }
3222
3223    /// Enable or disable listening for the given interrupts.
3224    #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3225    fn enable_listen(&self, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
3226        cfg_if::cfg_if! {
3227            if #[cfg(esp32)] {
3228                self.regs().slave().modify(|_, w| {
3229                    for interrupt in interrupts {
3230                        match interrupt {
3231                            SpiInterrupt::TransferDone => w.trans_inten().bit(enable),
3232                        };
3233                    }
3234                    w
3235                });
3236            } else if #[cfg(esp32s2)] {
3237                self.regs().slave().modify(|_, w| {
3238                    for interrupt in interrupts {
3239                        match interrupt {
3240                            SpiInterrupt::TransferDone => w.int_trans_done_en().bit(enable),
3241                            SpiInterrupt::DmaSegmentedTransferDone => w.int_dma_seg_trans_en().bit(enable),
3242                        };
3243                    }
3244                    w
3245                });
3246            } else {
3247                self.regs().dma_int_ena().modify(|_, w| {
3248                    for interrupt in interrupts {
3249                        match interrupt {
3250                            SpiInterrupt::TransferDone => w.trans_done().bit(enable),
3251                            SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
3252                            SpiInterrupt::App2 => w.app2().bit(enable),
3253                            SpiInterrupt::App1 => w.app1().bit(enable),
3254                        };
3255                    }
3256                    w
3257                });
3258            }
3259        }
3260    }
3261
3262    /// Gets asserted interrupts
3263    #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3264    fn interrupts(&self) -> EnumSet<SpiInterrupt> {
3265        let mut res = EnumSet::new();
3266
3267        cfg_if::cfg_if! {
3268            if #[cfg(esp32)] {
3269                if self.regs().slave().read().trans_done().bit() {
3270                    res.insert(SpiInterrupt::TransferDone);
3271                }
3272            } else if #[cfg(esp32s2)] {
3273                if self.regs().slave().read().trans_done().bit() {
3274                    res.insert(SpiInterrupt::TransferDone);
3275                }
3276                if self.regs().hold().read().dma_seg_trans_done().bit() {
3277                    res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3278                }
3279            } else {
3280                let ints = self.regs().dma_int_raw().read();
3281
3282                if ints.trans_done().bit() {
3283                    res.insert(SpiInterrupt::TransferDone);
3284                }
3285                if ints.dma_seg_trans_done().bit() {
3286                    res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3287                }
3288                if ints.app2().bit() {
3289                    res.insert(SpiInterrupt::App2);
3290                }
3291                if ints.app1().bit() {
3292                    res.insert(SpiInterrupt::App1);
3293                }
3294            }
3295        }
3296
3297        res
3298    }
3299
3300    /// Resets asserted interrupts
3301    #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3302    fn clear_interrupts(&self, interrupts: EnumSet<SpiInterrupt>) {
3303        cfg_if::cfg_if! {
3304            if #[cfg(esp32)] {
3305                for interrupt in interrupts {
3306                    match interrupt {
3307                        SpiInterrupt::TransferDone => {
3308                            self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3309                        }
3310                    }
3311                }
3312            } else if #[cfg(esp32s2)] {
3313                for interrupt in interrupts {
3314                    match interrupt {
3315                        SpiInterrupt::TransferDone => {
3316                            self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3317                        }
3318
3319                        SpiInterrupt::DmaSegmentedTransferDone => {
3320                            self.regs()
3321                                .hold()
3322                                .modify(|_, w| w.dma_seg_trans_done().clear_bit());
3323                        }
3324                    }
3325                }
3326            } else {
3327                self.regs().dma_int_clr().write(|w| {
3328                    for interrupt in interrupts {
3329                        match interrupt {
3330                            SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
3331                            SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
3332                            SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
3333                            SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
3334                        };
3335                    }
3336                    w
3337                });
3338            }
3339        }
3340    }
3341
3342    fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
3343        config.validate()?;
3344        self.ch_bus_freq(config)?;
3345        self.set_bit_order(config.read_bit_order, config.write_bit_order);
3346        self.set_data_mode(config.mode);
3347
3348        #[cfg(esp32)]
3349        self.calculate_half_duplex_values(config);
3350
3351        Ok(())
3352    }
3353
3354    #[cfg(esp32)]
3355    fn calculate_half_duplex_values(&self, config: &Config) {
3356        let f_apb = 80_000_000;
3357        let source_freq_hz = match config.clock_source {
3358            ClockSource::Apb => f_apb,
3359        };
3360
3361        let clock_reg = self.regs().clock().read();
3362        let eff_clk = if clock_reg.clk_equ_sysclk().bit_is_set() {
3363            f_apb
3364        } else {
3365            let pre = clock_reg.clkdiv_pre().bits() as i32 + 1;
3366            let n = clock_reg.clkcnt_n().bits() as i32 + 1;
3367            f_apb / (pre * n)
3368        };
3369
3370        let apbclk_khz = source_freq_hz / 1000;
3371        // how many apb clocks a period has
3372        let spiclk_apb_n = source_freq_hz / eff_clk;
3373
3374        // How many apb clocks the delay is, the 1 is to compensate in case
3375        // ``input_delay_ns`` is rounded off. Change from esp-idf: we use
3376        // `input_delay_ns` to also represent the GPIO matrix delay.
3377        let input_delay_ns = 25; // TODO: allow configuring input delay.
3378        let delay_apb_n = (1 + input_delay_ns) * apbclk_khz / 1000 / 1000;
3379
3380        let dummy_required = delay_apb_n / spiclk_apb_n;
3381        let timing_miso_delay = if dummy_required > 0 {
3382            // due to the clock delay between master and slave, there's a range in which
3383            // data is random give MISO a delay if needed to make sure we
3384            // sample at the time MISO is stable
3385            Some(((dummy_required + 1) * spiclk_apb_n - delay_apb_n - 1) as u8)
3386        } else if delay_apb_n * 4 <= spiclk_apb_n {
3387            // if the dummy is not required, maybe we should also delay half a SPI clock if
3388            // the data comes too early
3389            None
3390        } else {
3391            Some(0)
3392        };
3393
3394        self.state.esp32_hack.extra_dummy.set(dummy_required as u8);
3395        self.state
3396            .esp32_hack
3397            .timing_miso_delay
3398            .set(timing_miso_delay);
3399    }
3400
3401    fn set_data_mode(&self, data_mode: Mode) {
3402        cfg_if::cfg_if! {
3403            if #[cfg(esp32)] {
3404                let pin_reg = self.regs().pin();
3405            } else {
3406                let pin_reg = self.regs().misc();
3407            }
3408        };
3409
3410        pin_reg.modify(|_, w| {
3411            w.ck_idle_edge()
3412                .bit(matches!(data_mode, Mode::_2 | Mode::_3))
3413        });
3414        self.regs().user().modify(|_, w| {
3415            w.ck_out_edge()
3416                .bit(matches!(data_mode, Mode::_1 | Mode::_2))
3417        });
3418    }
3419
3420    fn ch_bus_freq(&self, bus_clock_config: &Config) -> Result<(), ConfigError> {
3421        fn enable_clocks(_reg_block: &RegisterBlock, _enable: bool) {
3422            #[cfg(gdma)]
3423            _reg_block.clk_gate().modify(|_, w| {
3424                w.clk_en().bit(_enable);
3425                w.mst_clk_active().bit(_enable);
3426                w.mst_clk_sel().bit(true) // TODO: support XTAL clock source
3427            });
3428        }
3429
3430        // Change clock frequency
3431        let raw = bus_clock_config.raw_clock_reg_value()?;
3432
3433        enable_clocks(self.regs(), false);
3434        self.regs().clock().write(|w| unsafe { w.bits(raw) });
3435        enable_clocks(self.regs(), true);
3436
3437        Ok(())
3438    }
3439
3440    #[cfg(not(any(esp32, esp32c3, esp32s2)))]
3441    fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3442        let read_value = match read_order {
3443            BitOrder::MsbFirst => 0,
3444            BitOrder::LsbFirst => 1,
3445        };
3446        let write_value = match write_order {
3447            BitOrder::MsbFirst => 0,
3448            BitOrder::LsbFirst => 1,
3449        };
3450        self.regs().ctrl().modify(|_, w| unsafe {
3451            w.rd_bit_order().bits(read_value);
3452            w.wr_bit_order().bits(write_value);
3453            w
3454        });
3455    }
3456
3457    #[cfg(any(esp32, esp32c3, esp32s2))]
3458    fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3459        let read_value = match read_order {
3460            BitOrder::MsbFirst => false,
3461            BitOrder::LsbFirst => true,
3462        };
3463        let write_value = match write_order {
3464            BitOrder::MsbFirst => false,
3465            BitOrder::LsbFirst => true,
3466        };
3467        self.regs().ctrl().modify(|_, w| {
3468            w.rd_bit_order().bit(read_value);
3469            w.wr_bit_order().bit(write_value);
3470            w
3471        });
3472    }
3473
3474    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3475    fn fill_fifo(&self, chunk: &[u8]) {
3476        // TODO: replace with `array_chunks` and `from_le_bytes`
3477        let mut c_iter = chunk.chunks_exact(4);
3478        let mut w_iter = self.regs().w_iter();
3479        for c in c_iter.by_ref() {
3480            if let Some(w_reg) = w_iter.next() {
3481                let word = (c[0] as u32)
3482                    | ((c[1] as u32) << 8)
3483                    | ((c[2] as u32) << 16)
3484                    | ((c[3] as u32) << 24);
3485                w_reg.write(|w| w.buf().set(word));
3486            }
3487        }
3488        let rem = c_iter.remainder();
3489        if !rem.is_empty()
3490            && let Some(w_reg) = w_iter.next()
3491        {
3492            let word = match rem.len() {
3493                3 => (rem[0] as u32) | ((rem[1] as u32) << 8) | ((rem[2] as u32) << 16),
3494                2 => (rem[0] as u32) | ((rem[1] as u32) << 8),
3495                1 => rem[0] as u32,
3496                _ => unreachable!(),
3497            };
3498            w_reg.write(|w| w.buf().set(word));
3499        }
3500    }
3501
3502    /// Write bytes to SPI.
3503    ///
3504    /// This function will return before all bytes of the last chunk to transmit
3505    /// have been sent to the wire. If you must ensure that the whole
3506    /// messages was written correctly, use [`Self::flush`].
3507    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3508    fn write(&self, words: &[u8]) -> Result<(), Error> {
3509        let num_chunks = words.len() / FIFO_SIZE;
3510
3511        // Flush in case previous writes have not completed yet, required as per
3512        // embedded-hal documentation (#1369).
3513        self.flush()?;
3514
3515        // The fifo has a limited fixed size, so the data must be chunked and then
3516        // transmitted
3517        for (i, chunk) in words.chunks(FIFO_SIZE).enumerate() {
3518            self.configure_datalen(0, chunk.len());
3519            self.fill_fifo(chunk);
3520
3521            self.start_operation();
3522
3523            // Wait for all chunks to complete except the last one.
3524            // The function is allowed to return before the bus is idle.
3525            // see [embedded-hal flushing](https://docs.rs/embedded-hal/1.0.0/embedded_hal/spi/index.html#flushing)
3526            if i < num_chunks {
3527                self.flush()?;
3528            }
3529        }
3530        Ok(())
3531    }
3532
3533    /// Write bytes to SPI.
3534    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3535    async fn write_async(&self, words: &[u8]) -> Result<(), Error> {
3536        // The fifo has a limited fixed size, so the data must be chunked and then
3537        // transmitted
3538        for chunk in words.chunks(FIFO_SIZE) {
3539            self.configure_datalen(0, chunk.len());
3540            self.fill_fifo(chunk);
3541            self.execute_operation_async().await;
3542        }
3543        Ok(())
3544    }
3545
3546    /// Read bytes from SPI.
3547    ///
3548    /// Sends out a stuffing byte for every byte to read. This function doesn't
3549    /// perform flushing. If you want to read the response to something you
3550    /// have written before, consider using [`Self::transfer`] instead.
3551    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3552    fn read(&self, words: &mut [u8]) -> Result<(), Error> {
3553        let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3554
3555        for chunk in words.chunks_mut(FIFO_SIZE) {
3556            self.write(&empty_array[0..chunk.len()])?;
3557            self.flush()?;
3558            self.read_from_fifo(chunk)?;
3559        }
3560        Ok(())
3561    }
3562
3563    /// Read bytes from SPI.
3564    ///
3565    /// Sends out a stuffing byte for every byte to read. This function doesn't
3566    /// perform flushing. If you want to read the response to something you
3567    /// have written before, consider using [`Self::transfer`] instead.
3568    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3569    async fn read_async(&self, words: &mut [u8]) -> Result<(), Error> {
3570        let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3571
3572        for chunk in words.chunks_mut(FIFO_SIZE) {
3573            self.write_async(&empty_array[0..chunk.len()]).await?;
3574            self.read_from_fifo(chunk)?;
3575        }
3576        Ok(())
3577    }
3578
3579    /// Read received bytes from SPI FIFO.
3580    ///
3581    /// Copies the contents of the SPI receive FIFO into `words`. This function
3582    /// doesn't perform flushing. If you want to read the response to
3583    /// something you have written before, consider using [`Self::transfer`]
3584    /// instead.
3585    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3586    fn read_from_fifo(&self, words: &mut [u8]) -> Result<(), Error> {
3587        let reg_block = self.regs();
3588
3589        for chunk in words.chunks_mut(FIFO_SIZE) {
3590            self.configure_datalen(chunk.len(), 0);
3591
3592            for (index, w_reg) in (0..chunk.len()).step_by(4).zip(reg_block.w_iter()) {
3593                let reg_val = w_reg.read().bits();
3594                let bytes = reg_val.to_le_bytes();
3595
3596                let len = usize::min(chunk.len(), index + 4) - index;
3597                chunk[index..(index + len)].clone_from_slice(&bytes[0..len]);
3598            }
3599        }
3600
3601        Ok(())
3602    }
3603
3604    fn busy(&self) -> bool {
3605        self.regs().cmd().read().usr().bit_is_set()
3606    }
3607
3608    // Check if the bus is busy and if it is wait for it to be idle
3609    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3610    async fn flush_async(&self) -> Result<(), Error> {
3611        if self.busy() {
3612            let future = SpiFuture::setup(self).await;
3613            future.await;
3614        }
3615
3616        Ok(())
3617    }
3618
3619    // Check if the bus is busy and if it is wait for it to be idle
3620    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3621    fn flush(&self) -> Result<(), Error> {
3622        while self.busy() {
3623            // wait for bus to be clear
3624        }
3625        Ok(())
3626    }
3627
3628    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3629    fn transfer(&self, words: &mut [u8]) -> Result<(), Error> {
3630        for chunk in words.chunks_mut(FIFO_SIZE) {
3631            self.write(chunk)?;
3632            self.flush()?;
3633            self.read_from_fifo(chunk)?;
3634        }
3635
3636        Ok(())
3637    }
3638
3639    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3640    async fn transfer_in_place_async(&self, words: &mut [u8]) -> Result<(), Error> {
3641        for chunk in words.chunks_mut(FIFO_SIZE) {
3642            // Cut the transfer short if the future is dropped. We'll block for a short
3643            // while to ensure the peripheral is idle.
3644            let cancel_on_drop = OnDrop::new(|| {
3645                self.abort_transfer();
3646                while self.busy() {}
3647            });
3648            let res = self.write_async(chunk).await;
3649            cancel_on_drop.defuse();
3650            res?;
3651
3652            self.read_from_fifo(chunk)?;
3653        }
3654
3655        Ok(())
3656    }
3657
3658    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3659    fn start_operation(&self) {
3660        self.update();
3661        self.regs().cmd().modify(|_, w| w.usr().set_bit());
3662    }
3663
3664    /// Starts the operation and waits for it to complete.
3665    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3666    async fn execute_operation_async(&self) {
3667        // On ESP32, the interrupt seems to not fire in specific circumstances, when
3668        // `listen` is called after `start_operation`. Let's call it before, to be sure.
3669        let future = SpiFuture::setup(self).await;
3670        self.start_operation();
3671        future.await;
3672    }
3673
3674    fn setup_full_duplex(&self) -> Result<(), Error> {
3675        self.regs().user().modify(|_, w| {
3676            w.usr_miso().set_bit();
3677            w.usr_mosi().set_bit();
3678            w.doutdin().set_bit();
3679            w.usr_dummy().clear_bit();
3680            w.sio().clear_bit()
3681        });
3682
3683        self.init_spi_data_mode(
3684            DataMode::SingleTwoDataLines,
3685            DataMode::SingleTwoDataLines,
3686            DataMode::SingleTwoDataLines,
3687        )?;
3688
3689        // For full-duplex, we don't need compensation according to esp-idf.
3690        #[cfg(esp32)]
3691        self.regs().ctrl2().modify(|_, w| unsafe {
3692            w.miso_delay_mode().bits(0);
3693            w.miso_delay_num().bits(0)
3694        });
3695
3696        Ok(())
3697    }
3698
3699    #[allow(clippy::too_many_arguments)]
3700    fn setup_half_duplex(
3701        &self,
3702        is_write: bool,
3703        cmd: Command,
3704        address: Address,
3705        dummy_idle: bool,
3706        dummy: u8,
3707        no_mosi_miso: bool,
3708        data_mode: DataMode,
3709    ) -> Result<(), Error> {
3710        self.init_spi_data_mode(cmd.mode(), address.mode(), data_mode)?;
3711
3712        #[cfg(esp32)]
3713        let mut dummy = dummy;
3714
3715        #[cfg(esp32)]
3716        self.regs().ctrl2().modify(|_, w| {
3717            let mut delay_mode = 0;
3718            let mut delay_num = 0;
3719
3720            if !is_write {
3721                // Values are set up in apply_config
3722                let timing_miso_delay = self.state.esp32_hack.timing_miso_delay.get();
3723                let extra_dummy = self.state.esp32_hack.extra_dummy.get();
3724                dummy += extra_dummy;
3725
3726                if let Some(delay) = timing_miso_delay {
3727                    delay_num = if extra_dummy > 0 { delay } else { 0 };
3728                } else {
3729                    let out_edge = self.regs().user().read().ck_out_edge().bit_is_set();
3730                    // SPI modes 1 and 2 need delay mode 1 according to esp-idf.
3731                    delay_mode = if out_edge { 1 } else { 2 };
3732                }
3733            }
3734
3735            unsafe {
3736                w.miso_delay_mode().bits(delay_mode);
3737                w.miso_delay_num().bits(delay_num)
3738            }
3739        });
3740
3741        let reg_block = self.regs();
3742        reg_block.user().modify(|_, w| {
3743            w.usr_miso_highpart().clear_bit();
3744            w.usr_mosi_highpart().clear_bit();
3745            // This bit tells the hardware whether we use Single or SingleTwoDataLines
3746            w.sio().bit(data_mode == DataMode::Single);
3747            w.doutdin().clear_bit();
3748            w.usr_miso().bit(!is_write && !no_mosi_miso);
3749            w.usr_mosi().bit(is_write && !no_mosi_miso);
3750            w.cs_hold().set_bit();
3751            w.usr_dummy_idle().bit(dummy_idle);
3752            w.usr_dummy().bit(dummy != 0);
3753            w.usr_addr().bit(!address.is_none());
3754            w.usr_command().bit(!cmd.is_none())
3755        });
3756
3757        #[cfg(gdma)]
3758        reg_block.clk_gate().modify(|_, w| {
3759            w.clk_en().set_bit();
3760            w.mst_clk_active().set_bit();
3761            w.mst_clk_sel().set_bit()
3762        });
3763
3764        #[cfg(any(esp32c6, esp32h2))]
3765        // use default clock source PLL_F80M_CLK
3766        crate::peripherals::PCR::regs()
3767            .spi2_clkm_conf()
3768            .modify(|_, w| unsafe { w.spi2_clkm_sel().bits(1) });
3769
3770        #[cfg(not(esp32))]
3771        reg_block.misc().write(|w| unsafe { w.bits(0) });
3772
3773        reg_block.slave().write(|w| unsafe { w.bits(0) });
3774
3775        self.update();
3776
3777        // set cmd, address, dummy cycles
3778        self.set_up_common_phases(cmd, address, dummy);
3779
3780        Ok(())
3781    }
3782
3783    fn set_up_common_phases(&self, cmd: Command, address: Address, dummy: u8) {
3784        let reg_block = self.regs();
3785        if !cmd.is_none() {
3786            reg_block.user2().modify(|_, w| unsafe {
3787                w.usr_command_bitlen().bits((cmd.width() - 1) as u8);
3788                w.usr_command_value().bits(cmd.value())
3789            });
3790        }
3791
3792        if !address.is_none() {
3793            reg_block
3794                .user1()
3795                .modify(|_, w| unsafe { w.usr_addr_bitlen().bits((address.width() - 1) as u8) });
3796
3797            let addr = address.value() << (32 - address.width());
3798            #[cfg(not(esp32))]
3799            reg_block
3800                .addr()
3801                .write(|w| unsafe { w.usr_addr_value().bits(addr) });
3802            #[cfg(esp32)]
3803            reg_block.addr().write(|w| unsafe { w.bits(addr) });
3804        }
3805
3806        if dummy > 0 {
3807            reg_block
3808                .user1()
3809                .modify(|_, w| unsafe { w.usr_dummy_cyclelen().bits(dummy - 1) });
3810        }
3811    }
3812
3813    fn update(&self) {
3814        cfg_if::cfg_if! {
3815            if #[cfg(gdma)] {
3816                let reg_block = self.regs();
3817
3818                reg_block.cmd().modify(|_, w| w.update().set_bit());
3819
3820                while reg_block.cmd().read().update().bit_is_set() {
3821                    // wait
3822                }
3823            } else {
3824                // Doesn't seem to be needed for ESP32 and ESP32-S2
3825            }
3826        }
3827    }
3828
3829    fn configure_datalen(&self, rx_len_bytes: usize, tx_len_bytes: usize) {
3830        let reg_block = self.regs();
3831
3832        let rx_len = rx_len_bytes as u32 * 8;
3833        let tx_len = tx_len_bytes as u32 * 8;
3834
3835        let rx_len = rx_len.saturating_sub(1);
3836        let tx_len = tx_len.saturating_sub(1);
3837
3838        cfg_if::cfg_if! {
3839            if #[cfg(esp32)] {
3840                let len = rx_len.max(tx_len);
3841                reg_block
3842                    .mosi_dlen()
3843                    .write(|w| unsafe { w.usr_mosi_dbitlen().bits(len) });
3844
3845                reg_block
3846                    .miso_dlen()
3847                    .write(|w| unsafe { w.usr_miso_dbitlen().bits(len) });
3848            } else if #[cfg(esp32s2)] {
3849                reg_block
3850                    .mosi_dlen()
3851                    .write(|w| unsafe { w.usr_mosi_dbitlen().bits(tx_len) });
3852
3853                reg_block
3854                    .miso_dlen()
3855                    .write(|w| unsafe { w.usr_miso_dbitlen().bits(rx_len) });
3856            } else {
3857                reg_block
3858                    .ms_dlen()
3859                    .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
3860            }
3861
3862        }
3863    }
3864}
3865
3866impl PartialEq for Info {
3867    fn eq(&self, other: &Self) -> bool {
3868        core::ptr::eq(self.register_block, other.register_block)
3869    }
3870}
3871
3872unsafe impl Sync for Info {}
3873
3874for_each_spi_master! {
3875    ($peri:ident, $sys:ident, $sclk:ident [$($cs:ident),+] [$($sio:ident),*] $(, $is_qspi:tt)?) => {
3876        impl Instance for crate::peripherals::$peri<'_> {
3877            #[inline(always)]
3878            fn parts(&self) -> (&'static Info, &'static State) {
3879                #[crate::handler]
3880                #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3881                fn irq_handler() {
3882                    handle_async(&INFO, &STATE)
3883                }
3884
3885                static INFO: Info = Info {
3886                    register_block: crate::peripherals::$peri::regs(),
3887                    peripheral: crate::system::Peripheral::$sys,
3888                    async_handler: irq_handler,
3889                    sclk: OutputSignal::$sclk,
3890                    cs: &[$(OutputSignal::$cs),+],
3891                    sio_inputs: &[$(InputSignal::$sio),*],
3892                    sio_outputs: &[$(OutputSignal::$sio),*],
3893                };
3894
3895                static STATE: State = State {
3896                    waker: AtomicWaker::new(),
3897                    #[cfg(esp32)]
3898                    esp32_hack: Esp32Hack {
3899                        timing_miso_delay: Cell::new(None),
3900                        extra_dummy: Cell::new(0),
3901                    },
3902                };
3903
3904                (&INFO, &STATE)
3905            }
3906        }
3907
3908        $(
3909            // If the extra pins are set, implement QspiInstance
3910            $crate::ignore!($is_qspi);
3911            impl QspiInstance for crate::peripherals::$peri<'_> {}
3912        )?
3913    };
3914}
3915
3916impl QspiInstance for AnySpi<'_> {}
3917
3918#[doc(hidden)]
3919pub struct State {
3920    waker: AtomicWaker,
3921
3922    #[cfg(esp32)]
3923    esp32_hack: Esp32Hack,
3924}
3925
3926#[cfg(esp32)]
3927struct Esp32Hack {
3928    timing_miso_delay: Cell<Option<u8>>,
3929    extra_dummy: Cell<u8>,
3930}
3931
3932#[cfg(esp32)]
3933unsafe impl Sync for Esp32Hack {}
3934
3935#[cfg_attr(place_spi_master_driver_in_ram, ram)]
3936fn handle_async(info: &'static Info, state: &'static State) {
3937    let driver = Driver { info, state };
3938    if driver.interrupts().contains(SpiInterrupt::TransferDone) {
3939        driver.enable_listen(SpiInterrupt::TransferDone.into(), false);
3940        state.waker.wake();
3941    }
3942}
3943
3944/// SPI data mode
3945#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3946#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3947#[instability::unstable]
3948pub enum DataMode {
3949    /// 1 bit, two data lines. (MOSI, MISO)
3950    SingleTwoDataLines,
3951    /// 1 bit, 1 data line (SIO0)
3952    Single,
3953    /// 2 bits, two data lines. (SIO0, SIO1)
3954    Dual,
3955    /// 4 bit, 4 data lines. (SIO0 .. SIO3)
3956    Quad,
3957    #[cfg(spi_master_has_octal)]
3958    /// 8 bit, 8 data lines. (SIO0 .. SIO7)
3959    Octal,
3960}
3961
3962crate::any_peripheral! {
3963    /// Any SPI peripheral.
3964    pub peripheral AnySpi<'d> {
3965        #[cfg(spi_master_spi2)]
3966        Spi2(crate::peripherals::SPI2<'d>),
3967        #[cfg(spi_master_spi3)]
3968        Spi3(crate::peripherals::SPI3<'d>),
3969    }
3970}
3971
3972impl<'d> DmaEligible for AnySpi<'d> {
3973    #[cfg(gdma)]
3974    type Dma = crate::dma::AnyGdmaChannel<'d>;
3975    #[cfg(pdma)]
3976    type Dma = crate::dma::AnySpiDmaChannel<'d>;
3977
3978    fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
3979        match &self.0 {
3980            #[cfg(spi_master_spi2)]
3981            any::Inner::Spi2(_) => crate::dma::DmaPeripheral::Spi2,
3982            #[cfg(spi_master_spi3)]
3983            any::Inner::Spi3(_) => crate::dma::DmaPeripheral::Spi3,
3984        }
3985    }
3986}
3987
3988impl Instance for AnySpi<'_> {
3989    #[inline]
3990    fn parts(&self) -> (&'static Info, &'static State) {
3991        any::delegate!(self, spi => { spi.parts() })
3992    }
3993}
3994
3995impl AnySpi<'_> {
3996    fn bind_peri_interrupt(&self, handler: unsafe extern "C" fn() -> ()) {
3997        any::delegate!(self, spi => { spi.bind_peri_interrupt(handler) })
3998    }
3999
4000    fn disable_peri_interrupt(&self) {
4001        any::delegate!(self, spi => { spi.disable_peri_interrupt() })
4002    }
4003
4004    fn enable_peri_interrupt(&self, priority: crate::interrupt::Priority) {
4005        any::delegate!(self, spi => { spi.enable_peri_interrupt(priority) })
4006    }
4007
4008    fn set_interrupt_handler(&self, handler: InterruptHandler) {
4009        self.disable_peri_interrupt();
4010        self.bind_peri_interrupt(handler.handler());
4011        self.enable_peri_interrupt(handler.priority());
4012    }
4013}
4014
4015struct SpiFuture<'a> {
4016    driver: &'a Driver,
4017}
4018
4019impl<'a> SpiFuture<'a> {
4020    #[cfg_attr(place_spi_master_driver_in_ram, ram)]
4021    fn setup(driver: &'a Driver) -> impl Future<Output = Self> {
4022        // Make sure this is called before starting an async operation. On the ESP32,
4023        // calling after may cause the interrupt to not fire.
4024        core::future::poll_fn(move |cx| {
4025            driver.state.waker.register(cx.waker());
4026            driver.clear_interrupts(SpiInterrupt::TransferDone.into());
4027            driver.enable_listen(SpiInterrupt::TransferDone.into(), true);
4028            Poll::Ready(Self { driver })
4029        })
4030    }
4031}
4032
4033use core::{
4034    future::Future,
4035    pin::Pin,
4036    task::{Context, Poll},
4037};
4038
4039use crate::dma::{Channel, PeripheralDmaChannel};
4040
4041impl Future for SpiFuture<'_> {
4042    type Output = ();
4043
4044    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
4045        if self
4046            .driver
4047            .interrupts()
4048            .contains(SpiInterrupt::TransferDone)
4049        {
4050            self.driver
4051                .clear_interrupts(SpiInterrupt::TransferDone.into());
4052            return Poll::Ready(());
4053        }
4054
4055        Poll::Pending
4056    }
4057}
4058
4059impl Drop for SpiFuture<'_> {
4060    fn drop(&mut self) {
4061        self.driver
4062            .enable_listen(SpiInterrupt::TransferDone.into(), false);
4063    }
4064}