1#[cfg(esp32)]
38use core::cell::Cell;
39use core::marker::PhantomData;
40
41#[instability::unstable]
42pub use dma::*;
43use enumset::{EnumSet, EnumSetType};
44use procmacros::doc_replace;
45#[cfg(place_spi_master_driver_in_ram)]
46use procmacros::ram;
47
48use super::{BitOrder, DmaError, Error, Mode};
49use crate::{
50 Async,
51 Blocking,
52 DriverMode,
53 asynch::AtomicWaker,
54 clock::Clocks,
55 dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer},
56 gpio::{
57 InputConfig,
58 InputSignal,
59 NoPin,
60 OutputConfig,
61 OutputSignal,
62 PinGuard,
63 interconnect::{self, PeripheralInput, PeripheralOutput},
64 },
65 interrupt::InterruptHandler,
66 pac::spi2::RegisterBlock,
67 private::{self, OnDrop, Sealed},
68 system::PeripheralGuard,
69 time::Rate,
70};
71
72#[derive(Debug, Hash, EnumSetType)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75#[non_exhaustive]
76#[instability::unstable]
77pub enum SpiInterrupt {
78 TransferDone,
83
84 #[cfg(any(esp32s2, gdma))]
86 DmaSegmentedTransferDone,
87
88 #[cfg(gdma)]
90 App2,
91
92 #[cfg(gdma)]
94 App1,
95}
96
97const FIFO_SIZE: usize = if cfg!(esp32s2) { 72 } else { 64 };
99
100const EMPTY_WRITE_PAD: u8 = 0x00;
102
103const MAX_DMA_SIZE: usize = 32736;
104
105#[non_exhaustive]
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
112#[instability::unstable]
113pub enum Command {
114 None,
116 _1Bit(u16, DataMode),
118 _2Bit(u16, DataMode),
120 _3Bit(u16, DataMode),
122 _4Bit(u16, DataMode),
124 _5Bit(u16, DataMode),
126 _6Bit(u16, DataMode),
128 _7Bit(u16, DataMode),
130 _8Bit(u16, DataMode),
132 _9Bit(u16, DataMode),
134 _10Bit(u16, DataMode),
136 _11Bit(u16, DataMode),
138 _12Bit(u16, DataMode),
140 _13Bit(u16, DataMode),
142 _14Bit(u16, DataMode),
144 _15Bit(u16, DataMode),
146 _16Bit(u16, DataMode),
148}
149
150impl Command {
151 fn width(&self) -> usize {
152 match self {
153 Command::None => 0,
154 Command::_1Bit(_, _) => 1,
155 Command::_2Bit(_, _) => 2,
156 Command::_3Bit(_, _) => 3,
157 Command::_4Bit(_, _) => 4,
158 Command::_5Bit(_, _) => 5,
159 Command::_6Bit(_, _) => 6,
160 Command::_7Bit(_, _) => 7,
161 Command::_8Bit(_, _) => 8,
162 Command::_9Bit(_, _) => 9,
163 Command::_10Bit(_, _) => 10,
164 Command::_11Bit(_, _) => 11,
165 Command::_12Bit(_, _) => 12,
166 Command::_13Bit(_, _) => 13,
167 Command::_14Bit(_, _) => 14,
168 Command::_15Bit(_, _) => 15,
169 Command::_16Bit(_, _) => 16,
170 }
171 }
172
173 fn value(&self) -> u16 {
174 match self {
175 Command::None => 0,
176 Command::_1Bit(value, _)
177 | Command::_2Bit(value, _)
178 | Command::_3Bit(value, _)
179 | Command::_4Bit(value, _)
180 | Command::_5Bit(value, _)
181 | Command::_6Bit(value, _)
182 | Command::_7Bit(value, _)
183 | Command::_8Bit(value, _)
184 | Command::_9Bit(value, _)
185 | Command::_10Bit(value, _)
186 | Command::_11Bit(value, _)
187 | Command::_12Bit(value, _)
188 | Command::_13Bit(value, _)
189 | Command::_14Bit(value, _)
190 | Command::_15Bit(value, _)
191 | Command::_16Bit(value, _) => *value,
192 }
193 }
194
195 fn mode(&self) -> DataMode {
196 match self {
197 Command::None => DataMode::SingleTwoDataLines,
198 Command::_1Bit(_, mode)
199 | Command::_2Bit(_, mode)
200 | Command::_3Bit(_, mode)
201 | Command::_4Bit(_, mode)
202 | Command::_5Bit(_, mode)
203 | Command::_6Bit(_, mode)
204 | Command::_7Bit(_, mode)
205 | Command::_8Bit(_, mode)
206 | Command::_9Bit(_, mode)
207 | Command::_10Bit(_, mode)
208 | Command::_11Bit(_, mode)
209 | Command::_12Bit(_, mode)
210 | Command::_13Bit(_, mode)
211 | Command::_14Bit(_, mode)
212 | Command::_15Bit(_, mode)
213 | Command::_16Bit(_, mode) => *mode,
214 }
215 }
216
217 fn is_none(&self) -> bool {
218 matches!(self, Command::None)
219 }
220}
221
222#[non_exhaustive]
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
229#[instability::unstable]
230pub enum Address {
231 None,
233 _1Bit(u32, DataMode),
235 _2Bit(u32, DataMode),
237 _3Bit(u32, DataMode),
239 _4Bit(u32, DataMode),
241 _5Bit(u32, DataMode),
243 _6Bit(u32, DataMode),
245 _7Bit(u32, DataMode),
247 _8Bit(u32, DataMode),
249 _9Bit(u32, DataMode),
251 _10Bit(u32, DataMode),
253 _11Bit(u32, DataMode),
255 _12Bit(u32, DataMode),
257 _13Bit(u32, DataMode),
259 _14Bit(u32, DataMode),
261 _15Bit(u32, DataMode),
263 _16Bit(u32, DataMode),
265 _17Bit(u32, DataMode),
267 _18Bit(u32, DataMode),
269 _19Bit(u32, DataMode),
271 _20Bit(u32, DataMode),
273 _21Bit(u32, DataMode),
275 _22Bit(u32, DataMode),
277 _23Bit(u32, DataMode),
279 _24Bit(u32, DataMode),
281 _25Bit(u32, DataMode),
283 _26Bit(u32, DataMode),
285 _27Bit(u32, DataMode),
287 _28Bit(u32, DataMode),
289 _29Bit(u32, DataMode),
291 _30Bit(u32, DataMode),
293 _31Bit(u32, DataMode),
295 _32Bit(u32, DataMode),
297}
298
299impl Address {
300 fn width(&self) -> usize {
301 match self {
302 Address::None => 0,
303 Address::_1Bit(_, _) => 1,
304 Address::_2Bit(_, _) => 2,
305 Address::_3Bit(_, _) => 3,
306 Address::_4Bit(_, _) => 4,
307 Address::_5Bit(_, _) => 5,
308 Address::_6Bit(_, _) => 6,
309 Address::_7Bit(_, _) => 7,
310 Address::_8Bit(_, _) => 8,
311 Address::_9Bit(_, _) => 9,
312 Address::_10Bit(_, _) => 10,
313 Address::_11Bit(_, _) => 11,
314 Address::_12Bit(_, _) => 12,
315 Address::_13Bit(_, _) => 13,
316 Address::_14Bit(_, _) => 14,
317 Address::_15Bit(_, _) => 15,
318 Address::_16Bit(_, _) => 16,
319 Address::_17Bit(_, _) => 17,
320 Address::_18Bit(_, _) => 18,
321 Address::_19Bit(_, _) => 19,
322 Address::_20Bit(_, _) => 20,
323 Address::_21Bit(_, _) => 21,
324 Address::_22Bit(_, _) => 22,
325 Address::_23Bit(_, _) => 23,
326 Address::_24Bit(_, _) => 24,
327 Address::_25Bit(_, _) => 25,
328 Address::_26Bit(_, _) => 26,
329 Address::_27Bit(_, _) => 27,
330 Address::_28Bit(_, _) => 28,
331 Address::_29Bit(_, _) => 29,
332 Address::_30Bit(_, _) => 30,
333 Address::_31Bit(_, _) => 31,
334 Address::_32Bit(_, _) => 32,
335 }
336 }
337
338 fn value(&self) -> u32 {
339 match self {
340 Address::None => 0,
341 Address::_1Bit(value, _)
342 | Address::_2Bit(value, _)
343 | Address::_3Bit(value, _)
344 | Address::_4Bit(value, _)
345 | Address::_5Bit(value, _)
346 | Address::_6Bit(value, _)
347 | Address::_7Bit(value, _)
348 | Address::_8Bit(value, _)
349 | Address::_9Bit(value, _)
350 | Address::_10Bit(value, _)
351 | Address::_11Bit(value, _)
352 | Address::_12Bit(value, _)
353 | Address::_13Bit(value, _)
354 | Address::_14Bit(value, _)
355 | Address::_15Bit(value, _)
356 | Address::_16Bit(value, _)
357 | Address::_17Bit(value, _)
358 | Address::_18Bit(value, _)
359 | Address::_19Bit(value, _)
360 | Address::_20Bit(value, _)
361 | Address::_21Bit(value, _)
362 | Address::_22Bit(value, _)
363 | Address::_23Bit(value, _)
364 | Address::_24Bit(value, _)
365 | Address::_25Bit(value, _)
366 | Address::_26Bit(value, _)
367 | Address::_27Bit(value, _)
368 | Address::_28Bit(value, _)
369 | Address::_29Bit(value, _)
370 | Address::_30Bit(value, _)
371 | Address::_31Bit(value, _)
372 | Address::_32Bit(value, _) => *value,
373 }
374 }
375
376 fn is_none(&self) -> bool {
377 matches!(self, Address::None)
378 }
379
380 fn mode(&self) -> DataMode {
381 match self {
382 Address::None => DataMode::SingleTwoDataLines,
383 Address::_1Bit(_, mode)
384 | Address::_2Bit(_, mode)
385 | Address::_3Bit(_, mode)
386 | Address::_4Bit(_, mode)
387 | Address::_5Bit(_, mode)
388 | Address::_6Bit(_, mode)
389 | Address::_7Bit(_, mode)
390 | Address::_8Bit(_, mode)
391 | Address::_9Bit(_, mode)
392 | Address::_10Bit(_, mode)
393 | Address::_11Bit(_, mode)
394 | Address::_12Bit(_, mode)
395 | Address::_13Bit(_, mode)
396 | Address::_14Bit(_, mode)
397 | Address::_15Bit(_, mode)
398 | Address::_16Bit(_, mode)
399 | Address::_17Bit(_, mode)
400 | Address::_18Bit(_, mode)
401 | Address::_19Bit(_, mode)
402 | Address::_20Bit(_, mode)
403 | Address::_21Bit(_, mode)
404 | Address::_22Bit(_, mode)
405 | Address::_23Bit(_, mode)
406 | Address::_24Bit(_, mode)
407 | Address::_25Bit(_, mode)
408 | Address::_26Bit(_, mode)
409 | Address::_27Bit(_, mode)
410 | Address::_28Bit(_, mode)
411 | Address::_29Bit(_, mode)
412 | Address::_30Bit(_, mode)
413 | Address::_31Bit(_, mode)
414 | Address::_32Bit(_, mode) => *mode,
415 }
416 }
417}
418
419#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
421#[cfg_attr(feature = "defmt", derive(defmt::Format))]
422#[instability::unstable]
423pub enum ClockSource {
424 Apb,
426 }
429
430#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, procmacros::BuilderLite)]
432#[cfg_attr(feature = "defmt", derive(defmt::Format))]
433#[non_exhaustive]
434pub struct Config {
435 #[builder_lite(skip)]
446 reg: Result<u32, ConfigError>,
447
448 #[builder_lite(skip_setter)]
450 frequency: Rate,
451
452 #[builder_lite(unstable)]
454 #[builder_lite(skip_setter)]
455 clock_source: ClockSource,
456
457 mode: Mode,
459
460 read_bit_order: BitOrder,
462
463 write_bit_order: BitOrder,
465}
466
467impl Default for Config {
468 fn default() -> Self {
469 let mut this = Config {
470 reg: Ok(0),
471 frequency: Rate::from_mhz(1),
472 clock_source: ClockSource::Apb,
473 mode: Mode::_0,
474 read_bit_order: BitOrder::MsbFirst,
475 write_bit_order: BitOrder::MsbFirst,
476 };
477
478 this.reg = this.recalculate();
479
480 this
481 }
482}
483
484impl Config {
485 pub fn with_frequency(mut self, frequency: Rate) -> Self {
487 self.frequency = frequency;
488 self.reg = self.recalculate();
489
490 self
491 }
492
493 #[instability::unstable]
495 pub fn with_clock_source(mut self, clock_source: ClockSource) -> Self {
496 self.clock_source = clock_source;
497 self.reg = self.recalculate();
498
499 self
500 }
501
502 fn clock_source_freq_hz(&self) -> Rate {
503 let clocks = Clocks::get();
504
505 cfg_if::cfg_if! {
507 if #[cfg(esp32h2)] {
508 clocks.pll_48m_clock
510 } else {
511 clocks.apb_clock
512 }
513 }
514 }
515
516 fn recalculate(&self) -> Result<u32, ConfigError> {
517 let source_freq = self.clock_source_freq_hz();
519
520 let reg_val: u32;
521 let duty_cycle = 128;
522
523 if self.frequency > ((source_freq / 4) * 3) {
527 reg_val = 1 << 31;
529 } else {
530 let mut pre: i32;
538 let mut bestn: i32 = -1;
539 let mut bestpre: i32 = -1;
540 let mut besterr: i32 = 0;
541 let mut errval: i32;
542
543 let target_freq_hz = self.frequency.as_hz() as i32;
544 let source_freq_hz = source_freq.as_hz() as i32;
545
546 for n in 2..=64 {
550 pre = ((source_freq_hz / n) + (target_freq_hz / 2)) / target_freq_hz;
554
555 if pre <= 0 {
556 pre = 1;
557 }
558
559 if pre > 16 {
560 pre = 16;
561 }
562
563 errval = (source_freq_hz / (pre * n) - target_freq_hz).abs();
564 if bestn == -1 || errval <= besterr {
565 besterr = errval;
566 bestn = n;
567 bestpre = pre;
568 }
569 }
570
571 let n: i32 = bestn;
572 pre = bestpre;
573 let l: i32 = n;
574
575 let mut h: i32 = (duty_cycle * n + 127) / 256;
579 if h <= 0 {
580 h = 1;
581 }
582
583 reg_val = (l as u32 - 1)
584 | ((h as u32 - 1) << 6)
585 | ((n as u32 - 1) << 12)
586 | ((pre as u32 - 1) << 18);
587 }
588
589 Ok(reg_val)
590 }
591
592 fn raw_clock_reg_value(&self) -> Result<u32, ConfigError> {
593 self.reg
594 }
595
596 fn validate(&self) -> Result<(), ConfigError> {
597 let source_freq = self.clock_source_freq_hz();
598 let min_divider = 1;
599 let max_divider = 16 * 64; if self.frequency < source_freq / max_divider || self.frequency > source_freq / min_divider
604 {
605 return Err(ConfigError::FrequencyOutOfRange);
606 }
607
608 Ok(())
609 }
610}
611
612#[derive(Debug)]
613#[cfg_attr(feature = "defmt", derive(defmt::Format))]
614struct SpiPinGuard {
615 sclk_pin: PinGuard,
616 cs_pin: PinGuard,
617 sio0_pin: PinGuard,
618 sio1_pin: PinGuard,
619 sio2_pin: Option<PinGuard>,
620 sio3_pin: Option<PinGuard>,
621 #[cfg(spi_master_has_octal)]
622 sio4_pin: Option<PinGuard>,
623 #[cfg(spi_master_has_octal)]
624 sio5_pin: Option<PinGuard>,
625 #[cfg(spi_master_has_octal)]
626 sio6_pin: Option<PinGuard>,
627 #[cfg(spi_master_has_octal)]
628 sio7_pin: Option<PinGuard>,
629}
630
631#[non_exhaustive]
633#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
634#[cfg_attr(feature = "defmt", derive(defmt::Format))]
635pub enum ConfigError {
636 FrequencyOutOfRange,
638}
639
640impl core::error::Error for ConfigError {}
641
642impl core::fmt::Display for ConfigError {
643 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
644 match self {
645 ConfigError::FrequencyOutOfRange => {
646 write!(f, "The requested frequency is not in the supported range")
647 }
648 }
649 }
650}
651#[procmacros::doc_replace]
652#[derive(Debug)]
674#[cfg_attr(feature = "defmt", derive(defmt::Format))]
675pub struct Spi<'d, Dm: DriverMode> {
676 spi: AnySpi<'d>,
677 _mode: PhantomData<Dm>,
678 guard: PeripheralGuard,
679 pins: SpiPinGuard,
680}
681
682impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
683
684impl<'d> Spi<'d, Blocking> {
685 #[procmacros::doc_replace]
686 pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
707 let guard = PeripheralGuard::new(spi.info().peripheral);
708
709 let mut this = Spi {
710 _mode: PhantomData,
711 guard,
712 pins: SpiPinGuard {
713 sclk_pin: PinGuard::new_unconnected(spi.info().sclk),
714 cs_pin: PinGuard::new_unconnected(spi.info().cs(0)),
715 sio0_pin: PinGuard::new_unconnected(spi.info().sio_output(0)),
716 sio1_pin: PinGuard::new_unconnected(spi.info().sio_output(1)),
717 sio2_pin: spi.info().opt_sio_output(2).map(PinGuard::new_unconnected),
718 sio3_pin: spi.info().opt_sio_output(3).map(PinGuard::new_unconnected),
719 #[cfg(spi_master_has_octal)]
720 sio4_pin: spi.info().opt_sio_output(4).map(PinGuard::new_unconnected),
721 #[cfg(spi_master_has_octal)]
722 sio5_pin: spi.info().opt_sio_output(5).map(PinGuard::new_unconnected),
723 #[cfg(spi_master_has_octal)]
724 sio6_pin: spi.info().opt_sio_output(6).map(PinGuard::new_unconnected),
725 #[cfg(spi_master_has_octal)]
726 sio7_pin: spi.info().opt_sio_output(7).map(PinGuard::new_unconnected),
727 },
728 spi: spi.degrade(),
729 };
730
731 this.driver().init();
732 this.apply_config(&config)?;
733
734 let this = this.with_sck(NoPin).with_cs(NoPin);
735
736 for sio in 0..8 {
737 if let Some(signal) = this.driver().info.opt_sio_input(sio) {
738 signal.connect_to(&NoPin);
739 }
740 if let Some(signal) = this.driver().info.opt_sio_output(sio) {
741 signal.connect_to(&NoPin);
742 }
743 }
744
745 Ok(this)
746 }
747
748 pub fn into_async(mut self) -> Spi<'d, Async> {
753 self.set_interrupt_handler(self.spi.info().async_handler);
754 Spi {
755 spi: self.spi,
756 _mode: PhantomData,
757 guard: self.guard,
758 pins: self.pins,
759 }
760 }
761
762 #[doc_replace(
763 "dma_channel" => {
764 cfg(any(esp32, esp32s2)) => "let dma_channel = peripherals.DMA_SPI2;",
765 _ => "let dma_channel = peripherals.DMA_CH0;",
766 }
767 )]
768 #[instability::unstable]
801 pub fn with_dma(self, channel: impl DmaChannelFor<AnySpi<'d>>) -> SpiDma<'d, Blocking> {
802 SpiDma::new(self.spi, self.pins, channel.degrade())
803 }
804
805 #[doc_replace(
806 "header" => {
807 cfg(multi_core) => "Registers an interrupt handler for the peripheral on the current core.",
808 _ => "Registers an interrupt handler for the peripheral.",
809 }
810 )]
811 #[instability::unstable]
824 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
825 self.spi.set_interrupt_handler(handler);
826 }
827}
828
829#[instability::unstable]
830impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
831 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
835 self.set_interrupt_handler(handler);
836 }
837}
838
839impl<'d> Spi<'d, Async> {
840 pub fn into_blocking(self) -> Spi<'d, Blocking> {
845 self.spi.disable_peri_interrupt();
846 Spi {
847 spi: self.spi,
848 _mode: PhantomData,
849 guard: self.guard,
850 pins: self.pins,
851 }
852 }
853
854 #[procmacros::doc_replace]
855 pub async fn flush_async(&mut self) -> Result<(), Error> {
878 self.driver().flush_async().await
879 }
880
881 #[procmacros::doc_replace]
882 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
909 self.driver().flush_async().await?;
912 self.driver().setup_full_duplex()?;
913 self.driver().transfer_in_place_async(words).await
914 }
915}
916
917macro_rules! def_with_sio_pin {
918 ($fn:ident, $field:ident, $n:literal) => {
919 #[doc = concat!(" Assign the SIO", stringify!($n), " pin for the SPI instance.")]
920 #[doc = " "]
921 #[doc = " Enables both input and output functionality for the pin, and connects it"]
922 #[doc = concat!(" to the SIO", stringify!($n), " output and input signals.")]
923 #[instability::unstable]
924 pub fn $fn(mut self, sio: impl PeripheralOutput<'d>) -> Self {
925 self.pins.$field = Some(self.connect_sio_pin(sio.into(), $n));
926
927 self
928 }
929 };
930}
931
932impl<'d, Dm> Spi<'d, Dm>
933where
934 Dm: DriverMode,
935{
936 fn connect_sio_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
937 let in_signal = self.spi.info().sio_input(n);
938 let out_signal = self.spi.info().sio_output(n);
939
940 pin.apply_input_config(&InputConfig::default());
941 pin.apply_output_config(&OutputConfig::default());
942
943 pin.set_input_enable(true);
944 pin.set_output_enable(false);
945
946 in_signal.connect_to(&pin);
947 pin.connect_with_guard(out_signal)
948 }
949
950 fn connect_sio_output_pin(&self, pin: interconnect::OutputSignal<'d>, n: usize) -> PinGuard {
951 let out_signal = self.spi.info().sio_output(n);
952
953 self.connect_output_pin(pin, out_signal)
954 }
955
956 fn connect_output_pin(
957 &self,
958 pin: interconnect::OutputSignal<'d>,
959 signal: OutputSignal,
960 ) -> PinGuard {
961 pin.apply_output_config(&OutputConfig::default());
962 pin.set_output_enable(true); pin.connect_with_guard(signal)
965 }
966
967 #[procmacros::doc_replace]
968 pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
988 self.pins.sclk_pin = self.connect_output_pin(sclk.into(), self.driver().info.sclk);
989
990 self
991 }
992
993 #[procmacros::doc_replace]
994 pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
1016 self.pins.sio0_pin = self.connect_sio_output_pin(mosi.into(), 0);
1017
1018 self
1019 }
1020
1021 #[procmacros::doc_replace]
1022 pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
1043 let miso = miso.into();
1044
1045 miso.apply_input_config(&InputConfig::default());
1046 miso.set_input_enable(true);
1047
1048 self.driver().info.sio_input(1).connect_to(&miso);
1049
1050 self
1051 }
1052
1053 #[instability::unstable]
1066 pub fn with_sio0(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
1067 self.pins.sio0_pin = self.connect_sio_pin(mosi.into(), 0);
1068
1069 self
1070 }
1071
1072 #[instability::unstable]
1084 pub fn with_sio1(mut self, sio1: impl PeripheralOutput<'d>) -> Self {
1085 self.pins.sio1_pin = self.connect_sio_pin(sio1.into(), 1);
1086
1087 self
1088 }
1089
1090 def_with_sio_pin!(with_sio2, sio2_pin, 2);
1091 def_with_sio_pin!(with_sio3, sio3_pin, 3);
1092
1093 #[cfg(spi_master_has_octal)]
1094 def_with_sio_pin!(with_sio4, sio4_pin, 4);
1095
1096 #[cfg(spi_master_has_octal)]
1097 def_with_sio_pin!(with_sio5, sio5_pin, 5);
1098
1099 #[cfg(spi_master_has_octal)]
1100 def_with_sio_pin!(with_sio6, sio6_pin, 6);
1101
1102 #[cfg(spi_master_has_octal)]
1103 def_with_sio_pin!(with_sio7, sio7_pin, 7);
1104
1105 #[instability::unstable]
1117 pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
1118 self.pins.cs_pin = self.connect_output_pin(cs.into(), self.driver().info.cs(0));
1119 self
1120 }
1121
1122 #[doc_replace(
1123 "max_frequency" => {
1124 cfg(esp32h2) => " 48MHz",
1125 _ => " 80MHz",
1126 }
1127 )]
1128 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1151 self.driver().apply_config(config)
1152 }
1153
1154 #[procmacros::doc_replace]
1155 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
1178 self.driver().setup_full_duplex()?;
1179 self.driver().write(words)?;
1180 self.driver().flush()?;
1181
1182 Ok(())
1183 }
1184
1185 #[procmacros::doc_replace]
1186 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
1209 self.driver().setup_full_duplex()?;
1210 self.driver().read(words)
1211 }
1212
1213 #[procmacros::doc_replace]
1214 pub fn transfer(&mut self, words: &mut [u8]) -> Result<(), Error> {
1237 self.driver().setup_full_duplex()?;
1238 self.driver().transfer(words)
1239 }
1240
1241 #[instability::unstable]
1250 pub fn half_duplex_read(
1251 &mut self,
1252 data_mode: DataMode,
1253 cmd: Command,
1254 address: Address,
1255 dummy: u8,
1256 buffer: &mut [u8],
1257 ) -> Result<(), Error> {
1258 if buffer.len() > FIFO_SIZE {
1259 return Err(Error::FifoSizeExeeded);
1260 }
1261
1262 if buffer.is_empty() {
1263 error!("Half-duplex mode does not support empty buffer");
1264 return Err(Error::Unsupported);
1265 }
1266
1267 self.driver().setup_half_duplex(
1268 false,
1269 cmd,
1270 address,
1271 false,
1272 dummy,
1273 buffer.is_empty(),
1274 data_mode,
1275 )?;
1276
1277 self.driver().configure_datalen(buffer.len(), 0);
1278 self.driver().start_operation();
1279 self.driver().flush()?;
1280 self.driver().read_from_fifo(buffer)
1281 }
1282
1283 #[cfg_attr(
1290 esp32,
1291 doc = "Dummy phase configuration is currently not supported, only value `0` is valid (see issue [#2240](https://github.com/esp-rs/esp-hal/issues/2240))."
1292 )]
1293 #[instability::unstable]
1294 pub fn half_duplex_write(
1295 &mut self,
1296 data_mode: DataMode,
1297 cmd: Command,
1298 address: Address,
1299 dummy: u8,
1300 buffer: &[u8],
1301 ) -> Result<(), Error> {
1302 if buffer.len() > FIFO_SIZE {
1303 return Err(Error::FifoSizeExeeded);
1304 }
1305
1306 cfg_if::cfg_if! {
1307 if #[cfg(all(esp32, spi_address_workaround))] {
1308 let mut buffer = buffer;
1309 let mut data_mode = data_mode;
1310 let mut address = address;
1311 let addr_bytes;
1312 if buffer.is_empty() && !address.is_none() {
1313 let bytes_to_write = address.width().div_ceil(8);
1316 addr_bytes = address.value().to_be_bytes();
1319 buffer = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1320 data_mode = address.mode();
1321 address = Address::None;
1322 }
1323
1324 if dummy > 0 {
1325 error!("Dummy bits are not supported without data");
1327 return Err(Error::Unsupported);
1328 }
1329 }
1330 }
1331
1332 self.driver().setup_half_duplex(
1333 true,
1334 cmd,
1335 address,
1336 false,
1337 dummy,
1338 buffer.is_empty(),
1339 data_mode,
1340 )?;
1341
1342 if !buffer.is_empty() {
1343 self.driver().write(buffer)?;
1345 } else {
1346 self.driver().start_operation();
1347 }
1348
1349 self.driver().flush()
1350 }
1351
1352 fn driver(&self) -> Driver {
1353 Driver {
1354 info: self.spi.info(),
1355 state: self.spi.state(),
1356 }
1357 }
1358}
1359
1360#[instability::unstable]
1361impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
1362where
1363 Dm: DriverMode,
1364{
1365 type Config = Config;
1366 type ConfigError = ConfigError;
1367
1368 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1369 self.apply_config(config)
1370 }
1371}
1372
1373mod dma {
1374 use core::{
1375 cmp::min,
1376 mem::ManuallyDrop,
1377 sync::atomic::{Ordering, fence},
1378 };
1379
1380 use super::*;
1381 use crate::{
1382 dma::{Channel, DmaRxBuf, DmaTxBuf, EmptyBuf, PeripheralDmaChannel, asynch::DmaRxFuture},
1383 spi::master::dma::asynch::DropGuard,
1384 };
1385
1386 #[doc_replace(
1387 "dma_channel" => {
1388 cfg(any(esp32, esp32s2)) => "let dma_channel = peripherals.DMA_SPI2;",
1389 _ => "let dma_channel = peripherals.DMA_CH0;",
1390 }
1391 )]
1392 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1428 pub struct SpiDma<'d, Dm>
1429 where
1430 Dm: DriverMode,
1431 {
1432 pub(crate) spi: AnySpi<'d>,
1433 pub(crate) channel: Channel<Dm, PeripheralDmaChannel<AnySpi<'d>>>,
1434 tx_transfer_in_progress: bool,
1435 rx_transfer_in_progress: bool,
1436 #[cfg(all(esp32, spi_address_workaround))]
1437 address_buffer: DmaTxBuf,
1438 guard: PeripheralGuard,
1439 pins: SpiPinGuard,
1440 }
1441
1442 impl<Dm> crate::private::Sealed for SpiDma<'_, Dm> where Dm: DriverMode {}
1443
1444 impl<'d> SpiDma<'d, Blocking> {
1445 #[instability::unstable]
1447 pub fn into_async(mut self) -> SpiDma<'d, Async> {
1448 self.set_interrupt_handler(self.spi.info().async_handler);
1449 SpiDma {
1450 spi: self.spi,
1451 channel: self.channel.into_async(),
1452 tx_transfer_in_progress: self.tx_transfer_in_progress,
1453 rx_transfer_in_progress: self.rx_transfer_in_progress,
1454 #[cfg(all(esp32, spi_address_workaround))]
1455 address_buffer: self.address_buffer,
1456 guard: self.guard,
1457 pins: self.pins,
1458 }
1459 }
1460
1461 pub(super) fn new(
1462 spi: AnySpi<'d>,
1463 pins: SpiPinGuard,
1464 channel: PeripheralDmaChannel<AnySpi<'d>>,
1465 ) -> Self {
1466 let channel = Channel::new(channel);
1467 channel.runtime_ensure_compatible(&spi);
1468 #[cfg(all(esp32, spi_address_workaround))]
1469 let address_buffer = {
1470 use crate::dma::DmaDescriptor;
1471 const SPI_NUM: usize = 2;
1472 static mut DESCRIPTORS: [[DmaDescriptor; 1]; SPI_NUM] =
1473 [[DmaDescriptor::EMPTY]; SPI_NUM];
1474 static mut BUFFERS: [[u32; 1]; SPI_NUM] = [[0; 1]; SPI_NUM];
1475
1476 let id = if spi.info() == unsafe { crate::peripherals::SPI2::steal().info() } {
1477 0
1478 } else {
1479 1
1480 };
1481
1482 unwrap!(DmaTxBuf::new(
1483 unsafe { &mut DESCRIPTORS[id] },
1484 crate::dma::as_mut_byte_array!(BUFFERS[id], 4)
1485 ))
1486 };
1487
1488 let guard = PeripheralGuard::new(spi.info().peripheral);
1489
1490 Self {
1491 spi,
1492 channel,
1493 #[cfg(all(esp32, spi_address_workaround))]
1494 address_buffer,
1495 tx_transfer_in_progress: false,
1496 rx_transfer_in_progress: false,
1497 guard,
1498 pins,
1499 }
1500 }
1501
1502 #[instability::unstable]
1504 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1505 self.driver().enable_listen(interrupts.into(), true);
1506 }
1507
1508 #[instability::unstable]
1510 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1511 self.driver().enable_listen(interrupts.into(), false);
1512 }
1513
1514 #[instability::unstable]
1516 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
1517 self.driver().interrupts()
1518 }
1519
1520 #[instability::unstable]
1522 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1523 self.driver().clear_interrupts(interrupts.into());
1524 }
1525
1526 #[cfg_attr(
1527 not(multi_core),
1528 doc = "Registers an interrupt handler for the peripheral."
1529 )]
1530 #[cfg_attr(
1531 multi_core,
1532 doc = "Registers an interrupt handler for the peripheral on the current core."
1533 )]
1534 #[doc = ""]
1535 #[instability::unstable]
1546 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1547 self.spi.set_interrupt_handler(handler);
1548 }
1549 }
1550
1551 impl<'d> SpiDma<'d, Async> {
1552 #[instability::unstable]
1554 pub fn into_blocking(self) -> SpiDma<'d, Blocking> {
1555 self.spi.disable_peri_interrupt();
1556 SpiDma {
1557 spi: self.spi,
1558 channel: self.channel.into_blocking(),
1559 tx_transfer_in_progress: self.tx_transfer_in_progress,
1560 rx_transfer_in_progress: self.rx_transfer_in_progress,
1561 #[cfg(all(esp32, spi_address_workaround))]
1562 address_buffer: self.address_buffer,
1563 guard: self.guard,
1564 pins: self.pins,
1565 }
1566 }
1567
1568 async fn wait_for_idle_async(&mut self) {
1569 if self.rx_transfer_in_progress {
1570 _ = DmaRxFuture::new(&mut self.channel.rx).await;
1571 self.rx_transfer_in_progress = false;
1572 }
1573
1574 struct Fut(Driver);
1575 impl Future for Fut {
1576 type Output = ();
1577
1578 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1579 if self.0.interrupts().contains(SpiInterrupt::TransferDone) {
1580 #[cfg(any(esp32, esp32s2))]
1581 if self.0.busy() {
1583 cx.waker().wake_by_ref();
1584 return Poll::Pending;
1585 }
1586
1587 self.0.clear_interrupts(SpiInterrupt::TransferDone.into());
1588 return Poll::Ready(());
1589 }
1590
1591 self.0.state.waker.register(cx.waker());
1592 self.0
1593 .enable_listen(SpiInterrupt::TransferDone.into(), true);
1594 Poll::Pending
1595 }
1596 }
1597 impl Drop for Fut {
1598 fn drop(&mut self) {
1599 self.0
1600 .enable_listen(SpiInterrupt::TransferDone.into(), false);
1601 }
1602 }
1603
1604 if !self.is_done() {
1605 Fut(self.driver()).await;
1606 }
1607
1608 if self.tx_transfer_in_progress {
1609 if !self.channel.tx.is_done() {
1611 self.channel.tx.stop_transfer();
1612 }
1613 self.tx_transfer_in_progress = false;
1614 }
1615 }
1616 }
1617
1618 impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
1619 where
1620 Dm: DriverMode,
1621 {
1622 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1627 f.debug_struct("SpiDma").field("spi", &self.spi).finish()
1628 }
1629 }
1630
1631 #[instability::unstable]
1632 impl crate::interrupt::InterruptConfigurable for SpiDma<'_, Blocking> {
1633 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1637 self.set_interrupt_handler(handler);
1638 }
1639 }
1640
1641 impl<Dm> SpiDma<'_, Dm>
1642 where
1643 Dm: DriverMode,
1644 {
1645 fn driver(&self) -> Driver {
1646 Driver {
1647 info: self.spi.info(),
1648 state: self.spi.state(),
1649 }
1650 }
1651
1652 fn dma_driver(&self) -> DmaDriver {
1653 DmaDriver {
1654 driver: self.driver(),
1655 dma_peripheral: self.spi.dma_peripheral(),
1656 }
1657 }
1658
1659 fn is_done(&self) -> bool {
1660 if self.driver().busy() {
1661 return false;
1662 }
1663 if self.rx_transfer_in_progress {
1664 if !self.channel.rx.is_done() && !self.channel.rx.has_dscr_empty_error() {
1672 return false;
1673 }
1674 }
1675 true
1676 }
1677
1678 fn wait_for_idle(&mut self) {
1679 while !self.is_done() {
1680 }
1682 self.rx_transfer_in_progress = false;
1683 self.tx_transfer_in_progress = false;
1684 fence(Ordering::Acquire);
1685 }
1686
1687 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1692 unsafe fn start_transfer_dma<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1693 &mut self,
1694 full_duplex: bool,
1695 bytes_to_read: usize,
1696 bytes_to_write: usize,
1697 rx_buffer: &mut RX,
1698 tx_buffer: &mut TX,
1699 ) -> Result<(), Error> {
1700 if bytes_to_read > MAX_DMA_SIZE || bytes_to_write > MAX_DMA_SIZE {
1701 return Err(Error::MaxDmaTransferSizeExceeded);
1702 }
1703
1704 self.rx_transfer_in_progress = bytes_to_read > 0;
1705 self.tx_transfer_in_progress = bytes_to_write > 0;
1706 unsafe {
1707 self.dma_driver().start_transfer_dma(
1708 full_duplex,
1709 bytes_to_read,
1710 bytes_to_write,
1711 rx_buffer,
1712 tx_buffer,
1713 &mut self.channel,
1714 )
1715 }
1716 }
1717
1718 #[cfg(all(esp32, spi_address_workaround))]
1719 fn set_up_address_workaround(
1720 &mut self,
1721 cmd: Command,
1722 address: Address,
1723 dummy: u8,
1724 ) -> Result<(), Error> {
1725 if dummy > 0 {
1726 error!("Dummy bits are not supported when there is no data to write");
1728 return Err(Error::Unsupported);
1729 }
1730
1731 let bytes_to_write = address.width().div_ceil(8);
1732 let addr_bytes = address.value().to_be_bytes();
1735 let addr_bytes = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1736 self.address_buffer.fill(addr_bytes);
1737
1738 self.driver().setup_half_duplex(
1739 true,
1740 cmd,
1741 Address::None,
1742 false,
1743 dummy,
1744 bytes_to_write == 0,
1745 address.mode(),
1746 )?;
1747
1748 self.tx_transfer_in_progress = true;
1751 unsafe {
1752 self.dma_driver().start_transfer_dma(
1753 false,
1754 0,
1755 bytes_to_write,
1756 &mut EmptyBuf,
1757 &mut self.address_buffer,
1758 &mut self.channel,
1759 )
1760 }
1761 }
1762
1763 fn cancel_transfer(&mut self) {
1764 if self.tx_transfer_in_progress || self.rx_transfer_in_progress {
1771 self.dma_driver().abort_transfer();
1772
1773 if self.tx_transfer_in_progress {
1775 self.channel.tx.stop_transfer();
1776 self.tx_transfer_in_progress = false;
1777 }
1778 if self.rx_transfer_in_progress {
1779 self.channel.rx.stop_transfer();
1780 self.rx_transfer_in_progress = false;
1781 }
1782 }
1783 }
1784 }
1785
1786 #[instability::unstable]
1787 impl<Dm> embassy_embedded_hal::SetConfig for SpiDma<'_, Dm>
1788 where
1789 Dm: DriverMode,
1790 {
1791 type Config = Config;
1792 type ConfigError = ConfigError;
1793
1794 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1795 self.apply_config(config)
1796 }
1797 }
1798
1799 #[instability::unstable]
1804 pub struct SpiDmaTransfer<'d, Dm, Buf>
1805 where
1806 Dm: DriverMode,
1807 {
1808 spi_dma: ManuallyDrop<SpiDma<'d, Dm>>,
1809 dma_buf: ManuallyDrop<Buf>,
1810 }
1811
1812 impl<Buf> SpiDmaTransfer<'_, Async, Buf> {
1813 #[instability::unstable]
1817 pub async fn wait_for_done(&mut self) {
1818 self.spi_dma.wait_for_idle_async().await;
1819 }
1820 }
1821
1822 impl<'d, Dm, Buf> SpiDmaTransfer<'d, Dm, Buf>
1823 where
1824 Dm: DriverMode,
1825 {
1826 fn new(spi_dma: SpiDma<'d, Dm>, dma_buf: Buf) -> Self {
1827 Self {
1828 spi_dma: ManuallyDrop::new(spi_dma),
1829 dma_buf: ManuallyDrop::new(dma_buf),
1830 }
1831 }
1832
1833 pub fn is_done(&self) -> bool {
1838 self.spi_dma.is_done()
1839 }
1840
1841 #[instability::unstable]
1846 pub fn wait(mut self) -> (SpiDma<'d, Dm>, Buf) {
1847 self.spi_dma.wait_for_idle();
1848 let retval = unsafe {
1849 (
1850 ManuallyDrop::take(&mut self.spi_dma),
1851 ManuallyDrop::take(&mut self.dma_buf),
1852 )
1853 };
1854 core::mem::forget(self);
1855 retval
1856 }
1857
1858 #[instability::unstable]
1860 pub fn cancel(&mut self) {
1861 if !self.spi_dma.is_done() {
1862 self.spi_dma.cancel_transfer();
1863 }
1864 }
1865 }
1866
1867 impl<Dm, Buf> Drop for SpiDmaTransfer<'_, Dm, Buf>
1868 where
1869 Dm: DriverMode,
1870 {
1871 fn drop(&mut self) {
1872 if !self.is_done() {
1873 self.spi_dma.cancel_transfer();
1874 self.spi_dma.wait_for_idle();
1875
1876 unsafe {
1877 ManuallyDrop::drop(&mut self.spi_dma);
1878 ManuallyDrop::drop(&mut self.dma_buf);
1879 }
1880 }
1881 }
1882 }
1883
1884 impl<'d, Dm> SpiDma<'d, Dm>
1885 where
1886 Dm: DriverMode,
1887 {
1888 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1893 unsafe fn start_dma_write(
1894 &mut self,
1895 bytes_to_write: usize,
1896 buffer: &mut impl DmaTxBuffer,
1897 ) -> Result<(), Error> {
1898 unsafe { self.start_dma_transfer(0, bytes_to_write, &mut EmptyBuf, buffer) }
1899 }
1900
1901 #[instability::unstable]
1907 pub fn with_buffers(self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf) -> SpiDmaBus<'d, Dm> {
1908 SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf)
1909 }
1910
1911 #[allow(clippy::type_complexity)]
1917 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1918 #[instability::unstable]
1919 pub fn write<TX: DmaTxBuffer>(
1920 mut self,
1921 bytes_to_write: usize,
1922 mut buffer: TX,
1923 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1924 self.wait_for_idle();
1925 if let Err(e) = self.driver().setup_full_duplex() {
1926 return Err((e, self, buffer));
1927 };
1928 match unsafe { self.start_dma_write(bytes_to_write, &mut buffer) } {
1929 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1930 Err(e) => Err((e, self, buffer)),
1931 }
1932 }
1933
1934 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1939 unsafe fn start_dma_read(
1940 &mut self,
1941 bytes_to_read: usize,
1942 buffer: &mut impl DmaRxBuffer,
1943 ) -> Result<(), Error> {
1944 unsafe { self.start_dma_transfer(bytes_to_read, 0, buffer, &mut EmptyBuf) }
1945 }
1946
1947 #[allow(clippy::type_complexity)]
1953 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1954 #[instability::unstable]
1955 pub fn read<RX: DmaRxBuffer>(
1956 mut self,
1957 bytes_to_read: usize,
1958 mut buffer: RX,
1959 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1960 self.wait_for_idle();
1961 if let Err(e) = self.driver().setup_full_duplex() {
1962 return Err((e, self, buffer));
1963 };
1964 match unsafe { self.start_dma_read(bytes_to_read, &mut buffer) } {
1965 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1966 Err(e) => Err((e, self, buffer)),
1967 }
1968 }
1969
1970 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1975 unsafe fn start_dma_transfer(
1976 &mut self,
1977 bytes_to_read: usize,
1978 bytes_to_write: usize,
1979 rx_buffer: &mut impl DmaRxBuffer,
1980 tx_buffer: &mut impl DmaTxBuffer,
1981 ) -> Result<(), Error> {
1982 unsafe {
1983 self.start_transfer_dma(true, bytes_to_read, bytes_to_write, rx_buffer, tx_buffer)
1984 }
1985 }
1986
1987 #[allow(clippy::type_complexity)]
1993 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1994 #[instability::unstable]
1995 pub fn transfer<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1996 mut self,
1997 bytes_to_read: usize,
1998 mut rx_buffer: RX,
1999 bytes_to_write: usize,
2000 mut tx_buffer: TX,
2001 ) -> Result<SpiDmaTransfer<'d, Dm, (RX, TX)>, (Error, Self, RX, TX)> {
2002 self.wait_for_idle();
2003 if let Err(e) = self.driver().setup_full_duplex() {
2004 return Err((e, self, rx_buffer, tx_buffer));
2005 };
2006 match unsafe {
2007 self.start_dma_transfer(
2008 bytes_to_read,
2009 bytes_to_write,
2010 &mut rx_buffer,
2011 &mut tx_buffer,
2012 )
2013 } {
2014 Ok(_) => Ok(SpiDmaTransfer::new(self, (rx_buffer, tx_buffer))),
2015 Err(e) => Err((e, self, rx_buffer, tx_buffer)),
2016 }
2017 }
2018
2019 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2024 unsafe fn start_half_duplex_read(
2025 &mut self,
2026 data_mode: DataMode,
2027 cmd: Command,
2028 address: Address,
2029 dummy: u8,
2030 bytes_to_read: usize,
2031 buffer: &mut impl DmaRxBuffer,
2032 ) -> Result<(), Error> {
2033 self.driver().setup_half_duplex(
2034 false,
2035 cmd,
2036 address,
2037 false,
2038 dummy,
2039 bytes_to_read == 0,
2040 data_mode,
2041 )?;
2042
2043 unsafe { self.start_transfer_dma(false, bytes_to_read, 0, buffer, &mut EmptyBuf) }
2044 }
2045
2046 #[allow(clippy::type_complexity)]
2048 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2049 #[instability::unstable]
2050 pub fn half_duplex_read<RX: DmaRxBuffer>(
2051 mut self,
2052 data_mode: DataMode,
2053 cmd: Command,
2054 address: Address,
2055 dummy: u8,
2056 bytes_to_read: usize,
2057 mut buffer: RX,
2058 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
2059 self.wait_for_idle();
2060
2061 match unsafe {
2062 self.start_half_duplex_read(
2063 data_mode,
2064 cmd,
2065 address,
2066 dummy,
2067 bytes_to_read,
2068 &mut buffer,
2069 )
2070 } {
2071 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
2072 Err(e) => Err((e, self, buffer)),
2073 }
2074 }
2075
2076 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2081 unsafe fn start_half_duplex_write(
2082 &mut self,
2083 data_mode: DataMode,
2084 cmd: Command,
2085 address: Address,
2086 dummy: u8,
2087 bytes_to_write: usize,
2088 buffer: &mut impl DmaTxBuffer,
2089 ) -> Result<(), Error> {
2090 #[cfg(all(esp32, spi_address_workaround))]
2091 {
2092 if bytes_to_write == 0 && address.mode() != DataMode::SingleTwoDataLines {
2095 return self.set_up_address_workaround(cmd, address, dummy);
2096 }
2097 }
2098
2099 self.driver().setup_half_duplex(
2100 true,
2101 cmd,
2102 address,
2103 false,
2104 dummy,
2105 bytes_to_write == 0,
2106 data_mode,
2107 )?;
2108
2109 unsafe { self.start_transfer_dma(false, 0, bytes_to_write, &mut EmptyBuf, buffer) }
2110 }
2111
2112 #[allow(clippy::type_complexity)]
2114 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2115 #[instability::unstable]
2116 pub fn half_duplex_write<TX: DmaTxBuffer>(
2117 mut self,
2118 data_mode: DataMode,
2119 cmd: Command,
2120 address: Address,
2121 dummy: u8,
2122 bytes_to_write: usize,
2123 mut buffer: TX,
2124 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
2125 self.wait_for_idle();
2126
2127 match unsafe {
2128 self.start_half_duplex_write(
2129 data_mode,
2130 cmd,
2131 address,
2132 dummy,
2133 bytes_to_write,
2134 &mut buffer,
2135 )
2136 } {
2137 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
2138 Err(e) => Err((e, self, buffer)),
2139 }
2140 }
2141
2142 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2148 #[cfg_attr(esp32h2, doc = " 48MHz")]
2149 #[instability::unstable]
2152 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2153 self.driver().apply_config(config)
2154 }
2155 }
2156
2157 #[derive(Debug)]
2162 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
2163 #[instability::unstable]
2164 pub struct SpiDmaBus<'d, Dm>
2165 where
2166 Dm: DriverMode,
2167 {
2168 spi_dma: SpiDma<'d, Dm>,
2169 rx_buf: DmaRxBuf,
2170 tx_buf: DmaTxBuf,
2171 }
2172
2173 impl<Dm> crate::private::Sealed for SpiDmaBus<'_, Dm> where Dm: DriverMode {}
2174
2175 impl<'d> SpiDmaBus<'d, Blocking> {
2176 #[instability::unstable]
2178 pub fn into_async(self) -> SpiDmaBus<'d, Async> {
2179 SpiDmaBus {
2180 spi_dma: self.spi_dma.into_async(),
2181 rx_buf: self.rx_buf,
2182 tx_buf: self.tx_buf,
2183 }
2184 }
2185
2186 #[instability::unstable]
2188 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2189 self.spi_dma.listen(interrupts.into());
2190 }
2191
2192 #[instability::unstable]
2194 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2195 self.spi_dma.unlisten(interrupts.into());
2196 }
2197
2198 #[instability::unstable]
2200 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
2201 self.spi_dma.interrupts()
2202 }
2203
2204 #[instability::unstable]
2206 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2207 self.spi_dma.clear_interrupts(interrupts.into());
2208 }
2209 }
2210
2211 impl<'d> SpiDmaBus<'d, Async> {
2212 #[instability::unstable]
2214 pub fn into_blocking(self) -> SpiDmaBus<'d, Blocking> {
2215 SpiDmaBus {
2216 spi_dma: self.spi_dma.into_blocking(),
2217 rx_buf: self.rx_buf,
2218 tx_buf: self.tx_buf,
2219 }
2220 }
2221
2222 #[instability::unstable]
2224 pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2225 self.spi_dma.wait_for_idle_async().await;
2226 self.spi_dma.driver().setup_full_duplex()?;
2227 let chunk_size = self.rx_buf.capacity();
2228
2229 for chunk in words.chunks_mut(chunk_size) {
2230 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2231
2232 unsafe { spi.start_dma_transfer(chunk.len(), 0, &mut self.rx_buf, &mut EmptyBuf)? };
2233
2234 spi.wait_for_idle_async().await;
2235
2236 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2237
2238 spi.defuse();
2239 }
2240
2241 Ok(())
2242 }
2243
2244 #[instability::unstable]
2246 pub async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
2247 self.spi_dma.wait_for_idle_async().await;
2248 self.spi_dma.driver().setup_full_duplex()?;
2249
2250 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2251 let chunk_size = self.tx_buf.capacity();
2252
2253 for chunk in words.chunks(chunk_size) {
2254 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2255
2256 unsafe { spi.start_dma_transfer(0, chunk.len(), &mut EmptyBuf, &mut self.tx_buf)? };
2257
2258 spi.wait_for_idle_async().await;
2259 }
2260 spi.defuse();
2261
2262 Ok(())
2263 }
2264
2265 #[instability::unstable]
2268 pub async fn transfer_async(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2269 self.spi_dma.wait_for_idle_async().await;
2270 self.spi_dma.driver().setup_full_duplex()?;
2271
2272 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2273 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2274
2275 let common_length = min(read.len(), write.len());
2276 let (read_common, read_remainder) = read.split_at_mut(common_length);
2277 let (write_common, write_remainder) = write.split_at(common_length);
2278
2279 for (read_chunk, write_chunk) in read_common
2280 .chunks_mut(chunk_size)
2281 .zip(write_common.chunks(chunk_size))
2282 {
2283 self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2284
2285 unsafe {
2286 spi.start_dma_transfer(
2287 read_chunk.len(),
2288 write_chunk.len(),
2289 &mut self.rx_buf,
2290 &mut self.tx_buf,
2291 )?;
2292 }
2293 spi.wait_for_idle_async().await;
2294
2295 read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2296 }
2297
2298 spi.defuse();
2299
2300 if !read_remainder.is_empty() {
2301 self.read_async(read_remainder).await
2302 } else if !write_remainder.is_empty() {
2303 self.write_async(write_remainder).await
2304 } else {
2305 Ok(())
2306 }
2307 }
2308
2309 #[instability::unstable]
2312 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2313 self.spi_dma.wait_for_idle_async().await;
2314 self.spi_dma.driver().setup_full_duplex()?;
2315
2316 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2317 for chunk in words.chunks_mut(self.tx_buf.capacity()) {
2318 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2319
2320 unsafe {
2321 spi.start_dma_transfer(
2322 chunk.len(),
2323 chunk.len(),
2324 &mut self.rx_buf,
2325 &mut self.tx_buf,
2326 )?;
2327 }
2328 spi.wait_for_idle_async().await;
2329 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2330 }
2331
2332 spi.defuse();
2333
2334 Ok(())
2335 }
2336 }
2337
2338 impl<'d, Dm> SpiDmaBus<'d, Dm>
2339 where
2340 Dm: DriverMode,
2341 {
2342 pub fn new(spi_dma: SpiDma<'d, Dm>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self {
2345 Self {
2346 spi_dma,
2347 rx_buf,
2348 tx_buf,
2349 }
2350 }
2351
2352 #[instability::unstable]
2354 pub fn split(mut self) -> (SpiDma<'d, Dm>, DmaRxBuf, DmaTxBuf) {
2355 self.wait_for_idle();
2356 (self.spi_dma, self.rx_buf, self.tx_buf)
2357 }
2358
2359 fn wait_for_idle(&mut self) {
2360 self.spi_dma.wait_for_idle();
2361 }
2362
2363 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2369 #[cfg_attr(esp32h2, doc = " 48MHz")]
2370 #[instability::unstable]
2373 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2374 self.spi_dma.apply_config(config)
2375 }
2376
2377 #[instability::unstable]
2379 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
2380 self.wait_for_idle();
2381 self.spi_dma.driver().setup_full_duplex()?;
2382 for chunk in words.chunks_mut(self.rx_buf.capacity()) {
2383 unsafe {
2384 self.spi_dma.start_dma_transfer(
2385 chunk.len(),
2386 0,
2387 &mut self.rx_buf,
2388 &mut EmptyBuf,
2389 )?;
2390 }
2391
2392 self.wait_for_idle();
2393 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2394 }
2395
2396 Ok(())
2397 }
2398
2399 #[instability::unstable]
2401 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
2402 self.wait_for_idle();
2403 self.spi_dma.driver().setup_full_duplex()?;
2404 for chunk in words.chunks(self.tx_buf.capacity()) {
2405 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2406
2407 unsafe {
2408 self.spi_dma.start_dma_transfer(
2409 0,
2410 chunk.len(),
2411 &mut EmptyBuf,
2412 &mut self.tx_buf,
2413 )?;
2414 }
2415
2416 self.wait_for_idle();
2417 }
2418
2419 Ok(())
2420 }
2421
2422 #[instability::unstable]
2424 pub fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2425 self.wait_for_idle();
2426 self.spi_dma.driver().setup_full_duplex()?;
2427 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2428
2429 let common_length = min(read.len(), write.len());
2430 let (read_common, read_remainder) = read.split_at_mut(common_length);
2431 let (write_common, write_remainder) = write.split_at(common_length);
2432
2433 for (read_chunk, write_chunk) in read_common
2434 .chunks_mut(chunk_size)
2435 .zip(write_common.chunks(chunk_size))
2436 {
2437 self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2438
2439 unsafe {
2440 self.spi_dma.start_dma_transfer(
2441 read_chunk.len(),
2442 write_chunk.len(),
2443 &mut self.rx_buf,
2444 &mut self.tx_buf,
2445 )?;
2446 }
2447 self.wait_for_idle();
2448
2449 read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2450 }
2451
2452 if !read_remainder.is_empty() {
2453 self.read(read_remainder)
2454 } else if !write_remainder.is_empty() {
2455 self.write(write_remainder)
2456 } else {
2457 Ok(())
2458 }
2459 }
2460
2461 #[instability::unstable]
2463 pub fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
2464 self.wait_for_idle();
2465 self.spi_dma.driver().setup_full_duplex()?;
2466 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2467
2468 for chunk in words.chunks_mut(chunk_size) {
2469 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2470
2471 unsafe {
2472 self.spi_dma.start_dma_transfer(
2473 chunk.len(),
2474 chunk.len(),
2475 &mut self.rx_buf,
2476 &mut self.tx_buf,
2477 )?;
2478 }
2479 self.wait_for_idle();
2480 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2481 }
2482
2483 Ok(())
2484 }
2485
2486 #[instability::unstable]
2488 pub fn half_duplex_read(
2489 &mut self,
2490 data_mode: DataMode,
2491 cmd: Command,
2492 address: Address,
2493 dummy: u8,
2494 buffer: &mut [u8],
2495 ) -> Result<(), Error> {
2496 if buffer.len() > self.rx_buf.capacity() {
2497 return Err(Error::from(DmaError::Overflow));
2498 }
2499 self.wait_for_idle();
2500
2501 unsafe {
2502 self.spi_dma.start_half_duplex_read(
2503 data_mode,
2504 cmd,
2505 address,
2506 dummy,
2507 buffer.len(),
2508 &mut self.rx_buf,
2509 )?;
2510 }
2511
2512 self.wait_for_idle();
2513
2514 buffer.copy_from_slice(&self.rx_buf.as_slice()[..buffer.len()]);
2515
2516 Ok(())
2517 }
2518
2519 #[instability::unstable]
2521 pub fn half_duplex_write(
2522 &mut self,
2523 data_mode: DataMode,
2524 cmd: Command,
2525 address: Address,
2526 dummy: u8,
2527 buffer: &[u8],
2528 ) -> Result<(), Error> {
2529 if buffer.len() > self.tx_buf.capacity() {
2530 return Err(Error::from(DmaError::Overflow));
2531 }
2532 self.wait_for_idle();
2533 self.tx_buf.as_mut_slice()[..buffer.len()].copy_from_slice(buffer);
2534
2535 unsafe {
2536 self.spi_dma.start_half_duplex_write(
2537 data_mode,
2538 cmd,
2539 address,
2540 dummy,
2541 buffer.len(),
2542 &mut self.tx_buf,
2543 )?;
2544 }
2545
2546 self.wait_for_idle();
2547
2548 Ok(())
2549 }
2550 }
2551
2552 #[instability::unstable]
2553 impl crate::interrupt::InterruptConfigurable for SpiDmaBus<'_, Blocking> {
2554 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
2558 self.spi_dma.set_interrupt_handler(handler);
2559 }
2560 }
2561
2562 #[instability::unstable]
2563 impl<Dm> embassy_embedded_hal::SetConfig for SpiDmaBus<'_, Dm>
2564 where
2565 Dm: DriverMode,
2566 {
2567 type Config = Config;
2568 type ConfigError = ConfigError;
2569
2570 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
2571 self.apply_config(config)
2572 }
2573 }
2574
2575 mod asynch {
2577 use core::ops::{Deref, DerefMut};
2578
2579 use super::*;
2580
2581 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2582 pub(crate) struct DropGuard<I, F: FnOnce(I)> {
2583 inner: ManuallyDrop<I>,
2584 on_drop: ManuallyDrop<F>,
2585 }
2586
2587 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2588 impl<I, F: FnOnce(I)> DropGuard<I, F> {
2589 pub(crate) fn new(inner: I, on_drop: F) -> Self {
2590 Self {
2591 inner: ManuallyDrop::new(inner),
2592 on_drop: ManuallyDrop::new(on_drop),
2593 }
2594 }
2595
2596 pub(crate) fn defuse(self) {}
2597 }
2598
2599 impl<I, F: FnOnce(I)> Drop for DropGuard<I, F> {
2600 fn drop(&mut self) {
2601 let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
2602 let on_drop = unsafe { ManuallyDrop::take(&mut self.on_drop) };
2603 (on_drop)(inner)
2604 }
2605 }
2606
2607 impl<I, F: FnOnce(I)> Deref for DropGuard<I, F> {
2608 type Target = I;
2609
2610 fn deref(&self) -> &I {
2611 &self.inner
2612 }
2613 }
2614
2615 impl<I, F: FnOnce(I)> DerefMut for DropGuard<I, F> {
2616 fn deref_mut(&mut self) -> &mut I {
2617 &mut self.inner
2618 }
2619 }
2620
2621 #[instability::unstable]
2622 impl embedded_hal_async::spi::SpiBus for SpiDmaBus<'_, Async> {
2623 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2624 self.read_async(words).await
2625 }
2626
2627 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2628 self.write_async(words).await
2629 }
2630
2631 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2632 self.transfer_async(read, write).await
2633 }
2634
2635 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2636 self.transfer_in_place_async(words).await
2637 }
2638
2639 async fn flush(&mut self) -> Result<(), Self::Error> {
2640 Ok(())
2642 }
2643 }
2644 }
2645
2646 mod ehal1 {
2647 #[cfg(feature = "unstable")]
2648 use embedded_hal::spi::{ErrorType, SpiBus};
2649
2650 #[cfg(feature = "unstable")]
2651 use super::*;
2652
2653 #[instability::unstable]
2654 impl<Dm> ErrorType for SpiDmaBus<'_, Dm>
2655 where
2656 Dm: DriverMode,
2657 {
2658 type Error = Error;
2659 }
2660
2661 #[instability::unstable]
2662 impl<Dm> SpiBus for SpiDmaBus<'_, Dm>
2663 where
2664 Dm: DriverMode,
2665 {
2666 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2667 self.read(words)
2668 }
2669
2670 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2671 self.write(words)
2672 }
2673
2674 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2675 self.transfer(read, write)
2676 }
2677
2678 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2679 self.transfer_in_place(words)
2680 }
2681
2682 fn flush(&mut self) -> Result<(), Self::Error> {
2683 Ok(())
2685 }
2686 }
2687 }
2688}
2689
2690mod ehal1 {
2691 use embedded_hal::spi::SpiBus;
2692 use embedded_hal_async::spi::SpiBus as SpiBusAsync;
2693
2694 use super::*;
2695
2696 impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
2697 where
2698 Dm: DriverMode,
2699 {
2700 type Error = Error;
2701 }
2702
2703 impl<Dm> SpiBus for Spi<'_, Dm>
2704 where
2705 Dm: DriverMode,
2706 {
2707 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2708 self.driver().read(words)
2709 }
2710
2711 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2712 self.driver().write(words)
2713 }
2714
2715 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2716 if read.is_empty() {
2718 return SpiBus::write(self, write);
2719 } else if write.is_empty() {
2720 return SpiBus::read(self, read);
2721 }
2722
2723 let mut write_from = 0;
2724 let mut read_from = 0;
2725
2726 loop {
2727 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2729 let write_to = write_from + write_inc;
2730 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2732 let read_to = read_from + read_inc;
2733
2734 if (write_inc == 0) && (read_inc == 0) {
2735 break;
2736 }
2737
2738 if write_to < read_to {
2741 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2743 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2744 SpiBus::write(self, &empty)?;
2745 } else {
2746 SpiBus::write(self, &write[write_from..write_to])?;
2747 }
2748
2749 if read_inc > 0 {
2750 SpiBus::flush(self)?;
2751 self.driver()
2752 .read_from_fifo(&mut read[read_from..read_to])?;
2753 }
2754
2755 write_from = write_to;
2756 read_from = read_to;
2757 }
2758 Ok(())
2759 }
2760
2761 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2762 self.driver().transfer(words)
2763 }
2764
2765 fn flush(&mut self) -> Result<(), Self::Error> {
2766 self.driver().flush()
2767 }
2768 }
2769
2770 impl SpiBusAsync for Spi<'_, Async> {
2771 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2772 self.flush_async().await?;
2775 self.driver().setup_full_duplex()?;
2776 self.driver().read_async(words).await
2777 }
2778
2779 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2780 self.flush_async().await?;
2783 self.driver().setup_full_duplex()?;
2784 self.driver().write_async(words).await
2785 }
2786
2787 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2788 if read.is_empty() {
2790 return SpiBusAsync::write(self, write).await;
2791 } else if write.is_empty() {
2792 return SpiBusAsync::read(self, read).await;
2793 }
2794
2795 let mut write_from = 0;
2796 let mut read_from = 0;
2797
2798 loop {
2799 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2801 let write_to = write_from + write_inc;
2802 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2804 let read_to = read_from + read_inc;
2805
2806 if (write_inc == 0) && (read_inc == 0) {
2807 break;
2808 }
2809
2810 if write_to < read_to {
2813 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2815 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2816 SpiBusAsync::write(self, &empty).await?;
2817 } else {
2818 SpiBusAsync::write(self, &write[write_from..write_to]).await?;
2819 }
2820
2821 if read_inc > 0 {
2822 self.driver()
2823 .read_from_fifo(&mut read[read_from..read_to])?;
2824 }
2825
2826 write_from = write_to;
2827 read_from = read_to;
2828 }
2829 Ok(())
2830 }
2831
2832 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2833 self.transfer_in_place_async(words).await
2834 }
2835
2836 async fn flush(&mut self) -> Result<(), Self::Error> {
2837 self.flush_async().await
2838 }
2839 }
2840}
2841
2842#[cfg_attr(not(feature = "unstable"), expect(private_bounds))] pub trait Instance: private::Sealed + any::Degrade + DmaEligible {
2845 #[doc(hidden)]
2846 fn parts(&self) -> (&'static Info, &'static State);
2848
2849 #[doc(hidden)]
2851 #[inline(always)]
2852 fn info(&self) -> &'static Info {
2853 self.parts().0
2854 }
2855
2856 #[doc(hidden)]
2858 #[inline(always)]
2859 fn state(&self) -> &'static State {
2860 self.parts().1
2861 }
2862}
2863
2864#[doc(hidden)]
2866pub trait QspiInstance: Instance {}
2867
2868#[doc(hidden)]
2870#[non_exhaustive]
2871pub struct Info {
2872 pub register_block: *const RegisterBlock,
2876
2877 pub peripheral: crate::system::Peripheral,
2879
2880 pub async_handler: InterruptHandler,
2882
2883 pub sclk: OutputSignal,
2885
2886 pub cs: &'static [OutputSignal],
2888
2889 pub sio_inputs: &'static [InputSignal],
2890 pub sio_outputs: &'static [OutputSignal],
2891}
2892
2893impl Info {
2894 fn cs(&self, n: usize) -> OutputSignal {
2895 *unwrap!(self.cs.get(n), "CS{} is not defined", n)
2896 }
2897
2898 fn opt_sio_input(&self, n: usize) -> Option<InputSignal> {
2899 self.sio_inputs.get(n).copied()
2900 }
2901
2902 fn opt_sio_output(&self, n: usize) -> Option<OutputSignal> {
2903 self.sio_outputs.get(n).copied()
2904 }
2905
2906 fn sio_input(&self, n: usize) -> InputSignal {
2907 unwrap!(self.opt_sio_input(n), "SIO{} is not defined", n)
2908 }
2909
2910 fn sio_output(&self, n: usize) -> OutputSignal {
2911 unwrap!(self.opt_sio_output(n), "SIO{} is not defined", n)
2912 }
2913}
2914
2915struct DmaDriver {
2916 driver: Driver,
2917 dma_peripheral: crate::dma::DmaPeripheral,
2918}
2919
2920impl DmaDriver {
2921 fn abort_transfer(&self) {
2922 self.driver.configure_datalen(1, 1);
2923 self.driver.update();
2924 }
2925
2926 fn regs(&self) -> &RegisterBlock {
2927 self.driver.regs()
2928 }
2929
2930 #[allow(clippy::too_many_arguments)]
2931 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2932 unsafe fn start_transfer_dma<Dm: DriverMode>(
2933 &self,
2934 _full_duplex: bool,
2935 rx_len: usize,
2936 tx_len: usize,
2937 rx_buffer: &mut impl DmaRxBuffer,
2938 tx_buffer: &mut impl DmaTxBuffer,
2939 channel: &mut Channel<Dm, PeripheralDmaChannel<AnySpi<'_>>>,
2940 ) -> Result<(), Error> {
2941 #[cfg(esp32s2)]
2942 {
2943 self.regs().dma_out_link().write(|w| unsafe { w.bits(0) });
2945 self.regs().dma_in_link().write(|w| unsafe { w.bits(0) });
2946 }
2947
2948 self.driver.configure_datalen(rx_len, tx_len);
2949
2950 self.regs()
2952 .user()
2953 .modify(|_, w| w.usr_miso().bit(rx_len > 0).usr_mosi().bit(tx_len > 0));
2954
2955 self.enable_dma();
2956
2957 if rx_len > 0 {
2958 unsafe {
2959 channel
2960 .rx
2961 .prepare_transfer(self.dma_peripheral, rx_buffer)
2962 .and_then(|_| channel.rx.start_transfer())?;
2963 }
2964 } else {
2965 #[cfg(esp32)]
2966 {
2967 if _full_duplex {
2970 self.regs()
2971 .dma_in_link()
2972 .modify(|_, w| unsafe { w.inlink_addr().bits(0) });
2973 self.regs()
2974 .dma_in_link()
2975 .modify(|_, w| w.inlink_start().set_bit());
2976 }
2977 }
2978 }
2979 if tx_len > 0 {
2980 unsafe {
2981 channel
2982 .tx
2983 .prepare_transfer(self.dma_peripheral, tx_buffer)
2984 .and_then(|_| channel.tx.start_transfer())?;
2985 }
2986 }
2987
2988 #[cfg(gdma)]
2989 self.reset_dma();
2990
2991 self.driver.start_operation();
2992
2993 Ok(())
2994 }
2995
2996 fn enable_dma(&self) {
2997 #[cfg(gdma)]
2998 self.regs().dma_conf().modify(|_, w| {
3000 w.dma_tx_ena().set_bit();
3001 w.dma_rx_ena().set_bit()
3002 });
3003
3004 #[cfg(pdma)]
3005 self.reset_dma();
3006 }
3007
3008 fn reset_dma(&self) {
3009 fn set_reset_bit(reg_block: &RegisterBlock, bit: bool) {
3010 #[cfg(pdma)]
3011 reg_block.dma_conf().modify(|_, w| {
3012 w.out_rst().bit(bit);
3013 w.in_rst().bit(bit);
3014 w.ahbm_fifo_rst().bit(bit);
3015 w.ahbm_rst().bit(bit)
3016 });
3017 #[cfg(gdma)]
3018 reg_block.dma_conf().modify(|_, w| {
3019 w.rx_afifo_rst().bit(bit);
3020 w.buf_afifo_rst().bit(bit);
3021 w.dma_afifo_rst().bit(bit)
3022 });
3023 }
3024
3025 set_reset_bit(self.regs(), true);
3026 set_reset_bit(self.regs(), false);
3027 self.clear_dma_interrupts();
3028 }
3029
3030 #[cfg(gdma)]
3031 fn clear_dma_interrupts(&self) {
3032 self.regs().dma_int_clr().write(|w| {
3033 w.dma_infifo_full_err().clear_bit_by_one();
3034 w.dma_outfifo_empty_err().clear_bit_by_one();
3035 w.trans_done().clear_bit_by_one();
3036 w.mst_rx_afifo_wfull_err().clear_bit_by_one();
3037 w.mst_tx_afifo_rempty_err().clear_bit_by_one()
3038 });
3039 }
3040
3041 #[cfg(pdma)]
3042 fn clear_dma_interrupts(&self) {
3043 self.regs().dma_int_clr().write(|w| {
3044 w.inlink_dscr_empty().clear_bit_by_one();
3045 w.outlink_dscr_error().clear_bit_by_one();
3046 w.inlink_dscr_error().clear_bit_by_one();
3047 w.in_done().clear_bit_by_one();
3048 w.in_err_eof().clear_bit_by_one();
3049 w.in_suc_eof().clear_bit_by_one();
3050 w.out_done().clear_bit_by_one();
3051 w.out_eof().clear_bit_by_one();
3052 w.out_total_eof().clear_bit_by_one()
3053 });
3054 }
3055}
3056
3057struct Driver {
3058 info: &'static Info,
3059 state: &'static State,
3060}
3061
3062impl Driver {
3065 pub fn regs(&self) -> &RegisterBlock {
3067 unsafe { &*self.info.register_block }
3068 }
3069
3070 fn abort_transfer(&self) {
3071 cfg_if::cfg_if! {
3076 if #[cfg(esp32)] {
3077 self.regs().slave().modify(|_, w| w.mode().set_bit());
3078 self.regs().slave().modify(|_, w| w.mode().clear_bit());
3079 } else {
3080 self.configure_datalen(1, 1);
3081 }
3082 }
3083 self.update();
3084 }
3085
3086 fn init(&self) {
3088 self.regs().user().modify(|_, w| {
3089 w.usr_miso_highpart().clear_bit();
3090 w.usr_mosi_highpart().clear_bit();
3091 w.doutdin().set_bit();
3092 w.usr_miso().set_bit();
3093 w.usr_mosi().set_bit();
3094 w.cs_hold().set_bit();
3095 w.usr_dummy_idle().set_bit();
3096 w.usr_addr().clear_bit();
3097 w.usr_command().clear_bit()
3098 });
3099
3100 #[cfg(gdma)]
3101 self.regs().clk_gate().modify(|_, w| {
3102 w.clk_en().set_bit();
3103 w.mst_clk_active().set_bit();
3104 w.mst_clk_sel().set_bit()
3105 });
3106
3107 #[cfg(any(esp32c6, esp32h2))]
3108 unsafe {
3109 crate::peripherals::PCR::regs()
3112 .spi2_clkm_conf()
3113 .modify(|_, w| w.spi2_clkm_sel().bits(1));
3114 }
3115
3116 #[cfg(gdma)]
3117 self.regs().ctrl().modify(|_, w| {
3118 w.q_pol().clear_bit();
3119 w.d_pol().clear_bit();
3120 w.hold_pol().clear_bit()
3121 });
3122
3123 #[cfg(esp32s2)]
3124 self.regs().ctrl().modify(|_, w| {
3125 w.q_pol().clear_bit();
3126 w.d_pol().clear_bit();
3127 w.wp().clear_bit()
3128 });
3129
3130 #[cfg(esp32)]
3131 self.regs().ctrl().modify(|_, w| w.wp().clear_bit());
3132
3133 #[cfg(not(esp32))]
3134 self.regs().misc().write(|w| unsafe { w.bits(0) });
3135
3136 self.regs().slave().write(|w| unsafe { w.bits(0) });
3137 }
3138
3139 #[cfg(not(esp32))]
3140 fn init_spi_data_mode(
3141 &self,
3142 cmd_mode: DataMode,
3143 address_mode: DataMode,
3144 data_mode: DataMode,
3145 ) -> Result<(), Error> {
3146 self.regs().ctrl().modify(|_, w| {
3147 w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
3148 w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
3149 w.faddr_dual().bit(address_mode == DataMode::Dual);
3150 w.faddr_quad().bit(address_mode == DataMode::Quad);
3151 w.fread_dual().bit(data_mode == DataMode::Dual);
3152 w.fread_quad().bit(data_mode == DataMode::Quad)
3153 });
3154 self.regs().user().modify(|_, w| {
3155 w.fwrite_dual().bit(data_mode == DataMode::Dual);
3156 w.fwrite_quad().bit(data_mode == DataMode::Quad)
3157 });
3158 Ok(())
3159 }
3160
3161 #[cfg(esp32)]
3162 fn init_spi_data_mode(
3163 &self,
3164 cmd_mode: DataMode,
3165 address_mode: DataMode,
3166 data_mode: DataMode,
3167 ) -> Result<(), Error> {
3168 match cmd_mode {
3169 DataMode::Single => (),
3170 DataMode::SingleTwoDataLines => (),
3171 _ => {
3173 error!("Commands must be single bit wide");
3174 return Err(Error::Unsupported);
3175 }
3176 }
3177
3178 match address_mode {
3179 DataMode::Single | DataMode::SingleTwoDataLines => {
3180 self.regs().ctrl().modify(|_, w| {
3181 w.fastrd_mode()
3182 .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3183 w.fread_dio().clear_bit();
3184 w.fread_qio().clear_bit();
3185 w.fread_dual().bit(data_mode == DataMode::Dual);
3186 w.fread_quad().bit(data_mode == DataMode::Quad)
3187 });
3188
3189 self.regs().user().modify(|_, w| {
3190 w.fwrite_dio().clear_bit();
3191 w.fwrite_qio().clear_bit();
3192 w.fwrite_dual().bit(data_mode == DataMode::Dual);
3193 w.fwrite_quad().bit(data_mode == DataMode::Quad)
3194 });
3195 }
3196 address_mode if address_mode == data_mode => {
3197 self.regs().ctrl().modify(|_, w| {
3198 w.fastrd_mode()
3199 .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3200 w.fread_dio().bit(address_mode == DataMode::Dual);
3201 w.fread_qio().bit(address_mode == DataMode::Quad);
3202 w.fread_dual().clear_bit();
3203 w.fread_quad().clear_bit()
3204 });
3205
3206 self.regs().user().modify(|_, w| {
3207 w.fwrite_dio().bit(address_mode == DataMode::Dual);
3208 w.fwrite_qio().bit(address_mode == DataMode::Quad);
3209 w.fwrite_dual().clear_bit();
3210 w.fwrite_quad().clear_bit()
3211 });
3212 }
3213 _ => {
3214 error!("Address mode must be single bit wide or equal to the data mode");
3216 return Err(Error::Unsupported);
3217 }
3218 }
3219
3220 Ok(())
3221 }
3222
3223 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3225 fn enable_listen(&self, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
3226 cfg_if::cfg_if! {
3227 if #[cfg(esp32)] {
3228 self.regs().slave().modify(|_, w| {
3229 for interrupt in interrupts {
3230 match interrupt {
3231 SpiInterrupt::TransferDone => w.trans_inten().bit(enable),
3232 };
3233 }
3234 w
3235 });
3236 } else if #[cfg(esp32s2)] {
3237 self.regs().slave().modify(|_, w| {
3238 for interrupt in interrupts {
3239 match interrupt {
3240 SpiInterrupt::TransferDone => w.int_trans_done_en().bit(enable),
3241 SpiInterrupt::DmaSegmentedTransferDone => w.int_dma_seg_trans_en().bit(enable),
3242 };
3243 }
3244 w
3245 });
3246 } else {
3247 self.regs().dma_int_ena().modify(|_, w| {
3248 for interrupt in interrupts {
3249 match interrupt {
3250 SpiInterrupt::TransferDone => w.trans_done().bit(enable),
3251 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
3252 SpiInterrupt::App2 => w.app2().bit(enable),
3253 SpiInterrupt::App1 => w.app1().bit(enable),
3254 };
3255 }
3256 w
3257 });
3258 }
3259 }
3260 }
3261
3262 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3264 fn interrupts(&self) -> EnumSet<SpiInterrupt> {
3265 let mut res = EnumSet::new();
3266
3267 cfg_if::cfg_if! {
3268 if #[cfg(esp32)] {
3269 if self.regs().slave().read().trans_done().bit() {
3270 res.insert(SpiInterrupt::TransferDone);
3271 }
3272 } else if #[cfg(esp32s2)] {
3273 if self.regs().slave().read().trans_done().bit() {
3274 res.insert(SpiInterrupt::TransferDone);
3275 }
3276 if self.regs().hold().read().dma_seg_trans_done().bit() {
3277 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3278 }
3279 } else {
3280 let ints = self.regs().dma_int_raw().read();
3281
3282 if ints.trans_done().bit() {
3283 res.insert(SpiInterrupt::TransferDone);
3284 }
3285 if ints.dma_seg_trans_done().bit() {
3286 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3287 }
3288 if ints.app2().bit() {
3289 res.insert(SpiInterrupt::App2);
3290 }
3291 if ints.app1().bit() {
3292 res.insert(SpiInterrupt::App1);
3293 }
3294 }
3295 }
3296
3297 res
3298 }
3299
3300 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3302 fn clear_interrupts(&self, interrupts: EnumSet<SpiInterrupt>) {
3303 cfg_if::cfg_if! {
3304 if #[cfg(esp32)] {
3305 for interrupt in interrupts {
3306 match interrupt {
3307 SpiInterrupt::TransferDone => {
3308 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3309 }
3310 }
3311 }
3312 } else if #[cfg(esp32s2)] {
3313 for interrupt in interrupts {
3314 match interrupt {
3315 SpiInterrupt::TransferDone => {
3316 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3317 }
3318
3319 SpiInterrupt::DmaSegmentedTransferDone => {
3320 self.regs()
3321 .hold()
3322 .modify(|_, w| w.dma_seg_trans_done().clear_bit());
3323 }
3324 }
3325 }
3326 } else {
3327 self.regs().dma_int_clr().write(|w| {
3328 for interrupt in interrupts {
3329 match interrupt {
3330 SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
3331 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
3332 SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
3333 SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
3334 };
3335 }
3336 w
3337 });
3338 }
3339 }
3340 }
3341
3342 fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
3343 config.validate()?;
3344 self.ch_bus_freq(config)?;
3345 self.set_bit_order(config.read_bit_order, config.write_bit_order);
3346 self.set_data_mode(config.mode);
3347
3348 #[cfg(esp32)]
3349 self.calculate_half_duplex_values(config);
3350
3351 Ok(())
3352 }
3353
3354 #[cfg(esp32)]
3355 fn calculate_half_duplex_values(&self, config: &Config) {
3356 let f_apb = 80_000_000;
3357 let source_freq_hz = match config.clock_source {
3358 ClockSource::Apb => f_apb,
3359 };
3360
3361 let clock_reg = self.regs().clock().read();
3362 let eff_clk = if clock_reg.clk_equ_sysclk().bit_is_set() {
3363 f_apb
3364 } else {
3365 let pre = clock_reg.clkdiv_pre().bits() as i32 + 1;
3366 let n = clock_reg.clkcnt_n().bits() as i32 + 1;
3367 f_apb / (pre * n)
3368 };
3369
3370 let apbclk_khz = source_freq_hz / 1000;
3371 let spiclk_apb_n = source_freq_hz / eff_clk;
3373
3374 let input_delay_ns = 25; let delay_apb_n = (1 + input_delay_ns) * apbclk_khz / 1000 / 1000;
3379
3380 let dummy_required = delay_apb_n / spiclk_apb_n;
3381 let timing_miso_delay = if dummy_required > 0 {
3382 Some(((dummy_required + 1) * spiclk_apb_n - delay_apb_n - 1) as u8)
3386 } else if delay_apb_n * 4 <= spiclk_apb_n {
3387 None
3390 } else {
3391 Some(0)
3392 };
3393
3394 self.state.esp32_hack.extra_dummy.set(dummy_required as u8);
3395 self.state
3396 .esp32_hack
3397 .timing_miso_delay
3398 .set(timing_miso_delay);
3399 }
3400
3401 fn set_data_mode(&self, data_mode: Mode) {
3402 cfg_if::cfg_if! {
3403 if #[cfg(esp32)] {
3404 let pin_reg = self.regs().pin();
3405 } else {
3406 let pin_reg = self.regs().misc();
3407 }
3408 };
3409
3410 pin_reg.modify(|_, w| {
3411 w.ck_idle_edge()
3412 .bit(matches!(data_mode, Mode::_2 | Mode::_3))
3413 });
3414 self.regs().user().modify(|_, w| {
3415 w.ck_out_edge()
3416 .bit(matches!(data_mode, Mode::_1 | Mode::_2))
3417 });
3418 }
3419
3420 fn ch_bus_freq(&self, bus_clock_config: &Config) -> Result<(), ConfigError> {
3421 fn enable_clocks(_reg_block: &RegisterBlock, _enable: bool) {
3422 #[cfg(gdma)]
3423 _reg_block.clk_gate().modify(|_, w| {
3424 w.clk_en().bit(_enable);
3425 w.mst_clk_active().bit(_enable);
3426 w.mst_clk_sel().bit(true) });
3428 }
3429
3430 let raw = bus_clock_config.raw_clock_reg_value()?;
3432
3433 enable_clocks(self.regs(), false);
3434 self.regs().clock().write(|w| unsafe { w.bits(raw) });
3435 enable_clocks(self.regs(), true);
3436
3437 Ok(())
3438 }
3439
3440 #[cfg(not(any(esp32, esp32c3, esp32s2)))]
3441 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3442 let read_value = match read_order {
3443 BitOrder::MsbFirst => 0,
3444 BitOrder::LsbFirst => 1,
3445 };
3446 let write_value = match write_order {
3447 BitOrder::MsbFirst => 0,
3448 BitOrder::LsbFirst => 1,
3449 };
3450 self.regs().ctrl().modify(|_, w| unsafe {
3451 w.rd_bit_order().bits(read_value);
3452 w.wr_bit_order().bits(write_value);
3453 w
3454 });
3455 }
3456
3457 #[cfg(any(esp32, esp32c3, esp32s2))]
3458 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3459 let read_value = match read_order {
3460 BitOrder::MsbFirst => false,
3461 BitOrder::LsbFirst => true,
3462 };
3463 let write_value = match write_order {
3464 BitOrder::MsbFirst => false,
3465 BitOrder::LsbFirst => true,
3466 };
3467 self.regs().ctrl().modify(|_, w| {
3468 w.rd_bit_order().bit(read_value);
3469 w.wr_bit_order().bit(write_value);
3470 w
3471 });
3472 }
3473
3474 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3475 fn fill_fifo(&self, chunk: &[u8]) {
3476 let mut c_iter = chunk.chunks_exact(4);
3478 let mut w_iter = self.regs().w_iter();
3479 for c in c_iter.by_ref() {
3480 if let Some(w_reg) = w_iter.next() {
3481 let word = (c[0] as u32)
3482 | ((c[1] as u32) << 8)
3483 | ((c[2] as u32) << 16)
3484 | ((c[3] as u32) << 24);
3485 w_reg.write(|w| w.buf().set(word));
3486 }
3487 }
3488 let rem = c_iter.remainder();
3489 if !rem.is_empty()
3490 && let Some(w_reg) = w_iter.next()
3491 {
3492 let word = match rem.len() {
3493 3 => (rem[0] as u32) | ((rem[1] as u32) << 8) | ((rem[2] as u32) << 16),
3494 2 => (rem[0] as u32) | ((rem[1] as u32) << 8),
3495 1 => rem[0] as u32,
3496 _ => unreachable!(),
3497 };
3498 w_reg.write(|w| w.buf().set(word));
3499 }
3500 }
3501
3502 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3508 fn write(&self, words: &[u8]) -> Result<(), Error> {
3509 let num_chunks = words.len() / FIFO_SIZE;
3510
3511 self.flush()?;
3514
3515 for (i, chunk) in words.chunks(FIFO_SIZE).enumerate() {
3518 self.configure_datalen(0, chunk.len());
3519 self.fill_fifo(chunk);
3520
3521 self.start_operation();
3522
3523 if i < num_chunks {
3527 self.flush()?;
3528 }
3529 }
3530 Ok(())
3531 }
3532
3533 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3535 async fn write_async(&self, words: &[u8]) -> Result<(), Error> {
3536 for chunk in words.chunks(FIFO_SIZE) {
3539 self.configure_datalen(0, chunk.len());
3540 self.fill_fifo(chunk);
3541 self.execute_operation_async().await;
3542 }
3543 Ok(())
3544 }
3545
3546 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3552 fn read(&self, words: &mut [u8]) -> Result<(), Error> {
3553 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3554
3555 for chunk in words.chunks_mut(FIFO_SIZE) {
3556 self.write(&empty_array[0..chunk.len()])?;
3557 self.flush()?;
3558 self.read_from_fifo(chunk)?;
3559 }
3560 Ok(())
3561 }
3562
3563 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3569 async fn read_async(&self, words: &mut [u8]) -> Result<(), Error> {
3570 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3571
3572 for chunk in words.chunks_mut(FIFO_SIZE) {
3573 self.write_async(&empty_array[0..chunk.len()]).await?;
3574 self.read_from_fifo(chunk)?;
3575 }
3576 Ok(())
3577 }
3578
3579 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3586 fn read_from_fifo(&self, words: &mut [u8]) -> Result<(), Error> {
3587 let reg_block = self.regs();
3588
3589 for chunk in words.chunks_mut(FIFO_SIZE) {
3590 self.configure_datalen(chunk.len(), 0);
3591
3592 for (index, w_reg) in (0..chunk.len()).step_by(4).zip(reg_block.w_iter()) {
3593 let reg_val = w_reg.read().bits();
3594 let bytes = reg_val.to_le_bytes();
3595
3596 let len = usize::min(chunk.len(), index + 4) - index;
3597 chunk[index..(index + len)].clone_from_slice(&bytes[0..len]);
3598 }
3599 }
3600
3601 Ok(())
3602 }
3603
3604 fn busy(&self) -> bool {
3605 self.regs().cmd().read().usr().bit_is_set()
3606 }
3607
3608 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3610 async fn flush_async(&self) -> Result<(), Error> {
3611 if self.busy() {
3612 let future = SpiFuture::setup(self).await;
3613 future.await;
3614 }
3615
3616 Ok(())
3617 }
3618
3619 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3621 fn flush(&self) -> Result<(), Error> {
3622 while self.busy() {
3623 }
3625 Ok(())
3626 }
3627
3628 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3629 fn transfer(&self, words: &mut [u8]) -> Result<(), Error> {
3630 for chunk in words.chunks_mut(FIFO_SIZE) {
3631 self.write(chunk)?;
3632 self.flush()?;
3633 self.read_from_fifo(chunk)?;
3634 }
3635
3636 Ok(())
3637 }
3638
3639 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3640 async fn transfer_in_place_async(&self, words: &mut [u8]) -> Result<(), Error> {
3641 for chunk in words.chunks_mut(FIFO_SIZE) {
3642 let cancel_on_drop = OnDrop::new(|| {
3645 self.abort_transfer();
3646 while self.busy() {}
3647 });
3648 let res = self.write_async(chunk).await;
3649 cancel_on_drop.defuse();
3650 res?;
3651
3652 self.read_from_fifo(chunk)?;
3653 }
3654
3655 Ok(())
3656 }
3657
3658 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3659 fn start_operation(&self) {
3660 self.update();
3661 self.regs().cmd().modify(|_, w| w.usr().set_bit());
3662 }
3663
3664 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3666 async fn execute_operation_async(&self) {
3667 let future = SpiFuture::setup(self).await;
3670 self.start_operation();
3671 future.await;
3672 }
3673
3674 fn setup_full_duplex(&self) -> Result<(), Error> {
3675 self.regs().user().modify(|_, w| {
3676 w.usr_miso().set_bit();
3677 w.usr_mosi().set_bit();
3678 w.doutdin().set_bit();
3679 w.usr_dummy().clear_bit();
3680 w.sio().clear_bit()
3681 });
3682
3683 self.init_spi_data_mode(
3684 DataMode::SingleTwoDataLines,
3685 DataMode::SingleTwoDataLines,
3686 DataMode::SingleTwoDataLines,
3687 )?;
3688
3689 #[cfg(esp32)]
3691 self.regs().ctrl2().modify(|_, w| unsafe {
3692 w.miso_delay_mode().bits(0);
3693 w.miso_delay_num().bits(0)
3694 });
3695
3696 Ok(())
3697 }
3698
3699 #[allow(clippy::too_many_arguments)]
3700 fn setup_half_duplex(
3701 &self,
3702 is_write: bool,
3703 cmd: Command,
3704 address: Address,
3705 dummy_idle: bool,
3706 dummy: u8,
3707 no_mosi_miso: bool,
3708 data_mode: DataMode,
3709 ) -> Result<(), Error> {
3710 self.init_spi_data_mode(cmd.mode(), address.mode(), data_mode)?;
3711
3712 #[cfg(esp32)]
3713 let mut dummy = dummy;
3714
3715 #[cfg(esp32)]
3716 self.regs().ctrl2().modify(|_, w| {
3717 let mut delay_mode = 0;
3718 let mut delay_num = 0;
3719
3720 if !is_write {
3721 let timing_miso_delay = self.state.esp32_hack.timing_miso_delay.get();
3723 let extra_dummy = self.state.esp32_hack.extra_dummy.get();
3724 dummy += extra_dummy;
3725
3726 if let Some(delay) = timing_miso_delay {
3727 delay_num = if extra_dummy > 0 { delay } else { 0 };
3728 } else {
3729 let out_edge = self.regs().user().read().ck_out_edge().bit_is_set();
3730 delay_mode = if out_edge { 1 } else { 2 };
3732 }
3733 }
3734
3735 unsafe {
3736 w.miso_delay_mode().bits(delay_mode);
3737 w.miso_delay_num().bits(delay_num)
3738 }
3739 });
3740
3741 let reg_block = self.regs();
3742 reg_block.user().modify(|_, w| {
3743 w.usr_miso_highpart().clear_bit();
3744 w.usr_mosi_highpart().clear_bit();
3745 w.sio().bit(data_mode == DataMode::Single);
3747 w.doutdin().clear_bit();
3748 w.usr_miso().bit(!is_write && !no_mosi_miso);
3749 w.usr_mosi().bit(is_write && !no_mosi_miso);
3750 w.cs_hold().set_bit();
3751 w.usr_dummy_idle().bit(dummy_idle);
3752 w.usr_dummy().bit(dummy != 0);
3753 w.usr_addr().bit(!address.is_none());
3754 w.usr_command().bit(!cmd.is_none())
3755 });
3756
3757 #[cfg(gdma)]
3758 reg_block.clk_gate().modify(|_, w| {
3759 w.clk_en().set_bit();
3760 w.mst_clk_active().set_bit();
3761 w.mst_clk_sel().set_bit()
3762 });
3763
3764 #[cfg(any(esp32c6, esp32h2))]
3765 crate::peripherals::PCR::regs()
3767 .spi2_clkm_conf()
3768 .modify(|_, w| unsafe { w.spi2_clkm_sel().bits(1) });
3769
3770 #[cfg(not(esp32))]
3771 reg_block.misc().write(|w| unsafe { w.bits(0) });
3772
3773 reg_block.slave().write(|w| unsafe { w.bits(0) });
3774
3775 self.update();
3776
3777 self.set_up_common_phases(cmd, address, dummy);
3779
3780 Ok(())
3781 }
3782
3783 fn set_up_common_phases(&self, cmd: Command, address: Address, dummy: u8) {
3784 let reg_block = self.regs();
3785 if !cmd.is_none() {
3786 reg_block.user2().modify(|_, w| unsafe {
3787 w.usr_command_bitlen().bits((cmd.width() - 1) as u8);
3788 w.usr_command_value().bits(cmd.value())
3789 });
3790 }
3791
3792 if !address.is_none() {
3793 reg_block
3794 .user1()
3795 .modify(|_, w| unsafe { w.usr_addr_bitlen().bits((address.width() - 1) as u8) });
3796
3797 let addr = address.value() << (32 - address.width());
3798 #[cfg(not(esp32))]
3799 reg_block
3800 .addr()
3801 .write(|w| unsafe { w.usr_addr_value().bits(addr) });
3802 #[cfg(esp32)]
3803 reg_block.addr().write(|w| unsafe { w.bits(addr) });
3804 }
3805
3806 if dummy > 0 {
3807 reg_block
3808 .user1()
3809 .modify(|_, w| unsafe { w.usr_dummy_cyclelen().bits(dummy - 1) });
3810 }
3811 }
3812
3813 fn update(&self) {
3814 cfg_if::cfg_if! {
3815 if #[cfg(gdma)] {
3816 let reg_block = self.regs();
3817
3818 reg_block.cmd().modify(|_, w| w.update().set_bit());
3819
3820 while reg_block.cmd().read().update().bit_is_set() {
3821 }
3823 } else {
3824 }
3826 }
3827 }
3828
3829 fn configure_datalen(&self, rx_len_bytes: usize, tx_len_bytes: usize) {
3830 let reg_block = self.regs();
3831
3832 let rx_len = rx_len_bytes as u32 * 8;
3833 let tx_len = tx_len_bytes as u32 * 8;
3834
3835 let rx_len = rx_len.saturating_sub(1);
3836 let tx_len = tx_len.saturating_sub(1);
3837
3838 cfg_if::cfg_if! {
3839 if #[cfg(esp32)] {
3840 let len = rx_len.max(tx_len);
3841 reg_block
3842 .mosi_dlen()
3843 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(len) });
3844
3845 reg_block
3846 .miso_dlen()
3847 .write(|w| unsafe { w.usr_miso_dbitlen().bits(len) });
3848 } else if #[cfg(esp32s2)] {
3849 reg_block
3850 .mosi_dlen()
3851 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(tx_len) });
3852
3853 reg_block
3854 .miso_dlen()
3855 .write(|w| unsafe { w.usr_miso_dbitlen().bits(rx_len) });
3856 } else {
3857 reg_block
3858 .ms_dlen()
3859 .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
3860 }
3861
3862 }
3863 }
3864}
3865
3866impl PartialEq for Info {
3867 fn eq(&self, other: &Self) -> bool {
3868 core::ptr::eq(self.register_block, other.register_block)
3869 }
3870}
3871
3872unsafe impl Sync for Info {}
3873
3874for_each_spi_master! {
3875 ($peri:ident, $sys:ident, $sclk:ident [$($cs:ident),+] [$($sio:ident),*] $(, $is_qspi:tt)?) => {
3876 impl Instance for crate::peripherals::$peri<'_> {
3877 #[inline(always)]
3878 fn parts(&self) -> (&'static Info, &'static State) {
3879 #[crate::handler]
3880 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3881 fn irq_handler() {
3882 handle_async(&INFO, &STATE)
3883 }
3884
3885 static INFO: Info = Info {
3886 register_block: crate::peripherals::$peri::regs(),
3887 peripheral: crate::system::Peripheral::$sys,
3888 async_handler: irq_handler,
3889 sclk: OutputSignal::$sclk,
3890 cs: &[$(OutputSignal::$cs),+],
3891 sio_inputs: &[$(InputSignal::$sio),*],
3892 sio_outputs: &[$(OutputSignal::$sio),*],
3893 };
3894
3895 static STATE: State = State {
3896 waker: AtomicWaker::new(),
3897 #[cfg(esp32)]
3898 esp32_hack: Esp32Hack {
3899 timing_miso_delay: Cell::new(None),
3900 extra_dummy: Cell::new(0),
3901 },
3902 };
3903
3904 (&INFO, &STATE)
3905 }
3906 }
3907
3908 $(
3909 $crate::ignore!($is_qspi);
3911 impl QspiInstance for crate::peripherals::$peri<'_> {}
3912 )?
3913 };
3914}
3915
3916impl QspiInstance for AnySpi<'_> {}
3917
3918#[doc(hidden)]
3919pub struct State {
3920 waker: AtomicWaker,
3921
3922 #[cfg(esp32)]
3923 esp32_hack: Esp32Hack,
3924}
3925
3926#[cfg(esp32)]
3927struct Esp32Hack {
3928 timing_miso_delay: Cell<Option<u8>>,
3929 extra_dummy: Cell<u8>,
3930}
3931
3932#[cfg(esp32)]
3933unsafe impl Sync for Esp32Hack {}
3934
3935#[cfg_attr(place_spi_master_driver_in_ram, ram)]
3936fn handle_async(info: &'static Info, state: &'static State) {
3937 let driver = Driver { info, state };
3938 if driver.interrupts().contains(SpiInterrupt::TransferDone) {
3939 driver.enable_listen(SpiInterrupt::TransferDone.into(), false);
3940 state.waker.wake();
3941 }
3942}
3943
3944#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3946#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3947#[instability::unstable]
3948pub enum DataMode {
3949 SingleTwoDataLines,
3951 Single,
3953 Dual,
3955 Quad,
3957 #[cfg(spi_master_has_octal)]
3958 Octal,
3960}
3961
3962crate::any_peripheral! {
3963 pub peripheral AnySpi<'d> {
3965 #[cfg(spi_master_spi2)]
3966 Spi2(crate::peripherals::SPI2<'d>),
3967 #[cfg(spi_master_spi3)]
3968 Spi3(crate::peripherals::SPI3<'d>),
3969 }
3970}
3971
3972impl<'d> DmaEligible for AnySpi<'d> {
3973 #[cfg(gdma)]
3974 type Dma = crate::dma::AnyGdmaChannel<'d>;
3975 #[cfg(pdma)]
3976 type Dma = crate::dma::AnySpiDmaChannel<'d>;
3977
3978 fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
3979 match &self.0 {
3980 #[cfg(spi_master_spi2)]
3981 any::Inner::Spi2(_) => crate::dma::DmaPeripheral::Spi2,
3982 #[cfg(spi_master_spi3)]
3983 any::Inner::Spi3(_) => crate::dma::DmaPeripheral::Spi3,
3984 }
3985 }
3986}
3987
3988impl Instance for AnySpi<'_> {
3989 #[inline]
3990 fn parts(&self) -> (&'static Info, &'static State) {
3991 any::delegate!(self, spi => { spi.parts() })
3992 }
3993}
3994
3995impl AnySpi<'_> {
3996 fn bind_peri_interrupt(&self, handler: unsafe extern "C" fn() -> ()) {
3997 any::delegate!(self, spi => { spi.bind_peri_interrupt(handler) })
3998 }
3999
4000 fn disable_peri_interrupt(&self) {
4001 any::delegate!(self, spi => { spi.disable_peri_interrupt() })
4002 }
4003
4004 fn enable_peri_interrupt(&self, priority: crate::interrupt::Priority) {
4005 any::delegate!(self, spi => { spi.enable_peri_interrupt(priority) })
4006 }
4007
4008 fn set_interrupt_handler(&self, handler: InterruptHandler) {
4009 self.disable_peri_interrupt();
4010 self.bind_peri_interrupt(handler.handler());
4011 self.enable_peri_interrupt(handler.priority());
4012 }
4013}
4014
4015struct SpiFuture<'a> {
4016 driver: &'a Driver,
4017}
4018
4019impl<'a> SpiFuture<'a> {
4020 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
4021 fn setup(driver: &'a Driver) -> impl Future<Output = Self> {
4022 core::future::poll_fn(move |cx| {
4025 driver.state.waker.register(cx.waker());
4026 driver.clear_interrupts(SpiInterrupt::TransferDone.into());
4027 driver.enable_listen(SpiInterrupt::TransferDone.into(), true);
4028 Poll::Ready(Self { driver })
4029 })
4030 }
4031}
4032
4033use core::{
4034 future::Future,
4035 pin::Pin,
4036 task::{Context, Poll},
4037};
4038
4039use crate::dma::{Channel, PeripheralDmaChannel};
4040
4041impl Future for SpiFuture<'_> {
4042 type Output = ();
4043
4044 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
4045 if self
4046 .driver
4047 .interrupts()
4048 .contains(SpiInterrupt::TransferDone)
4049 {
4050 self.driver
4051 .clear_interrupts(SpiInterrupt::TransferDone.into());
4052 return Poll::Ready(());
4053 }
4054
4055 Poll::Pending
4056 }
4057}
4058
4059impl Drop for SpiFuture<'_> {
4060 fn drop(&mut self) {
4061 self.driver
4062 .enable_listen(SpiInterrupt::TransferDone.into(), false);
4063 }
4064}