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