1use core::marker::{ConstParamTy, PhantomData};
2use core::ops::{Deref, DerefMut};
3use core::sync::atomic::Ordering;
4use core::sync::atomic;
5use crate::dma::*;
6use crate::gpio::alt::altmap::Remap;
7use crate::gpio::{self, NoPin};
8use crate::pac;
9use embedded_dma::WriteBuffer;
10use embedded_dma::ReadBuffer;
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum Polarity {
14 IdleLow,
16 IdleHigh,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Phase {
23 CaptureOnFirstTransition,
25 CaptureOnSecondTransition,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq, ConstParamTy)]
30pub enum TransferMode {
31 TransferModeNormal,
32 TransferModeBidirectional,
33 TransferModeRecieveOnly,
34 TransferModeTransmitOnly
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub struct Mode {
40 pub polarity: Polarity,
42 pub phase: Phase,
44}
45
46mod hal_02;
47mod hal_1;
48
49use crate::pac::spi1;
50use crate::rcc;
51
52use crate::rcc::Clocks;
53use enumflags2::BitFlags;
54use fugit::HertzU32 as Hertz;
55
56#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58#[derive(Debug, Eq, PartialEq, Copy, Clone)]
59#[non_exhaustive]
60pub enum Error {
61 Overrun,
63 ModeFault,
65 Crc,
67}
68
69pub type NoSck = NoPin;
71pub type NoMiso = NoPin;
73pub type NoMosi = NoPin;
75
76#[enumflags2::bitflags]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79#[derive(Debug, Eq, PartialEq, Copy, Clone)]
80#[repr(u32)]
81pub enum Event {
82 Error = 1 << 5,
89 RxNotEmpty = 1 << 6,
93 TxEmpty = 1 << 7,
97}
98
99#[enumflags2::bitflags]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102#[derive(Debug, Eq, PartialEq, Copy, Clone)]
103#[repr(u32)]
104pub enum Flag {
105 RxNotEmpty = 1 << 0,
107 TxEmpty = 1 << 1,
109 CrcError = 1 << 4,
111 ModeFault = 1 << 5,
113 Overrun = 1 << 6,
115 Busy = 1 << 7,
117 FrameError = 1 << 8,
119}
120
121#[enumflags2::bitflags]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
124#[derive(Debug, Eq, PartialEq, Copy, Clone)]
125#[repr(u32)]
126pub enum CFlag {
127 CrcError = 1 << 4,
129}
130
131pub trait FrameSize: Copy + Default {
132 const DFF: bool;
133}
134
135impl FrameSize for u8 {
136 const DFF: bool = false;
137}
138
139impl FrameSize for u16 {
140 const DFF: bool = true;
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145pub enum BitFormat {
146 LsbFirst,
148 MsbFirst,
150}
151
152#[derive(Debug)]
153pub struct Inner<SPI: Instance> {
154 spi: SPI,
155}
156
157#[derive(Debug)]
159pub struct Spi<SPI: Instance, const XFER_MODE : TransferMode = {TransferMode::TransferModeNormal}, W = u8> {
160 inner: Inner<SPI>,
161 pins: (SPI::Sck, SPI::Miso, SPI::Mosi),
162 _operation: PhantomData<W>,
163}
164
165impl<SPI: Instance, const XFER_MODE : TransferMode, W> Deref for Spi<SPI, XFER_MODE, W> {
166 type Target = Inner<SPI>;
167 fn deref(&self) -> &Self::Target {
168 &self.inner
169 }
170}
171
172impl<SPI: Instance, const XFER_MODE : TransferMode, W> DerefMut for Spi<SPI, XFER_MODE, W> {
173 fn deref_mut(&mut self) -> &mut Self::Target {
174 &mut self.inner
175 }
176}
177
178#[derive(Debug)]
180pub struct SpiSlave<SPI: Instance, const XFER_MODE : TransferMode = {TransferMode::TransferModeNormal}, W = u8> {
181 inner: Inner<SPI>,
182 pins: (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>),
183 _operation: PhantomData<W>,
184}
185
186impl<SPI: Instance, const XFER_MODE : TransferMode, W> Deref for SpiSlave<SPI, XFER_MODE, W> {
187 type Target = Inner<SPI>;
188 fn deref(&self) -> &Self::Target {
189 &self.inner
190 }
191}
192
193impl<SPI: Instance, const XFER_MODE : TransferMode, W> DerefMut for SpiSlave<SPI, XFER_MODE, W> {
194 fn deref_mut(&mut self) -> &mut Self::Target {
195 &mut self.inner
196 }
197}
198
199pub trait Instance:
201 crate::Sealed
202 + Deref<Target = spi1::RegisterBlock>
203 + rcc::Enable
204 + rcc::Reset
205 + rcc::BusClock
206 + gpio::alt::SpiCommon
207{
208 #[doc(hidden)]
209 fn ptr() -> *const spi1::RegisterBlock;
210}
211
212macro_rules! spi {
214 ($SPI:ty: $Spi:ident, $SpiSlave:ident) => {
215 pub type $Spi<const XFER_MODE : TransferMode = {TransferMode::TransferModeNormal}, W = u8> = Spi<$SPI, XFER_MODE, W>;
216 pub type $SpiSlave<const XFER_MODE : TransferMode = {TransferMode::TransferModeNormal}, W = u8> = SpiSlave<$SPI, XFER_MODE, W>;
217
218 impl Instance for $SPI {
219 fn ptr() -> *const spi1::RegisterBlock {
220 <$SPI>::ptr() as *const _
221 }
222 }
223 };
224}
225
226spi! { pac::Spi1: Spi1, SpiSlave1 }
227spi! { pac::Spi2: Spi2, SpiSlave2 }
228spi! { pac::Spi3: Spi3, SpiSlave3 }
229
230
231pub trait SpiExt: Sized + Instance {
232 fn spi<RMP : Remap,
233 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
234 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>,
235 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>>(
236 self,
237 pins: (SCK,MISO,MOSI),
238 mode: impl Into<Mode>,
239 freq: Hertz,
240 clocks: &Clocks,
241 afio: &mut pac::Afio,
242 ) -> Spi<Self, {TransferMode::TransferModeNormal}, u8>;
243
244 fn spi_bidi<RMP : Remap,
245 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
246 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>>(
247 self,
248 pins: (SCK,MOSI),
249 mode: impl Into<Mode>,
250 freq: Hertz,
251 clocks: &Clocks,
252 afio: &mut pac::Afio,
253 ) -> Spi<Self, {TransferMode::TransferModeBidirectional}, u8>
254 where
255 NoPin: Into<Self::Miso>;
256
257 fn spi_rxonly<RMP : Remap,
258 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
259 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>>(
260 self,
261 pins: (SCK,MISO),
262 mode: impl Into<Mode>,
263 freq: Hertz,
264 clocks: &Clocks,
265 afio: &mut pac::Afio,
266 ) -> Spi<Self, {TransferMode::TransferModeRecieveOnly}, u8>
267 where
268 NoPin: Into<Self::Mosi>;
269
270 fn spi_slave<RMP : Remap,
271 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
272 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>,
273 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>,
274 NSS: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Nss>>(
275 self,
276 pins: (
277 SCK,
278 MISO,
279 MOSI,
280 Option<NSS>
281 ),
282 mode: impl Into<Mode>,
283 ) -> SpiSlave<Self, {TransferMode::TransferModeNormal}, u8>;
284
285 fn spi_bidi_slave(
286 self,
287 pins: (
288 impl Into<Self::Sck>,
289 impl Into<Self::Miso>,
290 Option<Self::Nss>,
291 ),
292 mode: impl Into<Mode>,
293 ) -> SpiSlave<Self, {TransferMode::TransferModeBidirectional}, u8>
294 where
295 NoPin: Into<Self::Mosi>;
296}
297
298impl<SPI: Instance> SpiExt for SPI {
299 fn spi<RMP : Remap,SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
305 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>,
306 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>>(
307 self,
308 pins: (SCK,MISO,MOSI),
309 mode: impl Into<Mode>,
310 freq: Hertz,
311 clocks: &Clocks,
312 afio: &mut pac::Afio,
313 ) -> Spi<Self, {TransferMode::TransferModeNormal}, u8> {
314 RMP::remap(afio);
315 Spi::new(self, pins, mode, freq, clocks)
316 }
317 fn spi_bidi<RMP : Remap,
323 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
324 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>>(
325 self,
326 pins: (SCK,MOSI),
327 mode: impl Into<Mode>,
328 freq: Hertz,
329 clocks: &Clocks,
330 afio: &mut pac::Afio,
331 ) -> Spi<Self, {TransferMode::TransferModeBidirectional}, u8>
332 where
333 NoPin: Into<Self::Miso>,
334 {
335 RMP::remap(afio);
336 Spi::new_bidi(self, pins, mode, freq, clocks)
337 }
338
339 fn spi_rxonly<RMP : Remap,
345 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
346 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>>(
347 self,
348 pins: (SCK,MISO),
349 mode: impl Into<Mode>,
350 freq: Hertz,
351 clocks: &Clocks,
352 afio: &mut pac::Afio,
353
354 ) -> Spi<Self, {TransferMode::TransferModeRecieveOnly}, u8>
355 where
356 NoPin: Into<Self::Mosi>,
357 {
358 RMP::remap(afio);
359 Spi::new_rxonly(self, pins, mode, freq, clocks)
360 }
361 fn spi_slave<RMP : Remap,
367 SCK: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Sck>,
368 MISO: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Miso>,
369 MOSI: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Mosi>,
370 NSS: crate::gpio::alt::altmap::RemapIO<Self,RMP> + Into<Self::Nss>>(
371 self,
372 pins: (
373 SCK,
374 MISO,
375 MOSI,
376 Option<NSS>
377 ),
378 mode: impl Into<Mode>,
379 ) -> SpiSlave<Self, {TransferMode::TransferModeNormal}, u8> {
380 SpiSlave::new(self, pins, mode)
381 }
382 fn spi_bidi_slave(
388 self,
389 pins: (
390 impl Into<Self::Sck>,
391 impl Into<Self::Miso>,
392 Option<Self::Nss>,
393 ),
394 mode: impl Into<Mode>,
395 ) -> SpiSlave<Self, {TransferMode::TransferModeBidirectional}, u8>
396 where
397 NoPin: Into<Self::Mosi>,
398 {
399 SpiSlave::new_bidi(self, pins, mode)
400 }
401}
402
403impl<SPI: Instance, const XFER_MODE : TransferMode, W: FrameSize> Spi<SPI, XFER_MODE, W> {
404 pub fn init(self) -> Self {
405 self.spi.ctrl1().modify(|_, w| {
406 w.bidirmode().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
408 w.bidiroen().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
409 w.datff().bit(W::DFF);
411 w.spien().bit(XFER_MODE != TransferMode::TransferModeRecieveOnly)
413 });
414
415 self
416 }
417}
418
419impl<SPI: Instance, const XFER_MODE : TransferMode, W: FrameSize> SpiSlave<SPI, XFER_MODE, W> {
420 pub fn init(self) -> Self {
421 self.spi.ctrl1().modify(|_, w| {
422 w.bidirmode().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
424 w.bidiroen().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
425 w.datff().bit(W::DFF);
427 w.spien().set_bit()
429 });
430
431 self
432 }
433}
434
435impl<SPI: Instance, W: FrameSize> Spi<SPI, {TransferMode::TransferModeNormal}, W> {
436 pub fn to_bidi_transfer_mode(self) -> Spi<SPI, {TransferMode::TransferModeBidirectional}, W> {
437 self.into_mode()
438 }
439}
440
441impl<SPI: Instance, W: FrameSize> Spi<SPI, {TransferMode::TransferModeBidirectional}, W> {
442 pub fn to_normal_transfer_mode(self) -> Spi<SPI, {TransferMode::TransferModeNormal}, W> {
443 self.into_mode()
444 }
445}
446
447impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, {TransferMode::TransferModeNormal}, W> {
448 pub fn to_bidi_transfer_mode(self) -> SpiSlave<SPI, {TransferMode::TransferModeBidirectional}, W> {
449 self.into_mode()
450 }
451}
452
453impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, {TransferMode::TransferModeBidirectional}, W> {
454 pub fn to_normal_transfer_mode(self) -> SpiSlave<SPI, {TransferMode::TransferModeNormal}, W> {
455 self.into_mode()
456 }
457}
458
459impl<SPI, const XFER_MODE : TransferMode> Spi<SPI, XFER_MODE, u8>
460where
461 SPI: Instance,
462{
463 pub fn frame_size_16bit(self) -> Spi<SPI, XFER_MODE, u16> {
465 self.into_mode()
466 }
467}
468
469impl<SPI, const XFER_MODE : TransferMode> Spi<SPI, XFER_MODE, u16>
470where
471 SPI: Instance,
472{
473 pub fn frame_size_8bit(self) -> Spi<SPI, XFER_MODE, u8> {
475 self.into_mode()
476 }
477}
478
479impl<SPI, const XFER_MODE : TransferMode> SpiSlave<SPI, XFER_MODE, u8>
480where
481 SPI: Instance,
482{
483 pub fn frame_size_16bit(self) -> SpiSlave<SPI, XFER_MODE, u16> {
485 self.into_mode()
486 }
487}
488
489impl<SPI, const XFER_MODE : TransferMode> SpiSlave<SPI, XFER_MODE, u16>
490where
491 SPI: Instance,
492{
493 pub fn frame_size_8bit(self) -> SpiSlave<SPI, XFER_MODE, u8> {
495 self.into_mode()
496 }
497}
498
499impl<SPI: Instance> Spi<SPI, {TransferMode::TransferModeNormal}, u8> {
500 pub fn new<RMP : Remap,
506 SCK: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Sck>,
507 MISO: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Miso>,
508 MOSI: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Mosi>>(
509 spi: SPI,
510 pins: (SCK,MISO,MOSI),
511 mode: impl Into<Mode>,
512 freq: Hertz,
513 clocks: &Clocks,
514 ) -> Self {
515 unsafe {
516 SPI::enable_unchecked();
517 SPI::reset_unchecked();
518 }
519
520 let pins = (pins.0.into(), pins.1.into(), pins.2.into());
521
522 Self::_new(spi, pins)
523 .pre_init(mode.into(), freq, SPI::clock(clocks))
524 .init()
525 }
526}
527
528impl<SPI: Instance> Spi<SPI, {TransferMode::TransferModeRecieveOnly}, u8> {
529 pub fn new_rxonly(
535 spi: SPI,
536 pins: (impl Into<SPI::Sck>, impl Into<SPI::Miso>),
537 mode: impl Into<Mode>,
538 freq: Hertz,
539 clocks: &Clocks,
540 ) -> Self
541 where
542 NoPin: Into<SPI::Mosi>,
543 {
544 unsafe {
545 SPI::enable_unchecked();
546 SPI::reset_unchecked();
547 }
548
549 let pins = (pins.0.into(), pins.1.into(),NoPin::new().into());
550
551 Self::_new(spi, pins)
552 .pre_init(mode.into(), freq, SPI::clock(clocks))
553 .init()
554 }
555
556}
557
558impl<SPI: Instance> Spi<SPI, {TransferMode::TransferModeBidirectional}, u8> {
559 pub fn new_bidi(
565 spi: SPI,
566 pins: (impl Into<SPI::Sck>, impl Into<SPI::Mosi>),
567 mode: impl Into<Mode>,
568 freq: Hertz,
569 clocks: &Clocks,
570 ) -> Self
571 where
572 NoPin: Into<SPI::Miso>,
573 {
574 unsafe {
575 SPI::enable_unchecked();
576 SPI::reset_unchecked();
577 }
578
579 let pins = (pins.0.into(), NoPin::new().into(), pins.1.into());
580
581 Self::_new(spi, pins)
582 .pre_init(mode.into(), freq, SPI::clock(clocks))
583 .init()
584 }
585}
586
587impl<SPI: Instance> SpiSlave<SPI, {TransferMode::TransferModeNormal}, u8> {
588 pub fn new<RMP : Remap,
594 SCK: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Sck>,
595 MISO: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Miso>,
596 MOSI: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Mosi>,
597 NSS: crate::gpio::alt::altmap::RemapIO<SPI,RMP> + Into<SPI::Nss>>(
598 spi: SPI,
599 pins: (
600 SCK,
601 MISO,
602 MOSI,
603 Option<NSS>
604 ),
605 mode: impl Into<Mode>,
606 ) -> Self {
607 unsafe {
608 SPI::enable_unchecked();
609 SPI::reset_unchecked();
610 }
611
612 let pins = (pins.0.into(), pins.1.into(), pins.2.into(), pins.3.map(|v| v.into()));
613
614 Self::_new(spi, pins).pre_init(mode.into()).init()
615 }
616}
617
618impl<SPI: Instance> SpiSlave<SPI, {TransferMode::TransferModeBidirectional}, u8> {
619 pub fn new_bidi(
625 spi: SPI,
626 pins: (impl Into<SPI::Sck>, impl Into<SPI::Miso>, Option<SPI::Nss>),
627 mode: impl Into<Mode>,
628 ) -> Self
629 where
630 NoPin: Into<SPI::Mosi>,
631 {
632 unsafe {
633 SPI::enable_unchecked();
634 SPI::reset_unchecked();
635 }
636
637 let pins = (pins.0.into(), pins.1.into(), NoPin::new().into(), pins.2);
638
639 Self::_new(spi, pins).pre_init(mode.into()).init()
640 }
641}
642
643impl<SPI: Instance, const XFER_MODE : TransferMode, W> Spi<SPI, XFER_MODE, W> {
644 #[allow(clippy::type_complexity)]
645 pub fn release(self) -> (SPI, (SPI::Sck, SPI::Miso, SPI::Mosi)) {
646 (self.inner.spi, self.pins)
647 }
648}
649
650impl<SPI: Instance, const XFER_MODE : TransferMode, W> SpiSlave<SPI, XFER_MODE, W> {
651 #[allow(clippy::type_complexity)]
652 pub fn release(self) -> (SPI, (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>)) {
653 (self.inner.spi, self.pins)
654 }
655}
656
657impl<SPI: Instance, const XFER_MODE : TransferMode, W> Spi<SPI, XFER_MODE, W> {
658 fn _new(spi: SPI, pins: (SPI::Sck, SPI::Miso, SPI::Mosi)) -> Self {
659 Self {
660 inner: Inner::new(spi),
661 pins,
662 _operation: PhantomData,
663 }
664 }
665
666 fn into_mode<const XFER_MODE2: TransferMode, W2: FrameSize>(self) -> Spi<SPI, XFER_MODE2, W2> {
668 let mut spi = Spi::_new(self.inner.spi, self.pins);
669 spi.enable(false);
670 spi.init()
671 }
672}
673
674impl<SPI: Instance, const XFER_MODE : TransferMode, W> SpiSlave<SPI, XFER_MODE, W> {
675 fn _new(spi: SPI, pins: (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>)) -> Self {
676 Self {
677 inner: Inner::new(spi),
678 pins,
679 _operation: PhantomData,
680 }
681 }
682
683 fn into_mode<const XFER_MODE2: TransferMode, W2: FrameSize>(self) -> SpiSlave<SPI, XFER_MODE2, W2> {
685 let mut spi = SpiSlave::_new(self.inner.spi, self.pins);
686 spi.enable(false);
687 spi.init()
688 }
689}
690
691impl<SPI: Instance, const XFER_MODE : TransferMode, W> Spi<SPI, XFER_MODE, W> {
692 fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self {
694 self.spi.ctrl2().modify(|_,w| w.ssoen().clear_bit());
696
697 let br = match clock.raw() / freq.raw() {
698 0 => unreachable!(),
699 1..=2 => 0b000,
700 3..=5 => 0b001,
701 6..=11 => 0b010,
702 12..=23 => 0b011,
703 24..=47 => 0b100,
704 48..=95 => 0b101,
705 96..=191 => 0b110,
706 _ => 0b111,
707 };
708
709 self.spi.ctrl1().modify(|_,w| {
710 w.clkpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
711 w.clkpol().bit(mode.polarity == Polarity::IdleHigh);
712 w.msel().set_bit();
714 unsafe { w.br().bits(br) };
715 w.lsbff().clear_bit();
717 w.ssmen().set_bit();
719 w.ssel().set_bit();
721 w.ronly().bit(XFER_MODE == TransferMode::TransferModeRecieveOnly);
722 w.datff().clear_bit()
724 });
725
726 self
727 }
728}
729
730impl<SPI: Instance, const XFER_MODE : TransferMode, W> SpiSlave<SPI, XFER_MODE, W> {
731 fn pre_init(self, mode: Mode) -> Self {
733 self.spi.ctrl1().modify(|_,w| {
734 w.clkpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
735 w.clkpol().bit(mode.polarity == Polarity::IdleHigh);
736 w.msel().clear_bit();
738 unsafe { w.br().bits(0) };
739 w.lsbff().clear_bit();
741 w.ssmen().bit(self.pins.3.is_none());
743 w.ssel().set_bit();
745 w.ronly().clear_bit();
746 w.datff().clear_bit()
748 });
749
750 self
751 }
752
753 #[inline]
755 pub fn set_internal_nss(&mut self, value: bool) {
756 self.spi.ctrl1().modify(|_, w| w.ssel().bit(value));
757 }
758}
759
760impl<SPI: Instance> Inner<SPI> {
761 fn new(spi: SPI) -> Self {
762 Self { spi }
763 }
764
765 pub fn enable(&mut self, enable: bool) {
767 self.spi.ctrl1().modify(|_, w| {
768 w.spien().bit(enable)
770 });
771 }
772
773 pub fn bit_format(&mut self, format: BitFormat) {
775 self.spi
776 .ctrl1()
777 .modify(|_, w| w.lsbff().bit(format == BitFormat::LsbFirst));
778 }
779
780 #[inline]
783 pub fn is_tx_empty(&self) -> bool {
784 self.spi.sts().read().te().bit_is_set()
785 }
786
787 #[inline]
790 pub fn is_rx_not_empty(&self) -> bool {
791 self.spi.sts().read().rne().bit_is_set()
792 }
793
794 #[inline]
797 pub fn is_modf(&self) -> bool {
798 self.spi.sts().read().moderr().bit_is_set()
799 }
800
801 #[inline]
803 pub fn is_busy(&self) -> bool {
804 self.spi.sts().read().busy().bit_is_set()
805 }
806
807 #[inline]
810 pub fn is_overrun(&self) -> bool {
811 self.spi.sts().read().over().bit_is_set()
812 }
813
814 #[inline]
815 fn bidi_output(&mut self) {
816 self.spi.ctrl1().modify(|_, w| w.bidiroen().set_bit());
817 }
818
819 #[inline]
820 fn bidi_input(&mut self) {
821 self.spi.ctrl1().modify(|_, w| w.bidiroen().clear_bit());
822 }
823
824 fn read_data_reg<W: FrameSize>(&mut self) -> W {
825 unsafe { (*(self.spi.dat() as *const pac::spi1::Dat).cast::<vcell::VolatileCell<W>>()).get() }
828 }
829
830 fn write_data_reg<W: FrameSize>(&mut self, data: W) {
831 unsafe {
833 (*(self.spi.dat() as *const pac::spi1::Dat).cast::<vcell::VolatileCell<W>>()).set(data)
834 }
835 }
836
837 #[inline(always)]
838 fn check_read<W: FrameSize>(&mut self) -> nb::Result<W, Error> {
839 let sr = self.spi.sts().read();
840
841 Err(if sr.over().bit_is_set() {
842 Error::Overrun.into()
843 } else if sr.moderr().bit_is_set() {
844 Error::ModeFault.into()
845 } else if sr.crcerr().bit_is_set() {
846 Error::Crc.into()
847 } else if sr.rne().bit_is_set() {
848 return Ok(self.read_data_reg());
849 } else {
850 nb::Error::WouldBlock
851 })
852 }
853
854 #[inline(always)]
855 fn check_send<W: FrameSize>(&mut self, byte: W) -> nb::Result<(), Error> {
856 let sr = self.spi.sts().read();
857
858 Err(if sr.over().bit_is_set() {
859 let _ = self.spi.dat().read();
861 Error::Overrun.into()
862 } else if sr.moderr().bit_is_set() {
863 self.spi.ctrl1().modify(|_r, w| w);
865 Error::ModeFault.into()
866 } else if sr.crcerr().bit_is_set() {
867 self.spi.sts().modify(|_r, w| w.crcerr().clear_bit());
869 Error::Crc.into()
870 } else if sr.te().bit_is_set() {
871 self.write_data_reg(byte);
872 return Ok(());
873 } else {
874 nb::Error::WouldBlock
875 })
876 }
877 fn listen_event(&mut self, disable: Option<BitFlags<Event>>, enable: Option<BitFlags<Event>>) {
878 self.spi.ctrl2().modify(|r, w| unsafe {
879 w.bits({
880 let mut bits = r.bits();
881 if let Some(d) = disable {
882 bits &= !d.bits();
883 }
884 if let Some(e) = enable {
885 bits |= e.bits();
886 }
887 bits
888 })
889 });
890 }
891}
892
893impl<SPI: Instance> crate::Listen for Inner<SPI> {
894 type Event = Event;
895
896 fn listen(&mut self, event: impl Into<BitFlags<Self::Event>>) {
897 self.listen_event(None, Some(event.into()));
898 }
899
900 fn listen_only(&mut self, event: impl Into<BitFlags<Self::Event>>) {
901 self.listen_event(Some(BitFlags::ALL), Some(event.into()));
902 }
903
904 fn unlisten(&mut self, event: impl Into<BitFlags<Self::Event>>) {
905 self.listen_event(Some(event.into()), None);
906 }
907}
908
909impl<SPI: Instance> crate::ClearFlags for Inner<SPI> {
910 type Flag = CFlag;
911 fn clear_flags(&mut self, flags: impl Into<BitFlags<Self::Flag>>) {
912 if flags.into().contains(CFlag::CrcError) {
913 self.spi
914 .sts()
915 .write(|w| unsafe { w.bits(0xffff).crcerr().clear_bit() })
916 }
917 }
918}
919
920impl<SPI: Instance> crate::ReadFlags for Inner<SPI> {
921 type Flag = Flag;
922 fn flags(&self) -> BitFlags<Self::Flag> {
923 BitFlags::from_bits_truncate(self.spi.sts().read().bits())
924 }
925}
926
927impl<SPI: Instance, const XFER_MODE : TransferMode> Spi<SPI, XFER_MODE, u8> {
930 pub fn use_dma(self) -> DmaBuilder<SPI> {
931 DmaBuilder {
932 spi: self.inner.spi,
933 }
934 }
935}
936
937impl<SPI: Instance, const XFER_MODE : TransferMode> SpiSlave<SPI, XFER_MODE, u8> {
938 pub fn use_dma(self) -> DmaBuilder<SPI> {
939 DmaBuilder {
940 spi: self.inner.spi,
941 }
942 }
943}
944
945pub struct DmaBuilder<SPI> {
946 spi: SPI,
947}
948
949pub struct Tx<SPI> {
950 spi: PhantomData<SPI>,
951}
952
953pub struct Rx<SPI> {
954 spi: PhantomData<SPI>,
955}
956
957impl<SPI: Instance> DmaBuilder<SPI> {
958 pub fn tx(self) -> Tx<SPI> {
959 self.spi.ctrl2().modify(|_, w| w.tdmaen().set_bit());
960 Tx { spi: PhantomData }
961 }
962
963 pub fn rx(self) -> Rx<SPI> {
964 self.spi.ctrl2().modify(|_, w| w.rdmaen().set_bit());
965 Rx { spi: PhantomData }
966 }
967
968 pub fn txrx(self) -> (Tx<SPI>, Rx<SPI>) {
969 self.spi.ctrl2().modify(|_, w| {
970 w.tdmaen().set_bit();
971 w.rdmaen().set_bit()
972 });
973 (Tx { spi: PhantomData }, Rx { spi: PhantomData })
974 }
975}
976
977impl<SPI: Instance, const XFER_MODE : TransferMode, W: FrameSize> Spi<SPI, XFER_MODE, W> {
978 pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
979 if XFER_MODE == TransferMode::TransferModeBidirectional {
980 self.bidi_input();
981 }
982 self.check_read()
983 }
984
985 pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
986 if XFER_MODE == TransferMode::TransferModeBidirectional {
987 self.bidi_output();
988 }
989 self.check_send(byte)
990 }
991
992 pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
993 for word in words {
994 nb::block!(self.write_nonblocking(*word))?;
995 *word = nb::block!(self.read_nonblocking())?;
996 }
997
998 Ok(())
999 }
1000
1001 pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
1002 assert_eq!(data.len(), buff.len());
1003
1004 for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
1005 nb::block!(self.write_nonblocking(d))?;
1006 *b = nb::block!(self.read_nonblocking())?;
1007 }
1008
1009 Ok(())
1010 }
1011
1012 pub fn flush(&mut self) -> Result<(), Error> {
1013 Ok(())
1014 }
1015
1016 pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
1017 if XFER_MODE == TransferMode::TransferModeBidirectional {
1018 self.bidi_output();
1019 for word in words {
1020 nb::block!(self.check_send(*word))?;
1021 }
1022 } else {
1023 for word in words {
1024 nb::block!(self.check_send(*word))?;
1025 nb::block!(self.check_read::<W>())?;
1026 }
1027 }
1028
1029 Ok(())
1030 }
1031
1032 pub fn write_iter(&mut self, words: impl IntoIterator<Item = W>) -> Result<(), Error> {
1033 if XFER_MODE == TransferMode::TransferModeBidirectional {
1034 self.bidi_output();
1035 for word in words.into_iter() {
1036 nb::block!(self.check_send(word))?;
1037 }
1038 } else {
1039 for word in words.into_iter() {
1040 nb::block!(self.check_send(word))?;
1041 nb::block!(self.check_read::<W>())?;
1042 }
1043 }
1044
1045 Ok(())
1046 }
1047
1048 pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
1049 if XFER_MODE == TransferMode::TransferModeBidirectional {
1050 self.bidi_input();
1051 for word in words {
1052 *word = nb::block!(self.check_read())?;
1053 }
1054 } else if XFER_MODE == TransferMode::TransferModeRecieveOnly {
1055 self.spi.ctrl1().modify(|_,w| w.spien().set_bit());
1056 for word in words {
1057 *word = nb::block!(self.check_read())?;
1058 }
1059 self.spi.ctrl1().modify(|_,w| w.spien().clear_bit());
1060 } else {
1061 for word in words {
1062 nb::block!(self.check_send(W::default()))?;
1063 *word = nb::block!(self.check_read())?;
1064 }
1065 }
1066
1067 Ok(())
1068 }
1069}
1070
1071impl<SPI: Instance, const XFER_MODE : TransferMode, W: FrameSize> SpiSlave<SPI, XFER_MODE, W> {
1072 pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
1073 if XFER_MODE == TransferMode::TransferModeBidirectional {
1074 self.bidi_input();
1075 }
1076 self.check_read()
1077 }
1078
1079 pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
1080 if XFER_MODE == TransferMode::TransferModeBidirectional {
1081 self.bidi_output();
1082 }
1083 self.check_send(byte)
1084 }
1085
1086 pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
1087 for word in words {
1088 nb::block!(self.write_nonblocking(*word))?;
1089 *word = nb::block!(self.read_nonblocking())?;
1090 }
1091
1092 Ok(())
1093 }
1094
1095 pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
1096 assert_eq!(data.len(), buff.len());
1097
1098 for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
1099 nb::block!(self.write_nonblocking(d))?;
1100 *b = nb::block!(self.read_nonblocking())?;
1101 }
1102
1103 Ok(())
1104 }
1105
1106 pub fn flush(&mut self) -> Result<(), Error> {
1107 Ok(())
1108 }
1109
1110 pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
1111 if XFER_MODE == TransferMode::TransferModeBidirectional {
1112 self.bidi_output();
1113 for word in words {
1114 nb::block!(self.check_send(*word))?;
1115 }
1116 } else {
1117 for word in words {
1118 nb::block!(self.check_send(*word))?;
1119 nb::block!(self.check_read::<W>())?;
1120 }
1121 }
1122
1123 Ok(())
1124 }
1125
1126 pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
1127 if XFER_MODE == TransferMode::TransferModeBidirectional {
1128 self.bidi_input();
1129 for word in words {
1130 *word = nb::block!(self.check_read())?;
1131 }
1132 } else {
1133 for word in words {
1134 nb::block!(self.check_send(W::default()))?;
1135 *word = nb::block!(self.check_read())?;
1136 }
1137 }
1138
1139 Ok(())
1140 }
1141}
1142
1143pub type SpiTxDma<SPI, const XFER_MODE : TransferMode, CHANNEL> = TxDma<Spi<SPI, XFER_MODE, u8>, CHANNEL>;
1144pub type SpiRxDma<SPI, const XFER_MODE : TransferMode, CHANNEL> = RxDma<Spi<SPI, XFER_MODE, u8>, CHANNEL>;
1145pub type SpiRxTxDma<SPI, const XFER_MODE : TransferMode, RXCHANNEL, TXCHANNEL> =
1146 RxTxDma<Spi<SPI, XFER_MODE, u8>, RXCHANNEL, TXCHANNEL>;
1147
1148pub trait SpiDma<PER : Instance, const XFER_MODE : TransferMode, RXCH : crate::dma::CompatibleChannel<PER,R> + crate::dma::DMAChannel, TXCH : crate::dma::CompatibleChannel<PER,W> + crate::dma::DMAChannel> {
1149 fn with_rx_tx_dma(
1150 self,
1151 rxchannel: RXCH,
1152 txchannel: TXCH,
1153 ) -> SpiRxTxDma<PER, XFER_MODE, RXCH, TXCH>;
1154 fn with_rx_dma(self, channel: RXCH) -> SpiRxDma<PER, XFER_MODE, RXCH>;
1155 fn with_tx_dma(self, channel: TXCH) -> SpiTxDma<PER, XFER_MODE, TXCH>;
1156}
1157
1158macro_rules! spi_dma {
1159 ($SPIi:ty, $rxdma:ident, $txdma:ident, $rxtxdma:ident) => {
1160 pub type $rxdma<const XFER_MODE : TransferMode, RXCH> = SpiRxDma<$SPIi, XFER_MODE, RXCH>;
1161 pub type $txdma<const XFER_MODE : TransferMode, TXCH> = SpiTxDma<$SPIi, XFER_MODE, TXCH>;
1162 pub type $rxtxdma<const XFER_MODE : TransferMode,RXCH,TXCH> = SpiRxTxDma<$SPIi, XFER_MODE, RXCH, TXCH>;
1163
1164 impl<const XFER_MODE : TransferMode, RXCH,TXCH> SpiDma<$SPIi,XFER_MODE,RXCH,TXCH> for Spi<$SPIi,XFER_MODE,u8> where
1165 RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,
1166 TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel
1167 {
1168 fn with_tx_dma(self, mut channel: TXCH) -> SpiTxDma<$SPIi, XFER_MODE, TXCH> {
1169 self.spi.ctrl2().modify(|_, w| w.tdmaen().set_bit());
1170 channel.configure_channel();
1171 SpiTxDma {
1172 payload: self,
1173 channel,
1174 }
1175 }
1176 fn with_rx_dma(self, mut channel: RXCH) -> SpiRxDma<$SPIi, XFER_MODE, RXCH>
1177 {
1178 self.spi.ctrl2().modify(|_, w| w.rdmaen().set_bit());
1179 channel.configure_channel();
1180 SpiRxDma {
1181 payload: self,
1182 channel,
1183 }
1184 }
1185 fn with_rx_tx_dma(
1186 self,
1187 mut rxchannel: RXCH,
1188 mut txchannel: TXCH,
1189 ) -> SpiRxTxDma<$SPIi, XFER_MODE, RXCH, TXCH> {
1190 self.spi
1191 .ctrl2()
1192 .modify(|_, w| w.rdmaen().set_bit().tdmaen().set_bit());
1193 rxchannel.configure_channel();
1194 txchannel.configure_channel();
1195
1196 SpiRxTxDma {
1197 payload: self,
1198 rxchannel,
1199 txchannel,
1200 }
1201 }
1202 }
1203
1204 impl<const XFER_MODE : TransferMode,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> Transmit for SpiTxDma<$SPIi, XFER_MODE, TXCH> {
1205 type TxChannel = TXCH;
1206 type ReceivedWord = u8;
1207 }
1208
1209 impl<const XFER_MODE : TransferMode,RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel> Receive for SpiRxDma<$SPIi, XFER_MODE, RXCH> {
1210 type RxChannel = RXCH;
1211 type TransmittedWord = u8;
1212 }
1213
1214 impl<const XFER_MODE : TransferMode,RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> Transmit for SpiRxTxDma<$SPIi, XFER_MODE, RXCH,TXCH> {
1215 type TxChannel = TXCH;
1216 type ReceivedWord = u8;
1217 }
1218
1219 impl<const XFER_MODE : TransferMode,RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> Receive for SpiRxTxDma<$SPIi, XFER_MODE, RXCH,TXCH> {
1220 type RxChannel = RXCH;
1221 type TransmittedWord = u8;
1222 }
1223
1224 impl<const XFER_MODE : TransferMode, TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> SpiTxDma<$SPIi, XFER_MODE, TXCH> {
1225 pub fn release(self) -> (Spi<$SPIi, XFER_MODE, u8>, TXCH) {
1226 let SpiTxDma { payload, channel } = self;
1227 payload.spi.ctrl2().modify(|_, w| w.tdmaen().clear_bit());
1228 (payload, channel)
1229 }
1230 }
1231
1232 impl<const XFER_MODE : TransferMode, RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel> SpiRxDma<$SPIi, XFER_MODE, RXCH> {
1233 pub fn release(self) -> (Spi<$SPIi, XFER_MODE, u8>, RXCH) {
1234 let SpiRxDma { payload, channel } = self;
1235 payload.spi.ctrl2().modify(|_, w| w.rdmaen().clear_bit());
1236 (payload, channel)
1237 }
1238 }
1239
1240 impl<const XFER_MODE : TransferMode, RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> SpiRxTxDma<$SPIi, XFER_MODE, RXCH, TXCH> {
1241 pub fn release(self) -> (Spi<$SPIi, XFER_MODE, u8>, RXCH, TXCH) {
1242 let SpiRxTxDma {
1243 payload,
1244 rxchannel,
1245 txchannel,
1246 } = self;
1247 payload
1248 .spi
1249 .ctrl2()
1250 .modify(|_, w| w.rdmaen().clear_bit().tdmaen().clear_bit());
1251 (payload, rxchannel, txchannel)
1252 }
1253 }
1254
1255 impl<const XFER_MODE : TransferMode,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> TransferPayload for SpiTxDma<$SPIi, XFER_MODE, TXCH> {
1256 fn start(&mut self) {
1257 self.channel.start();
1258 }
1259 fn stop(&mut self) {
1260 self.channel.stop();
1261 }
1262 }
1263
1264 impl<const XFER_MODE : TransferMode,RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel> TransferPayload for SpiRxDma<$SPIi, XFER_MODE, RXCH> {
1265 fn start(&mut self) {
1266 self.channel.start();
1267 if XFER_MODE == TransferMode::TransferModeRecieveOnly {
1268 self.payload.enable(true);
1269 }
1270
1271 }
1272 fn stop(&mut self) {
1273 self.channel.stop();
1274 if XFER_MODE == TransferMode::TransferModeRecieveOnly {
1275 self.payload.enable(false);
1276 }
1277 }
1278 }
1279
1280 impl<const XFER_MODE : TransferMode,RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> TransferPayload for SpiRxTxDma<$SPIi, XFER_MODE,RXCH,TXCH> {
1281 fn start(&mut self) {
1282 self.rxchannel.start();
1283 self.txchannel.start();
1284 }
1285 fn stop(&mut self) {
1286 self.txchannel.stop();
1287 self.rxchannel.stop();
1288 }
1289 }
1290
1291 impl<B, const XFER_MODE : TransferMode, RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel> crate::dma::ReadDma<B, u8> for SpiRxDma<$SPIi, XFER_MODE, RXCH>
1292 where
1293 B: WriteBuffer<Word = u8>,
1294 {
1295 fn read(mut self, mut buffer: B) -> Transfer<W, B, Self> {
1296 let (ptr, len) = unsafe { buffer.write_buffer() };
1299 self.channel.set_peripheral_address(
1300 unsafe { (*<$SPIi>::ptr()).dat().as_ptr() as u32 },
1301 false,
1302 );
1303 self.channel.set_memory_address(ptr as u32, true);
1304 self.channel.set_transfer_length(len);
1305
1306 atomic::compiler_fence(Ordering::Release);
1307 self.channel.st().chcfg().modify(|_, w| {
1308 w
1309 .mem2mem()
1311 .disabled()
1312 .priolvl()
1314 .medium()
1315 .msize()
1317 .bits8()
1318 .psize()
1320 .bits8()
1321 .circ()
1323 .disabled()
1324 .dir()
1326 .from_peripheral()
1327 });
1328 self.start();
1329
1330 Transfer::w(buffer, self)
1331 }
1332 }
1333
1334 impl<B, const XFER_MODE : TransferMode,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> crate::dma::WriteDma<B, u8>
1335 for SpiTxDma<$SPIi, XFER_MODE, TXCH>
1336 where
1337 B: ReadBuffer<Word = u8>,
1338 {
1339 fn write(mut self, buffer: B) -> Transfer<R, B, Self> {
1340 let (ptr, len) = unsafe { buffer.read_buffer() };
1343 self.channel.set_peripheral_address(
1344 unsafe { (*<$SPIi>::ptr()).dat().as_ptr() as u32 },
1345 false,
1346 );
1347 self.channel.set_memory_address(ptr as u32, true);
1348 self.channel.set_transfer_length(len);
1349
1350 atomic::compiler_fence(Ordering::Release);
1351 self.channel.st().chcfg().modify(|_, w| {
1352 w
1353 .mem2mem()
1355 .disabled()
1356 .priolvl()
1358 .medium()
1359 .msize()
1361 .bits8()
1362 .psize()
1364 .bits8()
1365 .circ()
1367 .disabled()
1368 .dir()
1370 .from_memory()
1371 });
1372 self.start();
1373
1374 Transfer::r(buffer, self)
1375 }
1376 }
1377
1378 impl<RXB, TXB, const XFER_MODE : TransferMode, RXCH: crate::dma::CompatibleChannel<$SPIi,R> + crate::dma::DMAChannel,TXCH: crate::dma::CompatibleChannel<$SPIi,W> + crate::dma::DMAChannel> crate::dma::ReadWriteDma<RXB, TXB, u8>
1379 for SpiRxTxDma<$SPIi, XFER_MODE, RXCH, TXCH>
1380 where
1381 RXB: WriteBuffer<Word = u8>,
1382 TXB: ReadBuffer<Word = u8>,
1383 {
1384 fn read_write(
1385 mut self,
1386 mut rxbuffer: RXB,
1387 txbuffer: TXB,
1388 ) -> Transfer<W, (RXB, TXB), Self> {
1389 let (rxptr, rxlen) = unsafe { rxbuffer.write_buffer() };
1392 let (txptr, txlen) = unsafe { txbuffer.read_buffer() };
1393
1394 if rxlen != txlen {
1395 panic!("receive and send buffer lengths do not match!");
1396 }
1397
1398 self.rxchannel.set_peripheral_address(
1399 unsafe { (*<$SPIi>::ptr()).dat().as_ptr() as u32 },
1400 false,
1401 );
1402 self.rxchannel.set_memory_address(rxptr as u32, true);
1403 self.rxchannel.set_transfer_length(rxlen);
1404
1405 self.txchannel.set_peripheral_address(
1406 unsafe { (*<$SPIi>::ptr()).dat().as_ptr() as u32 },
1407 false,
1408 );
1409 self.txchannel.set_memory_address(txptr as u32, true);
1410 self.txchannel.set_transfer_length(txlen);
1411
1412 atomic::compiler_fence(Ordering::Release);
1413 self.rxchannel.st().chcfg().modify(|_, w| {
1414 w
1415 .mem2mem()
1417 .disabled()
1418 .priolvl()
1420 .medium()
1421 .msize()
1423 .bits8()
1424 .psize()
1426 .bits8()
1427 .circ()
1429 .disabled()
1430 .dir()
1432 .from_peripheral()
1433 });
1434 self.txchannel.st().chcfg().modify(|_, w| {
1435 w
1436 .mem2mem()
1438 .disabled()
1439 .priolvl()
1441 .medium()
1442 .msize()
1444 .bits8()
1445 .psize()
1447 .bits8()
1448 .circ()
1450 .disabled()
1451 .dir()
1453 .from_memory()
1454 });
1455 self.start();
1456
1457 Transfer::w((rxbuffer, txbuffer), self)
1458 }
1459 }
1460 };
1461}
1462
1463spi_dma!(
1464 pac::Spi1,
1465 Spi1RxDma,
1466 Spi1TxDma,
1467 Spi1RxTxDma
1468);
1469spi_dma!(
1470 pac::Spi2,
1471 Spi2RxDma,
1472 Spi2TxDma,
1473 Spi2RxTxDma
1474);
1475spi_dma!(
1476 pac::Spi3,
1477 Spi3RxDma,
1478 Spi3TxDma,
1479 Spi3RxTxDma
1480);