1#[cfg(esp32)]
38use core::cell::Cell;
39use core::marker::PhantomData;
40
41#[instability::unstable]
42pub use dma::*;
43use enumset::{EnumSet, EnumSetType};
44#[cfg(place_spi_master_driver_in_ram)]
45use procmacros::ram;
46
47use super::{BitOrder, DataMode, DmaError, Error, Mode};
48use crate::{
49 Async,
50 Blocking,
51 DriverMode,
52 asynch::AtomicWaker,
53 clock::Clocks,
54 dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer},
55 gpio::{
56 InputConfig,
57 InputSignal,
58 NoPin,
59 OutputConfig,
60 OutputSignal,
61 PinGuard,
62 interconnect::{PeripheralInput, PeripheralOutput},
63 },
64 interrupt::InterruptHandler,
65 pac::spi2::RegisterBlock,
66 private::{self, OnDrop, Sealed},
67 spi::AnySpi,
68 system::{Cpu, PeripheralGuard},
69 time::Rate,
70};
71
72#[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::UnsupportedFrequency);
606 }
607
608 Ok(())
609 }
610}
611
612#[derive(Debug)]
613#[cfg_attr(feature = "defmt", derive(defmt::Format))]
614struct SpiPinGuard {
615 mosi_pin: PinGuard,
616 sclk_pin: PinGuard,
617 cs_pin: PinGuard,
618 sio1_pin: PinGuard,
619 sio2_pin: Option<PinGuard>,
620 sio3_pin: Option<PinGuard>,
621}
622
623#[non_exhaustive]
625#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
626#[cfg_attr(feature = "defmt", derive(defmt::Format))]
627pub enum ConfigError {
628 UnsupportedFrequency,
630}
631
632impl core::error::Error for ConfigError {}
633
634impl core::fmt::Display for ConfigError {
635 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
636 match self {
637 ConfigError::UnsupportedFrequency => {
638 write!(f, "The requested frequency is not supported")
639 }
640 }
641 }
642}
643
644#[doc = crate::before_snippet!()]
649#[derive(Debug)]
664#[cfg_attr(feature = "defmt", derive(defmt::Format))]
665pub struct Spi<'d, Dm: DriverMode> {
666 spi: AnySpi<'d>,
667 _mode: PhantomData<Dm>,
668 guard: PeripheralGuard,
669 pins: SpiPinGuard,
670}
671
672impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
673
674impl<'d> Spi<'d, Blocking> {
675 pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
681 let guard = PeripheralGuard::new(spi.info().peripheral);
682
683 let mosi_pin = PinGuard::new_unconnected(spi.info().mosi);
684 let sclk_pin = PinGuard::new_unconnected(spi.info().sclk);
685 let cs_pin = PinGuard::new_unconnected(spi.info().cs[0]);
686 let sio1_pin = PinGuard::new_unconnected(spi.info().sio1_output);
687 let sio2_pin = spi.info().sio2_output.map(PinGuard::new_unconnected);
688 let sio3_pin = spi.info().sio3_output.map(PinGuard::new_unconnected);
689
690 let mut this = Spi {
691 spi: spi.degrade(),
692 _mode: PhantomData,
693 guard,
694 pins: SpiPinGuard {
695 mosi_pin,
696 sclk_pin,
697 cs_pin,
698 sio1_pin,
699 sio2_pin,
700 sio3_pin,
701 },
702 };
703
704 this.driver().init();
705 this.apply_config(&config)?;
706
707 let this = this
708 .with_sio0(NoPin)
709 .with_sio1(NoPin)
710 .with_sck(NoPin)
711 .with_cs(NoPin);
712
713 let is_qspi = this.driver().info.sio2_input.is_some();
714 if is_qspi {
715 unwrap!(this.driver().info.sio2_input).connect_to(&NoPin);
716 unwrap!(this.driver().info.sio2_output).connect_to(&NoPin);
717 unwrap!(this.driver().info.sio3_input).connect_to(&NoPin);
718 unwrap!(this.driver().info.sio3_output).connect_to(&NoPin);
719 }
720
721 Ok(this)
722 }
723
724 pub fn into_async(mut self) -> Spi<'d, Async> {
726 self.set_interrupt_handler(self.spi.handler());
727 Spi {
728 spi: self.spi,
729 _mode: PhantomData,
730 guard: self.guard,
731 pins: self.pins,
732 }
733 }
734
735 #[doc = crate::before_snippet!()]
742 #[cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = peripherals.DMA_SPI2;")]
747 #[cfg_attr(
748 not(any(esp32, esp32s2)),
749 doc = "let dma_channel = peripherals.DMA_CH0;"
750 )]
751 #[instability::unstable]
776 pub fn with_dma(self, channel: impl DmaChannelFor<AnySpi<'d>>) -> SpiDma<'d, Blocking> {
777 SpiDma::new(self.spi, self.pins, channel.degrade())
778 }
779
780 #[cfg_attr(
781 not(multi_core),
782 doc = "Registers an interrupt handler for the peripheral."
783 )]
784 #[cfg_attr(
785 multi_core,
786 doc = "Registers an interrupt handler for the peripheral on the current core."
787 )]
788 #[doc = ""]
789 #[instability::unstable]
800 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
801 let interrupt = self.driver().info.interrupt;
802 for core in Cpu::other() {
803 crate::interrupt::disable(core, interrupt);
804 }
805 unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
806 unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
807 }
808}
809
810#[instability::unstable]
811impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
812 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
816 Spi::set_interrupt_handler(self, handler);
817 }
818}
819
820impl<'d> Spi<'d, Async> {
821 pub fn into_blocking(self) -> Spi<'d, Blocking> {
823 crate::interrupt::disable(Cpu::current(), self.driver().info.interrupt);
824 Spi {
825 spi: self.spi,
826 _mode: PhantomData,
827 guard: self.guard,
828 pins: self.pins,
829 }
830 }
831
832 pub async fn flush_async(&mut self) -> Result<(), Error> {
834 self.driver().flush_async().await
835 }
836
837 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
844 self.driver().flush_async().await?;
847 self.driver().setup_full_duplex()?;
848 self.driver().transfer_in_place_async(words).await
849 }
850}
851
852impl<'d, Dm> Spi<'d, Dm>
853where
854 Dm: DriverMode,
855{
856 fn connect_sio_pin(
857 &self,
858 pin: impl PeripheralOutput<'d>,
859 in_signal: InputSignal,
860 out_signal: OutputSignal,
861 ) -> PinGuard {
862 let pin = pin.into();
863
864 pin.apply_input_config(&InputConfig::default());
865 pin.apply_output_config(&OutputConfig::default());
866
867 pin.set_input_enable(true);
868 pin.set_output_enable(false);
869
870 in_signal.connect_to(&pin);
871 pin.connect_with_guard(out_signal)
872 }
873
874 fn connect_output_pin(&self, pin: impl PeripheralOutput<'d>, signal: OutputSignal) -> PinGuard {
875 let pin = pin.into();
876
877 pin.apply_output_config(&OutputConfig::default());
878 pin.set_output_enable(true); pin.connect_with_guard(signal)
881 }
882
883 pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
890 self.pins.sclk_pin = self.connect_output_pin(sclk, self.driver().info.sclk);
891
892 self
893 }
894
895 pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
904 self.pins.mosi_pin = self.connect_output_pin(mosi, self.driver().info.mosi);
905
906 self
907 }
908
909 pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
917 let miso = miso.into();
918
919 miso.apply_input_config(&InputConfig::default());
920 miso.set_input_enable(true);
921
922 self.driver().info.miso.connect_to(&miso);
923
924 self
925 }
926
927 #[instability::unstable]
941 pub fn with_sio0(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
942 self.pins.mosi_pin =
943 self.connect_sio_pin(mosi, self.driver().info.sio0_input, self.driver().info.mosi);
944
945 self
946 }
947
948 #[instability::unstable]
961 pub fn with_sio1(mut self, sio1: impl PeripheralOutput<'d>) -> Self {
962 self.pins.sio1_pin = self.connect_sio_pin(
963 sio1,
964 self.driver().info.miso,
965 self.driver().info.sio1_output,
966 );
967
968 self
969 }
970
971 #[instability::unstable]
976 pub fn with_sio2(mut self, sio2: impl PeripheralOutput<'d>) -> Self {
977 self.pins.sio2_pin = Some(self.connect_sio_pin(
978 sio2,
979 unwrap!(self.driver().info.sio2_input),
980 unwrap!(self.driver().info.sio2_output),
981 ));
982
983 self
984 }
985
986 #[instability::unstable]
991 pub fn with_sio3(mut self, sio3: impl PeripheralOutput<'d>) -> Self {
992 self.pins.sio3_pin = Some(self.connect_sio_pin(
993 sio3,
994 unwrap!(self.driver().info.sio3_input),
995 unwrap!(self.driver().info.sio3_output),
996 ));
997
998 self
999 }
1000
1001 #[instability::unstable]
1013 pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
1014 self.pins.cs_pin = self.connect_output_pin(cs, self.driver().info.cs[0]);
1015 self
1016 }
1017
1018 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
1024 #[cfg_attr(esp32h2, doc = " 48MHz")]
1025 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1028 self.driver().apply_config(config)
1029 }
1030
1031 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
1034 self.driver().setup_full_duplex()?;
1035 self.driver().write(words)?;
1036 self.driver().flush()?;
1037
1038 Ok(())
1039 }
1040
1041 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
1044 self.driver().setup_full_duplex()?;
1045 self.driver().read(words)
1046 }
1047
1048 pub fn transfer(&mut self, words: &mut [u8]) -> Result<(), Error> {
1051 self.driver().setup_full_duplex()?;
1052 self.driver().transfer(words)
1053 }
1054
1055 #[instability::unstable]
1064 pub fn half_duplex_read(
1065 &mut self,
1066 data_mode: DataMode,
1067 cmd: Command,
1068 address: Address,
1069 dummy: u8,
1070 buffer: &mut [u8],
1071 ) -> Result<(), Error> {
1072 if buffer.len() > FIFO_SIZE {
1073 return Err(Error::FifoSizeExeeded);
1074 }
1075
1076 if buffer.is_empty() {
1077 error!("Half-duplex mode does not support empty buffer");
1078 return Err(Error::Unsupported);
1079 }
1080
1081 self.driver().setup_half_duplex(
1082 false,
1083 cmd,
1084 address,
1085 false,
1086 dummy,
1087 buffer.is_empty(),
1088 data_mode,
1089 )?;
1090
1091 self.driver().configure_datalen(buffer.len(), 0);
1092 self.driver().start_operation();
1093 self.driver().flush()?;
1094 self.driver().read_from_fifo(buffer)
1095 }
1096
1097 #[cfg_attr(
1104 esp32,
1105 doc = "Dummy phase configuration is currently not supported, only value `0` is valid (see issue [#2240](https://github.com/esp-rs/esp-hal/issues/2240))."
1106 )]
1107 #[instability::unstable]
1108 pub fn half_duplex_write(
1109 &mut self,
1110 data_mode: DataMode,
1111 cmd: Command,
1112 address: Address,
1113 dummy: u8,
1114 buffer: &[u8],
1115 ) -> Result<(), Error> {
1116 if buffer.len() > FIFO_SIZE {
1117 return Err(Error::FifoSizeExeeded);
1118 }
1119
1120 cfg_if::cfg_if! {
1121 if #[cfg(all(esp32, spi_address_workaround))] {
1122 let mut buffer = buffer;
1123 let mut data_mode = data_mode;
1124 let mut address = address;
1125 let addr_bytes;
1126 if buffer.is_empty() && !address.is_none() {
1127 let bytes_to_write = address.width().div_ceil(8);
1130 addr_bytes = address.value().to_be_bytes();
1133 buffer = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1134 data_mode = address.mode();
1135 address = Address::None;
1136 }
1137
1138 if dummy > 0 {
1139 error!("Dummy bits are not supported without data");
1141 return Err(Error::Unsupported);
1142 }
1143 }
1144 }
1145
1146 self.driver().setup_half_duplex(
1147 true,
1148 cmd,
1149 address,
1150 false,
1151 dummy,
1152 buffer.is_empty(),
1153 data_mode,
1154 )?;
1155
1156 if !buffer.is_empty() {
1157 self.driver().write(buffer)?;
1159 } else {
1160 self.driver().start_operation();
1161 }
1162
1163 self.driver().flush()
1164 }
1165
1166 fn driver(&self) -> Driver {
1167 Driver {
1168 info: self.spi.info(),
1169 state: self.spi.state(),
1170 }
1171 }
1172}
1173
1174#[instability::unstable]
1175impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
1176where
1177 Dm: DriverMode,
1178{
1179 type Config = Config;
1180 type ConfigError = ConfigError;
1181
1182 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1183 self.apply_config(config)
1184 }
1185}
1186
1187mod dma {
1188 use core::{
1189 cmp::min,
1190 mem::ManuallyDrop,
1191 sync::atomic::{Ordering, fence},
1192 };
1193
1194 use super::*;
1195 use crate::{
1196 dma::{Channel, DmaRxBuf, DmaTxBuf, EmptyBuf, PeripheralDmaChannel, asynch::DmaRxFuture},
1197 spi::master::dma::asynch::DropGuard,
1198 };
1199
1200 #[doc = crate::before_snippet!()]
1209 #[cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = peripherals.DMA_SPI2;")]
1214 #[cfg_attr(
1215 not(any(esp32, esp32s2)),
1216 doc = "let dma_channel = peripherals.DMA_CH0;"
1217 )]
1218 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1243 pub struct SpiDma<'d, Dm>
1244 where
1245 Dm: DriverMode,
1246 {
1247 pub(crate) spi: AnySpi<'d>,
1248 pub(crate) channel: Channel<Dm, PeripheralDmaChannel<AnySpi<'d>>>,
1249 tx_transfer_in_progress: bool,
1250 rx_transfer_in_progress: bool,
1251 #[cfg(all(esp32, spi_address_workaround))]
1252 address_buffer: DmaTxBuf,
1253 guard: PeripheralGuard,
1254 pins: SpiPinGuard,
1255 }
1256
1257 impl<Dm> crate::private::Sealed for SpiDma<'_, Dm> where Dm: DriverMode {}
1258
1259 impl<'d> SpiDma<'d, Blocking> {
1260 #[instability::unstable]
1262 pub fn into_async(mut self) -> SpiDma<'d, Async> {
1263 self.set_interrupt_handler(self.spi.handler());
1264 SpiDma {
1265 spi: self.spi,
1266 channel: self.channel.into_async(),
1267 tx_transfer_in_progress: self.tx_transfer_in_progress,
1268 rx_transfer_in_progress: self.rx_transfer_in_progress,
1269 #[cfg(all(esp32, spi_address_workaround))]
1270 address_buffer: self.address_buffer,
1271 guard: self.guard,
1272 pins: self.pins,
1273 }
1274 }
1275
1276 pub(super) fn new(
1277 spi: AnySpi<'d>,
1278 pins: SpiPinGuard,
1279 channel: PeripheralDmaChannel<AnySpi<'d>>,
1280 ) -> Self {
1281 let channel = Channel::new(channel);
1282 channel.runtime_ensure_compatible(&spi);
1283 #[cfg(all(esp32, spi_address_workaround))]
1284 let address_buffer = {
1285 use crate::dma::DmaDescriptor;
1286 const SPI_NUM: usize = 2;
1287 static mut DESCRIPTORS: [[DmaDescriptor; 1]; SPI_NUM] =
1288 [[DmaDescriptor::EMPTY]; SPI_NUM];
1289 static mut BUFFERS: [[u32; 1]; SPI_NUM] = [[0; 1]; SPI_NUM];
1290
1291 let id = if spi.info() == unsafe { crate::peripherals::SPI2::steal().info() } {
1292 0
1293 } else {
1294 1
1295 };
1296
1297 unwrap!(DmaTxBuf::new(
1298 unsafe { &mut DESCRIPTORS[id] },
1299 crate::dma::as_mut_byte_array!(BUFFERS[id], 4)
1300 ))
1301 };
1302
1303 let guard = PeripheralGuard::new(spi.info().peripheral);
1304
1305 Self {
1306 spi,
1307 channel,
1308 #[cfg(all(esp32, spi_address_workaround))]
1309 address_buffer,
1310 tx_transfer_in_progress: false,
1311 rx_transfer_in_progress: false,
1312 guard,
1313 pins,
1314 }
1315 }
1316
1317 #[instability::unstable]
1319 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1320 self.driver().enable_listen(interrupts.into(), true);
1321 }
1322
1323 #[instability::unstable]
1325 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1326 self.driver().enable_listen(interrupts.into(), false);
1327 }
1328
1329 #[instability::unstable]
1331 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
1332 self.driver().interrupts()
1333 }
1334
1335 #[instability::unstable]
1337 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1338 self.driver().clear_interrupts(interrupts.into());
1339 }
1340
1341 #[cfg_attr(
1342 not(multi_core),
1343 doc = "Registers an interrupt handler for the peripheral."
1344 )]
1345 #[cfg_attr(
1346 multi_core,
1347 doc = "Registers an interrupt handler for the peripheral on the current core."
1348 )]
1349 #[doc = ""]
1350 #[instability::unstable]
1361 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1362 let interrupt = self.driver().info.interrupt;
1363 for core in Cpu::other() {
1364 crate::interrupt::disable(core, interrupt);
1365 }
1366 unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
1367 unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
1368 }
1369 }
1370
1371 impl<'d> SpiDma<'d, Async> {
1372 #[instability::unstable]
1374 pub fn into_blocking(self) -> SpiDma<'d, Blocking> {
1375 crate::interrupt::disable(Cpu::current(), self.driver().info.interrupt);
1376 SpiDma {
1377 spi: self.spi,
1378 channel: self.channel.into_blocking(),
1379 tx_transfer_in_progress: self.tx_transfer_in_progress,
1380 rx_transfer_in_progress: self.rx_transfer_in_progress,
1381 #[cfg(all(esp32, spi_address_workaround))]
1382 address_buffer: self.address_buffer,
1383 guard: self.guard,
1384 pins: self.pins,
1385 }
1386 }
1387
1388 async fn wait_for_idle_async(&mut self) {
1389 if self.rx_transfer_in_progress {
1390 _ = DmaRxFuture::new(&mut self.channel.rx).await;
1391 self.rx_transfer_in_progress = false;
1392 }
1393
1394 struct Fut(Driver);
1395 impl Future for Fut {
1396 type Output = ();
1397
1398 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1399 if self.0.interrupts().contains(SpiInterrupt::TransferDone) {
1400 #[cfg(any(esp32, esp32s2))]
1401 if self.0.busy() {
1403 cx.waker().wake_by_ref();
1404 return Poll::Pending;
1405 }
1406
1407 self.0.clear_interrupts(SpiInterrupt::TransferDone.into());
1408 return Poll::Ready(());
1409 }
1410
1411 self.0.state.waker.register(cx.waker());
1412 self.0
1413 .enable_listen(SpiInterrupt::TransferDone.into(), true);
1414 Poll::Pending
1415 }
1416 }
1417 impl Drop for Fut {
1418 fn drop(&mut self) {
1419 self.0
1420 .enable_listen(SpiInterrupt::TransferDone.into(), false);
1421 }
1422 }
1423
1424 if !self.is_done() {
1425 Fut(self.driver()).await;
1426 }
1427
1428 if self.tx_transfer_in_progress {
1429 if !self.channel.tx.is_done() {
1431 self.channel.tx.stop_transfer();
1432 }
1433 self.tx_transfer_in_progress = false;
1434 }
1435 }
1436 }
1437
1438 impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
1439 where
1440 Dm: DriverMode,
1441 {
1442 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1447 f.debug_struct("SpiDma").field("spi", &self.spi).finish()
1448 }
1449 }
1450
1451 #[instability::unstable]
1452 impl crate::interrupt::InterruptConfigurable for SpiDma<'_, Blocking> {
1453 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1457 let interrupt = self.driver().info.interrupt;
1458 for core in crate::system::Cpu::other() {
1459 crate::interrupt::disable(core, interrupt);
1460 }
1461 unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
1462 unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
1463 }
1464 }
1465
1466 impl<Dm> SpiDma<'_, Dm>
1467 where
1468 Dm: DriverMode,
1469 {
1470 fn driver(&self) -> Driver {
1471 Driver {
1472 info: self.spi.info(),
1473 state: self.spi.state(),
1474 }
1475 }
1476
1477 fn dma_driver(&self) -> DmaDriver {
1478 DmaDriver {
1479 driver: self.driver(),
1480 dma_peripheral: self.spi.dma_peripheral(),
1481 }
1482 }
1483
1484 fn is_done(&self) -> bool {
1485 if self.driver().busy() {
1486 return false;
1487 }
1488 if self.rx_transfer_in_progress {
1489 if !self.channel.rx.is_done() && !self.channel.rx.has_dscr_empty_error() {
1497 return false;
1498 }
1499 }
1500 true
1501 }
1502
1503 fn wait_for_idle(&mut self) {
1504 while !self.is_done() {
1505 }
1507 self.rx_transfer_in_progress = false;
1508 self.tx_transfer_in_progress = false;
1509 fence(Ordering::Acquire);
1510 }
1511
1512 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1517 unsafe fn start_transfer_dma<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1518 &mut self,
1519 full_duplex: bool,
1520 bytes_to_read: usize,
1521 bytes_to_write: usize,
1522 rx_buffer: &mut RX,
1523 tx_buffer: &mut TX,
1524 ) -> Result<(), Error> {
1525 if bytes_to_read > MAX_DMA_SIZE || bytes_to_write > MAX_DMA_SIZE {
1526 return Err(Error::MaxDmaTransferSizeExceeded);
1527 }
1528
1529 self.rx_transfer_in_progress = bytes_to_read > 0;
1530 self.tx_transfer_in_progress = bytes_to_write > 0;
1531 unsafe {
1532 self.dma_driver().start_transfer_dma(
1533 full_duplex,
1534 bytes_to_read,
1535 bytes_to_write,
1536 rx_buffer,
1537 tx_buffer,
1538 &mut self.channel,
1539 )
1540 }
1541 }
1542
1543 #[cfg(all(esp32, spi_address_workaround))]
1544 fn set_up_address_workaround(
1545 &mut self,
1546 cmd: Command,
1547 address: Address,
1548 dummy: u8,
1549 ) -> Result<(), Error> {
1550 if dummy > 0 {
1551 error!("Dummy bits are not supported when there is no data to write");
1553 return Err(Error::Unsupported);
1554 }
1555
1556 let bytes_to_write = address.width().div_ceil(8);
1557 let addr_bytes = address.value().to_be_bytes();
1560 let addr_bytes = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1561 self.address_buffer.fill(addr_bytes);
1562
1563 self.driver().setup_half_duplex(
1564 true,
1565 cmd,
1566 Address::None,
1567 false,
1568 dummy,
1569 bytes_to_write == 0,
1570 address.mode(),
1571 )?;
1572
1573 self.tx_transfer_in_progress = true;
1576 unsafe {
1577 self.dma_driver().start_transfer_dma(
1578 false,
1579 0,
1580 bytes_to_write,
1581 &mut EmptyBuf,
1582 &mut self.address_buffer,
1583 &mut self.channel,
1584 )
1585 }
1586 }
1587
1588 fn cancel_transfer(&mut self) {
1589 if self.tx_transfer_in_progress || self.rx_transfer_in_progress {
1596 self.dma_driver().abort_transfer();
1597
1598 if self.tx_transfer_in_progress {
1600 self.channel.tx.stop_transfer();
1601 self.tx_transfer_in_progress = false;
1602 }
1603 if self.rx_transfer_in_progress {
1604 self.channel.rx.stop_transfer();
1605 self.rx_transfer_in_progress = false;
1606 }
1607 }
1608 }
1609 }
1610
1611 #[instability::unstable]
1612 impl<Dm> embassy_embedded_hal::SetConfig for SpiDma<'_, Dm>
1613 where
1614 Dm: DriverMode,
1615 {
1616 type Config = Config;
1617 type ConfigError = ConfigError;
1618
1619 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1620 self.apply_config(config)
1621 }
1622 }
1623
1624 #[instability::unstable]
1629 pub struct SpiDmaTransfer<'d, Dm, Buf>
1630 where
1631 Dm: DriverMode,
1632 {
1633 spi_dma: ManuallyDrop<SpiDma<'d, Dm>>,
1634 dma_buf: ManuallyDrop<Buf>,
1635 }
1636
1637 impl<Buf> SpiDmaTransfer<'_, Async, Buf> {
1638 #[instability::unstable]
1642 pub async fn wait_for_done(&mut self) {
1643 self.spi_dma.wait_for_idle_async().await;
1644 }
1645 }
1646
1647 impl<'d, Dm, Buf> SpiDmaTransfer<'d, Dm, Buf>
1648 where
1649 Dm: DriverMode,
1650 {
1651 fn new(spi_dma: SpiDma<'d, Dm>, dma_buf: Buf) -> Self {
1652 Self {
1653 spi_dma: ManuallyDrop::new(spi_dma),
1654 dma_buf: ManuallyDrop::new(dma_buf),
1655 }
1656 }
1657
1658 pub fn is_done(&self) -> bool {
1663 self.spi_dma.is_done()
1664 }
1665
1666 #[instability::unstable]
1671 pub fn wait(mut self) -> (SpiDma<'d, Dm>, Buf) {
1672 self.spi_dma.wait_for_idle();
1673 let retval = unsafe {
1674 (
1675 ManuallyDrop::take(&mut self.spi_dma),
1676 ManuallyDrop::take(&mut self.dma_buf),
1677 )
1678 };
1679 core::mem::forget(self);
1680 retval
1681 }
1682
1683 #[instability::unstable]
1685 pub fn cancel(&mut self) {
1686 if !self.spi_dma.is_done() {
1687 self.spi_dma.cancel_transfer();
1688 }
1689 }
1690 }
1691
1692 impl<Dm, Buf> Drop for SpiDmaTransfer<'_, Dm, Buf>
1693 where
1694 Dm: DriverMode,
1695 {
1696 fn drop(&mut self) {
1697 if !self.is_done() {
1698 self.spi_dma.cancel_transfer();
1699 self.spi_dma.wait_for_idle();
1700
1701 unsafe {
1702 ManuallyDrop::drop(&mut self.spi_dma);
1703 ManuallyDrop::drop(&mut self.dma_buf);
1704 }
1705 }
1706 }
1707 }
1708
1709 impl<'d, Dm> SpiDma<'d, Dm>
1710 where
1711 Dm: DriverMode,
1712 {
1713 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1718 unsafe fn start_dma_write(
1719 &mut self,
1720 bytes_to_write: usize,
1721 buffer: &mut impl DmaTxBuffer,
1722 ) -> Result<(), Error> {
1723 unsafe { self.start_dma_transfer(0, bytes_to_write, &mut EmptyBuf, buffer) }
1724 }
1725
1726 #[instability::unstable]
1732 pub fn with_buffers(self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf) -> SpiDmaBus<'d, Dm> {
1733 SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf)
1734 }
1735
1736 #[allow(clippy::type_complexity)]
1742 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1743 #[instability::unstable]
1744 pub fn write<TX: DmaTxBuffer>(
1745 mut self,
1746 bytes_to_write: usize,
1747 mut buffer: TX,
1748 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1749 self.wait_for_idle();
1750 if let Err(e) = self.driver().setup_full_duplex() {
1751 return Err((e, self, buffer));
1752 };
1753 match unsafe { self.start_dma_write(bytes_to_write, &mut buffer) } {
1754 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1755 Err(e) => Err((e, self, buffer)),
1756 }
1757 }
1758
1759 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1764 unsafe fn start_dma_read(
1765 &mut self,
1766 bytes_to_read: usize,
1767 buffer: &mut impl DmaRxBuffer,
1768 ) -> Result<(), Error> {
1769 unsafe { self.start_dma_transfer(bytes_to_read, 0, buffer, &mut EmptyBuf) }
1770 }
1771
1772 #[allow(clippy::type_complexity)]
1778 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1779 #[instability::unstable]
1780 pub fn read<RX: DmaRxBuffer>(
1781 mut self,
1782 bytes_to_read: usize,
1783 mut buffer: RX,
1784 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1785 self.wait_for_idle();
1786 if let Err(e) = self.driver().setup_full_duplex() {
1787 return Err((e, self, buffer));
1788 };
1789 match unsafe { self.start_dma_read(bytes_to_read, &mut buffer) } {
1790 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1791 Err(e) => Err((e, self, buffer)),
1792 }
1793 }
1794
1795 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1800 unsafe fn start_dma_transfer(
1801 &mut self,
1802 bytes_to_read: usize,
1803 bytes_to_write: usize,
1804 rx_buffer: &mut impl DmaRxBuffer,
1805 tx_buffer: &mut impl DmaTxBuffer,
1806 ) -> Result<(), Error> {
1807 unsafe {
1808 self.start_transfer_dma(true, bytes_to_read, bytes_to_write, rx_buffer, tx_buffer)
1809 }
1810 }
1811
1812 #[allow(clippy::type_complexity)]
1818 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1819 #[instability::unstable]
1820 pub fn transfer<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1821 mut self,
1822 bytes_to_read: usize,
1823 mut rx_buffer: RX,
1824 bytes_to_write: usize,
1825 mut tx_buffer: TX,
1826 ) -> Result<SpiDmaTransfer<'d, Dm, (RX, TX)>, (Error, Self, RX, TX)> {
1827 self.wait_for_idle();
1828 if let Err(e) = self.driver().setup_full_duplex() {
1829 return Err((e, self, rx_buffer, tx_buffer));
1830 };
1831 match unsafe {
1832 self.start_dma_transfer(
1833 bytes_to_read,
1834 bytes_to_write,
1835 &mut rx_buffer,
1836 &mut tx_buffer,
1837 )
1838 } {
1839 Ok(_) => Ok(SpiDmaTransfer::new(self, (rx_buffer, tx_buffer))),
1840 Err(e) => Err((e, self, rx_buffer, tx_buffer)),
1841 }
1842 }
1843
1844 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1849 unsafe fn start_half_duplex_read(
1850 &mut self,
1851 data_mode: DataMode,
1852 cmd: Command,
1853 address: Address,
1854 dummy: u8,
1855 bytes_to_read: usize,
1856 buffer: &mut impl DmaRxBuffer,
1857 ) -> Result<(), Error> {
1858 self.driver().setup_half_duplex(
1859 false,
1860 cmd,
1861 address,
1862 false,
1863 dummy,
1864 bytes_to_read == 0,
1865 data_mode,
1866 )?;
1867
1868 unsafe { self.start_transfer_dma(false, bytes_to_read, 0, buffer, &mut EmptyBuf) }
1869 }
1870
1871 #[allow(clippy::type_complexity)]
1873 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1874 #[instability::unstable]
1875 pub fn half_duplex_read<RX: DmaRxBuffer>(
1876 mut self,
1877 data_mode: DataMode,
1878 cmd: Command,
1879 address: Address,
1880 dummy: u8,
1881 bytes_to_read: usize,
1882 mut buffer: RX,
1883 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1884 self.wait_for_idle();
1885
1886 match unsafe {
1887 self.start_half_duplex_read(
1888 data_mode,
1889 cmd,
1890 address,
1891 dummy,
1892 bytes_to_read,
1893 &mut buffer,
1894 )
1895 } {
1896 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1897 Err(e) => Err((e, self, buffer)),
1898 }
1899 }
1900
1901 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1906 unsafe fn start_half_duplex_write(
1907 &mut self,
1908 data_mode: DataMode,
1909 cmd: Command,
1910 address: Address,
1911 dummy: u8,
1912 bytes_to_write: usize,
1913 buffer: &mut impl DmaTxBuffer,
1914 ) -> Result<(), Error> {
1915 #[cfg(all(esp32, spi_address_workaround))]
1916 {
1917 if bytes_to_write == 0 && address.mode() != DataMode::SingleTwoDataLines {
1920 return self.set_up_address_workaround(cmd, address, dummy);
1921 }
1922 }
1923
1924 self.driver().setup_half_duplex(
1925 true,
1926 cmd,
1927 address,
1928 false,
1929 dummy,
1930 bytes_to_write == 0,
1931 data_mode,
1932 )?;
1933
1934 unsafe { self.start_transfer_dma(false, 0, bytes_to_write, &mut EmptyBuf, buffer) }
1935 }
1936
1937 #[allow(clippy::type_complexity)]
1939 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
1940 #[instability::unstable]
1941 pub fn half_duplex_write<TX: DmaTxBuffer>(
1942 mut self,
1943 data_mode: DataMode,
1944 cmd: Command,
1945 address: Address,
1946 dummy: u8,
1947 bytes_to_write: usize,
1948 mut buffer: TX,
1949 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1950 self.wait_for_idle();
1951
1952 match unsafe {
1953 self.start_half_duplex_write(
1954 data_mode,
1955 cmd,
1956 address,
1957 dummy,
1958 bytes_to_write,
1959 &mut buffer,
1960 )
1961 } {
1962 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1963 Err(e) => Err((e, self, buffer)),
1964 }
1965 }
1966
1967 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
1973 #[cfg_attr(esp32h2, doc = " 48MHz")]
1974 #[instability::unstable]
1977 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1978 self.driver().apply_config(config)
1979 }
1980 }
1981
1982 #[derive(Debug)]
1987 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1988 #[instability::unstable]
1989 pub struct SpiDmaBus<'d, Dm>
1990 where
1991 Dm: DriverMode,
1992 {
1993 spi_dma: SpiDma<'d, Dm>,
1994 rx_buf: DmaRxBuf,
1995 tx_buf: DmaTxBuf,
1996 }
1997
1998 impl<Dm> crate::private::Sealed for SpiDmaBus<'_, Dm> where Dm: DriverMode {}
1999
2000 impl<'d> SpiDmaBus<'d, Blocking> {
2001 #[instability::unstable]
2003 pub fn into_async(self) -> SpiDmaBus<'d, Async> {
2004 SpiDmaBus {
2005 spi_dma: self.spi_dma.into_async(),
2006 rx_buf: self.rx_buf,
2007 tx_buf: self.tx_buf,
2008 }
2009 }
2010
2011 #[instability::unstable]
2013 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2014 self.spi_dma.listen(interrupts.into());
2015 }
2016
2017 #[instability::unstable]
2019 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2020 self.spi_dma.unlisten(interrupts.into());
2021 }
2022
2023 #[instability::unstable]
2025 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
2026 self.spi_dma.interrupts()
2027 }
2028
2029 #[instability::unstable]
2031 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2032 self.spi_dma.clear_interrupts(interrupts.into());
2033 }
2034 }
2035
2036 impl<'d> SpiDmaBus<'d, Async> {
2037 #[instability::unstable]
2039 pub fn into_blocking(self) -> SpiDmaBus<'d, Blocking> {
2040 SpiDmaBus {
2041 spi_dma: self.spi_dma.into_blocking(),
2042 rx_buf: self.rx_buf,
2043 tx_buf: self.tx_buf,
2044 }
2045 }
2046
2047 #[instability::unstable]
2049 pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2050 self.spi_dma.wait_for_idle_async().await;
2051 self.spi_dma.driver().setup_full_duplex()?;
2052 let chunk_size = self.rx_buf.capacity();
2053
2054 for chunk in words.chunks_mut(chunk_size) {
2055 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2056
2057 unsafe { spi.start_dma_transfer(chunk.len(), 0, &mut self.rx_buf, &mut EmptyBuf)? };
2058
2059 spi.wait_for_idle_async().await;
2060
2061 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2062
2063 spi.defuse();
2064 }
2065
2066 Ok(())
2067 }
2068
2069 #[instability::unstable]
2071 pub async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
2072 self.spi_dma.wait_for_idle_async().await;
2073 self.spi_dma.driver().setup_full_duplex()?;
2074
2075 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2076 let chunk_size = self.tx_buf.capacity();
2077
2078 for chunk in words.chunks(chunk_size) {
2079 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2080
2081 unsafe { spi.start_dma_transfer(0, chunk.len(), &mut EmptyBuf, &mut self.tx_buf)? };
2082
2083 spi.wait_for_idle_async().await;
2084 }
2085 spi.defuse();
2086
2087 Ok(())
2088 }
2089
2090 #[instability::unstable]
2093 pub async fn transfer_async(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2094 self.spi_dma.wait_for_idle_async().await;
2095 self.spi_dma.driver().setup_full_duplex()?;
2096
2097 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2098 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2099
2100 let common_length = min(read.len(), write.len());
2101 let (read_common, read_remainder) = read.split_at_mut(common_length);
2102 let (write_common, write_remainder) = write.split_at(common_length);
2103
2104 for (read_chunk, write_chunk) in read_common
2105 .chunks_mut(chunk_size)
2106 .zip(write_common.chunks(chunk_size))
2107 {
2108 self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2109
2110 unsafe {
2111 spi.start_dma_transfer(
2112 read_chunk.len(),
2113 write_chunk.len(),
2114 &mut self.rx_buf,
2115 &mut self.tx_buf,
2116 )?;
2117 }
2118 spi.wait_for_idle_async().await;
2119
2120 read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2121 }
2122
2123 spi.defuse();
2124
2125 if !read_remainder.is_empty() {
2126 self.read_async(read_remainder).await
2127 } else if !write_remainder.is_empty() {
2128 self.write_async(write_remainder).await
2129 } else {
2130 Ok(())
2131 }
2132 }
2133
2134 #[instability::unstable]
2137 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2138 self.spi_dma.wait_for_idle_async().await;
2139 self.spi_dma.driver().setup_full_duplex()?;
2140
2141 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2142 for chunk in words.chunks_mut(self.tx_buf.capacity()) {
2143 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2144
2145 unsafe {
2146 spi.start_dma_transfer(
2147 chunk.len(),
2148 chunk.len(),
2149 &mut self.rx_buf,
2150 &mut self.tx_buf,
2151 )?;
2152 }
2153 spi.wait_for_idle_async().await;
2154 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2155 }
2156
2157 spi.defuse();
2158
2159 Ok(())
2160 }
2161 }
2162
2163 impl<'d, Dm> SpiDmaBus<'d, Dm>
2164 where
2165 Dm: DriverMode,
2166 {
2167 pub fn new(spi_dma: SpiDma<'d, Dm>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self {
2170 Self {
2171 spi_dma,
2172 rx_buf,
2173 tx_buf,
2174 }
2175 }
2176
2177 #[instability::unstable]
2179 pub fn split(mut self) -> (SpiDma<'d, Dm>, DmaRxBuf, DmaTxBuf) {
2180 self.wait_for_idle();
2181 (self.spi_dma, self.rx_buf, self.tx_buf)
2182 }
2183
2184 fn wait_for_idle(&mut self) {
2185 self.spi_dma.wait_for_idle();
2186 }
2187
2188 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2194 #[cfg_attr(esp32h2, doc = " 48MHz")]
2195 #[instability::unstable]
2198 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2199 self.spi_dma.apply_config(config)
2200 }
2201
2202 #[instability::unstable]
2204 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
2205 self.wait_for_idle();
2206 self.spi_dma.driver().setup_full_duplex()?;
2207 for chunk in words.chunks_mut(self.rx_buf.capacity()) {
2208 unsafe {
2209 self.spi_dma.start_dma_transfer(
2210 chunk.len(),
2211 0,
2212 &mut self.rx_buf,
2213 &mut EmptyBuf,
2214 )?;
2215 }
2216
2217 self.wait_for_idle();
2218 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2219 }
2220
2221 Ok(())
2222 }
2223
2224 #[instability::unstable]
2226 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
2227 self.wait_for_idle();
2228 self.spi_dma.driver().setup_full_duplex()?;
2229 for chunk in words.chunks(self.tx_buf.capacity()) {
2230 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2231
2232 unsafe {
2233 self.spi_dma.start_dma_transfer(
2234 0,
2235 chunk.len(),
2236 &mut EmptyBuf,
2237 &mut self.tx_buf,
2238 )?;
2239 }
2240
2241 self.wait_for_idle();
2242 }
2243
2244 Ok(())
2245 }
2246
2247 #[instability::unstable]
2249 pub fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2250 self.wait_for_idle();
2251 self.spi_dma.driver().setup_full_duplex()?;
2252 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2253
2254 let common_length = min(read.len(), write.len());
2255 let (read_common, read_remainder) = read.split_at_mut(common_length);
2256 let (write_common, write_remainder) = write.split_at(common_length);
2257
2258 for (read_chunk, write_chunk) in read_common
2259 .chunks_mut(chunk_size)
2260 .zip(write_common.chunks(chunk_size))
2261 {
2262 self.tx_buf.as_mut_slice()[..write_chunk.len()].copy_from_slice(write_chunk);
2263
2264 unsafe {
2265 self.spi_dma.start_dma_transfer(
2266 read_chunk.len(),
2267 write_chunk.len(),
2268 &mut self.rx_buf,
2269 &mut self.tx_buf,
2270 )?;
2271 }
2272 self.wait_for_idle();
2273
2274 read_chunk.copy_from_slice(&self.rx_buf.as_slice()[..read_chunk.len()]);
2275 }
2276
2277 if !read_remainder.is_empty() {
2278 self.read(read_remainder)
2279 } else if !write_remainder.is_empty() {
2280 self.write(write_remainder)
2281 } else {
2282 Ok(())
2283 }
2284 }
2285
2286 #[instability::unstable]
2288 pub fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
2289 self.wait_for_idle();
2290 self.spi_dma.driver().setup_full_duplex()?;
2291 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2292
2293 for chunk in words.chunks_mut(chunk_size) {
2294 self.tx_buf.as_mut_slice()[..chunk.len()].copy_from_slice(chunk);
2295
2296 unsafe {
2297 self.spi_dma.start_dma_transfer(
2298 chunk.len(),
2299 chunk.len(),
2300 &mut self.rx_buf,
2301 &mut self.tx_buf,
2302 )?;
2303 }
2304 self.wait_for_idle();
2305 chunk.copy_from_slice(&self.rx_buf.as_slice()[..chunk.len()]);
2306 }
2307
2308 Ok(())
2309 }
2310
2311 #[instability::unstable]
2313 pub fn half_duplex_read(
2314 &mut self,
2315 data_mode: DataMode,
2316 cmd: Command,
2317 address: Address,
2318 dummy: u8,
2319 buffer: &mut [u8],
2320 ) -> Result<(), Error> {
2321 if buffer.len() > self.rx_buf.capacity() {
2322 return Err(Error::from(DmaError::Overflow));
2323 }
2324 self.wait_for_idle();
2325
2326 unsafe {
2327 self.spi_dma.start_half_duplex_read(
2328 data_mode,
2329 cmd,
2330 address,
2331 dummy,
2332 buffer.len(),
2333 &mut self.rx_buf,
2334 )?;
2335 }
2336
2337 self.wait_for_idle();
2338
2339 buffer.copy_from_slice(&self.rx_buf.as_slice()[..buffer.len()]);
2340
2341 Ok(())
2342 }
2343
2344 #[instability::unstable]
2346 pub fn half_duplex_write(
2347 &mut self,
2348 data_mode: DataMode,
2349 cmd: Command,
2350 address: Address,
2351 dummy: u8,
2352 buffer: &[u8],
2353 ) -> Result<(), Error> {
2354 if buffer.len() > self.tx_buf.capacity() {
2355 return Err(Error::from(DmaError::Overflow));
2356 }
2357 self.wait_for_idle();
2358 self.tx_buf.as_mut_slice()[..buffer.len()].copy_from_slice(buffer);
2359
2360 unsafe {
2361 self.spi_dma.start_half_duplex_write(
2362 data_mode,
2363 cmd,
2364 address,
2365 dummy,
2366 buffer.len(),
2367 &mut self.tx_buf,
2368 )?;
2369 }
2370
2371 self.wait_for_idle();
2372
2373 Ok(())
2374 }
2375 }
2376
2377 #[instability::unstable]
2378 impl crate::interrupt::InterruptConfigurable for SpiDmaBus<'_, Blocking> {
2379 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
2383 self.spi_dma.set_interrupt_handler(handler);
2384 }
2385 }
2386
2387 #[instability::unstable]
2388 impl<Dm> embassy_embedded_hal::SetConfig for SpiDmaBus<'_, Dm>
2389 where
2390 Dm: DriverMode,
2391 {
2392 type Config = Config;
2393 type ConfigError = ConfigError;
2394
2395 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
2396 self.apply_config(config)
2397 }
2398 }
2399
2400 mod asynch {
2402 use core::ops::{Deref, DerefMut};
2403
2404 use super::*;
2405
2406 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2407 pub(crate) struct DropGuard<I, F: FnOnce(I)> {
2408 inner: ManuallyDrop<I>,
2409 on_drop: ManuallyDrop<F>,
2410 }
2411
2412 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2413 impl<I, F: FnOnce(I)> DropGuard<I, F> {
2414 pub(crate) fn new(inner: I, on_drop: F) -> Self {
2415 Self {
2416 inner: ManuallyDrop::new(inner),
2417 on_drop: ManuallyDrop::new(on_drop),
2418 }
2419 }
2420
2421 pub(crate) fn defuse(self) {}
2422 }
2423
2424 impl<I, F: FnOnce(I)> Drop for DropGuard<I, F> {
2425 fn drop(&mut self) {
2426 let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
2427 let on_drop = unsafe { ManuallyDrop::take(&mut self.on_drop) };
2428 (on_drop)(inner)
2429 }
2430 }
2431
2432 impl<I, F: FnOnce(I)> Deref for DropGuard<I, F> {
2433 type Target = I;
2434
2435 fn deref(&self) -> &I {
2436 &self.inner
2437 }
2438 }
2439
2440 impl<I, F: FnOnce(I)> DerefMut for DropGuard<I, F> {
2441 fn deref_mut(&mut self) -> &mut I {
2442 &mut self.inner
2443 }
2444 }
2445
2446 #[instability::unstable]
2447 impl embedded_hal_async::spi::SpiBus for SpiDmaBus<'_, Async> {
2448 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2449 self.read_async(words).await
2450 }
2451
2452 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2453 self.write_async(words).await
2454 }
2455
2456 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2457 self.transfer_async(read, write).await
2458 }
2459
2460 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2461 self.transfer_in_place_async(words).await
2462 }
2463
2464 async fn flush(&mut self) -> Result<(), Self::Error> {
2465 Ok(())
2467 }
2468 }
2469 }
2470
2471 mod ehal1 {
2472 #[cfg(feature = "unstable")]
2473 use embedded_hal::spi::{ErrorType, SpiBus};
2474
2475 #[cfg(feature = "unstable")]
2476 use super::*;
2477
2478 #[instability::unstable]
2479 impl<Dm> ErrorType for SpiDmaBus<'_, Dm>
2480 where
2481 Dm: DriverMode,
2482 {
2483 type Error = Error;
2484 }
2485
2486 #[instability::unstable]
2487 impl<Dm> SpiBus for SpiDmaBus<'_, Dm>
2488 where
2489 Dm: DriverMode,
2490 {
2491 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2492 self.read(words)
2493 }
2494
2495 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2496 self.write(words)
2497 }
2498
2499 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2500 self.transfer(read, write)
2501 }
2502
2503 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2504 self.transfer_in_place(words)
2505 }
2506
2507 fn flush(&mut self) -> Result<(), Self::Error> {
2508 Ok(())
2510 }
2511 }
2512 }
2513}
2514
2515mod ehal1 {
2516 use embedded_hal::spi::SpiBus;
2517 use embedded_hal_async::spi::SpiBus as SpiBusAsync;
2518
2519 use super::*;
2520
2521 impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
2522 where
2523 Dm: DriverMode,
2524 {
2525 type Error = Error;
2526 }
2527
2528 impl<Dm> SpiBus for Spi<'_, Dm>
2529 where
2530 Dm: DriverMode,
2531 {
2532 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2533 self.driver().read(words)
2534 }
2535
2536 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2537 self.driver().write(words)
2538 }
2539
2540 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2541 if read.is_empty() {
2543 return SpiBus::write(self, write);
2544 } else if write.is_empty() {
2545 return SpiBus::read(self, read);
2546 }
2547
2548 let mut write_from = 0;
2549 let mut read_from = 0;
2550
2551 loop {
2552 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2554 let write_to = write_from + write_inc;
2555 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2557 let read_to = read_from + read_inc;
2558
2559 if (write_inc == 0) && (read_inc == 0) {
2560 break;
2561 }
2562
2563 if write_to < read_to {
2566 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2568 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2569 SpiBus::write(self, &empty)?;
2570 } else {
2571 SpiBus::write(self, &write[write_from..write_to])?;
2572 }
2573
2574 if read_inc > 0 {
2575 SpiBus::flush(self)?;
2576 self.driver()
2577 .read_from_fifo(&mut read[read_from..read_to])?;
2578 }
2579
2580 write_from = write_to;
2581 read_from = read_to;
2582 }
2583 Ok(())
2584 }
2585
2586 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2587 self.driver().transfer(words)
2588 }
2589
2590 fn flush(&mut self) -> Result<(), Self::Error> {
2591 self.driver().flush()
2592 }
2593 }
2594
2595 impl SpiBusAsync for Spi<'_, Async> {
2596 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2597 self.flush_async().await?;
2600 self.driver().setup_full_duplex()?;
2601 self.driver().read_async(words).await
2602 }
2603
2604 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2605 self.flush_async().await?;
2608 self.driver().setup_full_duplex()?;
2609 self.driver().write_async(words).await
2610 }
2611
2612 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2613 if read.is_empty() {
2615 return SpiBusAsync::write(self, write).await;
2616 } else if write.is_empty() {
2617 return SpiBusAsync::read(self, read).await;
2618 }
2619
2620 let mut write_from = 0;
2621 let mut read_from = 0;
2622
2623 loop {
2624 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2626 let write_to = write_from + write_inc;
2627 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2629 let read_to = read_from + read_inc;
2630
2631 if (write_inc == 0) && (read_inc == 0) {
2632 break;
2633 }
2634
2635 if write_to < read_to {
2638 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2640 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2641 SpiBusAsync::write(self, &empty).await?;
2642 } else {
2643 SpiBusAsync::write(self, &write[write_from..write_to]).await?;
2644 }
2645
2646 if read_inc > 0 {
2647 self.driver()
2648 .read_from_fifo(&mut read[read_from..read_to])?;
2649 }
2650
2651 write_from = write_to;
2652 read_from = read_to;
2653 }
2654 Ok(())
2655 }
2656
2657 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2658 self.transfer_in_place_async(words).await
2659 }
2660
2661 async fn flush(&mut self) -> Result<(), Self::Error> {
2662 self.flush_async().await
2663 }
2664 }
2665}
2666
2667#[doc(hidden)]
2669#[allow(private_bounds)]
2670pub trait PeripheralInstance: private::Sealed + DmaEligible {
2671 fn info(&self) -> &'static Info;
2673}
2674
2675#[doc(hidden)]
2677pub trait QspiInstance: PeripheralInstance {}
2678
2679#[doc(hidden)]
2681#[non_exhaustive]
2682pub struct Info {
2683 pub register_block: *const RegisterBlock,
2687
2688 pub peripheral: crate::system::Peripheral,
2690
2691 pub interrupt: crate::peripherals::Interrupt,
2693
2694 pub sclk: OutputSignal,
2696
2697 pub mosi: OutputSignal,
2699
2700 pub miso: InputSignal,
2702
2703 pub cs: &'static [OutputSignal],
2705
2706 pub sio0_input: InputSignal,
2708
2709 pub sio1_output: OutputSignal,
2711
2712 pub sio2_output: Option<OutputSignal>,
2714
2715 pub sio2_input: Option<InputSignal>,
2717
2718 pub sio3_output: Option<OutputSignal>,
2720
2721 pub sio3_input: Option<InputSignal>,
2723
2724 #[cfg(spi_octal)]
2726 pub sio4_output: Option<OutputSignal>,
2727
2728 #[cfg(spi_octal)]
2730 pub sio4_input: Option<InputSignal>,
2731
2732 #[cfg(spi_octal)]
2734 pub sio5_output: Option<OutputSignal>,
2735
2736 #[cfg(spi_octal)]
2738 pub sio5_input: Option<InputSignal>,
2739
2740 #[cfg(spi_octal)]
2742 pub sio6_output: Option<OutputSignal>,
2743
2744 #[cfg(spi_octal)]
2746 pub sio6_input: Option<InputSignal>,
2747
2748 #[cfg(spi_octal)]
2750 pub sio7_output: Option<OutputSignal>,
2751
2752 #[cfg(spi_octal)]
2754 pub sio7_input: Option<InputSignal>,
2755}
2756
2757struct DmaDriver {
2758 driver: Driver,
2759 dma_peripheral: crate::dma::DmaPeripheral,
2760}
2761
2762impl DmaDriver {
2763 fn abort_transfer(&self) {
2764 self.driver.configure_datalen(1, 1);
2765 self.driver.update();
2766 }
2767
2768 fn regs(&self) -> &RegisterBlock {
2769 self.driver.regs()
2770 }
2771
2772 #[allow(clippy::too_many_arguments)]
2773 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
2774 unsafe fn start_transfer_dma<Dm: DriverMode>(
2775 &self,
2776 _full_duplex: bool,
2777 rx_len: usize,
2778 tx_len: usize,
2779 rx_buffer: &mut impl DmaRxBuffer,
2780 tx_buffer: &mut impl DmaTxBuffer,
2781 channel: &mut Channel<Dm, PeripheralDmaChannel<AnySpi<'_>>>,
2782 ) -> Result<(), Error> {
2783 #[cfg(esp32s2)]
2784 {
2785 self.regs().dma_out_link().write(|w| unsafe { w.bits(0) });
2787 self.regs().dma_in_link().write(|w| unsafe { w.bits(0) });
2788 }
2789
2790 self.driver.configure_datalen(rx_len, tx_len);
2791
2792 self.regs()
2794 .user()
2795 .modify(|_, w| w.usr_miso().bit(rx_len > 0).usr_mosi().bit(tx_len > 0));
2796
2797 self.enable_dma();
2798
2799 if rx_len > 0 {
2800 unsafe {
2801 channel
2802 .rx
2803 .prepare_transfer(self.dma_peripheral, rx_buffer)
2804 .and_then(|_| channel.rx.start_transfer())?;
2805 }
2806 } else {
2807 #[cfg(esp32)]
2808 {
2809 if _full_duplex {
2812 self.regs()
2813 .dma_in_link()
2814 .modify(|_, w| unsafe { w.inlink_addr().bits(0) });
2815 self.regs()
2816 .dma_in_link()
2817 .modify(|_, w| w.inlink_start().set_bit());
2818 }
2819 }
2820 }
2821 if tx_len > 0 {
2822 unsafe {
2823 channel
2824 .tx
2825 .prepare_transfer(self.dma_peripheral, tx_buffer)
2826 .and_then(|_| channel.tx.start_transfer())?;
2827 }
2828 }
2829
2830 #[cfg(gdma)]
2831 self.reset_dma();
2832
2833 self.driver.start_operation();
2834
2835 Ok(())
2836 }
2837
2838 fn enable_dma(&self) {
2839 #[cfg(gdma)]
2840 self.regs().dma_conf().modify(|_, w| {
2842 w.dma_tx_ena().set_bit();
2843 w.dma_rx_ena().set_bit()
2844 });
2845
2846 #[cfg(pdma)]
2847 self.reset_dma();
2848 }
2849
2850 fn reset_dma(&self) {
2851 fn set_reset_bit(reg_block: &RegisterBlock, bit: bool) {
2852 #[cfg(pdma)]
2853 reg_block.dma_conf().modify(|_, w| {
2854 w.out_rst().bit(bit);
2855 w.in_rst().bit(bit);
2856 w.ahbm_fifo_rst().bit(bit);
2857 w.ahbm_rst().bit(bit)
2858 });
2859 #[cfg(gdma)]
2860 reg_block.dma_conf().modify(|_, w| {
2861 w.rx_afifo_rst().bit(bit);
2862 w.buf_afifo_rst().bit(bit);
2863 w.dma_afifo_rst().bit(bit)
2864 });
2865 }
2866
2867 set_reset_bit(self.regs(), true);
2868 set_reset_bit(self.regs(), false);
2869 self.clear_dma_interrupts();
2870 }
2871
2872 #[cfg(gdma)]
2873 fn clear_dma_interrupts(&self) {
2874 self.regs().dma_int_clr().write(|w| {
2875 w.dma_infifo_full_err().clear_bit_by_one();
2876 w.dma_outfifo_empty_err().clear_bit_by_one();
2877 w.trans_done().clear_bit_by_one();
2878 w.mst_rx_afifo_wfull_err().clear_bit_by_one();
2879 w.mst_tx_afifo_rempty_err().clear_bit_by_one()
2880 });
2881 }
2882
2883 #[cfg(pdma)]
2884 fn clear_dma_interrupts(&self) {
2885 self.regs().dma_int_clr().write(|w| {
2886 w.inlink_dscr_empty().clear_bit_by_one();
2887 w.outlink_dscr_error().clear_bit_by_one();
2888 w.inlink_dscr_error().clear_bit_by_one();
2889 w.in_done().clear_bit_by_one();
2890 w.in_err_eof().clear_bit_by_one();
2891 w.in_suc_eof().clear_bit_by_one();
2892 w.out_done().clear_bit_by_one();
2893 w.out_eof().clear_bit_by_one();
2894 w.out_total_eof().clear_bit_by_one()
2895 });
2896 }
2897}
2898
2899struct Driver {
2900 info: &'static Info,
2901 state: &'static State,
2902}
2903
2904impl Driver {
2907 pub fn regs(&self) -> &RegisterBlock {
2909 unsafe { &*self.info.register_block }
2910 }
2911
2912 fn abort_transfer(&self) {
2913 cfg_if::cfg_if! {
2918 if #[cfg(esp32)] {
2919 self.regs().slave().modify(|_, w| w.mode().set_bit());
2920 self.regs().slave().modify(|_, w| w.mode().clear_bit());
2921 } else {
2922 self.configure_datalen(1, 1);
2923 }
2924 }
2925 self.update();
2926 }
2927
2928 fn init(&self) {
2930 self.regs().user().modify(|_, w| {
2931 w.usr_miso_highpart().clear_bit();
2932 w.usr_mosi_highpart().clear_bit();
2933 w.doutdin().set_bit();
2934 w.usr_miso().set_bit();
2935 w.usr_mosi().set_bit();
2936 w.cs_hold().set_bit();
2937 w.usr_dummy_idle().set_bit();
2938 w.usr_addr().clear_bit();
2939 w.usr_command().clear_bit()
2940 });
2941
2942 #[cfg(gdma)]
2943 self.regs().clk_gate().modify(|_, w| {
2944 w.clk_en().set_bit();
2945 w.mst_clk_active().set_bit();
2946 w.mst_clk_sel().set_bit()
2947 });
2948
2949 #[cfg(any(esp32c6, esp32h2))]
2950 unsafe {
2951 crate::peripherals::PCR::regs()
2954 .spi2_clkm_conf()
2955 .modify(|_, w| w.spi2_clkm_sel().bits(1));
2956 }
2957
2958 #[cfg(gdma)]
2959 self.regs().ctrl().modify(|_, w| {
2960 w.q_pol().clear_bit();
2961 w.d_pol().clear_bit();
2962 w.hold_pol().clear_bit()
2963 });
2964
2965 #[cfg(esp32s2)]
2966 self.regs().ctrl().modify(|_, w| {
2967 w.q_pol().clear_bit();
2968 w.d_pol().clear_bit();
2969 w.wp().clear_bit()
2970 });
2971
2972 #[cfg(esp32)]
2973 self.regs().ctrl().modify(|_, w| w.wp().clear_bit());
2974
2975 #[cfg(not(esp32))]
2976 self.regs().misc().write(|w| unsafe { w.bits(0) });
2977
2978 self.regs().slave().write(|w| unsafe { w.bits(0) });
2979 }
2980
2981 #[cfg(not(esp32))]
2982 fn init_spi_data_mode(
2983 &self,
2984 cmd_mode: DataMode,
2985 address_mode: DataMode,
2986 data_mode: DataMode,
2987 ) -> Result<(), Error> {
2988 self.regs().ctrl().modify(|_, w| {
2989 w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
2990 w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
2991 w.faddr_dual().bit(address_mode == DataMode::Dual);
2992 w.faddr_quad().bit(address_mode == DataMode::Quad);
2993 w.fread_dual().bit(data_mode == DataMode::Dual);
2994 w.fread_quad().bit(data_mode == DataMode::Quad)
2995 });
2996 self.regs().user().modify(|_, w| {
2997 w.fwrite_dual().bit(data_mode == DataMode::Dual);
2998 w.fwrite_quad().bit(data_mode == DataMode::Quad)
2999 });
3000 Ok(())
3001 }
3002
3003 #[cfg(esp32)]
3004 fn init_spi_data_mode(
3005 &self,
3006 cmd_mode: DataMode,
3007 address_mode: DataMode,
3008 data_mode: DataMode,
3009 ) -> Result<(), Error> {
3010 match cmd_mode {
3011 DataMode::Single => (),
3012 DataMode::SingleTwoDataLines => (),
3013 _ => {
3015 error!("Commands must be single bit wide");
3016 return Err(Error::Unsupported);
3017 }
3018 }
3019
3020 match address_mode {
3021 DataMode::Single | DataMode::SingleTwoDataLines => {
3022 self.regs().ctrl().modify(|_, w| {
3023 w.fastrd_mode()
3024 .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3025 w.fread_dio().clear_bit();
3026 w.fread_qio().clear_bit();
3027 w.fread_dual().bit(data_mode == DataMode::Dual);
3028 w.fread_quad().bit(data_mode == DataMode::Quad)
3029 });
3030
3031 self.regs().user().modify(|_, w| {
3032 w.fwrite_dio().clear_bit();
3033 w.fwrite_qio().clear_bit();
3034 w.fwrite_dual().bit(data_mode == DataMode::Dual);
3035 w.fwrite_quad().bit(data_mode == DataMode::Quad)
3036 });
3037 }
3038 address_mode if address_mode == data_mode => {
3039 self.regs().ctrl().modify(|_, w| {
3040 w.fastrd_mode()
3041 .bit(matches!(data_mode, DataMode::Dual | DataMode::Quad));
3042 w.fread_dio().bit(address_mode == DataMode::Dual);
3043 w.fread_qio().bit(address_mode == DataMode::Quad);
3044 w.fread_dual().clear_bit();
3045 w.fread_quad().clear_bit()
3046 });
3047
3048 self.regs().user().modify(|_, w| {
3049 w.fwrite_dio().bit(address_mode == DataMode::Dual);
3050 w.fwrite_qio().bit(address_mode == DataMode::Quad);
3051 w.fwrite_dual().clear_bit();
3052 w.fwrite_quad().clear_bit()
3053 });
3054 }
3055 _ => {
3056 error!("Address mode must be single bit wide or equal to the data mode");
3058 return Err(Error::Unsupported);
3059 }
3060 }
3061
3062 Ok(())
3063 }
3064
3065 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3067 fn enable_listen(&self, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
3068 cfg_if::cfg_if! {
3069 if #[cfg(esp32)] {
3070 self.regs().slave().modify(|_, w| {
3071 for interrupt in interrupts {
3072 match interrupt {
3073 SpiInterrupt::TransferDone => w.trans_inten().bit(enable),
3074 };
3075 }
3076 w
3077 });
3078 } else if #[cfg(esp32s2)] {
3079 self.regs().slave().modify(|_, w| {
3080 for interrupt in interrupts {
3081 match interrupt {
3082 SpiInterrupt::TransferDone => w.int_trans_done_en().bit(enable),
3083 SpiInterrupt::DmaSegmentedTransferDone => w.int_dma_seg_trans_en().bit(enable),
3084 };
3085 }
3086 w
3087 });
3088 } else {
3089 self.regs().dma_int_ena().modify(|_, w| {
3090 for interrupt in interrupts {
3091 match interrupt {
3092 SpiInterrupt::TransferDone => w.trans_done().bit(enable),
3093 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
3094 SpiInterrupt::App2 => w.app2().bit(enable),
3095 SpiInterrupt::App1 => w.app1().bit(enable),
3096 };
3097 }
3098 w
3099 });
3100 }
3101 }
3102 }
3103
3104 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3106 fn interrupts(&self) -> EnumSet<SpiInterrupt> {
3107 let mut res = EnumSet::new();
3108
3109 cfg_if::cfg_if! {
3110 if #[cfg(esp32)] {
3111 if self.regs().slave().read().trans_done().bit() {
3112 res.insert(SpiInterrupt::TransferDone);
3113 }
3114 } else if #[cfg(esp32s2)] {
3115 if self.regs().slave().read().trans_done().bit() {
3116 res.insert(SpiInterrupt::TransferDone);
3117 }
3118 if self.regs().hold().read().dma_seg_trans_done().bit() {
3119 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3120 }
3121 } else {
3122 let ints = self.regs().dma_int_raw().read();
3123
3124 if ints.trans_done().bit() {
3125 res.insert(SpiInterrupt::TransferDone);
3126 }
3127 if ints.dma_seg_trans_done().bit() {
3128 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3129 }
3130 if ints.app2().bit() {
3131 res.insert(SpiInterrupt::App2);
3132 }
3133 if ints.app1().bit() {
3134 res.insert(SpiInterrupt::App1);
3135 }
3136 }
3137 }
3138
3139 res
3140 }
3141
3142 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3144 fn clear_interrupts(&self, interrupts: EnumSet<SpiInterrupt>) {
3145 cfg_if::cfg_if! {
3146 if #[cfg(esp32)] {
3147 for interrupt in interrupts {
3148 match interrupt {
3149 SpiInterrupt::TransferDone => {
3150 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3151 }
3152 }
3153 }
3154 } else if #[cfg(esp32s2)] {
3155 for interrupt in interrupts {
3156 match interrupt {
3157 SpiInterrupt::TransferDone => {
3158 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3159 }
3160
3161 SpiInterrupt::DmaSegmentedTransferDone => {
3162 self.regs()
3163 .hold()
3164 .modify(|_, w| w.dma_seg_trans_done().clear_bit());
3165 }
3166 }
3167 }
3168 } else {
3169 self.regs().dma_int_clr().write(|w| {
3170 for interrupt in interrupts {
3171 match interrupt {
3172 SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
3173 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
3174 SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
3175 SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
3176 };
3177 }
3178 w
3179 });
3180 }
3181 }
3182 }
3183
3184 fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
3185 config.validate()?;
3186 self.ch_bus_freq(config)?;
3187 self.set_bit_order(config.read_bit_order, config.write_bit_order);
3188 self.set_data_mode(config.mode);
3189
3190 #[cfg(esp32)]
3191 self.calculate_half_duplex_values(config);
3192
3193 Ok(())
3194 }
3195
3196 #[cfg(esp32)]
3197 fn calculate_half_duplex_values(&self, config: &Config) {
3198 let f_apb = 80_000_000;
3199 let source_freq_hz = match config.clock_source {
3200 ClockSource::Apb => f_apb,
3201 };
3202
3203 let clock_reg = self.regs().clock().read();
3204 let eff_clk = if clock_reg.clk_equ_sysclk().bit_is_set() {
3205 f_apb
3206 } else {
3207 let pre = clock_reg.clkdiv_pre().bits() as i32 + 1;
3208 let n = clock_reg.clkcnt_n().bits() as i32 + 1;
3209 f_apb / (pre * n)
3210 };
3211
3212 let apbclk_khz = source_freq_hz / 1000;
3213 let spiclk_apb_n = source_freq_hz / eff_clk;
3215
3216 let input_delay_ns = 25; let delay_apb_n = (1 + input_delay_ns) * apbclk_khz / 1000 / 1000;
3221
3222 let dummy_required = delay_apb_n / spiclk_apb_n;
3223 let timing_miso_delay = if dummy_required > 0 {
3224 Some(((dummy_required + 1) * spiclk_apb_n - delay_apb_n - 1) as u8)
3228 } else if delay_apb_n * 4 <= spiclk_apb_n {
3229 None
3232 } else {
3233 Some(0)
3234 };
3235
3236 self.state.esp32_hack.extra_dummy.set(dummy_required as u8);
3237 self.state
3238 .esp32_hack
3239 .timing_miso_delay
3240 .set(timing_miso_delay);
3241 }
3242
3243 fn set_data_mode(&self, data_mode: Mode) {
3244 cfg_if::cfg_if! {
3245 if #[cfg(esp32)] {
3246 let pin_reg = self.regs().pin();
3247 } else {
3248 let pin_reg = self.regs().misc();
3249 }
3250 };
3251
3252 pin_reg.modify(|_, w| {
3253 w.ck_idle_edge()
3254 .bit(matches!(data_mode, Mode::_2 | Mode::_3))
3255 });
3256 self.regs().user().modify(|_, w| {
3257 w.ck_out_edge()
3258 .bit(matches!(data_mode, Mode::_1 | Mode::_2))
3259 });
3260 }
3261
3262 fn ch_bus_freq(&self, bus_clock_config: &Config) -> Result<(), ConfigError> {
3263 fn enable_clocks(_reg_block: &RegisterBlock, _enable: bool) {
3264 #[cfg(gdma)]
3265 _reg_block.clk_gate().modify(|_, w| {
3266 w.clk_en().bit(_enable);
3267 w.mst_clk_active().bit(_enable);
3268 w.mst_clk_sel().bit(true) });
3270 }
3271
3272 let raw = bus_clock_config.raw_clock_reg_value()?;
3274
3275 enable_clocks(self.regs(), false);
3276 self.regs().clock().write(|w| unsafe { w.bits(raw) });
3277 enable_clocks(self.regs(), true);
3278
3279 Ok(())
3280 }
3281
3282 #[cfg(not(any(esp32, esp32c3, esp32s2)))]
3283 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3284 let read_value = match read_order {
3285 BitOrder::MsbFirst => 0,
3286 BitOrder::LsbFirst => 1,
3287 };
3288 let write_value = match write_order {
3289 BitOrder::MsbFirst => 0,
3290 BitOrder::LsbFirst => 1,
3291 };
3292 self.regs().ctrl().modify(|_, w| unsafe {
3293 w.rd_bit_order().bits(read_value);
3294 w.wr_bit_order().bits(write_value);
3295 w
3296 });
3297 }
3298
3299 #[cfg(any(esp32, esp32c3, esp32s2))]
3300 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3301 let read_value = match read_order {
3302 BitOrder::MsbFirst => false,
3303 BitOrder::LsbFirst => true,
3304 };
3305 let write_value = match write_order {
3306 BitOrder::MsbFirst => false,
3307 BitOrder::LsbFirst => true,
3308 };
3309 self.regs().ctrl().modify(|_, w| {
3310 w.rd_bit_order().bit(read_value);
3311 w.wr_bit_order().bit(write_value);
3312 w
3313 });
3314 }
3315
3316 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3317 fn fill_fifo(&self, chunk: &[u8]) {
3318 let mut c_iter = chunk.chunks_exact(4);
3320 let mut w_iter = self.regs().w_iter();
3321 for c in c_iter.by_ref() {
3322 if let Some(w_reg) = w_iter.next() {
3323 let word = (c[0] as u32)
3324 | ((c[1] as u32) << 8)
3325 | ((c[2] as u32) << 16)
3326 | ((c[3] as u32) << 24);
3327 w_reg.write(|w| w.buf().set(word));
3328 }
3329 }
3330 let rem = c_iter.remainder();
3331 if !rem.is_empty() {
3332 if let Some(w_reg) = w_iter.next() {
3333 let word = match rem.len() {
3334 3 => (rem[0] as u32) | ((rem[1] as u32) << 8) | ((rem[2] as u32) << 16),
3335 2 => (rem[0] as u32) | ((rem[1] as u32) << 8),
3336 1 => rem[0] as u32,
3337 _ => unreachable!(),
3338 };
3339 w_reg.write(|w| w.buf().set(word));
3340 }
3341 }
3342 }
3343
3344 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3350 fn write(&self, words: &[u8]) -> Result<(), Error> {
3351 let num_chunks = words.len() / FIFO_SIZE;
3352
3353 self.flush()?;
3356
3357 for (i, chunk) in words.chunks(FIFO_SIZE).enumerate() {
3360 self.configure_datalen(0, chunk.len());
3361 self.fill_fifo(chunk);
3362
3363 self.start_operation();
3364
3365 if i < num_chunks {
3369 self.flush()?;
3370 }
3371 }
3372 Ok(())
3373 }
3374
3375 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3377 async fn write_async(&self, words: &[u8]) -> Result<(), Error> {
3378 for chunk in words.chunks(FIFO_SIZE) {
3381 self.configure_datalen(0, chunk.len());
3382 self.fill_fifo(chunk);
3383 self.execute_operation_async().await;
3384 }
3385 Ok(())
3386 }
3387
3388 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3394 fn read(&self, words: &mut [u8]) -> Result<(), Error> {
3395 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3396
3397 for chunk in words.chunks_mut(FIFO_SIZE) {
3398 self.write(&empty_array[0..chunk.len()])?;
3399 self.flush()?;
3400 self.read_from_fifo(chunk)?;
3401 }
3402 Ok(())
3403 }
3404
3405 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3411 async fn read_async(&self, words: &mut [u8]) -> Result<(), Error> {
3412 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3413
3414 for chunk in words.chunks_mut(FIFO_SIZE) {
3415 self.write_async(&empty_array[0..chunk.len()]).await?;
3416 self.read_from_fifo(chunk)?;
3417 }
3418 Ok(())
3419 }
3420
3421 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3428 fn read_from_fifo(&self, words: &mut [u8]) -> Result<(), Error> {
3429 let reg_block = self.regs();
3430
3431 for chunk in words.chunks_mut(FIFO_SIZE) {
3432 self.configure_datalen(chunk.len(), 0);
3433
3434 for (index, w_reg) in (0..chunk.len()).step_by(4).zip(reg_block.w_iter()) {
3435 let reg_val = w_reg.read().bits();
3436 let bytes = reg_val.to_le_bytes();
3437
3438 let len = usize::min(chunk.len(), index + 4) - index;
3439 chunk[index..(index + len)].clone_from_slice(&bytes[0..len]);
3440 }
3441 }
3442
3443 Ok(())
3444 }
3445
3446 fn busy(&self) -> bool {
3447 self.regs().cmd().read().usr().bit_is_set()
3448 }
3449
3450 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3452 async fn flush_async(&self) -> Result<(), Error> {
3453 if self.busy() {
3454 let future = SpiFuture::setup(self).await;
3455 future.await;
3456 }
3457
3458 Ok(())
3459 }
3460
3461 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3463 fn flush(&self) -> Result<(), Error> {
3464 while self.busy() {
3465 }
3467 Ok(())
3468 }
3469
3470 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3471 fn transfer(&self, words: &mut [u8]) -> Result<(), Error> {
3472 for chunk in words.chunks_mut(FIFO_SIZE) {
3473 self.write(chunk)?;
3474 self.flush()?;
3475 self.read_from_fifo(chunk)?;
3476 }
3477
3478 Ok(())
3479 }
3480
3481 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3482 async fn transfer_in_place_async(&self, words: &mut [u8]) -> Result<(), Error> {
3483 for chunk in words.chunks_mut(FIFO_SIZE) {
3484 let cancel_on_drop = OnDrop::new(|| {
3487 self.abort_transfer();
3488 while self.busy() {}
3489 });
3490 let res = self.write_async(chunk).await;
3491 cancel_on_drop.defuse();
3492 res?;
3493
3494 self.read_from_fifo(chunk)?;
3495 }
3496
3497 Ok(())
3498 }
3499
3500 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3501 fn start_operation(&self) {
3502 self.update();
3503 self.regs().cmd().modify(|_, w| w.usr().set_bit());
3504 }
3505
3506 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3508 async fn execute_operation_async(&self) {
3509 let future = SpiFuture::setup(self).await;
3512 self.start_operation();
3513 future.await;
3514 }
3515
3516 fn setup_full_duplex(&self) -> Result<(), Error> {
3517 self.regs().user().modify(|_, w| {
3518 w.usr_miso().set_bit();
3519 w.usr_mosi().set_bit();
3520 w.doutdin().set_bit();
3521 w.usr_dummy().clear_bit();
3522 w.sio().clear_bit()
3523 });
3524
3525 self.init_spi_data_mode(
3526 DataMode::SingleTwoDataLines,
3527 DataMode::SingleTwoDataLines,
3528 DataMode::SingleTwoDataLines,
3529 )?;
3530
3531 #[cfg(esp32)]
3533 self.regs().ctrl2().modify(|_, w| unsafe {
3534 w.miso_delay_mode().bits(0);
3535 w.miso_delay_num().bits(0)
3536 });
3537
3538 Ok(())
3539 }
3540
3541 #[allow(clippy::too_many_arguments)]
3542 fn setup_half_duplex(
3543 &self,
3544 is_write: bool,
3545 cmd: Command,
3546 address: Address,
3547 dummy_idle: bool,
3548 dummy: u8,
3549 no_mosi_miso: bool,
3550 data_mode: DataMode,
3551 ) -> Result<(), Error> {
3552 self.init_spi_data_mode(cmd.mode(), address.mode(), data_mode)?;
3553
3554 #[cfg(esp32)]
3555 let mut dummy = dummy;
3556
3557 #[cfg(esp32)]
3558 self.regs().ctrl2().modify(|_, w| {
3559 let mut delay_mode = 0;
3560 let mut delay_num = 0;
3561
3562 if !is_write {
3563 let timing_miso_delay = self.state.esp32_hack.timing_miso_delay.get();
3565 let extra_dummy = self.state.esp32_hack.extra_dummy.get();
3566 dummy += extra_dummy;
3567
3568 if let Some(delay) = timing_miso_delay {
3569 delay_num = if extra_dummy > 0 { delay } else { 0 };
3570 } else {
3571 let out_edge = self.regs().user().read().ck_out_edge().bit_is_set();
3572 delay_mode = if out_edge { 1 } else { 2 };
3574 }
3575 }
3576
3577 unsafe {
3578 w.miso_delay_mode().bits(delay_mode);
3579 w.miso_delay_num().bits(delay_num)
3580 }
3581 });
3582
3583 let reg_block = self.regs();
3584 reg_block.user().modify(|_, w| {
3585 w.usr_miso_highpart().clear_bit();
3586 w.usr_mosi_highpart().clear_bit();
3587 w.sio().bit(data_mode == DataMode::Single);
3589 w.doutdin().clear_bit();
3590 w.usr_miso().bit(!is_write && !no_mosi_miso);
3591 w.usr_mosi().bit(is_write && !no_mosi_miso);
3592 w.cs_hold().set_bit();
3593 w.usr_dummy_idle().bit(dummy_idle);
3594 w.usr_dummy().bit(dummy != 0);
3595 w.usr_addr().bit(!address.is_none());
3596 w.usr_command().bit(!cmd.is_none())
3597 });
3598
3599 #[cfg(gdma)]
3600 reg_block.clk_gate().modify(|_, w| {
3601 w.clk_en().set_bit();
3602 w.mst_clk_active().set_bit();
3603 w.mst_clk_sel().set_bit()
3604 });
3605
3606 #[cfg(any(esp32c6, esp32h2))]
3607 crate::peripherals::PCR::regs()
3609 .spi2_clkm_conf()
3610 .modify(|_, w| unsafe { w.spi2_clkm_sel().bits(1) });
3611
3612 #[cfg(not(esp32))]
3613 reg_block.misc().write(|w| unsafe { w.bits(0) });
3614
3615 reg_block.slave().write(|w| unsafe { w.bits(0) });
3616
3617 self.update();
3618
3619 self.set_up_common_phases(cmd, address, dummy);
3621
3622 Ok(())
3623 }
3624
3625 fn set_up_common_phases(&self, cmd: Command, address: Address, dummy: u8) {
3626 let reg_block = self.regs();
3627 if !cmd.is_none() {
3628 reg_block.user2().modify(|_, w| unsafe {
3629 w.usr_command_bitlen().bits((cmd.width() - 1) as u8);
3630 w.usr_command_value().bits(cmd.value())
3631 });
3632 }
3633
3634 if !address.is_none() {
3635 reg_block
3636 .user1()
3637 .modify(|_, w| unsafe { w.usr_addr_bitlen().bits((address.width() - 1) as u8) });
3638
3639 let addr = address.value() << (32 - address.width());
3640 #[cfg(not(esp32))]
3641 reg_block
3642 .addr()
3643 .write(|w| unsafe { w.usr_addr_value().bits(addr) });
3644 #[cfg(esp32)]
3645 reg_block.addr().write(|w| unsafe { w.bits(addr) });
3646 }
3647
3648 if dummy > 0 {
3649 reg_block
3650 .user1()
3651 .modify(|_, w| unsafe { w.usr_dummy_cyclelen().bits(dummy - 1) });
3652 }
3653 }
3654
3655 fn update(&self) {
3656 cfg_if::cfg_if! {
3657 if #[cfg(gdma)] {
3658 let reg_block = self.regs();
3659
3660 reg_block.cmd().modify(|_, w| w.update().set_bit());
3661
3662 while reg_block.cmd().read().update().bit_is_set() {
3663 }
3665 } else {
3666 }
3668 }
3669 }
3670
3671 fn configure_datalen(&self, rx_len_bytes: usize, tx_len_bytes: usize) {
3672 let reg_block = self.regs();
3673
3674 let rx_len = rx_len_bytes as u32 * 8;
3675 let tx_len = tx_len_bytes as u32 * 8;
3676
3677 let rx_len = rx_len.saturating_sub(1);
3678 let tx_len = tx_len.saturating_sub(1);
3679
3680 cfg_if::cfg_if! {
3681 if #[cfg(esp32)] {
3682 let len = rx_len.max(tx_len);
3683 reg_block
3684 .mosi_dlen()
3685 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(len) });
3686
3687 reg_block
3688 .miso_dlen()
3689 .write(|w| unsafe { w.usr_miso_dbitlen().bits(len) });
3690 } else if #[cfg(esp32s2)] {
3691 reg_block
3692 .mosi_dlen()
3693 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(tx_len) });
3694
3695 reg_block
3696 .miso_dlen()
3697 .write(|w| unsafe { w.usr_miso_dbitlen().bits(rx_len) });
3698 } else {
3699 reg_block
3700 .ms_dlen()
3701 .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
3702 }
3703
3704 }
3705 }
3706}
3707
3708impl PartialEq for Info {
3709 fn eq(&self, other: &Self) -> bool {
3710 core::ptr::eq(self.register_block, other.register_block)
3711 }
3712}
3713
3714unsafe impl Sync for Info {}
3715
3716macro_rules! spi_instance {
3720 ($num:literal, $sclk:ident, $mosi:ident, $miso:ident, [$($cs:ident),+] $(, $sio2:ident, $sio3:ident $(, $sio4:ident, $sio5:ident, $sio6:ident, $sio7:ident)?)?) => {
3721 paste::paste! {
3722 impl PeripheralInstance for crate::peripherals::[<SPI $num>]<'_> {
3723 #[inline(always)]
3724 fn info(&self) -> &'static Info {
3725 static INFO: Info = Info {
3726 register_block: crate::peripherals::[<SPI $num>]::regs(),
3727 peripheral: crate::system::Peripheral::[<Spi $num>],
3728 interrupt: crate::peripherals::Interrupt::[<SPI $num>],
3729 sclk: OutputSignal::$sclk,
3730 mosi: OutputSignal::$mosi,
3731 miso: InputSignal::$miso,
3732 cs: &[$(OutputSignal::$cs),+],
3733 sio0_input: InputSignal::$mosi,
3734 sio1_output: OutputSignal::$miso,
3735 sio2_output: $crate::if_set!($(Some(OutputSignal::$sio2))?, None),
3736 sio2_input: $crate::if_set!($(Some(InputSignal::$sio2))?, None),
3737 sio3_output: $crate::if_set!($(Some(OutputSignal::$sio3))?, None),
3738 sio3_input: $crate::if_set!($(Some(InputSignal::$sio3))?, None),
3739 #[cfg(spi_octal)]
3740 sio4_output: $crate::if_set!($($(Some(OutputSignal::$sio4))?)?, None),
3741 #[cfg(spi_octal)]
3742 sio4_input: $crate::if_set!($($(Some(InputSignal::$sio4))?)?, None),
3743 #[cfg(spi_octal)]
3744 sio5_output: $crate::if_set!($($(Some(OutputSignal::$sio5))?)?, None),
3745 #[cfg(spi_octal)]
3746 sio5_input: $crate::if_set!($($(Some(InputSignal::$sio5))?)?, None),
3747 #[cfg(spi_octal)]
3748 sio6_output: $crate::if_set!($($(Some(OutputSignal::$sio6))?)?, None),
3749 #[cfg(spi_octal)]
3750 sio6_input: $crate::if_set!($($(Some(InputSignal::$sio6))?)?, None),
3751 #[cfg(spi_octal)]
3752 sio7_output: $crate::if_set!($($(Some(OutputSignal::$sio7))?)?, None),
3753 #[cfg(spi_octal)]
3754 sio7_input: $crate::if_set!($($(Some(InputSignal::$sio7))?)?, None),
3755 };
3756
3757 &INFO
3758 }
3759 }
3760
3761 $(
3762 $crate::ignore!($sio2);
3764 impl QspiInstance for crate::peripherals::[<SPI $num>]<'_> {}
3765 )?
3766 }
3767 }
3768}
3769
3770#[cfg(spi2)]
3771cfg_if::cfg_if! {
3772 if #[cfg(esp32)] {
3773 spi_instance!(2, HSPICLK, HSPID, HSPIQ, [HSPICS0, HSPICS1, HSPICS2], HSPIWP, HSPIHD);
3774 } else if #[cfg(any(esp32s2, esp32s3))] {
3775 spi_instance!(2, FSPICLK, FSPID, FSPIQ, [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5], FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7);
3776 } else {
3777 spi_instance!(2, FSPICLK_MUX, FSPID, FSPIQ, [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5], FSPIWP, FSPIHD);
3778 }
3779}
3780
3781#[cfg(spi3)]
3782cfg_if::cfg_if! {
3783 if #[cfg(esp32)] {
3784 spi_instance!(3, VSPICLK, VSPID, VSPIQ, [VSPICS0, VSPICS1, VSPICS2], VSPIWP, VSPIHD);
3785 } else if #[cfg(esp32s3)] {
3786 spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, [SPI3_CS0, SPI3_CS1, SPI3_CS2], SPI3_WP, SPI3_HD);
3787 } else {
3788 spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, [SPI3_CS0, SPI3_CS1, SPI3_CS2]);
3789 }
3790}
3791
3792impl PeripheralInstance for super::AnySpi<'_> {
3793 delegate::delegate! {
3794 to match &self.0 {
3795 super::AnySpiInner::Spi2(spi) => spi,
3796 #[cfg(spi3)]
3797 super::AnySpiInner::Spi3(spi) => spi,
3798 } {
3799 fn info(&self) -> &'static Info;
3800 }
3801 }
3802}
3803
3804impl QspiInstance for super::AnySpi<'_> {}
3805
3806#[doc(hidden)]
3807pub struct State {
3808 waker: AtomicWaker,
3809
3810 #[cfg(esp32)]
3811 esp32_hack: Esp32Hack,
3812}
3813
3814#[cfg(esp32)]
3815struct Esp32Hack {
3816 timing_miso_delay: Cell<Option<u8>>,
3817 extra_dummy: Cell<u8>,
3818}
3819
3820#[cfg(esp32)]
3821unsafe impl Sync for Esp32Hack {}
3822
3823#[cfg_attr(place_spi_master_driver_in_ram, ram)]
3824fn handle_async(instance: impl Instance) {
3825 let state = instance.state();
3826 let info = instance.info();
3827
3828 let driver = Driver { info, state };
3829 if driver.interrupts().contains(SpiInterrupt::TransferDone) {
3830 driver.enable_listen(SpiInterrupt::TransferDone.into(), false);
3831 state.waker.wake();
3832 }
3833}
3834
3835pub trait Instance: PeripheralInstance + super::IntoAnySpi {
3837 #[doc(hidden)]
3838 fn state(&self) -> &'static State;
3839 #[doc(hidden)]
3840 fn handler(&self) -> InterruptHandler;
3841}
3842
3843macro_rules! master_instance {
3844 ($peri:ident) => {
3845 impl Instance for $crate::peripherals::$peri<'_> {
3846 fn state(&self) -> &'static State {
3847 static STATE: State = State {
3848 waker: AtomicWaker::new(),
3849 #[cfg(esp32)]
3850 esp32_hack: Esp32Hack {
3851 timing_miso_delay: Cell::new(None),
3852 extra_dummy: Cell::new(0),
3853 },
3854 };
3855
3856 &STATE
3857 }
3858
3859 fn handler(&self) -> InterruptHandler {
3860 #[$crate::handler]
3861 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3862 fn handle() {
3863 handle_async(unsafe { $crate::peripherals::$peri::steal() })
3864 }
3865
3866 handle
3867 }
3868 }
3869 };
3870}
3871
3872master_instance!(SPI2);
3873#[cfg(spi3)]
3874master_instance!(SPI3);
3875
3876impl Instance for super::AnySpi<'_> {
3877 delegate::delegate! {
3878 to match &self.0 {
3879 super::AnySpiInner::Spi2(spi) => spi,
3880 #[cfg(spi3)]
3881 super::AnySpiInner::Spi3(spi) => spi,
3882 } {
3883 fn state(&self) -> &'static State;
3884 fn handler(&self) -> InterruptHandler;
3885 }
3886 }
3887}
3888
3889struct SpiFuture<'a> {
3890 driver: &'a Driver,
3891}
3892
3893impl<'a> SpiFuture<'a> {
3894 #[cfg_attr(place_spi_master_driver_in_ram, ram)]
3895 fn setup(driver: &'a Driver) -> impl Future<Output = Self> {
3896 core::future::poll_fn(move |cx| {
3899 driver.state.waker.register(cx.waker());
3900 driver.clear_interrupts(SpiInterrupt::TransferDone.into());
3901 driver.enable_listen(SpiInterrupt::TransferDone.into(), true);
3902 Poll::Ready(Self { driver })
3903 })
3904 }
3905}
3906
3907use core::{
3908 future::Future,
3909 pin::Pin,
3910 task::{Context, Poll},
3911};
3912
3913use crate::dma::{Channel, PeripheralDmaChannel};
3914
3915impl Future for SpiFuture<'_> {
3916 type Output = ();
3917
3918 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
3919 if self
3920 .driver
3921 .interrupts()
3922 .contains(SpiInterrupt::TransferDone)
3923 {
3924 self.driver
3925 .clear_interrupts(SpiInterrupt::TransferDone.into());
3926 return Poll::Ready(());
3927 }
3928
3929 Poll::Pending
3930 }
3931}
3932
3933impl Drop for SpiFuture<'_> {
3934 fn drop(&mut self) {
3935 self.driver
3936 .enable_listen(SpiInterrupt::TransferDone.into(), false);
3937 }
3938}