1
#![cfg_attr(docsrs, procmacros::doc_replace(
2
    "dma_channel" => {
3
        cfg(spi_slave_dma_engine = "SPI_DMA") => "DMA_SPI2",
4
        cfg(spi_slave_dma_engine = "AHB_GDMA") => "DMA_CH0",
5
        cfg(spi_slave_dma_engine = "AXI_GDMA") => "DMA_AXI_CH0",
6
    },
7
))]
8
//! # Serial Peripheral Interface - Slave Mode
9
//!
10
//! ## Overview
11
//!
12
//! In this mode, the SPI acts as slave and transfers data with its master when
13
//! its CS is asserted.
14
//!
15
//! ## Configuration
16
//!
17
//! The SPI slave driver allows using full-duplex and can only be used with DMA.
18
#![cfg_attr(
19
    spi_slave_supports_dma,
20
    doc = r#"
21
## Examples
22

            
23
### SPI Slave with DMA
24

            
25
```rust, no_run
26
# {before_snippet}
27
# use esp_hal::dma_rx_buffer;
28
# use esp_hal::dma_tx_buffer;
29
# use esp_hal::spi::Mode;
30
# use esp_hal::spi::slave::Spi;
31
let sclk = peripherals.GPIO0;
32
let miso = peripherals.GPIO1;
33
let mosi = peripherals.GPIO2;
34
let cs = peripherals.GPIO3;
35

            
36
let dma_rx_buf = dma_rx_buffer!(32000).unwrap();
37
let dma_tx_buf = dma_tx_buffer!(32000).unwrap();
38
let mut spi = Spi::new(peripherals.SPI2, Mode::_0)
39
    .with_sck(sclk)
40
    .with_mosi(mosi)
41
    .with_miso(miso)
42
    .with_cs(cs)
43
    .with_dma(peripherals.__dma_channel__);
44

            
45
let transfer = spi.transfer(50, dma_rx_buf, 50, dma_tx_buf)?;
46

            
47
transfer.wait();
48
# {after_snippet}
49
```
50
"#
51
)]
52
//! ## Implementation State
53
//!
54
//! This driver is currently **unstable**.
55
//!
56
//! There are several options for working with the SPI peripheral in slave mode,
57
//! but the code currently only supports:
58
//!     - Single transfers (not segmented transfers)
59
//!     - Full duplex, single bit (not dual or quad SPI)
60
//!     - DMA mode (not CPU mode).
61
#![cfg_attr(esp32, doc = "- ESP32 only supports SPI mode 1 and 3.\n\n")]
62
//! It also does not support blocking operations, as the actual
63
//! transfer is controlled by the SPI master; if these are necessary,
64
//! then the `SpiDmaTransfer` object can be `wait()`ed on or polled for
65
//! `is_done()`.
66
//!
67
//! See [tracking issue](https://github.com/esp-rs/esp-hal/issues/469) for more information.
68

            
69
use core::marker::PhantomData;
70

            
71
use super::Mode;
72
use crate::{
73
    Blocking,
74
    DriverMode,
75
    gpio::{
76
        InputSignal,
77
        NoPin,
78
        OutputConfig,
79
        OutputSignal,
80
        interconnect::{PeripheralInput, PeripheralOutput},
81
    },
82
    pac::spi2::RegisterBlock,
83
    system::PeripheralGuard,
84
};
85

            
86
/// SPI peripheral driver.
87
///
88
/// See the [module-level documentation][self] for more details.
89
#[instability::unstable]
90
pub struct Spi<'d, Dm: DriverMode> {
91
    spi: AnySpi<'d>,
92
    #[allow(dead_code)]
93
    data_mode: Mode,
94
    _mode: PhantomData<Dm>,
95
    _guard: PeripheralGuard,
96
}
97
impl<'d> Spi<'d, Blocking> {
98
    /// Creates a new SPI instance in 8-bit data-frame mode.
99
    #[instability::unstable]
100
    pub fn new(spi: impl Instance + 'd, mode: Mode) -> Spi<'d, Blocking> {
101
2
        let guard = PeripheralGuard::new(spi.info().peripheral);
102

            
103
        let this = Spi {
104
            spi: spi.degrade(),
105
            data_mode: mode,
106
            _mode: PhantomData,
107
            _guard: guard,
108
        };
109

            
110
2
        this.spi.info().init();
111
2
        this.spi.info().set_data_mode(mode, false);
112

            
113
        this.with_mosi(NoPin)
114
            .with_miso(NoPin)
115
            .with_sck(NoPin)
116
            .with_cs(NoPin)
117
    }
118

            
119
    fn connect_input_pin(&self, pin: impl PeripheralInput<'d>, signal: InputSignal) {
120
2
        let pin = pin.into();
121
        pin.set_input_enable(true);
122
        signal.connect_to(&pin);
123
    }
124

            
125
    /// Assigns the SCK (Serial Clock) pin for the SPI instance.
126
    #[instability::unstable]
127
    pub fn with_sck(self, sclk: impl PeripheralInput<'d>) -> Self {
128
2
        self.connect_input_pin(sclk, self.spi.info().sclk);
129
        self
130
    }
131

            
132
    /// Assigns the MOSI (Master Out Slave In) pin for the SPI instance.
133
    #[instability::unstable]
134
    pub fn with_mosi(self, mosi: impl PeripheralInput<'d>) -> Self {
135
2
        self.connect_input_pin(mosi, self.spi.info().mosi);
136
        self
137
    }
138

            
139
    /// Assigns the MISO (Master In Slave Out) pin for the SPI instance.
140
    #[instability::unstable]
141
    pub fn with_miso(self, miso: impl PeripheralOutput<'d>) -> Self {
142
2
        let miso = miso.into();
143

            
144
        miso.apply_output_config(&OutputConfig::default());
145
        miso.set_output_enable(true);
146

            
147
2
        self.spi.info().miso.connect_to(&miso);
148
        self
149
    }
150

            
151
    /// Assigns the CS (Chip Select) pin for the SPI instance.
152
    #[instability::unstable]
153
    pub fn with_cs(self, cs: impl PeripheralInput<'d>) -> Self {
154
2
        self.connect_input_pin(cs, self.spi.info().cs);
155
        self
156
    }
157
}
158

            
159
/// DMA (Direct Memory Access) functionality (Slave).
160
#[instability::unstable]
161
#[cfg(spi_slave_supports_dma)]
162
pub mod dma {
163
    use core::mem::ManuallyDrop;
164

            
165
    use enumset::enum_set;
166

            
167
    use super::*;
168
    #[cfg(not(spi_slave_dma_engine = "SPI_DMA"))]
169
    use crate::RegisterToggle;
170
    use crate::{
171
        DriverMode,
172
        dma::{Channel, DmaRxBuffer, DmaRxInterrupt, DmaTxBuffer, EmptyBuf},
173
        rtc_cntl::WakeLock,
174
        spi::Error,
175
    };
176

            
177
    const MAX_DMA_SIZE: usize = 32768 - 32;
178

            
179
    impl<'d> Spi<'d, Blocking> {
180
        /// Configures the SPI peripheral with the provided DMA channel and
181
        /// descriptors.
182
        #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")]
183
        #[instability::unstable]
184
        pub fn with_dma(
185
            self,
186
            channel: impl SpiSlaveDmaChannel<'d, AnySpi<'d>>,
187
        ) -> dma::SpiDma<'d, Blocking> {
188
2
            self.spi.info().set_data_mode(self.data_mode, true);
189
2
            dma::SpiDma::new(self.spi, channel.into())
190
        }
191
    }
192

            
193
    /// A structure representing a DMA transfer for SPI.
194
    #[instability::unstable]
195
    pub struct SpiDma<'d, Dm>
196
    where
197
        Dm: DriverMode,
198
    {
199
        pub(crate) spi: AnySpi<'d>,
200
        pub(crate) channel: Channel<Dm, SpiSlaveErased<'d>>,
201
        _guard: PeripheralGuard,
202
    }
203

            
204
    impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
205
    where
206
        Dm: DriverMode,
207
    {
208
        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209
            f.debug_struct("SpiDma").finish()
210
        }
211
    }
212

            
213
    impl<'d> SpiDma<'d, Blocking> {
214
2
        pub(super) fn new(spi: AnySpi<'d>, channel: SpiSlaveErased<'d>) -> Self {
215
2
            let channel = Channel::new(channel);
216
2
            channel.runtime_ensure_compatible(spi.dma_peripheral());
217
            let guard = PeripheralGuard::new(spi.info().peripheral);
218

            
219
2
            Self {
220
                spi,
221
                channel,
222
                _guard: guard,
223
            }
224
2
        }
225
    }
226

            
227
    impl<'d, Dm> SpiDma<'d, Dm>
228
    where
229
        Dm: DriverMode,
230
    {
231
        fn driver(&self) -> DmaDriver {
232
            DmaDriver {
233
                info: self.spi.info(),
234
                dma_peripheral: self.spi.dma_peripheral(),
235
            }
236
        }
237

            
238
        /// Registers a buffer for a DMA write.
239
        ///
240
        /// Returns a [`SpiDmaTransfer`] that can be used to wait for the transfer to complete.
241
        /// The maximum amount of data to be sent is 32736 bytes.
242
        ///
243
        /// The write is driven by the SPI master's sclk signal and cs line.
244
        #[instability::unstable]
245
        pub fn write<TX>(
246
            mut self,
247
            bytes_to_write: usize,
248
            mut buffer: TX,
249
        ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)>
250
        where
251
            TX: DmaTxBuffer,
252
        {
253
            if bytes_to_write > MAX_DMA_SIZE {
254
                return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
255
            }
256

            
257
            let result = unsafe {
258
                self.driver().start_transfer_dma(
259
                    0,
260
                    bytes_to_write,
261
                    &mut EmptyBuf,
262
                    &mut buffer,
263
                    &mut self.channel,
264
                )
265
            };
266
            if let Err(err) = result {
267
                return Err((err, self, buffer));
268
            }
269

            
270
            Ok(SpiDmaTransfer::new(self, buffer, false, true))
271
        }
272

            
273
        /// Registers a buffer for a DMA read.
274
        ///
275
        /// Returns a [`SpiDmaTransfer`] that can be used to wait for the transfer to complete.
276
        /// The maximum amount of data to be received is 32736 bytes.
277
        ///
278
        /// The read is driven by the SPI master's sclk signal and cs line.
279
        #[instability::unstable]
280
        pub fn read<RX>(
281
            mut self,
282
            bytes_to_read: usize,
283
            mut buffer: RX,
284
        ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)>
285
        where
286
            RX: DmaRxBuffer,
287
        {
288
            if bytes_to_read > MAX_DMA_SIZE {
289
                return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
290
            }
291

            
292
            let result = unsafe {
293
                self.driver().start_transfer_dma(
294
                    bytes_to_read,
295
                    0,
296
                    &mut buffer,
297
                    &mut EmptyBuf,
298
                    &mut self.channel,
299
                )
300
            };
301
            if let Err(err) = result {
302
                return Err((err, self, buffer));
303
            }
304

            
305
            Ok(SpiDmaTransfer::new(self, buffer, true, false))
306
        }
307

            
308
        /// Registers buffers for a DMA transfer.
309
        ///
310
        /// Returns a [`SpiDmaTransfer`] that can be used to wait for the transfer to complete.
311
        /// The maximum amount of data to be sent/received is 32736 bytes.
312
        ///
313
        /// The data transfer is driven by the SPI master's sclk signal and cs
314
        /// line.
315
        #[instability::unstable]
316
        #[allow(clippy::type_complexity)]
317
        pub fn transfer<RX, TX>(
318
            mut self,
319
            bytes_to_read: usize,
320
            mut rx_buffer: RX,
321
            bytes_to_write: usize,
322
            mut tx_buffer: TX,
323
        ) -> Result<SpiDmaTransfer<'d, Dm, (RX, TX)>, (Error, Self, RX, TX)>
324
        where
325
            RX: DmaRxBuffer,
326
            TX: DmaTxBuffer,
327
        {
328
            if bytes_to_read > MAX_DMA_SIZE || bytes_to_write > MAX_DMA_SIZE {
329
                return Err((
330
                    Error::MaxDmaTransferSizeExceeded,
331
                    self,
332
                    rx_buffer,
333
                    tx_buffer,
334
                ));
335
            }
336

            
337
            let result = unsafe {
338
2
                self.driver().start_transfer_dma(
339
                    bytes_to_read,
340
                    bytes_to_write,
341
                    &mut rx_buffer,
342
                    &mut tx_buffer,
343
                    &mut self.channel,
344
                )
345
            };
346
            if let Err(err) = result {
347
                return Err((err, self, rx_buffer, tx_buffer));
348
            }
349

            
350
            Ok(SpiDmaTransfer::new(
351
2
                self,
352
2
                (rx_buffer, tx_buffer),
353
                true,
354
                true,
355
            ))
356
        }
357
    }
358

            
359
    /// A structure representing a DMA transfer for SPI.
360
    ///
361
    /// Holds references to the SPI instance, DMA buffers, and transfer status.
362
    #[instability::unstable]
363
    pub struct SpiDmaTransfer<'d, Dm, Buf>
364
    where
365
        Dm: DriverMode,
366
    {
367
        spi_dma: ManuallyDrop<SpiDma<'d, Dm>>,
368
        dma_buf: ManuallyDrop<Buf>,
369
        has_rx: bool,
370
        has_tx: bool,
371
        _wake_lock: WakeLock,
372
    }
373

            
374
    impl<'d, Dm, Buf> SpiDmaTransfer<'d, Dm, Buf>
375
    where
376
        Dm: DriverMode,
377
    {
378
        fn new(spi_dma: SpiDma<'d, Dm>, dma_buf: Buf, has_rx: bool, has_tx: bool) -> Self {
379
2
            Self {
380
                spi_dma: ManuallyDrop::new(spi_dma),
381
                dma_buf: ManuallyDrop::new(dma_buf),
382
                has_rx,
383
                has_tx,
384
2
                _wake_lock: WakeLock::new(),
385
            }
386
        }
387

            
388
        /// Returns whether the transfer is complete.
389
        ///
390
        /// Both RX and TX operations are done, and the SPI instance is no longer
391
        /// busy.
392
        #[instability::unstable]
393
        pub fn is_done(&self) -> bool {
394
            if self.has_rx {
395
                let done_int =
396
                    enum_set!(DmaRxInterrupt::SuccessfulEof | DmaRxInterrupt::DescriptorEmpty);
397
11431097
                if self
398
                    .spi_dma
399
                    .channel
400
                    .rx
401
                    .pending_in_interrupts()
402
                    .is_disjoint(done_int)
403
                {
404
                    return false;
405
                }
406
            }
407
            !self.spi_dma.spi.info().is_bus_busy()
408
        }
409

            
410
        /// Waits for the DMA transfer to complete.
411
        ///
412
        /// Blocks until the transfer is finished and returns the
413
        /// `SpiDma` instance and the associated buffer.
414
        #[instability::unstable]
415
        pub fn wait(mut self) -> (SpiDma<'d, Dm>, Buf) {
416
            while !self.is_done() {
417
                // Wait for the SPI to become idle
418
            }
419

            
420
            if self.has_tx {
421
                // In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA.
422
                if !self.spi_dma.channel.tx.is_done() {
423
                    self.spi_dma.channel.tx.stop_transfer();
424
                }
425
            }
426

            
427
            let retval = unsafe {
428
                (
429
                    ManuallyDrop::take(&mut self.spi_dma),
430
                    ManuallyDrop::take(&mut self.dma_buf),
431
                )
432
            };
433
            core::mem::forget(self);
434
            retval
435
        }
436
    }
437

            
438
    impl<Dm, Buf> Drop for SpiDmaTransfer<'_, Dm, Buf>
439
    where
440
        Dm: DriverMode,
441
    {
442
        fn drop(&mut self) {
443
            while !self.is_done() {
444
                // Wait for the SPI to become idle
445
            }
446
            unsafe {
447
                ManuallyDrop::drop(&mut self.spi_dma);
448
                ManuallyDrop::drop(&mut self.dma_buf);
449
            }
450
        }
451
    }
452

            
453
    struct DmaDriver {
454
        info: &'static Info,
455
        dma_peripheral: crate::dma::DmaPeripheral,
456
    }
457

            
458
    impl DmaDriver {
459
        fn regs(&self) -> &RegisterBlock {
460
2
            self.info.regs()
461
        }
462

            
463
        unsafe fn start_transfer_dma<Dm: DriverMode>(
464
            &self,
465
            read_buffer_len: usize,
466
            write_buffer_len: usize,
467
            rx_buffer: &mut impl DmaRxBuffer,
468
            tx_buffer: &mut impl DmaTxBuffer,
469
            channel: &mut Channel<Dm, SpiSlaveErased<'_>>,
470
        ) -> Result<(), Error> {
471
2
            self.enable_dma();
472

            
473
2
            self.info.reset_spi();
474

            
475
            if read_buffer_len > 0 {
476
                unsafe {
477
                    channel
478
                        .rx
479
                        .prepare_transfer(self.dma_peripheral, rx_buffer)?;
480
                }
481
            }
482

            
483
            if write_buffer_len > 0 {
484
                unsafe {
485
2
                    channel
486
                        .tx
487
                        .prepare_transfer(self.dma_peripheral, tx_buffer)?;
488
                }
489
            }
490

            
491
            #[cfg(esp32)]
492
            self.info
493
                .prepare_length_and_lines(read_buffer_len, write_buffer_len);
494

            
495
            #[cfg(not(esp32))]
496
            self.regs()
497
                .dma_conf()
498
                .modify(|_, w| w.dma_slv_seg_trans_en().clear_bit());
499

            
500
2
            self.clear_dma_interrupts();
501
2
            self.info.setup_for_flush();
502

            
503
            if read_buffer_len > 0 {
504
2
                self.reset_dma_rx_fifo();
505
                channel.rx.start_transfer()?;
506
            }
507

            
508
            if write_buffer_len > 0 {
509
2
                self.reset_dma_tx_fifo();
510
                channel.tx.start_transfer()?;
511
            }
512

            
513
            // The SPI master owns SCLK and CS. Arm the peripheral only after
514
            // both GDMA directions can service the first edge.
515
            self.regs().cmd().modify(|_, w| w.usr().set_bit());
516

            
517
            Ok(())
518
        }
519

            
520
2
        fn reset_dma_rx_fifo(&self) {
521
            #[cfg(not(spi_slave_dma_engine = "SPI_DMA"))]
522
            self.regs()
523
                .dma_conf()
524
                .toggle(|w, bit| w.rx_afifo_rst().bit(bit));
525
2
        }
526

            
527
2
        fn reset_dma_tx_fifo(&self) {
528
            #[cfg(not(spi_slave_dma_engine = "SPI_DMA"))]
529
            self.regs()
530
                .dma_conf()
531
                .toggle(|w, bit| w.dma_afifo_rst().bit(bit));
532
2
        }
533

            
534
        fn enable_dma(&self) {
535
            cfg_select! {
536
                spi_slave_dma_engine = "SPI_DMA" => {
537
                    use crate::RegisterToggle;
538
                    self.regs().dma_conf().toggle(|w, bit| {
539
                        w.in_rst().bit(bit);
540
                        w.out_rst().bit(bit);
541
                        w.ahbm_fifo_rst().bit(bit);
542
                        #[cfg(esp32s2)]
543
                        w.dma_infifo_full_clr().bit(bit);
544
                        w.ahbm_rst().bit(bit)
545
                    });
546
                }
547
                _ => {
548
                    self.regs().dma_conf().modify(|_, w| {
549
                        w.dma_tx_ena().set_bit();
550
                        w.dma_rx_ena().set_bit();
551
                        w.rx_eof_en().clear_bit()
552
                    });
553
                }
554
            }
555
2
        }
556

            
557
        fn clear_dma_interrupts(&self) {
558
            self.regs().dma_int_clr().write(|w| {
559
                cfg_select! {
560
                    spi_slave_dma_engine = "SPI_DMA" => {
561
                        w.inlink_dscr_empty().clear_bit_by_one();
562
                        w.outlink_dscr_error().clear_bit_by_one();
563
                        w.inlink_dscr_error().clear_bit_by_one();
564
                        w.in_done().clear_bit_by_one();
565
                        w.in_err_eof().clear_bit_by_one();
566
                        w.in_suc_eof().clear_bit_by_one();
567
                        w.out_done().clear_bit_by_one();
568
                        w.out_eof().clear_bit_by_one();
569
                        w.out_total_eof().clear_bit_by_one()
570
                    }
571
                    _ => {
572
                        w.dma_infifo_full_err().clear_bit_by_one();
573
                        w.dma_outfifo_empty_err().clear_bit_by_one();
574
                        w.trans_done().clear_bit_by_one();
575
                        w.mst_rx_afifo_wfull_err().clear_bit_by_one();
576
                        w.mst_tx_afifo_rempty_err().clear_bit_by_one()
577
                    }
578
                }
579
            });
580
2
        }
581
    }
582

            
583
    /// A marker for DMA-capable SPI peripheral instances.
584
    #[doc(hidden)]
585
    #[allow(private_bounds)]
586
    pub trait InstanceDma: Instance {}
587

            
588
    #[cfg(soc_has_spi2)]
589
    impl InstanceDma for crate::peripherals::SPI2<'_> {}
590
    #[cfg(soc_has_spi3)]
591
    impl InstanceDma for crate::peripherals::SPI3<'_> {}
592

            
593
    impl InstanceDma for AnySpi<'_> {}
594

            
595
    with_spi_slave_dma_engine! {
596
        ($engine:tt, $any_channel:ident) => {
597
            /// DMA channel trait for SPI slave peripherals.
598
            #[diagnostic::on_unimplemented(
599
                message = "The DMA channel cannot be used with this SPI peripheral",
600
                label = "This DMA channel",
601
                note = "Use a channel that matches the SPI instance."
602
            )]
603
            pub trait SpiSlaveDmaChannel<'d, S>: crate::private::Sealed + Into<crate::dma::$any_channel<'d>> {}
604

            
605
            crate::macros::impl_dma_channel_trait! {
606
                $engine,
607
                any_peri = AnySpi<'d>,
608
                peris = for_each_spi_slave,
609
                ($peri:path, $ch:path) => {
610
                    impl<'d> SpiSlaveDmaChannel<'d, $peri> for $ch {}
611
                }
612
            }
613

            
614
            type SpiSlaveErased<'d> = crate::dma::$any_channel<'d>;
615
        };
616
    }
617
}
618

            
619
/// A peripheral singleton compatible with the SPI slave driver.
620
pub trait Instance: crate::private::Sealed + any::Degrade {
621
    /// Returns the peripheral data describing this SPI instance.
622
    #[doc(hidden)]
623
    fn info(&self) -> &'static Info;
624
}
625

            
626
/// Peripheral data describing a particular SPI instance.
627
#[non_exhaustive]
628
#[doc(hidden)]
629
pub struct Info {
630
    /// Pointer to the register block for this SPI instance.
631
    ///
632
    /// Used with [`Self::register_block`] to access the register block.
633
    pub register_block: *const RegisterBlock,
634

            
635
    /// System peripheral marker.
636
    pub peripheral: crate::system::Peripheral,
637

            
638
    /// SCLK signal.
639
    pub sclk: InputSignal,
640

            
641
    /// MOSI signal.
642
    pub mosi: InputSignal,
643

            
644
    /// MISO signal.
645
    pub miso: OutputSignal,
646

            
647
    /// Chip select signal.
648
    pub cs: InputSignal,
649
}
650

            
651
impl Info {
652
    /// Returns the register block for this SPI instance.
653
    #[instability::unstable]
654
    pub fn regs(&self) -> &RegisterBlock {
655
4
        unsafe { &*self.register_block }
656
    }
657

            
658
    fn reset_spi(&self) {
659
        #[cfg(esp32)]
660
        {
661
            self.regs().slave().modify(|_, w| w.sync_reset().set_bit());
662
            self.regs()
663
                .slave()
664
                .modify(|_, w| w.sync_reset().clear_bit());
665
        }
666

            
667
        #[cfg(not(esp32))]
668
        {
669
            self.regs().slave().modify(|_, w| w.soft_reset().set_bit());
670
            self.regs()
671
                .slave()
672
                .modify(|_, w| w.soft_reset().clear_bit());
673
        }
674
2
    }
675

            
676
    #[cfg(esp32)]
677
    fn prepare_length_and_lines(&self, rx_len: usize, tx_len: usize) {
678
        self.regs()
679
            .slv_rdbuf_dlen()
680
            .write(|w| unsafe { w.bits((rx_len as u32 * 8).saturating_sub(1)) });
681
        self.regs()
682
            .slv_wrbuf_dlen()
683
            .write(|w| unsafe { w.bits((tx_len as u32 * 8).saturating_sub(1)) });
684

            
685
        // SPI Slave mode on ESP32 requires MOSI/MISO enable
686
        self.regs().user().modify(|_, w| {
687
            w.usr_mosi().bit(rx_len > 0);
688
            w.usr_miso().bit(tx_len > 0)
689
        });
690
    }
691

            
692
    /// Initializes for full-duplex 1 bit mode.
693
    fn init(&self) {
694
        #[cfg(soc_has_pcr)]
695
        crate::peripherals::PCR::regs()
696
            .spi2_clkm_conf()
697
            .modify(|_, w| w.spi2_clkm_en().set_bit());
698

            
699
        self.regs().clock().write(|w| unsafe { w.bits(0) });
700
        self.regs().user().write(|w| unsafe { w.bits(0) });
701
        self.regs().ctrl().write(|w| unsafe { w.bits(0) });
702

            
703
        self.regs().slave().write(|w| {
704
            #[cfg(esp32)]
705
            w.slv_wr_rd_buf_en().set_bit();
706

            
707
            w.mode().set_bit()
708
        });
709
        self.reset_spi();
710

            
711
        self.regs().user().modify(|_, w| {
712
            w.doutdin().set_bit();
713
            w.sio().clear_bit()
714
        });
715

            
716
        #[cfg(not(esp32))]
717
        self.regs().misc().write(|w| unsafe { w.bits(0) });
718
2
    }
719

            
720
    fn set_data_mode(&self, data_mode: Mode, dma: bool) {
721
        #[cfg(esp32)]
722
        {
723
            self.regs().pin().modify(|_, w| {
724
                w.ck_idle_edge()
725
                    .bit(matches!(data_mode, Mode::_0 | Mode::_1))
726
            });
727
            self.regs()
728
                .user()
729
                .modify(|_, w| w.ck_i_edge().bit(matches!(data_mode, Mode::_1 | Mode::_2)));
730
            self.regs().ctrl2().modify(|_, w| unsafe {
731
                match data_mode {
732
                    Mode::_0 => {
733
                        w.miso_delay_mode().bits(0);
734
                        w.miso_delay_num().bits(0);
735
                        w.mosi_delay_mode().bits(2);
736
                        w.mosi_delay_num().bits(2)
737
                    }
738
                    Mode::_1 => {
739
                        w.miso_delay_mode().bits(2);
740
                        w.miso_delay_num().bits(0);
741
                        w.mosi_delay_mode().bits(0);
742
                        w.mosi_delay_num().bits(0)
743
                    }
744
                    Mode::_2 => {
745
                        w.miso_delay_mode().bits(0);
746
                        w.miso_delay_num().bits(0);
747
                        w.mosi_delay_mode().bits(1);
748
                        w.mosi_delay_num().bits(2)
749
                    }
750
                    Mode::_3 => {
751
                        w.miso_delay_mode().bits(1);
752
                        w.miso_delay_num().bits(0);
753
                        w.mosi_delay_mode().bits(0);
754
                        w.mosi_delay_num().bits(0)
755
                    }
756
                }
757
            });
758

            
759
            if dma {
760
                assert!(
761
                    matches!(data_mode, Mode::_1 | Mode::_3),
762
                    "Mode {:?} is not supported with DMA",
763
                    data_mode
764
                );
765
            }
766
        }
767

            
768
        #[cfg(not(esp32))]
769
        {
770
            _ = dma;
771
            self.regs().user().modify(|_, w| {
772
                w.tsck_i_edge()
773
4
                    .bit(matches!(data_mode, Mode::_1 | Mode::_2));
774
                w.rsck_i_edge()
775
                    .bit(matches!(data_mode, Mode::_1 | Mode::_2))
776
            });
777
            cfg_select! {
778
                esp32s2 => {
779
                    let ctrl1_reg = self.regs().ctrl1();
780
                }
781
                _ => {
782
                    let ctrl1_reg = self.regs().slave();
783
                }
784
            }
785
            ctrl1_reg.modify(|_, w| {
786
                w.clk_mode_13()
787
                    .bit(matches!(data_mode, Mode::_1 | Mode::_3))
788
            });
789
        }
790
4
    }
791

            
792
    #[cfg(spi_slave_supports_dma)]
793
    fn is_bus_busy(&self) -> bool {
794
        let reg = cfg_select! {
795
            any(esp32, esp32s2) => self.regs().slave(),
796
            _ => self.regs().dma_int_raw(),
797
        };
798
        reg.read().trans_done().bit_is_clear()
799
    }
800

            
801
    // Clear the transaction-done interrupt flag so flush() can work properly.
802
    #[cfg(spi_slave_supports_dma)]
803
    fn setup_for_flush(&self) {
804
        cfg_select! {
805
            any(esp32, esp32s2) => {
806
                self.regs()
807
                    .slave()
808
                    .modify(|_, w| w.trans_done().clear_bit());
809
            }
810
            _ => {
811
                self.regs()
812
                    .dma_int_clr()
813
                    .write(|w| w.trans_done().clear_bit_by_one());
814
            }
815
        }
816
2
    }
817
}
818

            
819
impl PartialEq for Info {
820
    fn eq(&self, other: &Self) -> bool {
821
        core::ptr::eq(self.register_block, other.register_block)
822
    }
823
}
824

            
825
unsafe impl Sync for Info {}
826

            
827
for_each_spi_slave! {
828
    ($peri:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident) => {
829
        impl Instance for crate::peripherals::$peri<'_> {
830
            #[inline(always)]
831
            fn info(&self) -> &'static Info {
832
                static INFO: Info = Info {
833
                    register_block: crate::peripherals::$peri::ptr(),
834
                    peripheral: crate::system::Peripheral::$sys,
835
                    sclk: InputSignal::$sclk,
836
                    mosi: InputSignal::$mosi,
837
                    miso: OutputSignal::$miso,
838
                    cs: InputSignal::$cs,
839
                };
840

            
841
                &INFO
842
            }
843
        }
844
    };
845
}
846

            
847
crate::any_peripheral! {
848
    /// Any SPI peripheral.
849
    pub peripheral AnySpi<'d> {
850
        #[cfg(spi_master_spi2)]
851
        Spi2(crate::peripherals::SPI2<'d>),
852
        #[cfg(spi_master_spi3)]
853
        Spi3(crate::peripherals::SPI3<'d>),
854
    }
855
}
856

            
857
#[cfg(spi_slave_supports_dma)]
858
with_spi_slave_dma_engine! {
859
    ($engine:tt, $any_ch:ident) => {
860
        use crate::dma::DmaEligiblePeripheral;
861

            
862
        impl<'d> DmaEligiblePeripheral<crate::dma::$any_ch<'d>> for AnySpi<'d> {
863
            fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
864
                any::delegate!(self, spi => { spi.dma_peripheral() })
865
            }
866
        }
867
    };
868
}
869

            
870
impl Instance for AnySpi<'_> {
871
    fn info(&self) -> &'static Info {
872
        any::delegate!(self, spi => { spi.info() })
873
    }
874
}