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