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