1use core::marker::PhantomData;
38
39#[instability::unstable]
40pub use dma::*;
41use enumset::{EnumSet, EnumSetType};
42#[cfg(place_spi_driver_in_ram)]
43use procmacros::ram;
44
45use super::{BitOrder, DataMode, DmaError, Error, Mode};
46use crate::{
47 asynch::AtomicWaker,
48 clock::Clocks,
49 dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
50 gpio::{
51 interconnect::{OutputConnection, PeripheralInput, PeripheralOutput},
52 InputSignal,
53 NoPin,
54 OutputSignal,
55 PinGuard,
56 },
57 interrupt::InterruptHandler,
58 pac::spi2::RegisterBlock,
59 peripheral::{Peripheral, PeripheralRef},
60 private::{self, Sealed},
61 spi::AnySpi,
62 system::{Cpu, PeripheralGuard},
63 time::Rate,
64 Async,
65 Blocking,
66 DriverMode,
67};
68
69#[derive(Debug, Hash, EnumSetType)]
71#[cfg_attr(feature = "defmt", derive(defmt::Format))]
72#[non_exhaustive]
73#[instability::unstable]
74pub enum SpiInterrupt {
75 TransferDone,
80
81 #[cfg(any(esp32s2, gdma))]
83 DmaSegmentedTransferDone,
84
85 #[cfg(gdma)]
87 App2,
88
89 #[cfg(gdma)]
91 App1,
92}
93
94const FIFO_SIZE: usize = if cfg!(esp32s2) { 72 } else { 64 };
96
97const EMPTY_WRITE_PAD: u8 = 0x00;
99
100const MAX_DMA_SIZE: usize = 32736;
101
102#[non_exhaustive]
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))]
109#[instability::unstable]
110pub enum Command {
111 None,
113 _1Bit(u16, DataMode),
115 _2Bit(u16, DataMode),
117 _3Bit(u16, DataMode),
119 _4Bit(u16, DataMode),
121 _5Bit(u16, DataMode),
123 _6Bit(u16, DataMode),
125 _7Bit(u16, DataMode),
127 _8Bit(u16, DataMode),
129 _9Bit(u16, DataMode),
131 _10Bit(u16, DataMode),
133 _11Bit(u16, DataMode),
135 _12Bit(u16, DataMode),
137 _13Bit(u16, DataMode),
139 _14Bit(u16, DataMode),
141 _15Bit(u16, DataMode),
143 _16Bit(u16, DataMode),
145}
146
147impl Command {
148 fn width(&self) -> usize {
149 match self {
150 Command::None => 0,
151 Command::_1Bit(_, _) => 1,
152 Command::_2Bit(_, _) => 2,
153 Command::_3Bit(_, _) => 3,
154 Command::_4Bit(_, _) => 4,
155 Command::_5Bit(_, _) => 5,
156 Command::_6Bit(_, _) => 6,
157 Command::_7Bit(_, _) => 7,
158 Command::_8Bit(_, _) => 8,
159 Command::_9Bit(_, _) => 9,
160 Command::_10Bit(_, _) => 10,
161 Command::_11Bit(_, _) => 11,
162 Command::_12Bit(_, _) => 12,
163 Command::_13Bit(_, _) => 13,
164 Command::_14Bit(_, _) => 14,
165 Command::_15Bit(_, _) => 15,
166 Command::_16Bit(_, _) => 16,
167 }
168 }
169
170 fn value(&self) -> u16 {
171 match self {
172 Command::None => 0,
173 Command::_1Bit(value, _)
174 | Command::_2Bit(value, _)
175 | Command::_3Bit(value, _)
176 | Command::_4Bit(value, _)
177 | Command::_5Bit(value, _)
178 | Command::_6Bit(value, _)
179 | Command::_7Bit(value, _)
180 | Command::_8Bit(value, _)
181 | Command::_9Bit(value, _)
182 | Command::_10Bit(value, _)
183 | Command::_11Bit(value, _)
184 | Command::_12Bit(value, _)
185 | Command::_13Bit(value, _)
186 | Command::_14Bit(value, _)
187 | Command::_15Bit(value, _)
188 | Command::_16Bit(value, _) => *value,
189 }
190 }
191
192 fn mode(&self) -> DataMode {
193 match self {
194 Command::None => DataMode::SingleTwoDataLines,
195 Command::_1Bit(_, mode)
196 | Command::_2Bit(_, mode)
197 | Command::_3Bit(_, mode)
198 | Command::_4Bit(_, mode)
199 | Command::_5Bit(_, mode)
200 | Command::_6Bit(_, mode)
201 | Command::_7Bit(_, mode)
202 | Command::_8Bit(_, mode)
203 | Command::_9Bit(_, mode)
204 | Command::_10Bit(_, mode)
205 | Command::_11Bit(_, mode)
206 | Command::_12Bit(_, mode)
207 | Command::_13Bit(_, mode)
208 | Command::_14Bit(_, mode)
209 | Command::_15Bit(_, mode)
210 | Command::_16Bit(_, mode) => *mode,
211 }
212 }
213
214 fn is_none(&self) -> bool {
215 matches!(self, Command::None)
216 }
217}
218
219#[non_exhaustive]
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225#[cfg_attr(feature = "defmt", derive(defmt::Format))]
226#[instability::unstable]
227pub enum Address {
228 None,
230 _1Bit(u32, DataMode),
232 _2Bit(u32, DataMode),
234 _3Bit(u32, DataMode),
236 _4Bit(u32, DataMode),
238 _5Bit(u32, DataMode),
240 _6Bit(u32, DataMode),
242 _7Bit(u32, DataMode),
244 _8Bit(u32, DataMode),
246 _9Bit(u32, DataMode),
248 _10Bit(u32, DataMode),
250 _11Bit(u32, DataMode),
252 _12Bit(u32, DataMode),
254 _13Bit(u32, DataMode),
256 _14Bit(u32, DataMode),
258 _15Bit(u32, DataMode),
260 _16Bit(u32, DataMode),
262 _17Bit(u32, DataMode),
264 _18Bit(u32, DataMode),
266 _19Bit(u32, DataMode),
268 _20Bit(u32, DataMode),
270 _21Bit(u32, DataMode),
272 _22Bit(u32, DataMode),
274 _23Bit(u32, DataMode),
276 _24Bit(u32, DataMode),
278 _25Bit(u32, DataMode),
280 _26Bit(u32, DataMode),
282 _27Bit(u32, DataMode),
284 _28Bit(u32, DataMode),
286 _29Bit(u32, DataMode),
288 _30Bit(u32, DataMode),
290 _31Bit(u32, DataMode),
292 _32Bit(u32, DataMode),
294}
295
296impl Address {
297 fn width(&self) -> usize {
298 match self {
299 Address::None => 0,
300 Address::_1Bit(_, _) => 1,
301 Address::_2Bit(_, _) => 2,
302 Address::_3Bit(_, _) => 3,
303 Address::_4Bit(_, _) => 4,
304 Address::_5Bit(_, _) => 5,
305 Address::_6Bit(_, _) => 6,
306 Address::_7Bit(_, _) => 7,
307 Address::_8Bit(_, _) => 8,
308 Address::_9Bit(_, _) => 9,
309 Address::_10Bit(_, _) => 10,
310 Address::_11Bit(_, _) => 11,
311 Address::_12Bit(_, _) => 12,
312 Address::_13Bit(_, _) => 13,
313 Address::_14Bit(_, _) => 14,
314 Address::_15Bit(_, _) => 15,
315 Address::_16Bit(_, _) => 16,
316 Address::_17Bit(_, _) => 17,
317 Address::_18Bit(_, _) => 18,
318 Address::_19Bit(_, _) => 19,
319 Address::_20Bit(_, _) => 20,
320 Address::_21Bit(_, _) => 21,
321 Address::_22Bit(_, _) => 22,
322 Address::_23Bit(_, _) => 23,
323 Address::_24Bit(_, _) => 24,
324 Address::_25Bit(_, _) => 25,
325 Address::_26Bit(_, _) => 26,
326 Address::_27Bit(_, _) => 27,
327 Address::_28Bit(_, _) => 28,
328 Address::_29Bit(_, _) => 29,
329 Address::_30Bit(_, _) => 30,
330 Address::_31Bit(_, _) => 31,
331 Address::_32Bit(_, _) => 32,
332 }
333 }
334
335 fn value(&self) -> u32 {
336 match self {
337 Address::None => 0,
338 Address::_1Bit(value, _)
339 | Address::_2Bit(value, _)
340 | Address::_3Bit(value, _)
341 | Address::_4Bit(value, _)
342 | Address::_5Bit(value, _)
343 | Address::_6Bit(value, _)
344 | Address::_7Bit(value, _)
345 | Address::_8Bit(value, _)
346 | Address::_9Bit(value, _)
347 | Address::_10Bit(value, _)
348 | Address::_11Bit(value, _)
349 | Address::_12Bit(value, _)
350 | Address::_13Bit(value, _)
351 | Address::_14Bit(value, _)
352 | Address::_15Bit(value, _)
353 | Address::_16Bit(value, _)
354 | Address::_17Bit(value, _)
355 | Address::_18Bit(value, _)
356 | Address::_19Bit(value, _)
357 | Address::_20Bit(value, _)
358 | Address::_21Bit(value, _)
359 | Address::_22Bit(value, _)
360 | Address::_23Bit(value, _)
361 | Address::_24Bit(value, _)
362 | Address::_25Bit(value, _)
363 | Address::_26Bit(value, _)
364 | Address::_27Bit(value, _)
365 | Address::_28Bit(value, _)
366 | Address::_29Bit(value, _)
367 | Address::_30Bit(value, _)
368 | Address::_31Bit(value, _)
369 | Address::_32Bit(value, _) => *value,
370 }
371 }
372
373 fn is_none(&self) -> bool {
374 matches!(self, Address::None)
375 }
376
377 fn mode(&self) -> DataMode {
378 match self {
379 Address::None => DataMode::SingleTwoDataLines,
380 Address::_1Bit(_, mode)
381 | Address::_2Bit(_, mode)
382 | Address::_3Bit(_, mode)
383 | Address::_4Bit(_, mode)
384 | Address::_5Bit(_, mode)
385 | Address::_6Bit(_, mode)
386 | Address::_7Bit(_, mode)
387 | Address::_8Bit(_, mode)
388 | Address::_9Bit(_, mode)
389 | Address::_10Bit(_, mode)
390 | Address::_11Bit(_, mode)
391 | Address::_12Bit(_, mode)
392 | Address::_13Bit(_, mode)
393 | Address::_14Bit(_, mode)
394 | Address::_15Bit(_, mode)
395 | Address::_16Bit(_, mode)
396 | Address::_17Bit(_, mode)
397 | Address::_18Bit(_, mode)
398 | Address::_19Bit(_, mode)
399 | Address::_20Bit(_, mode)
400 | Address::_21Bit(_, mode)
401 | Address::_22Bit(_, mode)
402 | Address::_23Bit(_, mode)
403 | Address::_24Bit(_, mode)
404 | Address::_25Bit(_, mode)
405 | Address::_26Bit(_, mode)
406 | Address::_27Bit(_, mode)
407 | Address::_28Bit(_, mode)
408 | Address::_29Bit(_, mode)
409 | Address::_30Bit(_, mode)
410 | Address::_31Bit(_, mode)
411 | Address::_32Bit(_, mode) => *mode,
412 }
413 }
414}
415
416#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
418#[cfg_attr(feature = "defmt", derive(defmt::Format))]
419#[instability::unstable]
420pub enum ClockSource {
421 Apb,
423 }
426
427#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, procmacros::BuilderLite)]
429#[cfg_attr(feature = "defmt", derive(defmt::Format))]
430#[non_exhaustive]
431pub struct Config {
432 #[builder_lite(skip)]
443 reg: Result<u32, ConfigError>,
444
445 #[builder_lite(skip_setter)]
447 frequency: Rate,
448
449 #[cfg_attr(not(feature = "unstable"), builder_lite(skip))]
451 #[builder_lite(skip_setter)]
452 clock_source: ClockSource,
453
454 mode: Mode,
456
457 read_bit_order: BitOrder,
459
460 write_bit_order: BitOrder,
462}
463
464impl Default for Config {
465 fn default() -> Self {
466 let mut this = Config {
467 reg: Ok(0),
468 frequency: Rate::from_mhz(1),
469 clock_source: ClockSource::Apb,
470 mode: Mode::_0,
471 read_bit_order: BitOrder::MsbFirst,
472 write_bit_order: BitOrder::MsbFirst,
473 };
474
475 this.reg = this.recalculate();
476
477 this
478 }
479}
480
481impl Config {
482 pub fn with_frequency(mut self, frequency: Rate) -> Self {
484 self.frequency = frequency;
485 self.reg = self.recalculate();
486
487 self
488 }
489
490 #[instability::unstable]
492 pub fn with_clock_source(mut self, clock_source: ClockSource) -> Self {
493 self.clock_source = clock_source;
494 self.reg = self.recalculate();
495
496 self
497 }
498
499 fn recalculate(&self) -> Result<u32, ConfigError> {
500 let clocks = Clocks::get();
503 cfg_if::cfg_if! {
504 if #[cfg(esp32h2)] {
505 let apb_clk_freq = clocks.pll_48m_clock;
507 } else {
508 let apb_clk_freq = clocks.apb_clock;
509 }
510 }
511
512 let reg_val: u32;
513 let duty_cycle = 128;
514
515 if self.frequency > ((apb_clk_freq / 4) * 3) {
519 reg_val = 1 << 31;
521 } else {
522 let mut pre: i32;
530 let mut bestn: i32 = -1;
531 let mut bestpre: i32 = -1;
532 let mut besterr: i32 = 0;
533 let mut errval: i32;
534
535 let raw_freq = self.frequency.as_hz() as i32;
536 let raw_apb_freq = apb_clk_freq.as_hz() as i32;
537
538 for n in 2..64 {
542 pre = ((raw_apb_freq / n) + (raw_freq / 2)) / raw_freq;
546
547 if pre <= 0 {
548 pre = 1;
549 }
550
551 if pre > 16 {
552 pre = 16;
553 }
554
555 errval = (raw_apb_freq / (pre * n) - raw_freq).abs();
556 if bestn == -1 || errval <= besterr {
557 besterr = errval;
558 bestn = n;
559 bestpre = pre;
560 }
561 }
562
563 let n: i32 = bestn;
564 pre = bestpre;
565 let l: i32 = n;
566
567 let mut h: i32 = (duty_cycle * n + 127) / 256;
571 if h <= 0 {
572 h = 1;
573 }
574
575 reg_val = (l as u32 - 1)
576 | ((h as u32 - 1) << 6)
577 | ((n as u32 - 1) << 12)
578 | ((pre as u32 - 1) << 18);
579 }
580
581 Ok(reg_val)
582 }
583
584 fn raw_clock_reg_value(&self) -> Result<u32, ConfigError> {
585 self.reg
586 }
587
588 fn validate(&self) -> Result<(), ConfigError> {
589 cfg_if::cfg_if! {
590 if #[cfg(esp32h2)] {
591 if self.frequency < Rate::from_khz(70) || self.frequency > Rate::from_mhz(48) {
592 return Err(ConfigError::UnsupportedFrequency);
593 }
594 } else {
595 if self.frequency < Rate::from_khz(70) || self.frequency > Rate::from_mhz(80) {
596 return Err(ConfigError::UnsupportedFrequency);
597 }
598 }
599 }
600 Ok(())
601 }
602}
603
604#[derive(Debug)]
605#[cfg_attr(feature = "defmt", derive(defmt::Format))]
606struct SpiPinGuard {
607 mosi_pin: PinGuard,
608 sclk_pin: PinGuard,
609 cs_pin: PinGuard,
610 sio1_pin: PinGuard,
611 sio2_pin: Option<PinGuard>,
612 sio3_pin: Option<PinGuard>,
613}
614
615#[non_exhaustive]
617#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
618#[cfg_attr(feature = "defmt", derive(defmt::Format))]
619pub enum ConfigError {
620 UnsupportedFrequency,
622}
623
624impl core::error::Error for ConfigError {}
625
626impl core::fmt::Display for ConfigError {
627 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
628 match self {
629 ConfigError::UnsupportedFrequency => {
630 write!(f, "The requested frequency is not supported")
631 }
632 }
633 }
634}
635
636#[doc = crate::before_snippet!()]
641#[derive(Debug)]
654#[cfg_attr(feature = "defmt", derive(defmt::Format))]
655pub struct Spi<'d, Dm: DriverMode> {
656 spi: PeripheralRef<'d, AnySpi>,
657 _mode: PhantomData<Dm>,
658 guard: PeripheralGuard,
659 pins: SpiPinGuard,
660}
661
662impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
663
664impl<Dm> Spi<'_, Dm>
665where
666 Dm: DriverMode,
667{
668 fn driver(&self) -> Driver {
669 Driver {
670 info: self.spi.info(),
671 state: self.spi.state(),
672 }
673 }
674
675 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
678 self.driver().write(words)?;
679 self.driver().flush()?;
680
681 Ok(())
682 }
683
684 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
687 self.driver().read(words)
688 }
689
690 pub fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Error> {
692 self.driver().transfer(words)
693 }
694}
695
696impl<'d> Spi<'d, Blocking> {
697 pub fn new(
703 spi: impl Peripheral<P = impl PeripheralInstance> + 'd,
704 config: Config,
705 ) -> Result<Self, ConfigError> {
706 crate::into_mapped_ref!(spi);
707
708 let guard = PeripheralGuard::new(spi.info().peripheral);
709
710 let mosi_pin = PinGuard::new_unconnected(spi.info().mosi);
711 let sclk_pin = PinGuard::new_unconnected(spi.info().sclk);
712 let cs_pin = PinGuard::new_unconnected(spi.info().cs);
713 let sio1_pin = PinGuard::new_unconnected(spi.info().sio1_output);
714 let sio2_pin = spi.info().sio2_output.map(PinGuard::new_unconnected);
715 let sio3_pin = spi.info().sio3_output.map(PinGuard::new_unconnected);
716
717 let mut this = Spi {
718 spi,
719 _mode: PhantomData,
720 guard,
721 pins: SpiPinGuard {
722 mosi_pin,
723 sclk_pin,
724 cs_pin,
725 sio1_pin,
726 sio2_pin,
727 sio3_pin,
728 },
729 };
730
731 this.driver().init();
732 this.apply_config(&config)?;
733
734 let this = this
735 .with_sio0(NoPin)
736 .with_sio1(NoPin)
737 .with_sck(NoPin)
738 .with_cs(NoPin);
739
740 let is_qspi = this.driver().info.sio2_input.is_some();
741 if is_qspi {
742 unwrap!(this.driver().info.sio2_input).connect_to(NoPin);
743 unwrap!(this.driver().info.sio2_output).connect_to(NoPin);
744 unwrap!(this.driver().info.sio3_input).connect_to(NoPin);
745 unwrap!(this.driver().info.sio3_output).connect_to(NoPin);
746 }
747
748 Ok(this)
749 }
750
751 pub fn into_async(mut self) -> Spi<'d, Async> {
753 self.set_interrupt_handler(self.spi.handler());
754 Spi {
755 spi: self.spi,
756 _mode: PhantomData,
757 guard: self.guard,
758 pins: self.pins,
759 }
760 }
761
762 #[doc = crate::before_snippet!()]
769 #[cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = peripherals.DMA_SPI2;")]
774 #[cfg_attr(
775 not(any(esp32, esp32s2)),
776 doc = "let dma_channel = peripherals.DMA_CH0;"
777 )]
778 #[instability::unstable]
801 pub fn with_dma<CH>(self, channel: impl Peripheral<P = CH> + 'd) -> SpiDma<'d, Blocking>
802 where
803 CH: DmaChannelFor<AnySpi>,
804 {
805 SpiDma::new(
806 self.spi,
807 self.pins,
808 channel.map(|ch| ch.degrade()).into_ref(),
809 )
810 }
811
812 #[cfg_attr(
813 not(multi_core),
814 doc = "Registers an interrupt handler for the peripheral."
815 )]
816 #[cfg_attr(
817 multi_core,
818 doc = "Registers an interrupt handler for the peripheral on the current core."
819 )]
820 #[doc = ""]
821 #[instability::unstable]
832 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
833 let interrupt = self.driver().info.interrupt;
834 for core in Cpu::other() {
835 crate::interrupt::disable(core, interrupt);
836 }
837 unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
838 unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
839 }
840}
841
842#[instability::unstable]
843impl crate::interrupt::InterruptConfigurable for Spi<'_, Blocking> {
844 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
848 Spi::set_interrupt_handler(self, handler);
849 }
850}
851
852impl<'d> Spi<'d, Async> {
853 pub fn into_blocking(self) -> Spi<'d, Blocking> {
855 crate::interrupt::disable(Cpu::current(), self.driver().info.interrupt);
856 Spi {
857 spi: self.spi,
858 _mode: PhantomData,
859 guard: self.guard,
860 pins: self.pins,
861 }
862 }
863
864 pub async fn flush_async(&mut self) -> Result<(), Error> {
866 let driver = self.driver();
867
868 if !driver.busy() {
869 return Ok(());
870 }
871
872 let future = SpiFuture::setup(&driver).await;
873 future.await;
874
875 Ok(())
876 }
877
878 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
880 self.flush_async().await?;
883 self.driver().transfer_in_place_async(words).await
884 }
885}
886
887impl<'d, Dm> Spi<'d, Dm>
888where
889 Dm: DriverMode,
890{
891 pub fn with_mosi<MOSI: PeripheralOutput>(
900 mut self,
901 mosi: impl Peripheral<P = MOSI> + 'd,
902 ) -> Self {
903 crate::into_mapped_ref!(mosi);
904 mosi.enable_output(false);
905
906 self.pins.mosi_pin = OutputConnection::connect_with_guard(mosi, self.driver().info.mosi);
907
908 self
909 }
910
911 #[instability::unstable]
925 pub fn with_sio0<MOSI: PeripheralOutput>(
926 mut self,
927 mosi: impl Peripheral<P = MOSI> + 'd,
928 ) -> Self {
929 crate::into_mapped_ref!(mosi);
930 mosi.enable_output(true);
931 mosi.enable_input(true);
932
933 self.driver().info.sio0_input.connect_to(&mut mosi);
934 self.pins.mosi_pin = OutputConnection::connect_with_guard(mosi, self.driver().info.mosi);
935
936 self
937 }
938
939 pub fn with_miso<MISO: PeripheralInput>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
947 crate::into_mapped_ref!(miso);
948 miso.enable_input(true);
949
950 self.driver().info.miso.connect_to(miso);
951
952 self
953 }
954
955 #[instability::unstable]
968 pub fn with_sio1<SIO1: PeripheralOutput>(
969 mut self,
970 miso: impl Peripheral<P = SIO1> + 'd,
971 ) -> Self {
972 crate::into_mapped_ref!(miso);
973 miso.enable_input(true);
974 miso.enable_output(true);
975
976 self.driver().info.miso.connect_to(&mut miso);
977 self.pins.sio1_pin =
978 OutputConnection::connect_with_guard(miso, self.driver().info.sio1_output);
979
980 self
981 }
982
983 pub fn with_sck<SCK: PeripheralOutput>(mut self, sclk: impl Peripheral<P = SCK> + 'd) -> Self {
990 crate::into_mapped_ref!(sclk);
991 sclk.set_to_push_pull_output();
992 self.pins.sclk_pin = OutputConnection::connect_with_guard(sclk, self.driver().info.sclk);
993
994 self
995 }
996
997 #[instability::unstable]
1009 pub fn with_cs<CS: PeripheralOutput>(mut self, cs: impl Peripheral<P = CS> + 'd) -> Self {
1010 crate::into_mapped_ref!(cs);
1011 cs.set_to_push_pull_output();
1012 self.pins.cs_pin = OutputConnection::connect_with_guard(cs, self.driver().info.cs);
1013
1014 self
1015 }
1016
1017 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
1023 #[cfg_attr(esp32h2, doc = " 48MHz")]
1024 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1027 self.driver().apply_config(config)
1028 }
1029}
1030
1031#[instability::unstable]
1032impl<Dm> embassy_embedded_hal::SetConfig for Spi<'_, Dm>
1033where
1034 Dm: DriverMode,
1035{
1036 type Config = Config;
1037 type ConfigError = ConfigError;
1038
1039 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1040 self.apply_config(config)
1041 }
1042}
1043
1044impl<'d, Dm> Spi<'d, Dm>
1045where
1046 Dm: DriverMode,
1047{
1048 #[instability::unstable]
1057 pub fn with_sio2<SIO2: PeripheralOutput>(
1058 mut self,
1059 sio2: impl Peripheral<P = SIO2> + 'd,
1060 ) -> Self {
1061 crate::into_mapped_ref!(sio2);
1063 sio2.enable_input(true);
1064 sio2.enable_output(true);
1065
1066 unwrap!(self.driver().info.sio2_input).connect_to(&mut sio2);
1067 self.pins.sio2_pin = self
1068 .driver()
1069 .info
1070 .sio2_output
1071 .map(|signal| OutputConnection::connect_with_guard(sio2, signal));
1072
1073 self
1074 }
1075
1076 #[instability::unstable]
1085 pub fn with_sio3<SIO3: PeripheralOutput>(
1086 mut self,
1087 sio3: impl Peripheral<P = SIO3> + 'd,
1088 ) -> Self {
1089 crate::into_mapped_ref!(sio3);
1091 sio3.enable_input(true);
1092 sio3.enable_output(true);
1093
1094 unwrap!(self.driver().info.sio3_input).connect_to(&mut sio3);
1095 self.pins.sio3_pin = self
1096 .driver()
1097 .info
1098 .sio3_output
1099 .map(|signal| OutputConnection::connect_with_guard(sio3, signal));
1100
1101 self
1102 }
1103}
1104
1105impl<Dm> Spi<'_, Dm>
1106where
1107 Dm: DriverMode,
1108{
1109 #[instability::unstable]
1118 pub fn half_duplex_read(
1119 &mut self,
1120 data_mode: DataMode,
1121 cmd: Command,
1122 address: Address,
1123 dummy: u8,
1124 buffer: &mut [u8],
1125 ) -> Result<(), Error> {
1126 if buffer.len() > FIFO_SIZE {
1127 return Err(Error::FifoSizeExeeded);
1128 }
1129
1130 if buffer.is_empty() {
1131 return Err(Error::Unsupported);
1132 }
1133
1134 self.driver().setup_half_duplex(
1135 false,
1136 cmd,
1137 address,
1138 false,
1139 dummy,
1140 buffer.is_empty(),
1141 data_mode,
1142 )?;
1143
1144 self.driver().configure_datalen(buffer.len(), 0);
1145 self.driver().start_operation();
1146 self.driver().flush()?;
1147 self.driver().read_from_fifo(buffer)
1148 }
1149
1150 #[cfg_attr(
1157 esp32,
1158 doc = "Dummy phase configuration is currently not supported, only value `0` is valid (see issue [#2240](https://github.com/esp-rs/esp-hal/issues/2240))."
1159 )]
1160 #[instability::unstable]
1161 pub fn half_duplex_write(
1162 &mut self,
1163 data_mode: DataMode,
1164 cmd: Command,
1165 address: Address,
1166 dummy: u8,
1167 buffer: &[u8],
1168 ) -> Result<(), Error> {
1169 if buffer.len() > FIFO_SIZE {
1170 return Err(Error::FifoSizeExeeded);
1171 }
1172
1173 cfg_if::cfg_if! {
1174 if #[cfg(all(esp32, spi_address_workaround))] {
1175 let mut buffer = buffer;
1176 let mut data_mode = data_mode;
1177 let mut address = address;
1178 let addr_bytes;
1179 if buffer.is_empty() && !address.is_none() {
1180 let bytes_to_write = address.width().div_ceil(8);
1183 addr_bytes = address.value().to_be_bytes();
1186 buffer = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1187 data_mode = address.mode();
1188 address = Address::None;
1189 }
1190
1191 if dummy > 0 {
1192 return Err(Error::Unsupported);
1194 }
1195 }
1196 }
1197
1198 self.driver().setup_half_duplex(
1199 true,
1200 cmd,
1201 address,
1202 false,
1203 dummy,
1204 buffer.is_empty(),
1205 data_mode,
1206 )?;
1207
1208 if !buffer.is_empty() {
1209 self.driver().write(buffer)?;
1211 } else {
1212 self.driver().start_operation();
1213 }
1214
1215 self.driver().flush()
1216 }
1217}
1218
1219mod dma {
1220 use core::{
1221 cmp::min,
1222 mem::ManuallyDrop,
1223 sync::atomic::{fence, Ordering},
1224 };
1225
1226 use super::*;
1227 use crate::dma::{
1228 asynch::{DmaRxFuture, DmaTxFuture},
1229 Channel,
1230 DmaRxBuf,
1231 DmaTxBuf,
1232 EmptyBuf,
1233 PeripheralDmaChannel,
1234 };
1235
1236 #[doc = crate::before_snippet!()]
1245 #[cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = peripherals.DMA_SPI2;")]
1250 #[cfg_attr(
1251 not(any(esp32, esp32s2)),
1252 doc = "let dma_channel = peripherals.DMA_CH0;"
1253 )]
1254 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1277 pub struct SpiDma<'d, Dm>
1278 where
1279 Dm: DriverMode,
1280 {
1281 pub(crate) spi: PeripheralRef<'d, AnySpi>,
1282 pub(crate) channel: Channel<'d, Dm, PeripheralDmaChannel<AnySpi>>,
1283 tx_transfer_in_progress: bool,
1284 rx_transfer_in_progress: bool,
1285 #[cfg(all(esp32, spi_address_workaround))]
1286 address_buffer: DmaTxBuf,
1287 guard: PeripheralGuard,
1288 pins: SpiPinGuard,
1289 }
1290
1291 impl<Dm> crate::private::Sealed for SpiDma<'_, Dm> where Dm: DriverMode {}
1292
1293 impl<'d> SpiDma<'d, Blocking> {
1294 #[instability::unstable]
1296 pub fn into_async(self) -> SpiDma<'d, Async> {
1297 SpiDma {
1298 spi: self.spi,
1299 channel: self.channel.into_async(),
1300 tx_transfer_in_progress: self.tx_transfer_in_progress,
1301 rx_transfer_in_progress: self.rx_transfer_in_progress,
1302 #[cfg(all(esp32, spi_address_workaround))]
1303 address_buffer: self.address_buffer,
1304 guard: self.guard,
1305 pins: self.pins,
1306 }
1307 }
1308 }
1309
1310 impl<'d> SpiDma<'d, Async> {
1311 #[instability::unstable]
1313 pub fn into_blocking(self) -> SpiDma<'d, Blocking> {
1314 SpiDma {
1315 spi: self.spi,
1316 channel: self.channel.into_blocking(),
1317 tx_transfer_in_progress: self.tx_transfer_in_progress,
1318 rx_transfer_in_progress: self.rx_transfer_in_progress,
1319 #[cfg(all(esp32, spi_address_workaround))]
1320 address_buffer: self.address_buffer,
1321 guard: self.guard,
1322 pins: self.pins,
1323 }
1324 }
1325 }
1326
1327 impl<Dm> core::fmt::Debug for SpiDma<'_, Dm>
1328 where
1329 Dm: DriverMode,
1330 {
1331 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1336 f.debug_struct("SpiDma").field("spi", &self.spi).finish()
1337 }
1338 }
1339
1340 #[instability::unstable]
1341 impl crate::interrupt::InterruptConfigurable for SpiDma<'_, Blocking> {
1342 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
1346 let interrupt = self.driver().info.interrupt;
1347 for core in crate::system::Cpu::other() {
1348 crate::interrupt::disable(core, interrupt);
1349 }
1350 unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
1351 unwrap!(crate::interrupt::enable(interrupt, handler.priority()));
1352 }
1353 }
1354
1355 impl SpiDma<'_, Blocking> {
1356 #[instability::unstable]
1358 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1359 self.driver().enable_listen(interrupts.into(), true);
1360 }
1361
1362 #[instability::unstable]
1364 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1365 self.driver().enable_listen(interrupts.into(), false);
1366 }
1367
1368 #[instability::unstable]
1370 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
1371 self.driver().interrupts()
1372 }
1373
1374 #[instability::unstable]
1376 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
1377 self.driver().clear_interrupts(interrupts.into());
1378 }
1379 }
1380
1381 impl<'d> SpiDma<'d, Blocking> {
1382 pub(super) fn new(
1383 spi: PeripheralRef<'d, AnySpi>,
1384 pins: SpiPinGuard,
1385 channel: PeripheralRef<'d, PeripheralDmaChannel<AnySpi>>,
1386 ) -> Self {
1387 let channel = Channel::new(channel);
1388 channel.runtime_ensure_compatible(&spi);
1389 #[cfg(all(esp32, spi_address_workaround))]
1390 let address_buffer = {
1391 use crate::dma::DmaDescriptor;
1392 const SPI_NUM: usize = 2;
1393 static mut DESCRIPTORS: [[DmaDescriptor; 1]; SPI_NUM] =
1394 [[DmaDescriptor::EMPTY]; SPI_NUM];
1395 static mut BUFFERS: [[u32; 1]; SPI_NUM] = [[0; 1]; SPI_NUM];
1396
1397 let id = if spi.info() == unsafe { crate::peripherals::SPI2::steal().info() } {
1398 0
1399 } else {
1400 1
1401 };
1402
1403 unwrap!(DmaTxBuf::new(
1404 unsafe { &mut DESCRIPTORS[id] },
1405 crate::dma::as_mut_byte_array!(BUFFERS[id], 4)
1406 ))
1407 };
1408
1409 let guard = PeripheralGuard::new(spi.info().peripheral);
1410
1411 Self {
1412 spi,
1413 channel,
1414 #[cfg(all(esp32, spi_address_workaround))]
1415 address_buffer,
1416 tx_transfer_in_progress: false,
1417 rx_transfer_in_progress: false,
1418 guard,
1419 pins,
1420 }
1421 }
1422 }
1423
1424 impl<'d, Dm> SpiDma<'d, Dm>
1425 where
1426 Dm: DriverMode,
1427 {
1428 fn driver(&self) -> Driver {
1429 Driver {
1430 info: self.spi.info(),
1431 state: self.spi.state(),
1432 }
1433 }
1434
1435 fn dma_driver(&self) -> DmaDriver {
1436 DmaDriver {
1437 driver: self.driver(),
1438 dma_peripheral: self.spi.dma_peripheral(),
1439 }
1440 }
1441
1442 fn is_done(&self) -> bool {
1443 if self.tx_transfer_in_progress && !self.channel.tx.is_done() {
1444 return false;
1445 }
1446 if self.driver().busy() {
1447 return false;
1448 }
1449 if self.rx_transfer_in_progress {
1450 if !self.channel.rx.is_done() && !self.channel.rx.has_dscr_empty_error() {
1458 return false;
1459 }
1460 }
1461 true
1462 }
1463
1464 fn wait_for_idle(&mut self) {
1465 while !self.is_done() {
1466 }
1468 self.rx_transfer_in_progress = false;
1469 self.tx_transfer_in_progress = false;
1470 fence(Ordering::Acquire);
1471 }
1472
1473 async fn wait_for_idle_async(&mut self) {
1474 if self.rx_transfer_in_progress {
1477 _ = DmaRxFuture::new(&mut self.channel.rx).await;
1478 self.rx_transfer_in_progress = false;
1479 }
1480 if self.tx_transfer_in_progress {
1481 _ = DmaTxFuture::new(&mut self.channel.tx).await;
1482 self.tx_transfer_in_progress = false;
1483 }
1484
1485 core::future::poll_fn(|cx| {
1486 use core::task::Poll;
1487 if self.is_done() {
1488 Poll::Ready(())
1489 } else {
1490 cx.waker().wake_by_ref();
1491 Poll::Pending
1492 }
1493 })
1494 .await;
1495 }
1496
1497 #[cfg_attr(place_spi_driver_in_ram, ram)]
1502 unsafe fn start_transfer_dma<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1503 &mut self,
1504 full_duplex: bool,
1505 bytes_to_read: usize,
1506 bytes_to_write: usize,
1507 rx_buffer: &mut RX,
1508 tx_buffer: &mut TX,
1509 ) -> Result<(), Error> {
1510 if bytes_to_read > MAX_DMA_SIZE || bytes_to_write > MAX_DMA_SIZE {
1511 return Err(Error::MaxDmaTransferSizeExceeded);
1512 }
1513
1514 self.rx_transfer_in_progress = bytes_to_read > 0;
1515 self.tx_transfer_in_progress = bytes_to_write > 0;
1516 unsafe {
1517 self.dma_driver().start_transfer_dma(
1518 full_duplex,
1519 bytes_to_read,
1520 bytes_to_write,
1521 rx_buffer,
1522 tx_buffer,
1523 &mut self.channel.rx,
1524 &mut self.channel.tx,
1525 )
1526 }
1527 }
1528
1529 #[cfg(all(esp32, spi_address_workaround))]
1530 fn set_up_address_workaround(
1531 &mut self,
1532 cmd: Command,
1533 address: Address,
1534 dummy: u8,
1535 ) -> Result<(), Error> {
1536 if dummy > 0 {
1537 return Err(Error::Unsupported);
1539 }
1540
1541 let bytes_to_write = address.width().div_ceil(8);
1542 let addr_bytes = address.value().to_be_bytes();
1545 let addr_bytes = &addr_bytes[4 - bytes_to_write..][..bytes_to_write];
1546 self.address_buffer.fill(addr_bytes);
1547
1548 self.driver().setup_half_duplex(
1549 true,
1550 cmd,
1551 Address::None,
1552 false,
1553 dummy,
1554 bytes_to_write == 0,
1555 address.mode(),
1556 )?;
1557
1558 self.tx_transfer_in_progress = true;
1561 unsafe {
1562 self.dma_driver().start_transfer_dma(
1563 false,
1564 0,
1565 bytes_to_write,
1566 &mut EmptyBuf,
1567 &mut self.address_buffer,
1568 &mut self.channel.rx,
1569 &mut self.channel.tx,
1570 )
1571 }
1572 }
1573
1574 fn cancel_transfer(&mut self) {
1575 if self.tx_transfer_in_progress || self.rx_transfer_in_progress {
1582 self.dma_driver().abort_transfer();
1583
1584 if self.tx_transfer_in_progress {
1586 self.channel.tx.stop_transfer();
1587 self.tx_transfer_in_progress = false;
1588 }
1589 if self.rx_transfer_in_progress {
1590 self.channel.rx.stop_transfer();
1591 self.rx_transfer_in_progress = false;
1592 }
1593 }
1594 }
1595
1596 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
1602 #[cfg_attr(esp32h2, doc = " 48MHz")]
1603 #[instability::unstable]
1606 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
1607 self.driver().apply_config(config)
1608 }
1609
1610 #[instability::unstable]
1616 pub fn with_buffers(self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf) -> SpiDmaBus<'d, Dm> {
1617 SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf)
1618 }
1619 }
1620
1621 #[instability::unstable]
1622 impl<Dm> embassy_embedded_hal::SetConfig for SpiDma<'_, Dm>
1623 where
1624 Dm: DriverMode,
1625 {
1626 type Config = Config;
1627 type ConfigError = ConfigError;
1628
1629 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
1630 self.apply_config(config)
1631 }
1632 }
1633
1634 #[instability::unstable]
1639 pub struct SpiDmaTransfer<'d, Dm, Buf>
1640 where
1641 Dm: DriverMode,
1642 {
1643 spi_dma: ManuallyDrop<SpiDma<'d, Dm>>,
1644 dma_buf: ManuallyDrop<Buf>,
1645 }
1646
1647 impl<'d, Dm, Buf> SpiDmaTransfer<'d, Dm, Buf>
1648 where
1649 Dm: DriverMode,
1650 {
1651 fn new(spi_dma: SpiDma<'d, Dm>, dma_buf: Buf) -> Self {
1652 Self {
1653 spi_dma: ManuallyDrop::new(spi_dma),
1654 dma_buf: ManuallyDrop::new(dma_buf),
1655 }
1656 }
1657
1658 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<Buf> SpiDmaTransfer<'_, Async, Buf> {
1710 #[instability::unstable]
1714 pub async fn wait_for_done(&mut self) {
1715 self.spi_dma.wait_for_idle_async().await;
1716 }
1717 }
1718
1719 impl<'d, Dm> SpiDma<'d, Dm>
1720 where
1721 Dm: DriverMode,
1722 {
1723 #[cfg_attr(place_spi_driver_in_ram, ram)]
1728 unsafe fn start_dma_write(
1729 &mut self,
1730 bytes_to_write: usize,
1731 buffer: &mut impl DmaTxBuffer,
1732 ) -> Result<(), Error> {
1733 self.start_dma_transfer(0, bytes_to_write, &mut EmptyBuf, buffer)
1734 }
1735
1736 #[allow(clippy::type_complexity)]
1742 #[cfg_attr(place_spi_driver_in_ram, ram)]
1743 #[instability::unstable]
1744 pub fn write<TX: DmaTxBuffer>(
1745 mut self,
1746 bytes_to_write: usize,
1747 mut buffer: TX,
1748 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1749 self.wait_for_idle();
1750
1751 match unsafe { self.start_dma_write(bytes_to_write, &mut buffer) } {
1752 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1753 Err(e) => Err((e, self, buffer)),
1754 }
1755 }
1756
1757 #[cfg_attr(place_spi_driver_in_ram, ram)]
1762 unsafe fn start_dma_read(
1763 &mut self,
1764 bytes_to_read: usize,
1765 buffer: &mut impl DmaRxBuffer,
1766 ) -> Result<(), Error> {
1767 self.start_dma_transfer(bytes_to_read, 0, buffer, &mut EmptyBuf)
1768 }
1769
1770 #[allow(clippy::type_complexity)]
1776 #[cfg_attr(place_spi_driver_in_ram, ram)]
1777 #[instability::unstable]
1778 pub fn read<RX: DmaRxBuffer>(
1779 mut self,
1780 bytes_to_read: usize,
1781 mut buffer: RX,
1782 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1783 self.wait_for_idle();
1784 match unsafe { self.start_dma_read(bytes_to_read, &mut buffer) } {
1785 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1786 Err(e) => Err((e, self, buffer)),
1787 }
1788 }
1789
1790 #[cfg_attr(place_spi_driver_in_ram, ram)]
1795 unsafe fn start_dma_transfer(
1796 &mut self,
1797 bytes_to_read: usize,
1798 bytes_to_write: usize,
1799 rx_buffer: &mut impl DmaRxBuffer,
1800 tx_buffer: &mut impl DmaTxBuffer,
1801 ) -> Result<(), Error> {
1802 self.start_transfer_dma(true, bytes_to_read, bytes_to_write, rx_buffer, tx_buffer)
1803 }
1804
1805 #[allow(clippy::type_complexity)]
1811 #[cfg_attr(place_spi_driver_in_ram, ram)]
1812 #[instability::unstable]
1813 pub fn transfer<RX: DmaRxBuffer, TX: DmaTxBuffer>(
1814 mut self,
1815 bytes_to_read: usize,
1816 mut rx_buffer: RX,
1817 bytes_to_write: usize,
1818 mut tx_buffer: TX,
1819 ) -> Result<SpiDmaTransfer<'d, Dm, (RX, TX)>, (Error, Self, RX, TX)> {
1820 self.wait_for_idle();
1821 match unsafe {
1822 self.start_dma_transfer(
1823 bytes_to_read,
1824 bytes_to_write,
1825 &mut rx_buffer,
1826 &mut tx_buffer,
1827 )
1828 } {
1829 Ok(_) => Ok(SpiDmaTransfer::new(self, (rx_buffer, tx_buffer))),
1830 Err(e) => Err((e, self, rx_buffer, tx_buffer)),
1831 }
1832 }
1833
1834 #[cfg_attr(place_spi_driver_in_ram, ram)]
1839 unsafe fn start_half_duplex_read(
1840 &mut self,
1841 data_mode: DataMode,
1842 cmd: Command,
1843 address: Address,
1844 dummy: u8,
1845 bytes_to_read: usize,
1846 buffer: &mut impl DmaRxBuffer,
1847 ) -> Result<(), Error> {
1848 self.driver().setup_half_duplex(
1849 false,
1850 cmd,
1851 address,
1852 false,
1853 dummy,
1854 bytes_to_read == 0,
1855 data_mode,
1856 )?;
1857
1858 self.start_transfer_dma(false, bytes_to_read, 0, buffer, &mut EmptyBuf)
1859 }
1860
1861 #[allow(clippy::type_complexity)]
1863 #[cfg_attr(place_spi_driver_in_ram, ram)]
1864 #[instability::unstable]
1865 pub fn half_duplex_read<RX: DmaRxBuffer>(
1866 mut self,
1867 data_mode: DataMode,
1868 cmd: Command,
1869 address: Address,
1870 dummy: u8,
1871 bytes_to_read: usize,
1872 mut buffer: RX,
1873 ) -> Result<SpiDmaTransfer<'d, Dm, RX>, (Error, Self, RX)> {
1874 self.wait_for_idle();
1875
1876 match unsafe {
1877 self.start_half_duplex_read(
1878 data_mode,
1879 cmd,
1880 address,
1881 dummy,
1882 bytes_to_read,
1883 &mut buffer,
1884 )
1885 } {
1886 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1887 Err(e) => Err((e, self, buffer)),
1888 }
1889 }
1890
1891 #[cfg_attr(place_spi_driver_in_ram, ram)]
1896 unsafe fn start_half_duplex_write(
1897 &mut self,
1898 data_mode: DataMode,
1899 cmd: Command,
1900 address: Address,
1901 dummy: u8,
1902 bytes_to_write: usize,
1903 buffer: &mut impl DmaTxBuffer,
1904 ) -> Result<(), Error> {
1905 #[cfg(all(esp32, spi_address_workaround))]
1906 {
1907 if bytes_to_write == 0 && address.mode() != DataMode::SingleTwoDataLines {
1910 return self.set_up_address_workaround(cmd, address, dummy);
1911 }
1912 }
1913
1914 self.driver().setup_half_duplex(
1915 true,
1916 cmd,
1917 address,
1918 false,
1919 dummy,
1920 bytes_to_write == 0,
1921 data_mode,
1922 )?;
1923
1924 self.start_transfer_dma(false, 0, bytes_to_write, &mut EmptyBuf, buffer)
1925 }
1926
1927 #[allow(clippy::type_complexity)]
1929 #[cfg_attr(place_spi_driver_in_ram, ram)]
1930 #[instability::unstable]
1931 pub fn half_duplex_write<TX: DmaTxBuffer>(
1932 mut self,
1933 data_mode: DataMode,
1934 cmd: Command,
1935 address: Address,
1936 dummy: u8,
1937 bytes_to_write: usize,
1938 mut buffer: TX,
1939 ) -> Result<SpiDmaTransfer<'d, Dm, TX>, (Error, Self, TX)> {
1940 self.wait_for_idle();
1941
1942 match unsafe {
1943 self.start_half_duplex_write(
1944 data_mode,
1945 cmd,
1946 address,
1947 dummy,
1948 bytes_to_write,
1949 &mut buffer,
1950 )
1951 } {
1952 Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)),
1953 Err(e) => Err((e, self, buffer)),
1954 }
1955 }
1956 }
1957
1958 #[derive(Debug)]
1963 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
1964 #[instability::unstable]
1965 pub struct SpiDmaBus<'d, Dm>
1966 where
1967 Dm: DriverMode,
1968 {
1969 spi_dma: SpiDma<'d, Dm>,
1970 rx_buf: DmaRxBuf,
1971 tx_buf: DmaTxBuf,
1972 }
1973
1974 impl<Dm> crate::private::Sealed for SpiDmaBus<'_, Dm> where Dm: DriverMode {}
1975
1976 impl<'d> SpiDmaBus<'d, Blocking> {
1977 #[instability::unstable]
1979 pub fn into_async(self) -> SpiDmaBus<'d, Async> {
1980 SpiDmaBus {
1981 spi_dma: self.spi_dma.into_async(),
1982 rx_buf: self.rx_buf,
1983 tx_buf: self.tx_buf,
1984 }
1985 }
1986 }
1987
1988 impl<'d> SpiDmaBus<'d, Async> {
1989 #[instability::unstable]
1991 pub fn into_blocking(self) -> SpiDmaBus<'d, Blocking> {
1992 SpiDmaBus {
1993 spi_dma: self.spi_dma.into_blocking(),
1994 rx_buf: self.rx_buf,
1995 tx_buf: self.tx_buf,
1996 }
1997 }
1998 }
1999
2000 impl<'d, Dm> SpiDmaBus<'d, Dm>
2001 where
2002 Dm: DriverMode,
2003 {
2004 pub fn new(spi_dma: SpiDma<'d, Dm>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self {
2007 Self {
2008 spi_dma,
2009 rx_buf,
2010 tx_buf,
2011 }
2012 }
2013
2014 #[instability::unstable]
2016 pub fn split(mut self) -> (SpiDma<'d, Dm>, DmaRxBuf, DmaTxBuf) {
2017 self.wait_for_idle();
2018 (self.spi_dma, self.rx_buf, self.tx_buf)
2019 }
2020 }
2021
2022 #[instability::unstable]
2023 impl crate::interrupt::InterruptConfigurable for SpiDmaBus<'_, Blocking> {
2024 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
2028 self.spi_dma.set_interrupt_handler(handler);
2029 }
2030 }
2031
2032 impl SpiDmaBus<'_, Blocking> {
2033 #[instability::unstable]
2035 pub fn listen(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2036 self.spi_dma.listen(interrupts.into());
2037 }
2038
2039 #[instability::unstable]
2041 pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2042 self.spi_dma.unlisten(interrupts.into());
2043 }
2044
2045 #[instability::unstable]
2047 pub fn interrupts(&mut self) -> EnumSet<SpiInterrupt> {
2048 self.spi_dma.interrupts()
2049 }
2050
2051 #[instability::unstable]
2053 pub fn clear_interrupts(&mut self, interrupts: impl Into<EnumSet<SpiInterrupt>>) {
2054 self.spi_dma.clear_interrupts(interrupts.into());
2055 }
2056 }
2057
2058 impl<Dm> SpiDmaBus<'_, Dm>
2059 where
2060 Dm: DriverMode,
2061 {
2062 fn wait_for_idle(&mut self) {
2063 self.spi_dma.wait_for_idle();
2064 }
2065
2066 #[cfg_attr(not(esp32h2), doc = " 80MHz")]
2072 #[cfg_attr(esp32h2, doc = " 48MHz")]
2073 #[instability::unstable]
2076 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
2077 self.spi_dma.apply_config(config)
2078 }
2079
2080 #[instability::unstable]
2082 pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
2083 self.wait_for_idle();
2084 for chunk in words.chunks_mut(self.rx_buf.capacity()) {
2085 self.rx_buf.set_length(chunk.len());
2086
2087 unsafe {
2088 self.spi_dma.start_dma_transfer(
2089 chunk.len(),
2090 0,
2091 &mut self.rx_buf,
2092 &mut EmptyBuf,
2093 )?;
2094 }
2095
2096 self.wait_for_idle();
2097
2098 let bytes_read = self.rx_buf.read_received_data(chunk);
2099 debug_assert_eq!(bytes_read, chunk.len());
2100 }
2101
2102 Ok(())
2103 }
2104
2105 #[instability::unstable]
2107 pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
2108 self.wait_for_idle();
2109 for chunk in words.chunks(self.tx_buf.capacity()) {
2110 self.tx_buf.fill(chunk);
2111
2112 unsafe {
2113 self.spi_dma.start_dma_transfer(
2114 0,
2115 chunk.len(),
2116 &mut EmptyBuf,
2117 &mut self.tx_buf,
2118 )?;
2119 }
2120
2121 self.wait_for_idle();
2122 }
2123
2124 Ok(())
2125 }
2126
2127 #[instability::unstable]
2129 pub fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
2130 self.wait_for_idle();
2131 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2132
2133 let common_length = min(read.len(), write.len());
2134 let (read_common, read_remainder) = read.split_at_mut(common_length);
2135 let (write_common, write_remainder) = write.split_at(common_length);
2136
2137 for (read_chunk, write_chunk) in read_common
2138 .chunks_mut(chunk_size)
2139 .zip(write_common.chunks(chunk_size))
2140 {
2141 self.tx_buf.fill(write_chunk);
2142 self.rx_buf.set_length(read_chunk.len());
2143
2144 unsafe {
2145 self.spi_dma.start_dma_transfer(
2146 read_chunk.len(),
2147 write_chunk.len(),
2148 &mut self.rx_buf,
2149 &mut self.tx_buf,
2150 )?;
2151 }
2152 self.wait_for_idle();
2153
2154 let bytes_read = self.rx_buf.read_received_data(read_chunk);
2155 debug_assert_eq!(bytes_read, read_chunk.len());
2156 }
2157
2158 if !read_remainder.is_empty() {
2159 self.read(read_remainder)
2160 } else if !write_remainder.is_empty() {
2161 self.write(write_remainder)
2162 } else {
2163 Ok(())
2164 }
2165 }
2166
2167 #[instability::unstable]
2169 pub fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
2170 self.wait_for_idle();
2171 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2172
2173 for chunk in words.chunks_mut(chunk_size) {
2174 self.tx_buf.fill(chunk);
2175 self.rx_buf.set_length(chunk.len());
2176
2177 unsafe {
2178 self.spi_dma.start_dma_transfer(
2179 chunk.len(),
2180 chunk.len(),
2181 &mut self.rx_buf,
2182 &mut self.tx_buf,
2183 )?;
2184 }
2185 self.wait_for_idle();
2186
2187 let bytes_read = self.rx_buf.read_received_data(chunk);
2188 debug_assert_eq!(bytes_read, chunk.len());
2189 }
2190
2191 Ok(())
2192 }
2193
2194 #[instability::unstable]
2196 pub fn half_duplex_read(
2197 &mut self,
2198 data_mode: DataMode,
2199 cmd: Command,
2200 address: Address,
2201 dummy: u8,
2202 buffer: &mut [u8],
2203 ) -> Result<(), Error> {
2204 if buffer.len() > self.rx_buf.capacity() {
2205 return Err(Error::from(DmaError::Overflow));
2206 }
2207 self.wait_for_idle();
2208 self.rx_buf.set_length(buffer.len());
2209
2210 unsafe {
2211 self.spi_dma.start_half_duplex_read(
2212 data_mode,
2213 cmd,
2214 address,
2215 dummy,
2216 buffer.len(),
2217 &mut self.rx_buf,
2218 )?;
2219 }
2220
2221 self.wait_for_idle();
2222
2223 let bytes_read = self.rx_buf.read_received_data(buffer);
2224 debug_assert_eq!(bytes_read, buffer.len());
2225
2226 Ok(())
2227 }
2228
2229 #[instability::unstable]
2231 pub fn half_duplex_write(
2232 &mut self,
2233 data_mode: DataMode,
2234 cmd: Command,
2235 address: Address,
2236 dummy: u8,
2237 buffer: &[u8],
2238 ) -> Result<(), Error> {
2239 if buffer.len() > self.tx_buf.capacity() {
2240 return Err(Error::from(DmaError::Overflow));
2241 }
2242 self.wait_for_idle();
2243 self.tx_buf.fill(buffer);
2244
2245 unsafe {
2246 self.spi_dma.start_half_duplex_write(
2247 data_mode,
2248 cmd,
2249 address,
2250 dummy,
2251 buffer.len(),
2252 &mut self.tx_buf,
2253 )?;
2254 }
2255
2256 self.wait_for_idle();
2257
2258 Ok(())
2259 }
2260 }
2261
2262 #[instability::unstable]
2263 impl<Dm> embassy_embedded_hal::SetConfig for SpiDmaBus<'_, Dm>
2264 where
2265 Dm: DriverMode,
2266 {
2267 type Config = Config;
2268 type ConfigError = ConfigError;
2269
2270 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
2271 self.apply_config(config)
2272 }
2273 }
2274
2275 mod asynch {
2277 #[cfg(any(doc, feature = "unstable"))]
2278 use core::cmp::min;
2279 use core::ops::{Deref, DerefMut};
2280
2281 use super::*;
2282
2283 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2284 struct DropGuard<I, F: FnOnce(I)> {
2285 inner: ManuallyDrop<I>,
2286 on_drop: ManuallyDrop<F>,
2287 }
2288
2289 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
2290 impl<I, F: FnOnce(I)> DropGuard<I, F> {
2291 fn new(inner: I, on_drop: F) -> Self {
2292 Self {
2293 inner: ManuallyDrop::new(inner),
2294 on_drop: ManuallyDrop::new(on_drop),
2295 }
2296 }
2297
2298 fn defuse(self) {}
2299 }
2300
2301 impl<I, F: FnOnce(I)> Drop for DropGuard<I, F> {
2302 fn drop(&mut self) {
2303 let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
2304 let on_drop = unsafe { ManuallyDrop::take(&mut self.on_drop) };
2305 (on_drop)(inner)
2306 }
2307 }
2308
2309 impl<I, F: FnOnce(I)> Deref for DropGuard<I, F> {
2310 type Target = I;
2311
2312 fn deref(&self) -> &I {
2313 &self.inner
2314 }
2315 }
2316
2317 impl<I, F: FnOnce(I)> DerefMut for DropGuard<I, F> {
2318 fn deref_mut(&mut self) -> &mut I {
2319 &mut self.inner
2320 }
2321 }
2322
2323 impl SpiDmaBus<'_, Async> {
2324 #[instability::unstable]
2326 pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2327 self.spi_dma.wait_for_idle_async().await;
2328 let chunk_size = self.rx_buf.capacity();
2329
2330 for chunk in words.chunks_mut(chunk_size) {
2331 self.rx_buf.set_length(chunk.len());
2332
2333 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2334
2335 unsafe {
2336 spi.start_dma_transfer(chunk.len(), 0, &mut self.rx_buf, &mut EmptyBuf)?
2337 };
2338
2339 spi.wait_for_idle_async().await;
2340
2341 let bytes_read = self.rx_buf.read_received_data(chunk);
2342 debug_assert_eq!(bytes_read, chunk.len());
2343
2344 spi.defuse();
2345 }
2346
2347 Ok(())
2348 }
2349
2350 #[instability::unstable]
2352 pub async fn write_async(&mut self, words: &[u8]) -> Result<(), Error> {
2353 self.spi_dma.wait_for_idle_async().await;
2354
2355 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2356 let chunk_size = self.tx_buf.capacity();
2357
2358 for chunk in words.chunks(chunk_size) {
2359 self.tx_buf.fill(chunk);
2360
2361 unsafe {
2362 spi.start_dma_transfer(0, chunk.len(), &mut EmptyBuf, &mut self.tx_buf)?
2363 };
2364
2365 spi.wait_for_idle_async().await;
2366 }
2367 spi.defuse();
2368
2369 Ok(())
2370 }
2371
2372 #[instability::unstable]
2375 pub async fn transfer_async(
2376 &mut self,
2377 read: &mut [u8],
2378 write: &[u8],
2379 ) -> Result<(), Error> {
2380 self.spi_dma.wait_for_idle_async().await;
2381
2382 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2383 let chunk_size = min(self.tx_buf.capacity(), self.rx_buf.capacity());
2384
2385 let common_length = min(read.len(), write.len());
2386 let (read_common, read_remainder) = read.split_at_mut(common_length);
2387 let (write_common, write_remainder) = write.split_at(common_length);
2388
2389 for (read_chunk, write_chunk) in read_common
2390 .chunks_mut(chunk_size)
2391 .zip(write_common.chunks(chunk_size))
2392 {
2393 self.tx_buf.fill(write_chunk);
2394 self.rx_buf.set_length(read_chunk.len());
2395
2396 unsafe {
2397 spi.start_dma_transfer(
2398 read_chunk.len(),
2399 write_chunk.len(),
2400 &mut self.rx_buf,
2401 &mut self.tx_buf,
2402 )?;
2403 }
2404 spi.wait_for_idle_async().await;
2405
2406 let bytes_read = self.rx_buf.read_received_data(read_chunk);
2407 debug_assert_eq!(bytes_read, read_chunk.len());
2408 }
2409
2410 spi.defuse();
2411
2412 if !read_remainder.is_empty() {
2413 self.read_async(read_remainder).await
2414 } else if !write_remainder.is_empty() {
2415 self.write_async(write_remainder).await
2416 } else {
2417 Ok(())
2418 }
2419 }
2420
2421 #[instability::unstable]
2424 pub async fn transfer_in_place_async(&mut self, words: &mut [u8]) -> Result<(), Error> {
2425 self.spi_dma.wait_for_idle_async().await;
2426
2427 let mut spi = DropGuard::new(&mut self.spi_dma, |spi| spi.cancel_transfer());
2428 for chunk in words.chunks_mut(self.tx_buf.capacity()) {
2429 self.tx_buf.fill(chunk);
2430 self.rx_buf.set_length(chunk.len());
2431
2432 unsafe {
2433 spi.start_dma_transfer(
2434 chunk.len(),
2435 chunk.len(),
2436 &mut self.rx_buf,
2437 &mut self.tx_buf,
2438 )?;
2439 }
2440 spi.wait_for_idle_async().await;
2441
2442 let bytes_read = self.rx_buf.read_received_data(chunk);
2443 debug_assert_eq!(bytes_read, chunk.len());
2444 }
2445
2446 spi.defuse();
2447
2448 Ok(())
2449 }
2450 }
2451
2452 #[instability::unstable]
2453 impl embedded_hal_async::spi::SpiBus for SpiDmaBus<'_, Async> {
2454 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2455 self.read_async(words).await
2456 }
2457
2458 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2459 self.write_async(words).await
2460 }
2461
2462 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2463 self.transfer_async(read, write).await
2464 }
2465
2466 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2467 self.transfer_in_place_async(words).await
2468 }
2469
2470 async fn flush(&mut self) -> Result<(), Self::Error> {
2471 Ok(())
2473 }
2474 }
2475 }
2476
2477 mod ehal1 {
2478 #[cfg(any(doc, feature = "unstable"))]
2479 use embedded_hal::spi::{ErrorType, SpiBus};
2480
2481 #[cfg(any(doc, feature = "unstable"))]
2482 use super::*;
2483
2484 #[instability::unstable]
2485 impl<Dm> ErrorType for SpiDmaBus<'_, Dm>
2486 where
2487 Dm: DriverMode,
2488 {
2489 type Error = Error;
2490 }
2491
2492 #[instability::unstable]
2493 impl<Dm> SpiBus for SpiDmaBus<'_, Dm>
2494 where
2495 Dm: DriverMode,
2496 {
2497 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2498 self.read(words)
2499 }
2500
2501 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2502 self.write(words)
2503 }
2504
2505 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2506 self.transfer(read, write)
2507 }
2508
2509 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2510 self.transfer_in_place(words)
2511 }
2512
2513 fn flush(&mut self) -> Result<(), Self::Error> {
2514 Ok(())
2516 }
2517 }
2518 }
2519}
2520
2521mod ehal1 {
2522 use embedded_hal::spi::SpiBus;
2523 use embedded_hal_async::spi::SpiBus as SpiBusAsync;
2524
2525 use super::*;
2526
2527 impl<Dm> embedded_hal::spi::ErrorType for Spi<'_, Dm>
2528 where
2529 Dm: DriverMode,
2530 {
2531 type Error = Error;
2532 }
2533
2534 impl<Dm> SpiBus for Spi<'_, Dm>
2535 where
2536 Dm: DriverMode,
2537 {
2538 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2539 self.driver().read(words)
2540 }
2541
2542 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2543 self.driver().write(words)
2544 }
2545
2546 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2547 if read.is_empty() {
2549 return SpiBus::write(self, write);
2550 } else if write.is_empty() {
2551 return SpiBus::read(self, read);
2552 }
2553
2554 let mut write_from = 0;
2555 let mut read_from = 0;
2556
2557 loop {
2558 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2560 let write_to = write_from + write_inc;
2561 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2563 let read_to = read_from + read_inc;
2564
2565 if (write_inc == 0) && (read_inc == 0) {
2566 break;
2567 }
2568
2569 if write_to < read_to {
2572 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2574 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2575 SpiBus::write(self, &empty)?;
2576 } else {
2577 SpiBus::write(self, &write[write_from..write_to])?;
2578 }
2579
2580 if read_inc > 0 {
2581 SpiBus::flush(self)?;
2582 self.driver()
2583 .read_from_fifo(&mut read[read_from..read_to])?;
2584 }
2585
2586 write_from = write_to;
2587 read_from = read_to;
2588 }
2589 Ok(())
2590 }
2591
2592 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2593 self.driver().transfer(words).map(|_| ())
2594 }
2595
2596 fn flush(&mut self) -> Result<(), Self::Error> {
2597 self.driver().flush()
2598 }
2599 }
2600
2601 impl SpiBusAsync for Spi<'_, Async> {
2602 async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2603 self.flush_async().await?;
2606 self.driver().read_async(words).await
2607 }
2608
2609 async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
2610 self.flush_async().await?;
2613 self.driver().write_async(words).await
2614 }
2615
2616 async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
2617 if read.is_empty() {
2619 return SpiBusAsync::write(self, write).await;
2620 } else if write.is_empty() {
2621 return SpiBusAsync::read(self, read).await;
2622 }
2623
2624 let mut write_from = 0;
2625 let mut read_from = 0;
2626
2627 loop {
2628 let write_inc = core::cmp::min(FIFO_SIZE, write.len() - write_from);
2630 let write_to = write_from + write_inc;
2631 let read_inc = core::cmp::min(FIFO_SIZE, read.len() - read_from);
2633 let read_to = read_from + read_inc;
2634
2635 if (write_inc == 0) && (read_inc == 0) {
2636 break;
2637 }
2638
2639 if write_to < read_to {
2642 let mut empty = [EMPTY_WRITE_PAD; FIFO_SIZE];
2644 empty[0..write_inc].copy_from_slice(&write[write_from..write_to]);
2645 SpiBusAsync::write(self, &empty).await?;
2646 } else {
2647 SpiBusAsync::write(self, &write[write_from..write_to]).await?;
2648 }
2649
2650 if read_inc > 0 {
2651 self.driver()
2652 .read_from_fifo(&mut read[read_from..read_to])?;
2653 }
2654
2655 write_from = write_to;
2656 read_from = read_to;
2657 }
2658 Ok(())
2659 }
2660
2661 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
2662 self.transfer_in_place_async(words).await
2663 }
2664
2665 async fn flush(&mut self) -> Result<(), Self::Error> {
2666 self.flush_async().await
2667 }
2668 }
2669}
2670
2671#[doc(hidden)]
2673pub trait PeripheralInstance: private::Sealed + Into<AnySpi> + DmaEligible + 'static {
2674 fn info(&self) -> &'static Info;
2676}
2677
2678#[doc(hidden)]
2680pub trait QspiInstance: PeripheralInstance {}
2681
2682#[doc(hidden)]
2684#[non_exhaustive]
2685pub struct Info {
2686 pub register_block: *const RegisterBlock,
2690
2691 pub peripheral: crate::system::Peripheral,
2693
2694 pub interrupt: crate::peripherals::Interrupt,
2696
2697 pub sclk: OutputSignal,
2699
2700 pub mosi: OutputSignal,
2702
2703 pub miso: InputSignal,
2705
2706 pub cs: OutputSignal,
2708
2709 pub sio0_input: InputSignal,
2711
2712 pub sio1_output: OutputSignal,
2714
2715 pub sio2_output: Option<OutputSignal>,
2717
2718 pub sio2_input: Option<InputSignal>,
2720
2721 pub sio3_output: Option<OutputSignal>,
2723
2724 pub sio3_input: Option<InputSignal>,
2726}
2727
2728struct DmaDriver {
2729 driver: Driver,
2730 dma_peripheral: crate::dma::DmaPeripheral,
2731}
2732
2733impl DmaDriver {
2734 fn abort_transfer(&self) {
2735 self.driver.configure_datalen(1, 1);
2736 self.driver.update();
2737 }
2738
2739 fn regs(&self) -> &RegisterBlock {
2740 self.driver.regs()
2741 }
2742
2743 #[allow(clippy::too_many_arguments)]
2744 #[cfg_attr(place_spi_driver_in_ram, ram)]
2745 unsafe fn start_transfer_dma<RX: Rx, TX: Tx>(
2746 &self,
2747 _full_duplex: bool,
2748 rx_len: usize,
2749 tx_len: usize,
2750 rx_buffer: &mut impl DmaRxBuffer,
2751 tx_buffer: &mut impl DmaTxBuffer,
2752 rx: &mut RX,
2753 tx: &mut TX,
2754 ) -> Result<(), Error> {
2755 #[cfg(esp32s2)]
2756 {
2757 self.regs().dma_out_link().write(|w| w.bits(0));
2759 self.regs().dma_in_link().write(|w| w.bits(0));
2760 }
2761
2762 self.driver.configure_datalen(rx_len, tx_len);
2763
2764 self.regs()
2766 .user()
2767 .modify(|_, w| w.usr_miso().bit(rx_len > 0).usr_mosi().bit(tx_len > 0));
2768
2769 self.enable_dma();
2770
2771 if rx_len > 0 {
2772 rx.prepare_transfer(self.dma_peripheral, rx_buffer)
2773 .and_then(|_| rx.start_transfer())?;
2774 } else {
2775 #[cfg(esp32)]
2776 {
2777 if _full_duplex {
2780 self.regs()
2781 .dma_in_link()
2782 .modify(|_, w| unsafe { w.inlink_addr().bits(0) });
2783 self.regs()
2784 .dma_in_link()
2785 .modify(|_, w| w.inlink_start().set_bit());
2786 }
2787 }
2788 }
2789 if tx_len > 0 {
2790 tx.prepare_transfer(self.dma_peripheral, tx_buffer)
2791 .and_then(|_| tx.start_transfer())?;
2792 }
2793
2794 #[cfg(gdma)]
2795 self.reset_dma();
2796
2797 self.driver.start_operation();
2798
2799 Ok(())
2800 }
2801
2802 fn enable_dma(&self) {
2803 #[cfg(gdma)]
2804 self.regs().dma_conf().modify(|_, w| {
2806 w.dma_tx_ena().set_bit();
2807 w.dma_rx_ena().set_bit()
2808 });
2809
2810 #[cfg(pdma)]
2811 self.reset_dma();
2812 }
2813
2814 fn reset_dma(&self) {
2815 fn set_reset_bit(reg_block: &RegisterBlock, bit: bool) {
2816 #[cfg(pdma)]
2817 reg_block.dma_conf().modify(|_, w| {
2818 w.out_rst().bit(bit);
2819 w.in_rst().bit(bit);
2820 w.ahbm_fifo_rst().bit(bit);
2821 w.ahbm_rst().bit(bit)
2822 });
2823 #[cfg(gdma)]
2824 reg_block.dma_conf().modify(|_, w| {
2825 w.rx_afifo_rst().bit(bit);
2826 w.buf_afifo_rst().bit(bit);
2827 w.dma_afifo_rst().bit(bit)
2828 });
2829 }
2830
2831 set_reset_bit(self.regs(), true);
2832 set_reset_bit(self.regs(), false);
2833 self.clear_dma_interrupts();
2834 }
2835
2836 #[cfg(gdma)]
2837 fn clear_dma_interrupts(&self) {
2838 self.regs().dma_int_clr().write(|w| {
2839 w.dma_infifo_full_err().clear_bit_by_one();
2840 w.dma_outfifo_empty_err().clear_bit_by_one();
2841 w.trans_done().clear_bit_by_one();
2842 w.mst_rx_afifo_wfull_err().clear_bit_by_one();
2843 w.mst_tx_afifo_rempty_err().clear_bit_by_one()
2844 });
2845 }
2846
2847 #[cfg(pdma)]
2848 fn clear_dma_interrupts(&self) {
2849 self.regs().dma_int_clr().write(|w| {
2850 w.inlink_dscr_empty().clear_bit_by_one();
2851 w.outlink_dscr_error().clear_bit_by_one();
2852 w.inlink_dscr_error().clear_bit_by_one();
2853 w.in_done().clear_bit_by_one();
2854 w.in_err_eof().clear_bit_by_one();
2855 w.in_suc_eof().clear_bit_by_one();
2856 w.out_done().clear_bit_by_one();
2857 w.out_eof().clear_bit_by_one();
2858 w.out_total_eof().clear_bit_by_one()
2859 });
2860 }
2861}
2862
2863struct Driver {
2864 info: &'static Info,
2865 state: &'static State,
2866}
2867
2868impl Driver {
2871 pub fn regs(&self) -> &RegisterBlock {
2873 unsafe { &*self.info.register_block }
2874 }
2875
2876 fn init(&self) {
2878 self.regs().user().modify(|_, w| {
2879 w.usr_miso_highpart().clear_bit();
2880 w.usr_mosi_highpart().clear_bit();
2881 w.doutdin().set_bit();
2882 w.usr_miso().set_bit();
2883 w.usr_mosi().set_bit();
2884 w.cs_hold().set_bit();
2885 w.usr_dummy_idle().set_bit();
2886 w.usr_addr().clear_bit();
2887 w.usr_command().clear_bit()
2888 });
2889
2890 #[cfg(gdma)]
2891 self.regs().clk_gate().modify(|_, w| {
2892 w.clk_en().set_bit();
2893 w.mst_clk_active().set_bit();
2894 w.mst_clk_sel().set_bit()
2895 });
2896
2897 #[cfg(any(esp32c6, esp32h2))]
2898 unsafe {
2899 crate::peripherals::PCR::regs()
2902 .spi2_clkm_conf()
2903 .modify(|_, w| w.spi2_clkm_sel().bits(1));
2904 }
2905
2906 #[cfg(gdma)]
2907 self.regs().ctrl().modify(|_, w| {
2908 w.q_pol().clear_bit();
2909 w.d_pol().clear_bit();
2910 w.hold_pol().clear_bit()
2911 });
2912
2913 #[cfg(esp32s2)]
2914 self.regs().ctrl().modify(|_, w| {
2915 w.q_pol().clear_bit();
2916 w.d_pol().clear_bit();
2917 w.wp().clear_bit()
2918 });
2919
2920 #[cfg(esp32)]
2921 self.regs().ctrl().modify(|_, w| w.wp().clear_bit());
2922
2923 #[cfg(not(esp32))]
2924 self.regs().misc().write(|w| unsafe { w.bits(0) });
2925
2926 self.regs().slave().write(|w| unsafe { w.bits(0) });
2927 }
2928
2929 #[cfg(not(esp32))]
2930 fn init_spi_data_mode(
2931 &self,
2932 cmd_mode: DataMode,
2933 address_mode: DataMode,
2934 data_mode: DataMode,
2935 ) -> Result<(), Error> {
2936 self.regs().ctrl().modify(|_, w| {
2937 w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
2938 w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
2939 w.faddr_dual().bit(address_mode == DataMode::Dual);
2940 w.faddr_quad().bit(address_mode == DataMode::Quad);
2941 w.fread_dual().bit(data_mode == DataMode::Dual);
2942 w.fread_quad().bit(data_mode == DataMode::Quad)
2943 });
2944 self.regs().user().modify(|_, w| {
2945 w.fwrite_dual().bit(data_mode == DataMode::Dual);
2946 w.fwrite_quad().bit(data_mode == DataMode::Quad)
2947 });
2948 Ok(())
2949 }
2950
2951 #[cfg(esp32)]
2952 fn init_spi_data_mode(
2953 &self,
2954 cmd_mode: DataMode,
2955 address_mode: DataMode,
2956 data_mode: DataMode,
2957 ) -> Result<(), Error> {
2958 match cmd_mode {
2959 DataMode::Single => (),
2960 DataMode::SingleTwoDataLines => (),
2961 _ => return Err(Error::Unsupported),
2963 }
2964
2965 match address_mode {
2966 DataMode::Single | DataMode::SingleTwoDataLines => {
2967 self.regs().ctrl().modify(|_, w| {
2968 w.fread_dio().clear_bit();
2969 w.fread_qio().clear_bit();
2970 w.fread_dual().bit(data_mode == DataMode::Dual);
2971 w.fread_quad().bit(data_mode == DataMode::Quad)
2972 });
2973
2974 self.regs().user().modify(|_, w| {
2975 w.fwrite_dio().clear_bit();
2976 w.fwrite_qio().clear_bit();
2977 w.fwrite_dual().bit(data_mode == DataMode::Dual);
2978 w.fwrite_quad().bit(data_mode == DataMode::Quad)
2979 });
2980 }
2981 address_mode if address_mode == data_mode => {
2982 self.regs().ctrl().modify(|_, w| {
2983 w.fastrd_mode().set_bit();
2984 w.fread_dio().bit(address_mode == DataMode::Dual);
2985 w.fread_qio().bit(address_mode == DataMode::Quad);
2986 w.fread_dual().clear_bit();
2987 w.fread_quad().clear_bit()
2988 });
2989
2990 self.regs().user().modify(|_, w| {
2991 w.fwrite_dio().bit(address_mode == DataMode::Dual);
2992 w.fwrite_qio().bit(address_mode == DataMode::Quad);
2993 w.fwrite_dual().clear_bit();
2994 w.fwrite_quad().clear_bit()
2995 });
2996 }
2997 _ => return Err(Error::Unsupported),
2999 }
3000
3001 Ok(())
3002 }
3003
3004 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3006 fn enable_listen(&self, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
3007 cfg_if::cfg_if! {
3008 if #[cfg(esp32)] {
3009 self.regs().slave().modify(|_, w| {
3010 for interrupt in interrupts {
3011 match interrupt {
3012 SpiInterrupt::TransferDone => w.trans_inten().bit(enable),
3013 };
3014 }
3015 w
3016 });
3017 } else if #[cfg(esp32s2)] {
3018 self.regs().slave().modify(|_, w| {
3019 for interrupt in interrupts {
3020 match interrupt {
3021 SpiInterrupt::TransferDone => w.int_trans_done_en().bit(enable),
3022 SpiInterrupt::DmaSegmentedTransferDone => w.int_dma_seg_trans_en().bit(enable),
3023 };
3024 }
3025 w
3026 });
3027 } else {
3028 self.regs().dma_int_ena().modify(|_, w| {
3029 for interrupt in interrupts {
3030 match interrupt {
3031 SpiInterrupt::TransferDone => w.trans_done().bit(enable),
3032 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
3033 SpiInterrupt::App2 => w.app2().bit(enable),
3034 SpiInterrupt::App1 => w.app1().bit(enable),
3035 };
3036 }
3037 w
3038 });
3039 }
3040 }
3041 }
3042
3043 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3045 fn interrupts(&self) -> EnumSet<SpiInterrupt> {
3046 let mut res = EnumSet::new();
3047
3048 cfg_if::cfg_if! {
3049 if #[cfg(esp32)] {
3050 if self.regs().slave().read().trans_done().bit() {
3051 res.insert(SpiInterrupt::TransferDone);
3052 }
3053 } else if #[cfg(esp32s2)] {
3054 if self.regs().slave().read().trans_done().bit() {
3055 res.insert(SpiInterrupt::TransferDone);
3056 }
3057 if self.regs().hold().read().dma_seg_trans_done().bit() {
3058 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3059 }
3060 } else {
3061 let ints = self.regs().dma_int_raw().read();
3062
3063 if ints.trans_done().bit() {
3064 res.insert(SpiInterrupt::TransferDone);
3065 }
3066 if ints.dma_seg_trans_done().bit() {
3067 res.insert(SpiInterrupt::DmaSegmentedTransferDone);
3068 }
3069 if ints.app2().bit() {
3070 res.insert(SpiInterrupt::App2);
3071 }
3072 if ints.app1().bit() {
3073 res.insert(SpiInterrupt::App1);
3074 }
3075 }
3076 }
3077
3078 res
3079 }
3080
3081 #[cfg_attr(not(feature = "unstable"), allow(dead_code))]
3083 fn clear_interrupts(&self, interrupts: EnumSet<SpiInterrupt>) {
3084 cfg_if::cfg_if! {
3085 if #[cfg(esp32)] {
3086 for interrupt in interrupts {
3087 match interrupt {
3088 SpiInterrupt::TransferDone => {
3089 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3090 }
3091 }
3092 }
3093 } else if #[cfg(esp32s2)] {
3094 for interrupt in interrupts {
3095 match interrupt {
3096 SpiInterrupt::TransferDone => {
3097 self.regs().slave().modify(|_, w| w.trans_done().clear_bit());
3098 }
3099
3100 SpiInterrupt::DmaSegmentedTransferDone => {
3101 self.regs()
3102 .hold()
3103 .modify(|_, w| w.dma_seg_trans_done().clear_bit());
3104 }
3105 }
3106 }
3107 } else {
3108 self.regs().dma_int_clr().write(|w| {
3109 for interrupt in interrupts {
3110 match interrupt {
3111 SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
3112 SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
3113 SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
3114 SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
3115 };
3116 }
3117 w
3118 });
3119 }
3120 }
3121 }
3122
3123 fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
3124 config.validate()?;
3125 self.ch_bus_freq(config)?;
3126 self.set_bit_order(config.read_bit_order, config.write_bit_order);
3127 self.set_data_mode(config.mode);
3128 Ok(())
3129 }
3130
3131 fn set_data_mode(&self, data_mode: Mode) {
3132 cfg_if::cfg_if! {
3133 if #[cfg(esp32)] {
3134 let pin_reg = self.regs().pin();
3135 } else {
3136 let pin_reg = self.regs().misc();
3137 }
3138 };
3139
3140 pin_reg.modify(|_, w| {
3141 w.ck_idle_edge()
3142 .bit(matches!(data_mode, Mode::_2 | Mode::_3))
3143 });
3144 self.regs().user().modify(|_, w| {
3145 w.ck_out_edge()
3146 .bit(matches!(data_mode, Mode::_1 | Mode::_2))
3147 });
3148 }
3149
3150 fn ch_bus_freq(&self, bus_clock_config: &Config) -> Result<(), ConfigError> {
3151 fn enable_clocks(_reg_block: &RegisterBlock, _enable: bool) {
3152 #[cfg(gdma)]
3153 _reg_block.clk_gate().modify(|_, w| {
3154 w.clk_en().bit(_enable);
3155 w.mst_clk_active().bit(_enable);
3156 w.mst_clk_sel().bit(true) });
3158 }
3159
3160 let raw = bus_clock_config.raw_clock_reg_value()?;
3162
3163 enable_clocks(self.regs(), false);
3164 self.regs().clock().write(|w| unsafe { w.bits(raw) });
3165 enable_clocks(self.regs(), true);
3166
3167 Ok(())
3168 }
3169
3170 #[cfg(not(any(esp32, esp32c3, esp32s2)))]
3171 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3172 let read_value = match read_order {
3173 BitOrder::MsbFirst => 0,
3174 BitOrder::LsbFirst => 1,
3175 };
3176 let write_value = match write_order {
3177 BitOrder::MsbFirst => 0,
3178 BitOrder::LsbFirst => 1,
3179 };
3180 self.regs().ctrl().modify(|_, w| unsafe {
3181 w.rd_bit_order().bits(read_value);
3182 w.wr_bit_order().bits(write_value);
3183 w
3184 });
3185 }
3186
3187 #[cfg(any(esp32, esp32c3, esp32s2))]
3188 fn set_bit_order(&self, read_order: BitOrder, write_order: BitOrder) {
3189 let read_value = match read_order {
3190 BitOrder::MsbFirst => false,
3191 BitOrder::LsbFirst => true,
3192 };
3193 let write_value = match write_order {
3194 BitOrder::MsbFirst => false,
3195 BitOrder::LsbFirst => true,
3196 };
3197 self.regs().ctrl().modify(|_, w| {
3198 w.rd_bit_order().bit(read_value);
3199 w.wr_bit_order().bit(write_value);
3200 w
3201 });
3202 }
3203
3204 #[cfg_attr(place_spi_driver_in_ram, ram)]
3205 fn fill_fifo(&self, chunk: &[u8]) {
3206 let mut c_iter = chunk.chunks_exact(4);
3208 let mut w_iter = self.regs().w_iter();
3209 for c in c_iter.by_ref() {
3210 if let Some(w_reg) = w_iter.next() {
3211 let word = (c[0] as u32)
3212 | ((c[1] as u32) << 8)
3213 | ((c[2] as u32) << 16)
3214 | ((c[3] as u32) << 24);
3215 w_reg.write(|w| w.buf().set(word));
3216 }
3217 }
3218 let rem = c_iter.remainder();
3219 if !rem.is_empty() {
3220 if let Some(w_reg) = w_iter.next() {
3221 let word = match rem.len() {
3222 3 => (rem[0] as u32) | ((rem[1] as u32) << 8) | ((rem[2] as u32) << 16),
3223 2 => (rem[0] as u32) | ((rem[1] as u32) << 8),
3224 1 => rem[0] as u32,
3225 _ => unreachable!(),
3226 };
3227 w_reg.write(|w| w.buf().set(word));
3228 }
3229 }
3230 }
3231
3232 #[cfg_attr(place_spi_driver_in_ram, ram)]
3238 fn write(&self, words: &[u8]) -> Result<(), Error> {
3239 let num_chunks = words.len() / FIFO_SIZE;
3240
3241 self.flush()?;
3244
3245 for (i, chunk) in words.chunks(FIFO_SIZE).enumerate() {
3248 self.configure_datalen(0, chunk.len());
3249 self.fill_fifo(chunk);
3250
3251 self.start_operation();
3252
3253 if i < num_chunks {
3257 self.flush()?;
3258 }
3259 }
3260 Ok(())
3261 }
3262
3263 #[cfg_attr(place_spi_driver_in_ram, ram)]
3265 async fn write_async(&self, words: &[u8]) -> Result<(), Error> {
3266 for chunk in words.chunks(FIFO_SIZE) {
3269 self.configure_datalen(0, chunk.len());
3270 self.fill_fifo(chunk);
3271 self.execute_operation_async().await;
3272 }
3273 Ok(())
3274 }
3275
3276 #[cfg_attr(place_spi_driver_in_ram, ram)]
3282 fn read(&self, words: &mut [u8]) -> Result<(), Error> {
3283 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3284
3285 for chunk in words.chunks_mut(FIFO_SIZE) {
3286 self.write(&empty_array[0..chunk.len()])?;
3287 self.flush()?;
3288 self.read_from_fifo(chunk)?;
3289 }
3290 Ok(())
3291 }
3292
3293 #[cfg_attr(place_spi_driver_in_ram, ram)]
3299 async fn read_async(&self, words: &mut [u8]) -> Result<(), Error> {
3300 let empty_array = [EMPTY_WRITE_PAD; FIFO_SIZE];
3301
3302 for chunk in words.chunks_mut(FIFO_SIZE) {
3303 self.write_async(&empty_array[0..chunk.len()]).await?;
3304 self.read_from_fifo(chunk)?;
3305 }
3306 Ok(())
3307 }
3308
3309 #[cfg_attr(place_spi_driver_in_ram, ram)]
3316 fn read_from_fifo(&self, words: &mut [u8]) -> Result<(), Error> {
3317 let reg_block = self.regs();
3318
3319 for chunk in words.chunks_mut(FIFO_SIZE) {
3320 self.configure_datalen(chunk.len(), 0);
3321
3322 for (index, w_reg) in (0..chunk.len()).step_by(4).zip(reg_block.w_iter()) {
3323 let reg_val = w_reg.read().bits();
3324 let bytes = reg_val.to_le_bytes();
3325
3326 let len = usize::min(chunk.len(), index + 4) - index;
3327 chunk[index..(index + len)].clone_from_slice(&bytes[0..len]);
3328 }
3329 }
3330
3331 Ok(())
3332 }
3333
3334 fn busy(&self) -> bool {
3335 let reg_block = self.regs();
3336 reg_block.cmd().read().usr().bit_is_set()
3337 }
3338
3339 fn flush(&self) -> Result<(), Error> {
3341 while self.busy() {
3342 }
3344 Ok(())
3345 }
3346
3347 #[cfg_attr(place_spi_driver_in_ram, ram)]
3348 fn transfer<'w>(&self, words: &'w mut [u8]) -> Result<&'w [u8], Error> {
3349 for chunk in words.chunks_mut(FIFO_SIZE) {
3350 self.write(chunk)?;
3351 self.flush()?;
3352 self.read_from_fifo(chunk)?;
3353 }
3354
3355 Ok(words)
3356 }
3357
3358 #[cfg_attr(place_spi_driver_in_ram, ram)]
3359 async fn transfer_in_place_async(&self, words: &mut [u8]) -> Result<(), Error> {
3360 for chunk in words.chunks_mut(FIFO_SIZE) {
3361 self.write_async(chunk).await?;
3362 self.read_from_fifo(chunk)?;
3363 }
3364
3365 Ok(())
3366 }
3367
3368 fn start_operation(&self) {
3369 self.update();
3370 self.regs().cmd().modify(|_, w| w.usr().set_bit());
3371 }
3372
3373 async fn execute_operation_async(&self) {
3375 let future = SpiFuture::setup(self).await;
3378 self.start_operation();
3379 future.await;
3380 }
3381
3382 #[allow(clippy::too_many_arguments)]
3383 fn setup_half_duplex(
3384 &self,
3385 is_write: bool,
3386 cmd: Command,
3387 address: Address,
3388 dummy_idle: bool,
3389 dummy: u8,
3390 no_mosi_miso: bool,
3391 data_mode: DataMode,
3392 ) -> Result<(), Error> {
3393 let three_wire = cmd.mode() == DataMode::Single
3394 || address.mode() == DataMode::Single
3395 || data_mode == DataMode::Single;
3396
3397 if three_wire
3398 && ((cmd != Command::None && cmd.mode() != DataMode::Single)
3399 || (address != Address::None && address.mode() != DataMode::Single)
3400 || data_mode != DataMode::Single)
3401 {
3402 return Err(Error::Unsupported);
3403 }
3404
3405 self.init_spi_data_mode(cmd.mode(), address.mode(), data_mode)?;
3406
3407 let reg_block = self.regs();
3408 reg_block.user().modify(|_, w| {
3409 w.usr_miso_highpart().clear_bit();
3410 w.usr_mosi_highpart().clear_bit();
3411 w.sio().bit(three_wire);
3412 w.doutdin().clear_bit();
3413 w.usr_miso().bit(!is_write && !no_mosi_miso);
3414 w.usr_mosi().bit(is_write && !no_mosi_miso);
3415 w.cs_hold().set_bit();
3416 w.usr_dummy_idle().bit(dummy_idle);
3417 w.usr_dummy().bit(dummy != 0);
3418 w.usr_addr().bit(!address.is_none());
3419 w.usr_command().bit(!cmd.is_none())
3420 });
3421
3422 #[cfg(gdma)]
3423 reg_block.clk_gate().modify(|_, w| {
3424 w.clk_en().set_bit();
3425 w.mst_clk_active().set_bit();
3426 w.mst_clk_sel().set_bit()
3427 });
3428
3429 #[cfg(any(esp32c6, esp32h2))]
3430 crate::peripherals::PCR::regs()
3432 .spi2_clkm_conf()
3433 .modify(|_, w| unsafe { w.spi2_clkm_sel().bits(1) });
3434
3435 #[cfg(not(esp32))]
3436 reg_block.misc().write(|w| unsafe { w.bits(0) });
3437
3438 reg_block.slave().write(|w| unsafe { w.bits(0) });
3439
3440 self.update();
3441
3442 self.set_up_common_phases(cmd, address, dummy);
3444
3445 Ok(())
3446 }
3447
3448 fn set_up_common_phases(&self, cmd: Command, address: Address, dummy: u8) {
3449 let reg_block = self.regs();
3450 if !cmd.is_none() {
3451 reg_block.user2().modify(|_, w| unsafe {
3452 w.usr_command_bitlen().bits((cmd.width() - 1) as u8);
3453 w.usr_command_value().bits(cmd.value())
3454 });
3455 }
3456
3457 if !address.is_none() {
3458 reg_block
3459 .user1()
3460 .modify(|_, w| unsafe { w.usr_addr_bitlen().bits((address.width() - 1) as u8) });
3461
3462 let addr = address.value() << (32 - address.width());
3463 #[cfg(not(esp32))]
3464 reg_block
3465 .addr()
3466 .write(|w| unsafe { w.usr_addr_value().bits(addr) });
3467 #[cfg(esp32)]
3468 reg_block.addr().write(|w| unsafe { w.bits(addr) });
3469 }
3470
3471 if dummy > 0 {
3472 reg_block
3473 .user1()
3474 .modify(|_, w| unsafe { w.usr_dummy_cyclelen().bits(dummy - 1) });
3475 }
3476 }
3477
3478 fn update(&self) {
3479 cfg_if::cfg_if! {
3480 if #[cfg(gdma)] {
3481 let reg_block = self.regs();
3482
3483 reg_block.cmd().modify(|_, w| w.update().set_bit());
3484
3485 while reg_block.cmd().read().update().bit_is_set() {
3486 }
3488 } else {
3489 }
3491 }
3492 }
3493
3494 fn configure_datalen(&self, rx_len_bytes: usize, tx_len_bytes: usize) {
3495 let reg_block = self.regs();
3496
3497 let rx_len = rx_len_bytes as u32 * 8;
3498 let tx_len = tx_len_bytes as u32 * 8;
3499
3500 let rx_len = rx_len.saturating_sub(1);
3501 let tx_len = tx_len.saturating_sub(1);
3502
3503 cfg_if::cfg_if! {
3504 if #[cfg(esp32)] {
3505 let len = rx_len.max(tx_len);
3506 reg_block
3507 .mosi_dlen()
3508 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(len) });
3509
3510 reg_block
3511 .miso_dlen()
3512 .write(|w| unsafe { w.usr_miso_dbitlen().bits(len) });
3513 } else if #[cfg(esp32s2)] {
3514 reg_block
3515 .mosi_dlen()
3516 .write(|w| unsafe { w.usr_mosi_dbitlen().bits(tx_len) });
3517
3518 reg_block
3519 .miso_dlen()
3520 .write(|w| unsafe { w.usr_miso_dbitlen().bits(rx_len) });
3521 } else {
3522 reg_block
3523 .ms_dlen()
3524 .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
3525 }
3526
3527 }
3528 }
3529}
3530
3531impl PartialEq for Info {
3532 fn eq(&self, other: &Self) -> bool {
3533 self.register_block == other.register_block
3534 }
3535}
3536
3537unsafe impl Sync for Info {}
3538
3539macro_rules! spi_instance {
3543 ($num:literal, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident $(, $sio2:ident, $sio3:ident)?) => {
3544 paste::paste! {
3545 impl PeripheralInstance for crate::peripherals::[<SPI $num>] {
3546 #[inline(always)]
3547 fn info(&self) -> &'static Info {
3548 static INFO: Info = Info {
3549 register_block: crate::peripherals::[<SPI $num>]::regs(),
3550 peripheral: crate::system::Peripheral::[<Spi $num>],
3551 interrupt: crate::peripherals::Interrupt::[<SPI $num>],
3552 sclk: OutputSignal::$sclk,
3553 mosi: OutputSignal::$mosi,
3554 miso: InputSignal::$miso,
3555 cs: OutputSignal::$cs,
3556 sio0_input: InputSignal::$mosi,
3557 sio1_output: OutputSignal::$miso,
3558 sio2_output: $crate::if_set!($(Some(OutputSignal::$sio2))?, None),
3559 sio2_input: $crate::if_set!($(Some(InputSignal::$sio2))?, None),
3560 sio3_output: $crate::if_set!($(Some(OutputSignal::$sio3))?, None),
3561 sio3_input: $crate::if_set!($(Some(InputSignal::$sio3))?, None),
3562 };
3563
3564 &INFO
3565 }
3566 }
3567
3568 $(
3569 $crate::ignore!($sio2);
3571 impl QspiInstance for crate::peripherals::[<SPI $num>] {}
3572 )?
3573 }
3574 }
3575}
3576
3577#[cfg(spi2)]
3578cfg_if::cfg_if! {
3579 if #[cfg(esp32)] {
3580 spi_instance!(2, HSPICLK, HSPID, HSPIQ, HSPICS0, HSPIWP, HSPIHD);
3581 } else if #[cfg(any(esp32s2, esp32s3))] {
3582 spi_instance!(2, FSPICLK, FSPID, FSPIQ, FSPICS0, FSPIWP, FSPIHD);
3583 } else {
3584 spi_instance!(2, FSPICLK_MUX, FSPID, FSPIQ, FSPICS0, FSPIWP, FSPIHD);
3585 }
3586}
3587
3588#[cfg(spi3)]
3589cfg_if::cfg_if! {
3590 if #[cfg(esp32)] {
3591 spi_instance!(3, VSPICLK, VSPID, VSPIQ, VSPICS0, HSPIWP, HSPIHD);
3592 } else if #[cfg(esp32s3)] {
3593 spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, SPI3_CS0, SPI3_WP, SPI3_HD);
3594 } else {
3595 spi_instance!(3, SPI3_CLK, SPI3_D, SPI3_Q, SPI3_CS0);
3596 }
3597}
3598
3599impl PeripheralInstance for super::AnySpi {
3600 delegate::delegate! {
3601 to match &self.0 {
3602 super::AnySpiInner::Spi2(spi) => spi,
3603 #[cfg(spi3)]
3604 super::AnySpiInner::Spi3(spi) => spi,
3605 } {
3606 fn info(&self) -> &'static Info;
3607 }
3608 }
3609}
3610
3611impl QspiInstance for super::AnySpi {}
3612
3613#[doc(hidden)]
3614pub struct State {
3615 waker: AtomicWaker,
3616}
3617
3618#[cfg_attr(place_spi_driver_in_ram, ram)]
3619fn handle_async<I: Instance>(instance: I) {
3620 let state = instance.state();
3621 let info = instance.info();
3622
3623 let driver = Driver { info, state };
3624 if driver.interrupts().contains(SpiInterrupt::TransferDone) {
3625 state.waker.wake();
3626 driver.enable_listen(SpiInterrupt::TransferDone.into(), false);
3627 }
3628}
3629
3630#[doc(hidden)]
3631pub trait Instance: PeripheralInstance {
3632 fn state(&self) -> &'static State;
3633 fn handler(&self) -> InterruptHandler;
3634}
3635
3636macro_rules! master_instance {
3637 ($peri:ident) => {
3638 impl Instance for $crate::peripherals::$peri {
3639 fn state(&self) -> &'static State {
3640 static STATE: State = State {
3641 waker: AtomicWaker::new(),
3642 };
3643
3644 &STATE
3645 }
3646
3647 fn handler(&self) -> InterruptHandler {
3648 #[$crate::handler]
3649 #[cfg_attr(place_spi_driver_in_ram, ram)]
3650 fn handle() {
3651 handle_async(unsafe { $crate::peripherals::$peri::steal() })
3652 }
3653
3654 handle
3655 }
3656 }
3657 };
3658}
3659
3660master_instance!(SPI2);
3661#[cfg(spi3)]
3662master_instance!(SPI3);
3663
3664impl Instance for super::AnySpi {
3665 delegate::delegate! {
3666 to match &self.0 {
3667 super::AnySpiInner::Spi2(spi) => spi,
3668 #[cfg(spi3)]
3669 super::AnySpiInner::Spi3(spi) => spi,
3670 } {
3671 fn state(&self) -> &'static State;
3672 fn handler(&self) -> InterruptHandler;
3673 }
3674 }
3675}
3676
3677struct SpiFuture<'a> {
3678 driver: &'a Driver,
3679}
3680
3681impl<'a> SpiFuture<'a> {
3682 fn setup(driver: &'a Driver) -> impl Future<Output = Self> {
3683 core::future::poll_fn(move |cx| {
3686 driver.state.waker.register(cx.waker());
3687 driver.clear_interrupts(SpiInterrupt::TransferDone.into());
3688 driver.enable_listen(SpiInterrupt::TransferDone.into(), true);
3689 Poll::Ready(Self { driver })
3690 })
3691 }
3692}
3693
3694use core::{
3695 future::Future,
3696 pin::Pin,
3697 task::{Context, Poll},
3698};
3699
3700impl Future for SpiFuture<'_> {
3701 type Output = ();
3702
3703 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
3704 if self
3705 .driver
3706 .interrupts()
3707 .contains(SpiInterrupt::TransferDone)
3708 {
3709 self.driver
3710 .clear_interrupts(SpiInterrupt::TransferDone.into());
3711 return Poll::Ready(());
3712 }
3713
3714 Poll::Pending
3715 }
3716}
3717
3718impl Drop for SpiFuture<'_> {
3719 fn drop(&mut self) {
3720 self.driver
3721 .enable_listen(SpiInterrupt::TransferDone.into(), false);
3722 }
3723}