1
//! # Serial Peripheral Interface - Master Mode
2
//!
3
//! ## Overview
4
//!
5
//! In this mode, the SPI acts as master and initiates the SPI transactions.
6
//!
7
//! ## Configuration
8
//!
9
//! The peripheral can be used in full-duplex and half-duplex mode and can
10
//! leverage DMA for data transfers. It can also be used in blocking or async.
11
//!
12
//! ### Exclusive access to the SPI bus
13
//!
14
//! If all you want to do is to communicate to a single device, and you initiate
15
//! transactions yourself, there are a number of ways to achieve this:
16
//!
17
//! - Use the [`SpiBus`] or [`SpiBusAsync`] trait and its associated functions to initiate
18
//!   transactions with simultaneous reads and writes, or
19
//! - Use the `ExclusiveDevice` struct from [`embedded-hal-bus`] or `SpiDevice` from
20
//!   [`embassy-embedded-hal`].
21
//!
22
//! ### Shared SPI access
23
//!
24
//! If you have multiple devices on the same SPI bus that each have their own CS
25
//! line (and optionally, configuration), you may want to have a look at the
26
//! implementations provided by [`embedded-hal-bus`] and
27
//! [`embassy-embedded-hal`].
28
//!
29
//! ## Usage
30
//!
31
//! The module implements several third-party traits from embedded-hal@1.x.x
32
//! and [`embassy-embedded-hal`].
33
//!
34
//! [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/spi/index.html
35
//! [`embassy-embedded-hal`]: embassy_embedded_hal::shared_bus
36

            
37
use core::{marker::PhantomData, sync::atomic::Ordering};
38

            
39
#[cfg(spi_master_supports_dma)]
40
mod dma;
41
mod low_level;
42

            
43
#[instability::unstable]
44
#[cfg(spi_master_supports_dma)]
45
pub use dma::*;
46
use embedded_hal::spi::SpiBus;
47
use embedded_hal_async::spi::SpiBus as SpiBusAsync;
48
use enumset::EnumSetType;
49
use low_level::{Driver, SpiWrapper};
50
pub use low_level::{Info, Instance, QspiInstance, State};
51
use procmacros::doc_replace;
52

            
53
use super::{BitOrder, Error, Mode};
54
use crate::{
55
    Async,
56
    Blocking,
57
    DriverMode,
58
    gpio::{
59
        InputConfig,
60
        NoPin,
61
        OutputConfig,
62
        OutputSignal,
63
        PinGuard,
64
        interconnect::{self, PeripheralInput, PeripheralOutput},
65
    },
66
    interrupt::InterruptHandler,
67
    private::Sealed,
68
    spi::master::low_level::SpiClockGuard,
69
    time::Rate,
70
};
71

            
72
/// Enumeration of possible SPI interrupt events.
73
#[derive(Debug, Hash, EnumSetType)]
74
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75
#[non_exhaustive]
76
#[instability::unstable]
77
pub enum SpiInterrupt {
78
    /// Indicates that the SPI transaction has completed successfully.
79
    ///
80
    /// This interrupt is triggered when an SPI transaction has finished
81
    /// transmitting and receiving data.
82
    TransferDone,
83

            
84
    /// Triggered at the end of configurable segmented transfer.
85
    #[cfg(spi_master_has_dma_segmented_transfer)]
86
    DmaSegmentedTransferDone,
87

            
88
    /// Used and triggered by software. Only used for user defined function.
89
    #[cfg(spi_master_has_app_interrupts)]
90
    App2,
91

            
92
    /// Used and triggered by software. Only used for user defined function.
93
    #[cfg(spi_master_has_app_interrupts)]
94
    App1,
95
}
96

            
97
/// The size of the FIFO buffer for SPI.
98
const FIFO_SIZE: usize = property!("spi_master.fifo_size");
99

            
100
/// Padding byte for empty write transfers
101
const EMPTY_WRITE_PAD: u8 = 0x00;
102

            
103
/// SPI commands, each consisting of a 16-bit command value and a data mode.
104
///
105
/// Used to define specific commands sent over the SPI bus.
106
/// Can be [Command::None] if command phase should be suppressed.
107
#[non_exhaustive]
108
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
109
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
110
#[instability::unstable]
111
pub enum Command {
112
    /// No command is sent.
113
    None,
114
    /// A 1-bit command.
115
    _1Bit(u16, DataMode),
116
    /// A 2-bit command.
117
    _2Bit(u16, DataMode),
118
    /// A 3-bit command.
119
    _3Bit(u16, DataMode),
120
    /// A 4-bit command.
121
    _4Bit(u16, DataMode),
122
    /// A 5-bit command.
123
    _5Bit(u16, DataMode),
124
    /// A 6-bit command.
125
    _6Bit(u16, DataMode),
126
    /// A 7-bit command.
127
    _7Bit(u16, DataMode),
128
    /// A 8-bit command.
129
    _8Bit(u16, DataMode),
130
    /// A 9-bit command.
131
    _9Bit(u16, DataMode),
132
    /// A 10-bit command.
133
    _10Bit(u16, DataMode),
134
    /// A 11-bit command.
135
    _11Bit(u16, DataMode),
136
    /// A 12-bit command.
137
    _12Bit(u16, DataMode),
138
    /// A 13-bit command.
139
    _13Bit(u16, DataMode),
140
    /// A 14-bit command.
141
    _14Bit(u16, DataMode),
142
    /// A 15-bit command.
143
    _15Bit(u16, DataMode),
144
    /// A 16-bit command.
145
    _16Bit(u16, DataMode),
146
}
147

            
148
impl Command {
149
    fn width(&self) -> usize {
150
        match self {
151
            Command::None => 0,
152
            Command::_1Bit(_, _) => 1,
153
            Command::_2Bit(_, _) => 2,
154
            Command::_3Bit(_, _) => 3,
155
            Command::_4Bit(_, _) => 4,
156
            Command::_5Bit(_, _) => 5,
157
            Command::_6Bit(_, _) => 6,
158
            Command::_7Bit(_, _) => 7,
159
            Command::_8Bit(_, _) => 8,
160
            Command::_9Bit(_, _) => 9,
161
            Command::_10Bit(_, _) => 10,
162
            Command::_11Bit(_, _) => 11,
163
            Command::_12Bit(_, _) => 12,
164
            Command::_13Bit(_, _) => 13,
165
            Command::_14Bit(_, _) => 14,
166
            Command::_15Bit(_, _) => 15,
167
            Command::_16Bit(_, _) => 16,
168
        }
169
    }
170

            
171
    fn value(&self) -> u16 {
172
        match self {
173
            Command::None => 0,
174
            Command::_1Bit(value, _)
175
            | Command::_2Bit(value, _)
176
            | Command::_3Bit(value, _)
177
            | Command::_4Bit(value, _)
178
            | Command::_5Bit(value, _)
179
            | Command::_6Bit(value, _)
180
            | Command::_7Bit(value, _)
181
            | Command::_8Bit(value, _)
182
            | Command::_9Bit(value, _)
183
            | Command::_10Bit(value, _)
184
            | Command::_11Bit(value, _)
185
            | Command::_12Bit(value, _)
186
            | Command::_13Bit(value, _)
187
            | Command::_14Bit(value, _)
188
            | Command::_15Bit(value, _)
189
            | Command::_16Bit(value, _) => *value,
190
        }
191
    }
192

            
193
    fn mode(&self) -> DataMode {
194
76
        match self {
195
            Command::None => DataMode::SingleTwoDataLines,
196
            Command::_1Bit(_, mode)
197
            | Command::_2Bit(_, mode)
198
            | Command::_3Bit(_, mode)
199
            | Command::_4Bit(_, mode)
200
            | Command::_5Bit(_, mode)
201
            | Command::_6Bit(_, mode)
202
            | Command::_7Bit(_, mode)
203
            | Command::_8Bit(_, mode)
204
            | Command::_9Bit(_, mode)
205
            | Command::_10Bit(_, mode)
206
            | Command::_11Bit(_, mode)
207
            | Command::_12Bit(_, mode)
208
            | Command::_13Bit(_, mode)
209
            | Command::_14Bit(_, mode)
210
            | Command::_15Bit(_, mode)
211
            | Command::_16Bit(_, mode) => *mode,
212
        }
213
    }
214

            
215
    fn is_none(&self) -> bool {
216
        matches!(self, Command::None)
217
    }
218
}
219

            
220
/// SPI address, ranging from 1 to 32 bits, paired with a data mode.
221
///
222
/// This can be used to specify the address phase of SPI transactions.
223
/// Can be [Address::None] if address phase should be suppressed.
224
#[non_exhaustive]
225
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
226
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
227
#[instability::unstable]
228
pub enum Address {
229
    /// No address phase.
230
    None,
231
    /// A 1-bit address.
232
    _1Bit(u32, DataMode),
233
    /// A 2-bit address.
234
    _2Bit(u32, DataMode),
235
    /// A 3-bit address.
236
    _3Bit(u32, DataMode),
237
    /// A 4-bit address.
238
    _4Bit(u32, DataMode),
239
    /// A 5-bit address.
240
    _5Bit(u32, DataMode),
241
    /// A 6-bit address.
242
    _6Bit(u32, DataMode),
243
    /// A 7-bit address.
244
    _7Bit(u32, DataMode),
245
    /// A 8-bit address.
246
    _8Bit(u32, DataMode),
247
    /// A 9-bit address.
248
    _9Bit(u32, DataMode),
249
    /// A 10-bit address.
250
    _10Bit(u32, DataMode),
251
    /// A 11-bit address.
252
    _11Bit(u32, DataMode),
253
    /// A 12-bit address.
254
    _12Bit(u32, DataMode),
255
    /// A 13-bit address.
256
    _13Bit(u32, DataMode),
257
    /// A 14-bit address.
258
    _14Bit(u32, DataMode),
259
    /// A 15-bit address.
260
    _15Bit(u32, DataMode),
261
    /// A 16-bit address.
262
    _16Bit(u32, DataMode),
263
    /// A 17-bit address.
264
    _17Bit(u32, DataMode),
265
    /// A 18-bit address.
266
    _18Bit(u32, DataMode),
267
    /// A 19-bit address.
268
    _19Bit(u32, DataMode),
269
    /// A 20-bit address.
270
    _20Bit(u32, DataMode),
271
    /// A 21-bit address.
272
    _21Bit(u32, DataMode),
273
    /// A 22-bit address.
274
    _22Bit(u32, DataMode),
275
    /// A 23-bit address.
276
    _23Bit(u32, DataMode),
277
    /// A 24-bit address.
278
    _24Bit(u32, DataMode),
279
    /// A 25-bit address.
280
    _25Bit(u32, DataMode),
281
    /// A 26-bit address.
282
    _26Bit(u32, DataMode),
283
    /// A 27-bit address.
284
    _27Bit(u32, DataMode),
285
    /// A 28-bit address.
286
    _28Bit(u32, DataMode),
287
    /// A 29-bit address.
288
    _29Bit(u32, DataMode),
289
    /// A 30-bit address.
290
    _30Bit(u32, DataMode),
291
    /// A 31-bit address.
292
    _31Bit(u32, DataMode),
293
    /// A 32-bit address.
294
    _32Bit(u32, DataMode),
295
}
296

            
297
impl Address {
298
    fn width(&self) -> usize {
299
        match self {
300
            Address::None => 0,
301
            Address::_1Bit(_, _) => 1,
302
            Address::_2Bit(_, _) => 2,
303
            Address::_3Bit(_, _) => 3,
304
            Address::_4Bit(_, _) => 4,
305
            Address::_5Bit(_, _) => 5,
306
            Address::_6Bit(_, _) => 6,
307
            Address::_7Bit(_, _) => 7,
308
            Address::_8Bit(_, _) => 8,
309
            Address::_9Bit(_, _) => 9,
310
            Address::_10Bit(_, _) => 10,
311
            Address::_11Bit(_, _) => 11,
312
            Address::_12Bit(_, _) => 12,
313
            Address::_13Bit(_, _) => 13,
314
            Address::_14Bit(_, _) => 14,
315
            Address::_15Bit(_, _) => 15,
316
            Address::_16Bit(_, _) => 16,
317
            Address::_17Bit(_, _) => 17,
318
            Address::_18Bit(_, _) => 18,
319
            Address::_19Bit(_, _) => 19,
320
            Address::_20Bit(_, _) => 20,
321
            Address::_21Bit(_, _) => 21,
322
            Address::_22Bit(_, _) => 22,
323
            Address::_23Bit(_, _) => 23,
324
            Address::_24Bit(_, _) => 24,
325
            Address::_25Bit(_, _) => 25,
326
            Address::_26Bit(_, _) => 26,
327
            Address::_27Bit(_, _) => 27,
328
            Address::_28Bit(_, _) => 28,
329
            Address::_29Bit(_, _) => 29,
330
            Address::_30Bit(_, _) => 30,
331
            Address::_31Bit(_, _) => 31,
332
            Address::_32Bit(_, _) => 32,
333
        }
334
    }
335

            
336
    fn value(&self) -> u32 {
337
        match self {
338
            Address::None => 0,
339
            Address::_1Bit(value, _)
340
            | Address::_2Bit(value, _)
341
            | Address::_3Bit(value, _)
342
            | Address::_4Bit(value, _)
343
            | Address::_5Bit(value, _)
344
            | Address::_6Bit(value, _)
345
            | Address::_7Bit(value, _)
346
            | Address::_8Bit(value, _)
347
            | Address::_9Bit(value, _)
348
            | Address::_10Bit(value, _)
349
            | Address::_11Bit(value, _)
350
            | Address::_12Bit(value, _)
351
            | Address::_13Bit(value, _)
352
            | Address::_14Bit(value, _)
353
            | Address::_15Bit(value, _)
354
            | Address::_16Bit(value, _)
355
            | Address::_17Bit(value, _)
356
            | Address::_18Bit(value, _)
357
            | Address::_19Bit(value, _)
358
            | Address::_20Bit(value, _)
359
            | Address::_21Bit(value, _)
360
            | Address::_22Bit(value, _)
361
            | Address::_23Bit(value, _)
362
            | Address::_24Bit(value, _)
363
            | Address::_25Bit(value, _)
364
            | Address::_26Bit(value, _)
365
            | Address::_27Bit(value, _)
366
            | Address::_28Bit(value, _)
367
            | Address::_29Bit(value, _)
368
            | Address::_30Bit(value, _)
369
            | Address::_31Bit(value, _)
370
            | Address::_32Bit(value, _) => *value,
371
        }
372
    }
373

            
374
    fn is_none(&self) -> bool {
375
        matches!(self, Address::None)
376
    }
377

            
378
    fn mode(&self) -> DataMode {
379
76
        match self {
380
            Address::None => DataMode::SingleTwoDataLines,
381
            Address::_1Bit(_, mode)
382
            | Address::_2Bit(_, mode)
383
            | Address::_3Bit(_, mode)
384
            | Address::_4Bit(_, mode)
385
            | Address::_5Bit(_, mode)
386
            | Address::_6Bit(_, mode)
387
            | Address::_7Bit(_, mode)
388
            | Address::_8Bit(_, mode)
389
            | Address::_9Bit(_, mode)
390
            | Address::_10Bit(_, mode)
391
            | Address::_11Bit(_, mode)
392
            | Address::_12Bit(_, mode)
393
            | Address::_13Bit(_, mode)
394
            | Address::_14Bit(_, mode)
395
            | Address::_15Bit(_, mode)
396
            | Address::_16Bit(_, mode)
397
            | Address::_17Bit(_, mode)
398
            | Address::_18Bit(_, mode)
399
            | Address::_19Bit(_, mode)
400
            | Address::_20Bit(_, mode)
401
            | Address::_21Bit(_, mode)
402
            | Address::_22Bit(_, mode)
403
            | Address::_23Bit(_, mode)
404
            | Address::_24Bit(_, mode)
405
            | Address::_25Bit(_, mode)
406
            | Address::_26Bit(_, mode)
407
            | Address::_27Bit(_, mode)
408
            | Address::_28Bit(_, mode)
409
            | Address::_29Bit(_, mode)
410
            | Address::_30Bit(_, mode)
411
            | Address::_31Bit(_, mode)
412
            | Address::_32Bit(_, mode) => *mode,
413
        }
414
    }
415
}
416

            
417
/// SPI clock source.
418
#[instability::unstable]
419
pub use crate::soc::clocks::SpiFunctionClockConfig as ClockSource;
420

            
421
/// SPI peripheral configuration
422
24
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, procmacros::BuilderLite)]
423
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
424
#[non_exhaustive]
425
pub struct Config {
426
    /// The precomputed clock configuration register value.
427
    ///
428
    /// Clock divider calculations are relatively expensive, and the SPI
429
    /// peripheral is commonly expected to be used in a shared bus
430
    /// configuration, where different devices may need different bus clock
431
    /// frequencies. To reduce the time required to reconfigure the bus, the
432
    /// clock register value is cached here for each configuration.
433
    ///
434
    /// This field is not intended to be set from application code, and is only used
435
    /// internally.
436
    #[builder_lite(skip)]
437
    reg: Result<u32, ConfigError>,
438

            
439
    /// The target frequency.
440
    #[builder_lite(skip_setter)]
441
    frequency: Rate,
442

            
443
    /// The clock source.
444
    #[builder_lite(unstable)]
445
    #[builder_lite(skip_setter)]
446
    clock_source: ClockSource,
447

            
448
    /// SPI sample/shift mode.
449
    mode: Mode,
450

            
451
    /// Bit order of the read data.
452
    read_bit_order: BitOrder,
453

            
454
    /// Bit order of the written data.
455
    write_bit_order: BitOrder,
456

            
457
    /// Minimum transfer size in bytes below which CPU-driven (blocking) I/O
458
    /// is used instead of async or DMA transfers.
459
    ///
460
    /// This can reduce overhead for small transfers where DMA setup or
461
    /// async context-switch cost exceeds the benefit. For
462
    /// [`SpiDma`][crate::spi::master::dma::SpiDma], the threshold applies in
463
    /// both blocking and async DMA modes: when met, DMA is disabled and the
464
    /// transfer is performed by the CPU. This applies to both full-duplex and
465
    /// half-duplex transfers.
466
    ///
467
    /// A value of `0` (the default) disables the threshold — all transfers use
468
    /// the driver's default method.
469
    #[builder_lite(unstable)]
470
    min_async_transfer_size: usize,
471
}
472

            
473
impl Default for Config {
474
90
    fn default() -> Self {
475
        let mut this = Config {
476
            reg: Ok(0),
477
            frequency: Rate::from_mhz(1),
478
            clock_source: ClockSource::default(),
479
            mode: Mode::_0,
480
            read_bit_order: BitOrder::MsbFirst,
481
            write_bit_order: BitOrder::MsbFirst,
482
            min_async_transfer_size: 0,
483
        };
484

            
485
90
        this.reg = this.recalculate();
486

            
487
90
        this
488
90
    }
489
}
490

            
491
impl Config {
492
    /// Sets the frequency of the SPI bus clock.
493
    ///
494
    /// The closest available frequency that does not exceed `frequency` is used,
495
    /// so the bus never runs faster than requested.
496
88
    pub fn with_frequency(mut self, frequency: Rate) -> Self {
497
88
        self.frequency = frequency;
498
88
        self.reg = self.recalculate();
499

            
500
88
        self
501
88
    }
502

            
503
    /// Sets the clock source of the SPI bus.
504
    #[instability::unstable]
505
52
    pub fn with_clock_source(mut self, clock_source: ClockSource) -> Self {
506
52
        self.clock_source = clock_source;
507
52
        self.reg = self.recalculate();
508

            
509
52
        self
510
52
    }
511

            
512
    fn clock_source_freq_hz(&self) -> Rate {
513
        Rate::from_hz(
514
230
            crate::soc::clocks::SpiInstance::function_clock_source_frequency(self.clock_source),
515
        )
516
    }
517

            
518
230
    fn recalculate(&self) -> Result<u32, ConfigError> {
519
        // TODO: model peripheral-side clock divider, allow the user to directly configure it
520
        // taken from https://github.com/apache/incubator-nuttx/blob/8267a7618629838231256edfa666e44b5313348e/arch/risc-v/src/esp32c3/esp32c3_spi.c#L496
521
        let source_freq = self.clock_source_freq_hz();
522

            
523
        // In HW, n, h and l fields range from 1 to 64, pre ranges from 1 to 8K.
524
        // The value written to register is one lower than the used value.
525

            
526
183
        if self.frequency >= source_freq {
527
            // Bypass the divider, which is exactly the source frequency.
528
            // Set the SPI_CLK_EQU_SYSCLK bit.
529
            return Ok(1 << 31);
530
        }
531

            
532
        let (n, pre) = Self::divider_pair(source_freq.as_hz(), self.frequency.as_hz());
533

            
534
        // In master mode, L == N
535
        let l = n;
536

            
537
        // In master mode, this field must be floor((SPI_CLKCNT_N + 1)/2 - 1)
538
225
        let h = (n / 2).max(1);
539

            
540
225
        Ok((l - 1) // SPI_CLKCNT_L
541
225
            | ((h - 1) << 6) // SPI_CLKCNT_H
542
225
            | ((n - 1) << 12) // SPI_CLKCNT_N
543
225
            | ((pre - 1) << 18)) // SPI_CLKDIV_PRE
544
225
    }
545

            
546
    /// Finds the `(n, pre)` pair producing the highest bus frequency that does
547
    /// not exceed `target_freq_hz`, where `n` is `SPI_CLKCNT_N + 1` and `pre` is
548
    /// `SPI_CLKDIV_PRE + 1`.
549
    ///
550
    /// The peripheral divides the source clock by `pre * n`, so this is the
551
    /// smallest divider that does not overshoot. `n` also determines the duty
552
    /// cycle resolution, so among pairs forming that divider the one with the
553
    /// largest `n` is preferred.
554
    ///
555
    /// Out-of-range frequencies (see [`Config::validate`]) yield the slowest pair
556
    /// available rather than an error.
557
    fn divider_pair(source_freq_hz: u32, target_freq_hz: u32) -> (u32, u32) {
558
        // A zero target is rejected by `validate`, but must not divide by zero
559
        // here.
560
225
        if target_freq_hz == 0 {
561
            return (64, 16);
562
        }
563

            
564
        // Any smaller divider would run the bus faster than requested. `n` starts
565
        // at 2 so that h/l can describe at least one high and one low pulse.
566
        let min_divider = source_freq_hz.div_ceil(target_freq_hz).max(2);
567

            
568
        // A `pre` of 1 offers every divider up to 64, so if the smallest usable
569
        // divider is in that range we can form it directly, with the largest `n`
570
        // that produces it.
571
225
        if min_divider <= 64 {
572
            return (min_divider, 1);
573
        }
574

            
575
        // `n` maxes out at 64, so a smaller `pre` cannot bring the source clock
576
        // down to the target. As `n` shrinks when `pre` grows, walking `pre`
577
        // upwards visits the candidates in order of decreasing duty cycle
578
        // resolution, which lets us keep the first of several that share a
579
        // divider.
580
        //
581
        // The seed is the slowest pair, which also answers requests below the
582
        // supported range.
583
        let mut best = (64, 16);
584
        let mut best_divider = 64 * 16;
585

            
586
        // A `for` loop over a range would leave a divide-by-zero check on `pre`
587
        // in the generated code, as the lower bound is not visible through the
588
        // range iterator on all targets.
589
        let mut pre = min_divider.div_ceil(64);
590
186
        while pre <= 16 {
591
            // The smallest `n` that keeps `pre * n` from overshooting. The lower
592
            // bound on `pre` keeps this at or below 64.
593
            let n = min_divider.div_ceil(pre);
594
347
            let divider = pre * n;
595

            
596
347
            if divider < best_divider {
597
                best = (n, pre);
598
                best_divider = divider;
599

            
600
                // Nothing can beat hitting the smallest usable divider exactly.
601
261
                if divider == min_divider {
602
                    break;
603
                }
604
            }
605

            
606
170
            pre += 1;
607
        }
608

            
609
        best
610
    }
611

            
612
    fn raw_clock_reg_value(&self) -> Result<u32, ConfigError> {
613
90
        self.reg
614
    }
615

            
616
    fn validate(&self) -> Result<(), ConfigError> {
617
        let source_freq = self.clock_source_freq_hz();
618
        let min_divider = 1;
619
        // FIXME: while ESP32 and S2 support pre dividers as large as 8192,
620
        // those values are not currently supported by the divider calculation.
621
        let max_divider = 16 * 64; // n * pre
622

            
623
90
        if self.frequency < source_freq / max_divider || self.frequency > source_freq / min_divider
624
        {
625
            return Err(ConfigError::FrequencyOutOfRange);
626
        }
627

            
628
        Ok(())
629
    }
630
}
631

            
632
const SIO_PIN_COUNT: usize = 4 + cfg!(spi_master_has_octal) as usize * 4;
633

            
634
#[derive(Debug)]
635
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
636
struct SpiPinGuard {
637
    sclk_pin: PinGuard,
638
    cs_pin: PinGuard,
639
    sio_pins: [PinGuard; SIO_PIN_COUNT],
640
}
641

            
642
impl SpiPinGuard {
643
    const fn new_unconnected() -> Self {
644
        Self {
645
            sclk_pin: PinGuard::new_unconnected(),
646
            cs_pin: PinGuard::new_unconnected(),
647
            sio_pins: [const { PinGuard::new_unconnected() }; SIO_PIN_COUNT],
648
        }
649
    }
650
}
651

            
652
/// Configuration errors.
653
#[non_exhaustive]
654
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
655
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
656
pub enum ConfigError {
657
    /// The requested frequency is not in the supported range.
658
    FrequencyOutOfRange,
659
}
660

            
661
impl core::error::Error for ConfigError {}
662

            
663
impl core::fmt::Display for ConfigError {
664
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
665
        match self {
666
            ConfigError::FrequencyOutOfRange => {
667
                write!(f, "The requested frequency is not in the supported range")
668
            }
669
        }
670
    }
671
}
672

            
673
#[procmacros::doc_replace]
674
/// SPI peripheral driver
675
///
676
/// # Examples
677
///
678
/// ```rust, no_run
679
/// # {before_snippet}
680
/// use esp_hal::spi::{
681
///     Mode,
682
///     master::{Config, Spi},
683
/// };
684
/// let mut spi = Spi::new(
685
///     peripherals.SPI2,
686
///     Config::default()
687
///         .with_frequency(Rate::from_khz(100))
688
///         .with_mode(Mode::_0),
689
/// )?
690
/// .with_sck(peripherals.GPIO0)
691
/// .with_mosi(peripherals.GPIO1)
692
/// .with_miso(peripherals.GPIO2);
693
/// # {after_snippet}
694
/// ```
695
#[derive(Debug)]
696
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
697
pub struct Spi<'d, Dm: DriverMode> {
698
    spi: SpiWrapper<'d>,
699
    _mode: PhantomData<Dm>,
700
}
701

            
702
impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
703

            
704
impl<'d> Spi<'d, Blocking> {
705
    #[procmacros::doc_replace]
706
    /// Creates a new SPI instance in 8-bit data-frame mode.
707
    ///
708
    /// # Examples
709
    ///
710
    /// ```rust, no_run
711
    /// # {before_snippet}
712
    /// use esp_hal::spi::{
713
    ///     Mode,
714
    ///     master::{Config, Spi},
715
    /// };
716
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
717
    ///     .with_sck(peripherals.GPIO0)
718
    ///     .with_mosi(peripherals.GPIO1)
719
    ///     .with_miso(peripherals.GPIO2);
720
    /// # {after_snippet}
721
    /// ```
722
    ///
723
    /// # Errors
724
    ///
725
    /// See [`Spi::apply_config`]
726
70
    pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
727
70
        let mut this = Spi {
728
            _mode: PhantomData,
729
            spi: SpiWrapper::new(spi),
730
        };
731

            
732
70
        this.driver().init();
733
        this.apply_config(&config)?;
734

            
735
        let this = this.with_sck(NoPin).with_cs(NoPin);
736

            
737
        for sio in 0..8 {
738
            if let Some(signal) = this.driver().info.opt_sio_input(sio) {
739
                signal.connect_to(&NoPin);
740
            }
741
            if let Some(signal) = this.driver().info.opt_sio_output(sio) {
742
                signal.connect_to(&NoPin);
743
            }
744
        }
745

            
746
        Ok(this)
747
70
    }
748

            
749
    /// Reconfigures the driver to operate in [`Async`] mode.
750
    ///
751
    /// See the [`Async`] documentation for an example on how to use this
752
    /// method.
753
16
    pub fn into_async(mut self) -> Spi<'d, Async> {
754
        self.set_interrupt_handler(self.spi.info().async_handler);
755
        Spi {
756
            spi: self.spi,
757
            _mode: PhantomData,
758
        }
759
16
    }
760

            
761
    #[doc_replace(
762
        "peripheral_on" => {
763
            cfg(multi_core) => "peripheral on the current core",
764
            _ => "peripheral",
765
        }
766
    )]
767
    /// Registers an interrupt handler for the __peripheral_on__.
768
    ///
769
    /// Replaces any previously registered interrupt handlers.
770
    ///
771
    /// The default/unhandled interrupt handler can be restored with
772
    /// [crate::interrupt::DEFAULT_INTERRUPT_HANDLER]
773
    ///
774
    /// # Panics
775
    ///
776
    /// Panics if passed interrupt handler is invalid (e.g. has priority
777
    /// `None`)
778
    #[instability::unstable]
779
    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
780
        self.spi.set_interrupt_handler(handler);
781
    }
782
}
783

            
784
#[instability::unstable]
785
impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
786
    /// Sets the interrupt handler.
787
    ///
788
    /// Interrupts are not enabled at the peripheral level here.
789
    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
790
        self.set_interrupt_handler(handler);
791
    }
792
}
793

            
794
impl<'d> Spi<'d, Async> {
795
    /// Reconfigures the driver to operate in [`Blocking`] mode.
796
    ///
797
    /// See the [`Blocking`] documentation for an example on how to use this
798
    /// method.
799
    pub fn into_blocking(self) -> Spi<'d, Blocking> {
800
        self.spi.disable_peri_interrupt_on_all_cores();
801
        Spi {
802
            spi: self.spi,
803
            _mode: PhantomData,
804
        }
805
    }
806

            
807
    #[procmacros::doc_replace]
808
    /// Waits for the completion of previous operations.
809
    ///
810
    /// # Examples
811
    ///
812
    /// ```rust, no_run
813
    /// # {before_snippet}
814
    /// use esp_hal::spi::{
815
    ///     Mode,
816
    ///     master::{Config, Spi},
817
    /// };
818
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
819
    ///     .with_sck(peripherals.GPIO0)
820
    ///     .with_mosi(peripherals.GPIO1)
821
    ///     .with_miso(peripherals.GPIO2)
822
    ///     .into_async();
823
    ///
824
    /// let mut buffer = [0; 10];
825
    /// spi.transfer_in_place_async(&mut buffer).await?;
826
    /// spi.flush_async().await?;
827
    ///
828
    /// # {after_snippet}
829
    /// ```
830
    pub async fn flush_async(&mut self) -> Result<(), Error> {
831
        Ok(())
832
    }
833

            
834
    #[procmacros::doc_replace]
835
    /// Sends `words` to the slave. Returns the `words` received from the slave.
836
    ///
837
    /// Aborts the transfer when its Future is dropped. Some amount of data may have
838
    /// been transferred before the Future is dropped. Dropping the future may block
839
    /// for a short while to ensure the transfer is aborted.
840
    ///
841
    /// # Examples
842
    ///
843
    /// ```rust, no_run
844
    /// # {before_snippet}
845
    /// use esp_hal::spi::{
846
    ///     Mode,
847
    ///     master::{Config, Spi},
848
    /// };
849
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
850
    ///     .with_sck(peripherals.GPIO0)
851
    ///     .with_mosi(peripherals.GPIO1)
852
    ///     .with_miso(peripherals.GPIO2)
853
    ///     .into_async();
854
    ///
855
    /// let mut buffer = [0; 10];
856
    /// spi.transfer_in_place_async(&mut buffer).await?;
857
    ///
858
    /// # {after_snippet}
859
    /// ```
860
332
    pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
861
4
        let _clock = SpiClockGuard::new(self.spi.info());
862

            
863
4
        self.driver().setup_full_duplex()?;
864

            
865
4
        if self.use_blocking_transfer(words.len()) {
866
            return self.driver().transfer_in_place(words);
867
        }
868

            
869
4
        self.driver().transfer_in_place_async(words).await
870
2
    }
871

            
872
    /// Half-duplex read.
873
    ///
874
    /// Transfers larger than the hardware FIFO are split into chunks. CS remains asserted across
875
    /// chunks, but the clock pauses while the CPU prepares each subsequent chunk.
876
    ///
877
    /// Aborts the transfer when its Future is dropped. Some amount of data may have
878
    /// been transferred before the Future is dropped. Dropping the future may block
879
    /// for a short while to ensure the transfer is aborted.
880
    ///
881
    /// # Errors
882
    ///
883
    /// [`Error::Unsupported`] when the buffer is empty (currently unsupported).
884
    /// `DataMode::Single` cannot be combined with any other [`DataMode`], otherwise
885
    /// [`Error::Unsupported`].
886
    #[instability::unstable]
887
    pub async fn half_duplex_read_async(
888
        &mut self,
889
6
        data_mode: DataMode,
890
6
        cmd: Command,
891
6
        address: Address,
892
6
        dummy: u8,
893
6
        buffer: &mut [u8],
894
24
    ) -> Result<(), Error> {
895
6
        let _clock = SpiClockGuard::new(self.spi.info());
896

            
897
6
        if self.use_blocking_transfer(buffer.len()) {
898
            return self
899
                .driver()
900
                .half_duplex_read(data_mode, cmd, address, dummy, buffer);
901
        }
902

            
903
6
        self.driver()
904
            .half_duplex_read_async(data_mode, cmd, address, dummy, buffer)
905
18
            .await
906
    }
907

            
908
    /// Half-duplex write.
909
    ///
910
    /// Transfers larger than the hardware FIFO are split into chunks. CS remains asserted across
911
    /// chunks, but the clock pauses while the CPU prepares each subsequent chunk.
912
    ///
913
    /// Aborts the transfer when its Future is dropped. Some amount of data may have
914
    /// been transferred before the Future is dropped. Dropping the future may block
915
    /// for a short while to ensure the transfer is aborted.
916
    ///
917
    /// # Errors
918
    ///
919
    /// [`Error::Unsupported`] for unsupported combinations of command, address,
920
    /// dummy, and data modes.
921
    #[cfg_attr(
922
        esp32,
923
        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))."
924
    )]
925
    #[instability::unstable]
926
    pub async fn half_duplex_write_async(
927
        &mut self,
928
        data_mode: DataMode,
929
        cmd: Command,
930
        address: Address,
931
        dummy: u8,
932
        buffer: &[u8],
933
    ) -> Result<(), Error> {
934
        let _clock = SpiClockGuard::new(self.spi.info());
935

            
936
        if self.use_blocking_transfer(buffer.len()) {
937
            return self
938
                .driver()
939
                .half_duplex_write(data_mode, cmd, address, dummy, buffer);
940
        }
941

            
942
        self.driver()
943
            .half_duplex_write_async(data_mode, cmd, address, dummy, buffer)
944
            .await
945
    }
946

            
947
    // TODO: These inherent methods should be public
948

            
949
    async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
950
        let _clock = SpiClockGuard::new(self.spi.info());
951

            
952
        self.driver().setup_full_duplex()?;
953

            
954
        if self.use_blocking_transfer(words.len()) {
955
            return self.driver().read(words);
956
        }
957

            
958
        self.driver().read_async(words).await
959
    }
960

            
961
    async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
962
        let _clock = SpiClockGuard::new(self.spi.info());
963

            
964
        self.driver().setup_full_duplex()?;
965

            
966
        if self.use_blocking_transfer(words.len()) {
967
            return self.driver().write(words);
968
        }
969

            
970
        self.driver().write_async(words).await
971
    }
972
}
973

            
974
macro_rules! def_with_sio_pin {
975
    ($fn:ident, $n:literal) => {
976
        #[doc = concat!(" Assign the SIO", stringify!($n), " pin for the SPI instance.")]
977
        #[doc = " "]
978
        #[doc = " Enables both input and output functionality for the pin, and connects it"]
979
        #[doc = concat!(" to the SIO", stringify!($n), " output and input signals.")]
980
        #[instability::unstable]
981
        pub fn $fn(mut self, sio: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
982
2
            self.spi.pins().sio_pins[$n] = self.connect_sio_pin(sio.into(), $n);
983

            
984
            self
985
        }
986
    };
987
}
988

            
989
impl<'d, Dm> Spi<'d, Dm>
990
where
991
    Dm: DriverMode,
992
{
993
24
    fn connect_sio_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
994
24
        let in_signal = self.spi.info().sio_input(n);
995
24
        let out_signal = self.spi.info().sio_output(n);
996

            
997
        pin.apply_input_config(&InputConfig::default());
998
        pin.apply_output_config(&OutputConfig::default());
999

            
        pin.set_input_enable(true);
        pin.set_output_enable(false);
        in_signal.connect_to(&pin);
24
        pin.connect_with_guard(out_signal)
24
    }
    fn connect_sio_output_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
34
        let out_signal = self.spi.info().sio_output(n);
34
        self.connect_output_pin(pin, out_signal)
    }
80
    fn connect_output_pin(
        &self,
        pin: interconnect::OutputSignal<'d>,
        signal: OutputSignal,
    ) -> PinGuard {
        pin.apply_output_config(&OutputConfig::default());
        pin.set_output_enable(true); // TODO turn this bool into a Yes/No/PeripheralControl trio
80
        pin.connect_with_guard(signal)
    }
    #[procmacros::doc_replace]
    /// Assigns the SCK (Serial Clock) pin for the SPI instance.
    ///
    /// Configures the specified pin to push-pull output and connects it to the
    /// SPI clock signal.
    ///
    /// Disconnects the previous pin that was assigned with `with_sck`.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_sck(peripherals.GPIO0);
    ///
    /// # {after_snippet}
    /// ```
    pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
        let info = self.spi.info();
70
        self.spi.pins().sclk_pin = self.connect_output_pin(sclk.into(), info.sclk);
        self
    }
    #[procmacros::doc_replace]
    /// Assigns the MOSI (Master Out Slave In) pin for the SPI instance.
    ///
    /// Enables output functionality for the pin, and connects it as the MOSI
    /// signal. Use this for full-duplex SPI or
    /// when using [DataMode::SingleTwoDataLines].
    ///
    /// Disconnects the previous pin that was assigned with `with_mosi` or
    /// `with_sio0`.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_mosi(peripherals.GPIO1);
    ///
    /// # {after_snippet}
    /// ```
    pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
34
        self.spi.pins().sio_pins[0] = self.connect_sio_output_pin(mosi.into(), 0);
        self
    }
    #[procmacros::doc_replace]
    /// Assigns the MISO (Master In Slave Out) pin for the SPI instance.
    ///
    /// Enables input functionality for the pin, and connects it to the MISO
    /// signal.
    ///
    /// Use this for full-duplex SPI or
    /// [DataMode::SingleTwoDataLines]
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?.with_miso(peripherals.GPIO2);
    ///
    /// # {after_snippet}
    /// ```
    pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
34
        let miso = miso.into();
        miso.apply_input_config(&InputConfig::default());
        miso.set_input_enable(true);
34
        self.driver().info.sio_input(1).connect_to(&miso);
        self
    }
    /// Assigns the SIO0 pin for the SPI instance.
    ///
    /// Enables both input and output functionality for the pin, and connects it
    /// to the MOSI output signal and SIO0 input signal.
    ///
    /// Disconnects the previous pin that was assigned with `with_sio0` or
    /// `with_mosi`.
    ///
    /// Use this if any of the devices on the bus use half-duplex SPI.
    ///
    /// See also [Self::with_mosi] for a one-directional MOSI
    /// signal.
    #[instability::unstable]
    pub fn with_sio0(mut self, mosi: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
2
        self.spi.pins().sio_pins[0] = self.connect_sio_pin(mosi.into(), 0);
        self
    }
    /// Assigns the SIO1/MISO pin for the SPI instance.
    ///
    /// Enables both input and output functionality for the pin, and connects it
    /// to the MISO input signal and SIO1 output signal.
    ///
    /// Disconnects the previous pin that was assigned with `with_sio1`.
    ///
    /// Use this if any of the devices on the bus use half-duplex SPI.
    ///
    /// See also [Self::with_miso] for a one-directional MISO
    /// signal.
    #[instability::unstable]
    pub fn with_sio1(mut self, sio1: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
2
        self.spi.pins().sio_pins[1] = self.connect_sio_pin(sio1.into(), 1);
        self
    }
    def_with_sio_pin!(with_sio2, 2);
    def_with_sio_pin!(with_sio3, 3);
    #[cfg(spi_master_has_octal)]
    def_with_sio_pin!(with_sio4, 4);
    #[cfg(spi_master_has_octal)]
    def_with_sio_pin!(with_sio5, 5);
    #[cfg(spi_master_has_octal)]
    def_with_sio_pin!(with_sio6, 6);
    #[cfg(spi_master_has_octal)]
    def_with_sio_pin!(with_sio7, 7);
    /// Assigns the CS (Chip Select) pin for the SPI instance.
    ///
    /// Configures the specified pin to push-pull output and connects it to the
    /// SPI CS signal.
    ///
    /// Disconnects the previous pin that was assigned with `with_cs`.
    ///
    /// # Current Stability Limitations
    /// The hardware chip select functionality is limited; only one CS line can
    /// be set, regardless of the total number available. There is no
    /// mechanism to select which CS line to use.
    #[instability::unstable]
    pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
        let info = self.spi.info();
70
        self.spi.pins().cs_pin = self.connect_output_pin(cs.into(), info.cs(0));
        self
    }
    #[doc_replace(
        "max_frequency" => {
            cfg(esp32h2) => "48MHz",
            _ => "80MHz",
        }
    )]
    /// Changes the bus configuration.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?;
    ///
    /// spi.apply_config(&Config::default().with_frequency(Rate::from_khz(100)));
    /// #
    /// # {after_snippet}
    /// ```
    ///
    /// # Errors
    ///
    /// [`ConfigError::FrequencyOutOfRange`] when frequency passed in config exceeds
    /// __max_frequency__ or is below 70 kHz.
    pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
70
        self.driver().apply_config(config)
    }
    #[procmacros::doc_replace]
    /// Writes bytes to SPI. After writing, flush is called to ensure all data
    /// has been transmitted.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
    ///     .with_sck(peripherals.GPIO0)
    ///     .with_mosi(peripherals.GPIO1)
    ///     .with_miso(peripherals.GPIO2)
    ///     .into_async();
    ///
    /// let buffer = [0; 10];
    /// spi.write(&buffer)?;
    ///
    /// # {after_snippet}
    /// ```
    pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
        let _clock = SpiClockGuard::new(self.spi.info());
        self.driver().setup_full_duplex()?;
        self.driver().write(words)
    }
    #[procmacros::doc_replace]
    /// Reads bytes from SPI. The provided slice is filled with data received
    /// from the slave.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
    ///     .with_sck(peripherals.GPIO0)
    ///     .with_mosi(peripherals.GPIO1)
    ///     .with_miso(peripherals.GPIO2)
    ///     .into_async();
    ///
    /// let mut buffer = [0; 10];
    /// spi.read(&mut buffer)?;
    ///
    /// # {after_snippet}
    /// ```
    pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
        let _clock = SpiClockGuard::new(self.spi.info());
        self.driver().setup_full_duplex()?;
        self.driver().read(words)
    }
    #[procmacros::doc_replace]
    /// Sends `words` to the slave. The received data will be written to
    /// `words`, overwriting its contents.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::spi::{
    ///     Mode,
    ///     master::{Config, Spi},
    /// };
    /// let mut spi = Spi::new(peripherals.SPI2, Config::default())?
    ///     .with_sck(peripherals.GPIO0)
    ///     .with_mosi(peripherals.GPIO1)
    ///     .with_miso(peripherals.GPIO2)
    ///     .into_async();
    ///
    /// let mut buffer = [0; 10];
    /// spi.transfer(&mut buffer)?;
    ///
    /// # {after_snippet}
    /// ```
    pub fn transfer(&mut self, words: &mut [u8]) -> Result<(), Error> {
1
        let _clock = SpiClockGuard::new(self.spi.info());
1
        self.driver().setup_full_duplex()?;
1
        self.driver().transfer_in_place(words)
    }
    /// Half-duplex read.
    ///
    /// Transfers larger than the hardware FIFO are split into chunks. CS remains asserted across
    /// chunks, but the clock pauses while the CPU prepares each subsequent chunk.
    ///
    /// # Errors
    ///
    /// [`Error::Unsupported`] when the buffer is empty (currently unsupported).
    /// `DataMode::Single` cannot be combined with any other [`DataMode`], otherwise
    /// [`Error::Unsupported`].
    #[instability::unstable]
    pub fn half_duplex_read(
        &mut self,
        data_mode: DataMode,
        cmd: Command,
        address: Address,
        dummy: u8,
        buffer: &mut [u8],
    ) -> Result<(), Error> {
2
        let _clock = SpiClockGuard::new(self.spi.info());
        self.driver()
2
            .half_duplex_read(data_mode, cmd, address, dummy, buffer)
    }
    /// Half-duplex write.
    ///
    /// Transfers larger than the hardware FIFO are split into chunks. CS remains asserted across
    /// chunks, but the clock pauses while the CPU prepares each subsequent chunk.
    ///
    /// # Errors
    ///
    /// [`Error::Unsupported`] for unsupported combinations of command, address,
    /// dummy, and data modes.
    #[cfg_attr(
        esp32,
        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))."
    )]
    #[instability::unstable]
    pub fn half_duplex_write(
        &mut self,
        data_mode: DataMode,
        cmd: Command,
        address: Address,
        dummy: u8,
        buffer: &[u8],
    ) -> Result<(), Error> {
        let _clock = SpiClockGuard::new(self.spi.info());
        self.driver()
            .half_duplex_write(data_mode, cmd, address, dummy, buffer)
    }
    fn use_blocking_transfer(&self, transfer_size: usize) -> bool {
        let threshold = self
            .spi
            .state()
            .min_async_transfer_size
            .load(Ordering::Relaxed);
        threshold > 0 && transfer_size < threshold
    }
    fn driver(&self) -> Driver {
70
        Driver {
            info: self.spi.info(),
            state: self.spi.state(),
        }
    }
}
#[instability::unstable]
impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
where
    Dm: DriverMode,
{
    type Config = Config;
    type ConfigError = ConfigError;
    fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
        self.apply_config(config)
    }
}
impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
where
    Dm: DriverMode,
{
    type Error = Error;
}
impl<Dm> SpiBus for Spi<'_, Dm>
where
    Dm: DriverMode,
{
    fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
        self.read(words)
    }
    fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
        self.write(words)
    }
    fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2
        let _clock = SpiClockGuard::new(self.spi.info());
2
        self.driver().setup_full_duplex()?;
        if read.is_empty() {
            self.driver().write(write)
        } else if write.is_empty() {
            self.driver().read(read)
        } else {
2
            self.driver().transfer(read, write)
        }
    }
    fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2
        let _clock = SpiClockGuard::new(self.spi.info());
2
        self.driver().setup_full_duplex()?;
2
        self.driver().transfer_in_place(words)
    }
    fn flush(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}
impl SpiBusAsync for Spi<'_, Async> {
    async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
        self.read_async(words).await
    }
    async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
        self.write_async(words).await
    }
136
    async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
8
        let _clock = SpiClockGuard::new(self.spi.info());
8
        self.driver().setup_full_duplex()?;
8
        if self.use_blocking_transfer(read.len().max(write.len())) {
            return if read.is_empty() {
                self.driver().write(write)
            } else if write.is_empty() {
                self.driver().read(read)
            } else {
                self.driver().transfer(read, write)
            };
        }
8
        if read.is_empty() {
            self.driver().write_async(write).await
8
        } else if write.is_empty() {
            self.driver().read_async(read).await
        } else {
8
            self.driver().transfer_async(read, write).await
        }
8
    }
128
    async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
130
        self.transfer_in_place_async(words).await
    }
    async fn flush(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}
/// SPI data mode.
76
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum DataMode {
    /// 1 bit, two data lines. (MOSI, MISO)
    SingleTwoDataLines,
    /// 1 bit, 1 data line (SIO0)
    Single,
    /// 2 bits, two data lines. (SIO0, SIO1)
    Dual,
    /// 4 bit, 4 data lines. (SIO0 .. SIO3)
    Quad,
    #[cfg(spi_master_has_octal)]
    /// 8 bit, 8 data lines. (SIO0 .. SIO7)
    Octal,
}
crate::any_peripheral! {
    /// Any SPI peripheral.
    pub peripheral AnySpi<'d> {
        #[cfg(spi_master_spi2)]
        Spi2(crate::peripherals::SPI2<'d>),
        #[cfg(spi_master_spi3)]
        Spi3(crate::peripherals::SPI3<'d>),
    }
}
#[cfg(spi_master_supports_dma)]
with_spi_master_dma_engine! {
    ($engine:tt, $any_ch:ident) => {
        use crate::dma::DmaEligiblePeripheral;
        impl<'d> DmaEligiblePeripheral<crate::dma::$any_ch<'d>> for AnySpi<'d> {
            fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
                any::delegate!(self, spi => { spi.dma_peripheral() })
            }
        }
    };
}
impl QspiInstance for AnySpi<'_> {}
impl Instance for AnySpi<'_> {
    #[inline]
    fn parts(&self) -> (&'static Info, &'static State) {
        any::delegate!(self, spi => { spi.parts() })
    }
}
impl AnySpi<'_> {
    fn bind_peri_interrupt(&self, handler: InterruptHandler) {
        any::delegate!(self, spi => { spi.bind_peri_interrupt(handler) })
    }
    fn disable_peri_interrupt_on_all_cores(&self) {
        any::delegate!(self, spi => { spi.disable_peri_interrupt_on_all_cores() })
    }
    fn set_interrupt_handler(&self, handler: InterruptHandler) {
        self.disable_peri_interrupt_on_all_cores();
        self.bind_peri_interrupt(handler);
    }
}