1use core::marker::PhantomData;
2use core::ops::{Deref, DerefMut};
3
4use crate::dma::traits::{DMASet, PeriAddress};
5use crate::dma::{MemoryToPeripheral, PeripheralToMemory};
6use crate::gpio;
7use crate::pac;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub enum Polarity {
12 IdleLow,
14 IdleHigh,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub enum Phase {
21 CaptureOnFirstTransition,
23 CaptureOnSecondTransition,
25}
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct Mode {
30 pub polarity: Polarity,
32 pub phase: Phase,
34}
35
36mod hal_02;
37mod hal_1;
38
39use crate::pac::{spi1, RCC};
40use crate::rcc::{self, Rcc};
41
42use enumflags2::BitFlags;
43use fugit::HertzU32 as Hertz;
44
45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
47#[derive(Debug, Eq, PartialEq, Copy, Clone)]
48#[non_exhaustive]
49pub enum Error {
50 Overrun,
52 ModeFault,
54 Crc,
56}
57
58#[enumflags2::bitflags]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61#[derive(Debug, Eq, PartialEq, Copy, Clone)]
62#[repr(u16)]
63pub enum Event {
64 Error = 1 << 5,
71 RxNotEmpty = 1 << 6,
75 TxEmpty = 1 << 7,
79}
80
81#[enumflags2::bitflags]
83#[cfg_attr(feature = "defmt", derive(defmt::Format))]
84#[derive(Debug, Eq, PartialEq, Copy, Clone)]
85#[repr(u16)]
86pub enum Flag {
87 RxNotEmpty = 1 << 0,
89 TxEmpty = 1 << 1,
91 CrcError = 1 << 4,
93 ModeFault = 1 << 5,
95 Overrun = 1 << 6,
97 Busy = 1 << 7,
99 FrameError = 1 << 8,
101}
102
103#[enumflags2::bitflags]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106#[derive(Debug, Eq, PartialEq, Copy, Clone)]
107#[repr(u32)]
108pub enum CFlag {
109 CrcError = 1 << 4,
111}
112
113#[allow(non_upper_case_globals)]
115pub const TransferModeNormal: bool = false;
116#[allow(non_upper_case_globals)]
118pub const TransferModeBidi: bool = true;
119
120pub trait FrameSize: Copy + Default {
121 const DFF: bool;
122 #[doc(hidden)]
123 fn read_data(spi: &spi1::RegisterBlock) -> Self;
124 #[doc(hidden)]
125 fn write_data(self, spi: &spi1::RegisterBlock);
126}
127
128impl FrameSize for u8 {
129 const DFF: bool = false;
130 fn read_data(spi: &spi1::RegisterBlock) -> Self {
131 spi.dr8().read().dr().bits()
132 }
133 fn write_data(self, spi: &spi1::RegisterBlock) {
134 spi.dr8().write(|w| w.dr().set(self));
135 }
136}
137
138impl FrameSize for u16 {
139 const DFF: bool = true;
140 fn read_data(spi: &spi1::RegisterBlock) -> Self {
141 spi.dr().read().dr().bits()
142 }
143 fn write_data(self, spi: &spi1::RegisterBlock) {
144 spi.dr().write(|w| w.dr().set(self));
145 }
146}
147
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150pub enum BitFormat {
151 LsbFirst,
153 MsbFirst,
155}
156
157#[derive(Debug)]
158pub struct Inner<SPI: Instance> {
159 spi: SPI,
160}
161
162#[derive(Debug)]
164#[allow(clippy::type_complexity)]
165pub struct Spi<SPI: Instance, const BIDI: bool = false, W = u8> {
166 inner: Inner<SPI>,
167 pins: (Option<SPI::Sck>, Option<SPI::Miso>, Option<SPI::Mosi>),
168 _operation: PhantomData<W>,
169}
170
171impl<SPI: Instance, const BIDI: bool, W> Deref for Spi<SPI, BIDI, W> {
172 type Target = Inner<SPI>;
173 fn deref(&self) -> &Self::Target {
174 &self.inner
175 }
176}
177
178impl<SPI: Instance, const BIDI: bool, W> DerefMut for Spi<SPI, BIDI, W> {
179 fn deref_mut(&mut self) -> &mut Self::Target {
180 &mut self.inner
181 }
182}
183
184#[derive(Debug)]
186#[allow(clippy::type_complexity)]
187pub struct SpiSlave<SPI: Instance, const BIDI: bool = false, W = u8> {
188 inner: Inner<SPI>,
189 pins: (
190 Option<SPI::Sck>,
191 Option<SPI::Miso>,
192 Option<SPI::Mosi>,
193 Option<SPI::Nss>,
194 ),
195 _operation: PhantomData<W>,
196}
197
198impl<SPI: Instance, const BIDI: bool, W> Deref for SpiSlave<SPI, BIDI, W> {
199 type Target = Inner<SPI>;
200 fn deref(&self) -> &Self::Target {
201 &self.inner
202 }
203}
204
205impl<SPI: Instance, const BIDI: bool, W> DerefMut for SpiSlave<SPI, BIDI, W> {
206 fn deref_mut(&mut self) -> &mut Self::Target {
207 &mut self.inner
208 }
209}
210
211pub trait Instance:
213 crate::Sealed
214 + crate::Ptr<RB = spi1::RegisterBlock>
215 + Deref<Target = Self::RB>
216 + rcc::Enable
217 + rcc::Reset
218 + rcc::BusClock
219 + gpio::alt::SpiCommon
220{
221}
222
223macro_rules! spi {
225 ($SPI:ty: $Spi:ident, $SpiSlave:ident) => {
226 pub type $Spi<const BIDI: bool = false, W = u8> = Spi<$SPI, BIDI, W>;
227 pub type $SpiSlave<const BIDI: bool = false, W = u8> = SpiSlave<$SPI, BIDI, W>;
228
229 impl Instance for $SPI {}
230 };
231}
232
233spi! { pac::SPI1: Spi1, SpiSlave1 }
234spi! { pac::SPI2: Spi2, SpiSlave2 }
235
236#[cfg(feature = "spi3")]
237spi! { pac::SPI3: Spi3, SpiSlave3 }
238
239#[cfg(feature = "spi4")]
240spi! { pac::SPI4: Spi4, SpiSlave4 }
241
242#[cfg(feature = "spi5")]
243spi! { pac::SPI5: Spi5, SpiSlave5 }
244
245#[cfg(feature = "spi6")]
246spi! { pac::SPI6: Spi6, SpiSlave6 }
247
248#[allow(non_upper_case_globals)]
249pub trait SpiExt: Sized + Instance {
250 const NoSck: Option<Self::Sck> = None;
251 const NoMiso: Option<Self::Miso> = None;
252 const NoMosi: Option<Self::Mosi> = None;
253 const NoNss: Option<Self::Nss> = None;
254 fn spi(
255 self,
256 pins: (
257 Option<impl Into<Self::Sck>>,
258 Option<impl Into<Self::Miso>>,
259 Option<impl Into<Self::Mosi>>,
260 ),
261 mode: impl Into<Mode>,
262 freq: Hertz,
263 rcc: &mut Rcc,
264 ) -> Spi<Self, false, u8>;
265
266 fn spi_bidi(
267 self,
268 pins: (Option<impl Into<Self::Sck>>, Option<impl Into<Self::Mosi>>),
269 mode: impl Into<Mode>,
270 freq: Hertz,
271 rcc: &mut Rcc,
272 ) -> Spi<Self, true, u8>;
273
274 fn spi_slave(
275 self,
276 pins: (
277 Option<impl Into<Self::Sck>>,
278 Option<impl Into<Self::Miso>>,
279 Option<impl Into<Self::Mosi>>,
280 Option<impl Into<Self::Nss>>,
281 ),
282 mode: impl Into<Mode>,
283 rcc: &mut RCC,
284 ) -> SpiSlave<Self, false, u8>;
285
286 fn spi_bidi_slave(
287 self,
288 pins: (
289 Option<impl Into<Self::Sck>>,
290 Option<impl Into<Self::Miso>>,
291 Option<impl Into<Self::Nss>>,
292 ),
293 mode: impl Into<Mode>,
294 rcc: &mut RCC,
295 ) -> SpiSlave<Self, true, u8>;
296}
297
298impl<SPI: Instance> SpiExt for SPI {
299 fn spi(
305 self,
306 pins: (
307 Option<impl Into<Self::Sck>>,
308 Option<impl Into<Self::Miso>>,
309 Option<impl Into<Self::Mosi>>,
310 ),
311 mode: impl Into<Mode>,
312 freq: Hertz,
313 rcc: &mut Rcc,
314 ) -> Spi<Self, false, u8> {
315 Spi::new(self, pins, mode, freq, rcc)
316 }
317 fn spi_bidi(
323 self,
324 pins: (Option<impl Into<Self::Sck>>, Option<impl Into<Self::Mosi>>),
325 mode: impl Into<Mode>,
326 freq: Hertz,
327 rcc: &mut Rcc,
328 ) -> Spi<Self, true, u8> {
329 Spi::new_bidi(self, pins, mode, freq, rcc)
330 }
331 fn spi_slave(
337 self,
338 pins: (
339 Option<impl Into<Self::Sck>>,
340 Option<impl Into<Self::Miso>>,
341 Option<impl Into<Self::Mosi>>,
342 Option<impl Into<Self::Nss>>,
343 ),
344 mode: impl Into<Mode>,
345 rcc: &mut RCC,
346 ) -> SpiSlave<Self, false, u8> {
347 SpiSlave::new(self, pins, mode, rcc)
348 }
349 fn spi_bidi_slave(
355 self,
356 pins: (
357 Option<impl Into<Self::Sck>>,
358 Option<impl Into<Self::Miso>>,
359 Option<impl Into<Self::Nss>>,
360 ),
361 mode: impl Into<Mode>,
362 rcc: &mut RCC,
363 ) -> SpiSlave<Self, true, u8> {
364 SpiSlave::new_bidi(self, pins, mode, rcc)
365 }
366}
367
368impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
369 pub fn init(self) -> Self {
370 self.spi.cr1().modify(|_, w| {
371 w.bidimode().bit(BIDI);
373 w.bidioe().bit(BIDI);
374 w.dff().bit(W::DFF);
376 w.spe().set_bit()
378 });
379
380 self
381 }
382}
383
384impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
385 pub fn init(self) -> Self {
386 self.spi.cr1().modify(|_, w| {
387 w.bidimode().bit(BIDI);
389 w.bidioe().bit(BIDI);
390 w.dff().bit(W::DFF);
392 w.spe().set_bit()
394 });
395
396 self
397 }
398}
399
400impl<SPI: Instance, W: FrameSize> Spi<SPI, false, W> {
401 pub fn to_bidi_transfer_mode(self) -> Spi<SPI, true, W> {
402 self.into_mode()
403 }
404}
405
406impl<SPI: Instance, W: FrameSize> Spi<SPI, true, W> {
407 pub fn to_normal_transfer_mode(self) -> Spi<SPI, false, W> {
408 self.into_mode()
409 }
410}
411
412impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, false, W> {
413 pub fn to_bidi_transfer_mode(self) -> SpiSlave<SPI, true, W> {
414 self.into_mode()
415 }
416}
417
418impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, true, W> {
419 pub fn to_normal_transfer_mode(self) -> SpiSlave<SPI, false, W> {
420 self.into_mode()
421 }
422}
423
424impl<SPI, const BIDI: bool> Spi<SPI, BIDI, u8>
425where
426 SPI: Instance,
427{
428 pub fn frame_size_16bit(self) -> Spi<SPI, BIDI, u16> {
430 self.into_mode()
431 }
432}
433
434impl<SPI, const BIDI: bool> Spi<SPI, BIDI, u16>
435where
436 SPI: Instance,
437{
438 pub fn frame_size_8bit(self) -> Spi<SPI, BIDI, u8> {
440 self.into_mode()
441 }
442}
443
444impl<SPI, const BIDI: bool> SpiSlave<SPI, BIDI, u8>
445where
446 SPI: Instance,
447{
448 pub fn frame_size_16bit(self) -> SpiSlave<SPI, BIDI, u16> {
450 self.into_mode()
451 }
452}
453
454impl<SPI, const BIDI: bool> SpiSlave<SPI, BIDI, u16>
455where
456 SPI: Instance,
457{
458 pub fn frame_size_8bit(self) -> SpiSlave<SPI, BIDI, u8> {
460 self.into_mode()
461 }
462}
463
464impl<SPI: Instance> Spi<SPI, false, u8> {
465 pub fn new(
471 spi: SPI,
472 pins: (
473 Option<impl Into<SPI::Sck>>,
474 Option<impl Into<SPI::Miso>>,
475 Option<impl Into<SPI::Mosi>>,
476 ),
477 mode: impl Into<Mode>,
478 freq: Hertz,
479 rcc: &mut Rcc,
480 ) -> Self {
481 SPI::enable(rcc);
482 SPI::reset(rcc);
483
484 let pins = (
485 pins.0.map(Into::into),
486 pins.1.map(Into::into),
487 pins.2.map(Into::into),
488 );
489
490 Self::_new(spi, pins)
491 .pre_init(mode.into(), freq, SPI::clock(&rcc.clocks))
492 .init()
493 }
494}
495
496impl<SPI: Instance> Spi<SPI, true, u8> {
497 pub fn new_bidi(
503 spi: SPI,
504 pins: (Option<impl Into<SPI::Sck>>, Option<impl Into<SPI::Mosi>>),
505 mode: impl Into<Mode>,
506 freq: Hertz,
507 rcc: &mut Rcc,
508 ) -> Self {
509 SPI::enable(rcc);
510 SPI::reset(rcc);
511
512 let pins = (pins.0, SPI::NoMiso, pins.1);
513
514 Self::_new(spi, pins)
515 .pre_init(mode.into(), freq, SPI::clock(&rcc.clocks))
516 .init()
517 }
518}
519
520impl<SPI: Instance> SpiSlave<SPI, false, u8> {
521 pub fn new(
527 spi: SPI,
528 pins: (
529 Option<impl Into<SPI::Sck>>,
530 Option<impl Into<SPI::Miso>>,
531 Option<impl Into<SPI::Mosi>>,
532 Option<impl Into<SPI::Nss>>,
533 ),
534 mode: impl Into<Mode>,
535 rcc: &mut RCC,
536 ) -> Self {
537 SPI::enable(rcc);
538 SPI::reset(rcc);
539
540 let pins = (pins.0, pins.1, pins.2, pins.3);
541
542 Self::_new(spi, pins).pre_init(mode.into()).init()
543 }
544}
545
546impl<SPI: Instance> SpiSlave<SPI, true, u8> {
547 pub fn new_bidi(
553 spi: SPI,
554 pins: (
555 Option<impl Into<SPI::Sck>>,
556 Option<impl Into<SPI::Miso>>,
557 Option<impl Into<SPI::Nss>>,
558 ),
559 mode: impl Into<Mode>,
560 rcc: &mut RCC,
561 ) -> Self {
562 SPI::enable(rcc);
563 SPI::reset(rcc);
564
565 let pins = (pins.0, pins.1, SPI::NoMosi, pins.2);
566
567 Self::_new(spi, pins).pre_init(mode.into()).init()
568 }
569}
570
571impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
572 #[allow(clippy::type_complexity)]
573 pub fn release(
574 self,
575 ) -> (
576 SPI,
577 (Option<SPI::Sck>, Option<SPI::Miso>, Option<SPI::Mosi>),
578 ) {
579 (self.inner.spi, self.pins)
580 }
581}
582
583impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
584 #[allow(clippy::type_complexity)]
585 pub fn release(
586 self,
587 ) -> (
588 SPI,
589 (
590 Option<SPI::Sck>,
591 Option<SPI::Miso>,
592 Option<SPI::Mosi>,
593 Option<SPI::Nss>,
594 ),
595 ) {
596 (self.inner.spi, self.pins)
597 }
598}
599
600impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
601 fn _new(
602 spi: SPI,
603 pins: (
604 Option<impl Into<SPI::Sck>>,
605 Option<impl Into<SPI::Miso>>,
606 Option<impl Into<SPI::Mosi>>,
607 ),
608 ) -> Self {
609 Self {
610 inner: Inner::new(spi),
611 pins: (
612 pins.0.map(Into::into),
613 pins.1.map(Into::into),
614 pins.2.map(Into::into),
615 ),
616 _operation: PhantomData,
617 }
618 }
619
620 fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> Spi<SPI, BIDI2, W2> {
622 let mut spi = Spi::_new(self.inner.spi, self.pins);
623 spi.enable(false);
624 spi.init()
625 }
626}
627
628impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
629 fn _new(
630 spi: SPI,
631 pins: (
632 Option<impl Into<SPI::Sck>>,
633 Option<impl Into<SPI::Miso>>,
634 Option<impl Into<SPI::Mosi>>,
635 Option<impl Into<SPI::Nss>>,
636 ),
637 ) -> Self {
638 Self {
639 inner: Inner::new(spi),
640 pins: (
641 pins.0.map(Into::into),
642 pins.1.map(Into::into),
643 pins.2.map(Into::into),
644 pins.3.map(Into::into),
645 ),
646 _operation: PhantomData,
647 }
648 }
649
650 fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> SpiSlave<SPI, BIDI2, W2> {
652 let mut spi = SpiSlave::_new(self.inner.spi, self.pins);
653 spi.enable(false);
654 spi.init()
655 }
656}
657
658impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
659 fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self {
661 self.spi.cr2().write(|w| w.ssoe().clear_bit());
663
664 let br = match clock.raw() / freq.raw() {
665 0 => unreachable!(),
666 1..=2 => 0b000,
667 3..=5 => 0b001,
668 6..=11 => 0b010,
669 12..=23 => 0b011,
670 24..=47 => 0b100,
671 48..=95 => 0b101,
672 96..=191 => 0b110,
673 _ => 0b111,
674 };
675
676 self.spi.cr1().write(|w| {
677 w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
678 w.cpol().bit(mode.polarity == Polarity::IdleHigh);
679 w.mstr().set_bit();
681 w.br().set(br);
682 w.lsbfirst().clear_bit();
684 w.ssm().set_bit();
686 w.ssi().set_bit();
688 w.rxonly().clear_bit();
689 w.dff().clear_bit()
691 });
692
693 self
694 }
695}
696
697impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
698 fn pre_init(self, mode: Mode) -> Self {
700 self.spi.cr1().write(|w| {
701 w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
702 w.cpol().bit(mode.polarity == Polarity::IdleHigh);
703 w.mstr().clear_bit();
705 w.br().set(0);
706 w.lsbfirst().clear_bit();
708 w.ssm().bit(self.pins.3.is_none());
710 w.ssi().set_bit();
712 w.rxonly().clear_bit();
713 w.dff().clear_bit()
715 });
716
717 self
718 }
719
720 #[inline]
722 pub fn set_internal_nss(&mut self, value: bool) {
723 self.spi.cr1().modify(|_, w| w.ssi().bit(value));
724 }
725}
726
727impl<SPI: Instance> Inner<SPI> {
728 fn new(spi: SPI) -> Self {
729 Self { spi }
730 }
731
732 pub fn enable(&mut self, enable: bool) {
734 self.spi.cr1().modify(|_, w| {
735 w.spe().bit(enable)
737 });
738 }
739
740 pub fn bit_format(&mut self, format: BitFormat) {
742 self.spi
743 .cr1()
744 .modify(|_, w| w.lsbfirst().bit(format == BitFormat::LsbFirst));
745 }
746
747 #[inline]
750 pub fn is_tx_empty(&self) -> bool {
751 self.spi.sr().read().txe().bit_is_set()
752 }
753
754 #[inline]
757 pub fn is_rx_not_empty(&self) -> bool {
758 self.spi.sr().read().rxne().bit_is_set()
759 }
760
761 #[inline]
764 pub fn is_modf(&self) -> bool {
765 self.spi.sr().read().modf().bit_is_set()
766 }
767
768 #[inline]
770 pub fn is_busy(&self) -> bool {
771 self.spi.sr().read().bsy().bit_is_set()
772 }
773
774 #[inline]
777 pub fn is_overrun(&self) -> bool {
778 self.spi.sr().read().ovr().bit_is_set()
779 }
780
781 #[inline]
782 fn bidi_output(&mut self) {
783 self.spi.cr1().modify(|_, w| w.bidioe().set_bit());
784 }
785
786 #[inline]
787 fn bidi_input(&mut self) {
788 self.spi.cr1().modify(|_, w| w.bidioe().set_bit());
789 }
790
791 fn read_data_reg<W: FrameSize>(&mut self) -> W {
792 W::read_data(&self.spi)
793 }
794
795 fn write_data_reg<W: FrameSize>(&mut self, data: W) {
796 data.write_data(&self.spi)
797 }
798
799 #[inline(always)]
800 fn check_read<W: FrameSize>(&mut self) -> nb::Result<W, Error> {
801 let sr = self.spi.sr().read();
802
803 Err(if sr.ovr().bit_is_set() {
804 Error::Overrun.into()
805 } else if sr.modf().bit_is_set() {
806 Error::ModeFault.into()
807 } else if sr.crcerr().bit_is_set() {
808 Error::Crc.into()
809 } else if sr.rxne().bit_is_set() {
810 return Ok(self.read_data_reg());
811 } else {
812 nb::Error::WouldBlock
813 })
814 }
815
816 #[inline(always)]
817 fn check_send<W: FrameSize>(&mut self, byte: W) -> nb::Result<(), Error> {
818 let sr = self.spi.sr().read();
819
820 Err(if sr.ovr().bit_is_set() {
821 let _ = self.spi.dr().read();
823 Error::Overrun.into()
824 } else if sr.modf().bit_is_set() {
825 self.spi.cr1().modify(|_r, w| w);
827 Error::ModeFault.into()
828 } else if sr.crcerr().bit_is_set() {
829 self.spi.sr().modify(|_r, w| w.crcerr().clear_bit());
831 Error::Crc.into()
832 } else if sr.txe().bit_is_set() {
833 self.write_data_reg(byte);
834 return Ok(());
835 } else {
836 nb::Error::WouldBlock
837 })
838 }
839
840 fn spi_write<const BIDI: bool, W: FrameSize>(
841 &mut self,
842 words: impl IntoIterator<Item = W>,
843 ) -> Result<(), Error> {
844 if BIDI {
845 self.bidi_output();
846 for word in words.into_iter() {
847 nb::block!(self.check_send(word))?;
848 }
849 } else {
850 for word in words.into_iter() {
851 nb::block!(self.check_send(word))?;
852 nb::block!(self.check_read::<W>())?;
853 }
854 }
855
856 Ok(())
857 }
858
859 fn listen_event(&mut self, disable: Option<BitFlags<Event>>, enable: Option<BitFlags<Event>>) {
860 self.spi.cr2().modify(|r, w| unsafe {
861 w.bits({
862 let mut bits = r.bits();
863 if let Some(d) = disable {
864 bits &= !d.bits();
865 }
866 if let Some(e) = enable {
867 bits |= e.bits();
868 }
869 bits
870 })
871 });
872 }
873}
874
875impl<SPI: Instance> crate::Listen for Inner<SPI> {
876 type Event = Event;
877
878 fn listen(&mut self, event: impl Into<BitFlags<Self::Event>>) {
879 self.listen_event(None, Some(event.into()));
880 }
881
882 fn listen_only(&mut self, event: impl Into<BitFlags<Self::Event>>) {
883 self.listen_event(Some(BitFlags::ALL), Some(event.into()));
884 }
885
886 fn unlisten(&mut self, event: impl Into<BitFlags<Self::Event>>) {
887 self.listen_event(Some(event.into()), None);
888 }
889}
890
891impl<SPI: Instance> crate::ClearFlags for Inner<SPI> {
892 type Flag = CFlag;
893 fn clear_flags(&mut self, flags: impl Into<BitFlags<Self::Flag>>) {
894 if flags.into().contains(CFlag::CrcError) {
895 self.spi
896 .sr()
897 .write(|w| unsafe { w.bits(0xffff).crcerr().clear_bit() });
898 }
899 }
900}
901
902impl<SPI: Instance> crate::ReadFlags for Inner<SPI> {
903 type Flag = Flag;
904 fn flags(&self) -> BitFlags<Self::Flag> {
905 BitFlags::from_bits_truncate(self.spi.sr().read().bits())
906 }
907}
908
909impl<SPI: Instance, const BIDI: bool> Spi<SPI, BIDI, u8> {
912 pub fn use_dma(self) -> DmaBuilder<SPI> {
913 DmaBuilder {
914 spi: self.inner.spi,
915 }
916 }
917}
918
919impl<SPI: Instance, const BIDI: bool> SpiSlave<SPI, BIDI, u8> {
920 pub fn use_dma(self) -> DmaBuilder<SPI> {
921 DmaBuilder {
922 spi: self.inner.spi,
923 }
924 }
925}
926
927pub struct DmaBuilder<SPI> {
928 spi: SPI,
929}
930
931pub struct Tx<SPI> {
932 spi: PhantomData<SPI>,
933}
934
935pub struct Rx<SPI> {
936 spi: PhantomData<SPI>,
937}
938
939impl<SPI: Instance> DmaBuilder<SPI> {
940 pub fn tx(self) -> Tx<SPI> {
941 self.spi.cr2().modify(|_, w| w.txdmaen().enabled());
942 Tx { spi: PhantomData }
943 }
944
945 pub fn rx(self) -> Rx<SPI> {
946 self.spi.cr2().modify(|_, w| w.rxdmaen().enabled());
947 Rx { spi: PhantomData }
948 }
949
950 pub fn txrx(self) -> (Tx<SPI>, Rx<SPI>) {
951 self.spi.cr2().modify(|_, w| {
952 w.txdmaen().enabled();
953 w.rxdmaen().enabled()
954 });
955 (Tx { spi: PhantomData }, Rx { spi: PhantomData })
956 }
957}
958
959unsafe impl<SPI: Instance> PeriAddress for Rx<SPI> {
960 #[inline(always)]
961 fn address(&self) -> u32 {
962 unsafe { (*SPI::PTR).dr().as_ptr() as u32 }
963 }
964
965 type MemSize = u8;
966}
967
968unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, PeripheralToMemory> for Rx<SPI> where
969 SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>
970{
971}
972
973unsafe impl<SPI: Instance> PeriAddress for Tx<SPI> {
974 #[inline(always)]
975 fn address(&self) -> u32 {
976 unsafe { (*SPI::PTR).dr().as_ptr() as u32 }
977 }
978
979 type MemSize = u8;
980}
981
982unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeripheral> for Tx<SPI> where
983 SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>
984{
985}
986
987macro_rules! spi_transfer {
988 ($Spi: ident) => {
989 impl<SPI: Instance, const BIDI: bool, W: FrameSize> $Spi<SPI, BIDI, W> {
990 pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
991 if BIDI {
992 self.bidi_input();
993 }
994 self.check_read()
995 }
996
997 pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
998 if BIDI {
999 self.bidi_output();
1000 }
1001 self.check_send(byte)
1002 }
1003
1004 pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
1005 for word in words {
1006 nb::block!(self.write_nonblocking(*word))?;
1007 *word = nb::block!(self.read_nonblocking())?;
1008 }
1009
1010 Ok(())
1011 }
1012
1013 pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
1014 if data.len() == buff.len() {
1015 for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
1016 nb::block!(self.write_nonblocking(d))?;
1017 *b = nb::block!(self.read_nonblocking())?;
1018 }
1019 } else {
1020 let mut iter_r = buff.iter_mut();
1021 let mut iter_w = data.iter().cloned();
1022 loop {
1023 match (iter_r.next(), iter_w.next()) {
1024 (Some(r), Some(w)) => {
1025 nb::block!(self.write_nonblocking(w))?;
1026 *r = nb::block!(self.read_nonblocking())?;
1027 }
1028 (Some(r), None) => {
1029 nb::block!(self.write_nonblocking(W::default()))?;
1030 *r = nb::block!(self.read_nonblocking())?;
1031 }
1032 (None, Some(w)) => {
1033 nb::block!(self.write_nonblocking(w))?;
1034 let _ = nb::block!(self.read_nonblocking())?;
1035 }
1036 (None, None) => break,
1037 }
1038 }
1039 }
1040
1041 Ok(())
1042 }
1043
1044 pub fn flush(&mut self) -> Result<(), Error> {
1045 Ok(())
1046 }
1047
1048 pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
1049 self.spi_write::<BIDI, W>(words.iter().copied())
1050 }
1051
1052 pub fn write_iter(&mut self, words: impl IntoIterator<Item = W>) -> Result<(), Error> {
1053 self.spi_write::<BIDI, W>(words)
1054 }
1055
1056 pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
1057 if BIDI {
1058 self.bidi_input();
1059 for word in words {
1060 *word = nb::block!(self.check_read())?;
1061 }
1062 } else {
1063 for word in words {
1064 nb::block!(self.check_send(W::default()))?;
1065 *word = nb::block!(self.check_read())?;
1066 }
1067 }
1068
1069 Ok(())
1070 }
1071 }
1072 };
1073}
1074
1075spi_transfer!(Spi);
1076spi_transfer!(SpiSlave);