1mod hal_02;
66mod hal_1;
67
68use core::ops::{Deref, DerefMut};
69
70use crate::pac::{self, RCC};
71
72use crate::afio::{self, RInto, Rmp};
73use crate::dma::dma1;
74#[cfg(feature = "connectivity")]
75use crate::dma::dma2;
76use crate::dma::{self, Receive, RxDma, RxTxDma, Transfer, TransferPayload, Transmit, TxDma};
77use crate::gpio::{Floating, PushPull, UpMode};
78use crate::rcc::{BusClock, Enable, Rcc, Reset};
79use crate::time::Hertz;
80
81use core::sync::atomic::{self, Ordering};
82use embedded_dma::{ReadBuffer, WriteBuffer};
83
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86pub enum Polarity {
87 IdleLow,
89 IdleHigh,
91}
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq)]
95pub enum Phase {
96 CaptureOnFirstTransition,
98 CaptureOnSecondTransition,
100}
101
102#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104pub struct Mode {
105 pub polarity: Polarity,
107 pub phase: Phase,
109}
110
111type SpiRB = pac::spi1::RegisterBlock;
112
113pub trait FrameSize: Copy + Default {
114 const DFF: bool;
115 #[doc(hidden)]
116 fn read_data(spi: &SpiRB) -> Self;
117 #[doc(hidden)]
118 fn write_data(self, spi: &SpiRB);
119}
120
121impl FrameSize for u8 {
122 const DFF: bool = false;
123 fn read_data(spi: &SpiRB) -> Self {
124 spi.dr8().read().dr().bits()
125 }
126 fn write_data(self, spi: &SpiRB) {
127 spi.dr8().write(|w| w.dr().set(self));
128 }
129}
130
131impl FrameSize for u16 {
132 const DFF: bool = true;
133 fn read_data(spi: &SpiRB) -> Self {
134 spi.dr().read().dr().bits()
135 }
136 fn write_data(self, spi: &SpiRB) {
137 spi.dr().write(|w| w.dr().set(self));
138 }
139}
140
141pub enum Event {
143 Rxne,
145 Txe,
147 Error,
149}
150
151#[derive(Debug)]
153#[non_exhaustive]
154pub enum Error {
155 Overrun,
157 ModeFault,
159 Crc,
161}
162
163use core::marker::PhantomData;
164
165#[allow(non_upper_case_globals)]
166pub trait SpiExt: Sized + Instance {
167 const NoSck: Option<Self::MSck> = None;
168 const NoMiso: Option<Self::Mi<Floating>> = None;
169 const NoMosi: Option<Self::Mo> = None;
170 const NoSSck: Option<Self::SSck> = None;
171 const NoSo: Option<Self::So<PushPull>> = None;
172 const NoSi: Option<Self::Si<Floating>> = None;
173 fn spi<PULL: UpMode>(
174 self,
175 pins: (
176 Option<impl RInto<Self::MSck, 0>>,
177 Option<impl RInto<Self::Mi<PULL>, 0>>,
178 Option<impl RInto<Self::Mo, 0>>,
179 ),
180 mode: Mode,
181 freq: Hertz,
182 rcc: &mut Rcc,
183 ) -> Spi<Self, u8, PULL>;
184 fn spi_u16<PULL: UpMode>(
185 self,
186 pins: (
187 Option<impl RInto<Self::MSck, 0>>,
188 Option<impl RInto<Self::Mi<PULL>, 0>>,
189 Option<impl RInto<Self::Mo, 0>>,
190 ),
191 mode: Mode,
192 freq: Hertz,
193 rcc: &mut Rcc,
194 ) -> Spi<Self, u16, PULL> {
195 Self::spi(self, pins, mode, freq, rcc).frame_size_16bit()
196 }
197 fn spi_slave<Otype, PULL: UpMode>(
198 self,
199 pins: (
200 Option<impl RInto<Self::SSck, 0>>,
201 Option<impl RInto<Self::So<Otype>, 0>>,
202 Option<impl RInto<Self::Si<PULL>, 0>>,
203 ),
204 mode: Mode,
205 rcc: &mut RCC,
206 ) -> SpiSlave<Self, u8, Otype, PULL>;
207 fn spi_slave_u16<Otype, PULL: UpMode>(
208 self,
209 pins: (
210 Option<impl RInto<Self::SSck, 0>>,
211 Option<impl RInto<Self::So<Otype>, 0>>,
212 Option<impl RInto<Self::Si<PULL>, 0>>,
213 ),
214 mode: Mode,
215 rcc: &mut RCC,
216 ) -> SpiSlave<Self, u16, Otype, PULL> {
217 Self::spi_slave(self, pins, mode, rcc).frame_size_16bit()
218 }
219}
220
221impl<SPI: Instance> SpiExt for SPI {
222 fn spi<PULL: UpMode>(
223 self,
224 pins: (
225 Option<impl RInto<Self::MSck, 0>>,
226 Option<impl RInto<Self::Mi<PULL>, 0>>,
227 Option<impl RInto<Self::Mo, 0>>,
228 ),
229 mode: Mode,
230 freq: Hertz,
231 rcc: &mut Rcc,
232 ) -> Spi<Self, u8, PULL> {
233 Spi::new(self, pins, mode, freq, rcc)
234 }
235 fn spi_slave<Otype, PULL: UpMode>(
236 self,
237 pins: (
238 Option<impl RInto<Self::SSck, 0>>,
239 Option<impl RInto<Self::So<Otype>, 0>>,
240 Option<impl RInto<Self::Si<PULL>, 0>>,
241 ),
242 mode: Mode,
243 rcc: &mut RCC,
244 ) -> SpiSlave<Self, u8, Otype, PULL> {
245 SpiSlave::new(self, pins, mode, rcc)
246 }
247}
248
249pub struct SpiInner<SPI, W> {
250 spi: SPI,
251 _framesize: PhantomData<W>,
252}
253
254impl<SPI, W> SpiInner<SPI, W> {
255 fn new(spi: SPI) -> Self {
256 Self {
257 spi,
258 _framesize: PhantomData,
259 }
260 }
261}
262
263pub struct Spi<SPI: Instance, W, PULL = Floating> {
265 inner: SpiInner<SPI, W>,
266 #[allow(clippy::type_complexity)]
267 pins: (Option<SPI::MSck>, Option<SPI::Mi<PULL>>, Option<SPI::Mo>),
268}
269
270pub struct SpiSlave<SPI: Instance, W, Otype = PushPull, PULL = Floating> {
272 inner: SpiInner<SPI, W>,
273 #[allow(clippy::type_complexity)]
274 pins: (
275 Option<SPI::SSck>,
276 Option<SPI::So<Otype>>,
277 Option<SPI::Si<PULL>>,
278 ),
279}
280
281impl<SPI: Instance, W, PULL> Deref for Spi<SPI, W, PULL> {
282 type Target = SpiInner<SPI, W>;
283 fn deref(&self) -> &Self::Target {
284 &self.inner
285 }
286}
287
288impl<SPI: Instance, W, PULL> DerefMut for Spi<SPI, W, PULL> {
289 fn deref_mut(&mut self) -> &mut Self::Target {
290 &mut self.inner
291 }
292}
293
294impl<SPI: Instance, W, Otype, PULL> Deref for SpiSlave<SPI, W, Otype, PULL> {
295 type Target = SpiInner<SPI, W>;
296 fn deref(&self) -> &Self::Target {
297 &self.inner
298 }
299}
300
301impl<SPI: Instance, W, Otype, PULL> DerefMut for SpiSlave<SPI, W, Otype, PULL> {
302 fn deref_mut(&mut self) -> &mut Self::Target {
303 &mut self.inner
304 }
305}
306
307#[derive(Debug, Clone, Copy)]
309pub enum SpiBitFormat {
310 LsbFirst,
312 MsbFirst,
314}
315
316pub trait Instance:
317 crate::Sealed
318 + Deref<Target = crate::pac::spi1::RegisterBlock>
319 + Enable
320 + Reset
321 + BusClock
322 + afio::SpiCommon
323{
324}
325
326impl Instance for pac::SPI1 {}
327impl Instance for pac::SPI2 {}
328#[cfg(any(feature = "high", feature = "connectivity"))]
329impl Instance for pac::SPI3 {}
330
331impl<SPI: Instance, const R: u8> Rmp<SPI, R> {
332 pub fn spi<PULL: UpMode>(
333 self,
334 pins: (
335 Option<impl RInto<SPI::MSck, R>>,
336 Option<impl RInto<SPI::Mi<PULL>, R>>,
337 Option<impl RInto<SPI::Mo, R>>,
338 ),
339 mode: Mode,
340 freq: Hertz,
341 rcc: &mut Rcc,
342 ) -> Spi<SPI, u8, PULL> {
343 let spi = self.0;
344 SPI::enable(rcc);
346 SPI::reset(rcc);
347
348 spi.cr2().write(|w| w.ssoe().clear_bit());
350
351 let br = match SPI::clock(&rcc.clocks) / freq {
352 0 => unreachable!(),
353 1..=2 => 0b000,
354 3..=5 => 0b001,
355 6..=11 => 0b010,
356 12..=23 => 0b011,
357 24..=47 => 0b100,
358 48..=95 => 0b101,
359 96..=191 => 0b110,
360 _ => 0b111,
361 };
362
363 let pins = (
364 pins.0.map(RInto::rinto),
365 pins.1.map(RInto::rinto),
366 pins.2.map(RInto::rinto),
367 );
368
369 spi.cr1().write(|w| {
370 w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
372 w.cpol().bit(mode.polarity == Polarity::IdleHigh);
374 w.mstr().set_bit();
376 w.br().set(br);
378 w.lsbfirst().clear_bit();
380 w.ssm().set_bit();
382 w.ssi().set_bit();
384 w.dff().clear_bit();
386 w.bidimode().clear_bit();
388 w.rxonly().clear_bit();
390 w.spe().set_bit()
392 });
393
394 Spi {
395 inner: SpiInner::new(spi),
396 pins,
397 }
398 }
399 pub fn spi_u16<PULL: UpMode>(
400 self,
401 pins: (
402 Option<impl RInto<SPI::MSck, R>>,
403 Option<impl RInto<SPI::Mi<PULL>, R>>,
404 Option<impl RInto<SPI::Mo, R>>,
405 ),
406 mode: Mode,
407 freq: Hertz,
408 rcc: &mut Rcc,
409 ) -> Spi<SPI, u16, PULL> {
410 self.spi(pins, mode, freq, rcc).frame_size_16bit()
411 }
412 pub fn spi_slave<Otype, PULL: UpMode>(
413 self,
414 pins: (
415 Option<impl RInto<SPI::SSck, R>>,
416 Option<impl RInto<SPI::So<Otype>, R>>,
417 Option<impl RInto<SPI::Si<PULL>, R>>,
418 ),
419 mode: Mode,
420 rcc: &mut RCC,
421 ) -> SpiSlave<SPI, u8, Otype, PULL> {
422 let spi = self.0;
423 SPI::enable(rcc);
425 SPI::reset(rcc);
426
427 spi.cr2().write(|w| w.ssoe().clear_bit());
429
430 let pins = (
431 pins.0.map(RInto::rinto),
432 pins.1.map(RInto::rinto),
433 pins.2.map(RInto::rinto),
434 );
435
436 spi.cr1().write(|w| {
437 w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
439 w.cpol().bit(mode.polarity == Polarity::IdleHigh);
441 w.mstr().clear_bit();
443 w.lsbfirst().clear_bit();
445 w.ssm().set_bit();
447 w.ssi().clear_bit();
449 w.dff().clear_bit();
451 w.bidimode().clear_bit();
453 w.rxonly().clear_bit();
455 w.spe().set_bit()
457 });
458
459 SpiSlave {
460 inner: SpiInner::new(spi),
461 pins,
462 }
463 }
464 pub fn spi_slave_u16<Otype, PULL: UpMode>(
465 self,
466 pins: (
467 Option<impl RInto<SPI::SSck, R>>,
468 Option<impl RInto<SPI::So<Otype>, R>>,
469 Option<impl RInto<SPI::Si<PULL>, R>>,
470 ),
471 mode: Mode,
472 rcc: &mut RCC,
473 ) -> SpiSlave<SPI, u16, Otype, PULL> {
474 self.spi_slave(pins, mode, rcc).frame_size_16bit()
475 }
476}
477
478impl<SPI: Instance, PULL: UpMode> Spi<SPI, u8, PULL> {
479 pub fn new<const R: u8>(
487 spi: impl Into<Rmp<SPI, R>>,
488 pins: (
489 Option<impl RInto<SPI::MSck, R>>,
490 Option<impl RInto<SPI::Mi<PULL>, R>>,
491 Option<impl RInto<SPI::Mo, R>>,
492 ),
493 mode: Mode,
494 freq: Hertz,
495 rcc: &mut Rcc,
496 ) -> Self {
497 spi.into().spi(pins, mode, freq, rcc)
498 }
499}
500
501impl<SPI: Instance, PULL> Spi<SPI, u8, PULL> {
502 #[allow(clippy::type_complexity)]
503 pub fn release(
504 self,
505 ) -> (
506 SPI,
507 (Option<SPI::MSck>, Option<SPI::Mi<PULL>>, Option<SPI::Mo>),
508 ) {
509 (self.inner.spi, self.pins)
510 }
511}
512
513impl<SPI: Instance, Otype, PULL: UpMode> SpiSlave<SPI, u8, Otype, PULL> {
514 pub fn new<const R: u8>(
522 spi: impl Into<Rmp<SPI, R>>,
523 pins: (
524 Option<impl RInto<SPI::SSck, R>>,
525 Option<impl RInto<SPI::So<Otype>, R>>,
526 Option<impl RInto<SPI::Si<PULL>, R>>,
527 ),
528 mode: Mode,
529 rcc: &mut RCC,
530 ) -> Self {
531 spi.into().spi_slave(pins, mode, rcc)
532 }
533}
534
535impl<SPI: Instance, Otype, PULL> SpiSlave<SPI, u8, Otype, PULL> {
536 #[allow(clippy::type_complexity)]
537 pub fn release(
538 self,
539 ) -> (
540 SPI,
541 (
542 Option<SPI::SSck>,
543 Option<SPI::So<Otype>>,
544 Option<SPI::Si<PULL>>,
545 ),
546 ) {
547 (self.inner.spi, self.pins)
548 }
549}
550
551impl<SPI: Instance, W: FrameSize> SpiInner<SPI, W> {
552 fn spi_write(&mut self, words: &[W]) -> Result<(), Error> {
557 for word in words {
559 loop {
560 let sr = self.spi.sr().read();
561 if sr.txe().bit_is_set() {
562 (*word).write_data(&self.spi);
563 if sr.modf().bit_is_set() {
564 return Err(Error::ModeFault);
565 }
566 break;
567 }
568 }
569 }
570 while !self.is_tx_empty() {}
572 while self.is_busy() {}
574 let _ = W::read_data(&self.spi);
576 let _ = self.spi.sr().read();
577 Ok(())
578 }
579}
580
581impl<SPI: Instance, W> SpiInner<SPI, W> {
582 pub fn bit_format(&mut self, format: SpiBitFormat) {
584 self.spi
585 .cr1()
586 .modify(|_, w| w.lsbfirst().bit(matches!(format, SpiBitFormat::LsbFirst)));
587 }
588
589 pub fn listen(&mut self, event: Event) {
593 self.spi.cr2().modify(|_, w| match event {
594 Event::Rxne => w.rxneie().set_bit(),
595 Event::Txe => w.txeie().set_bit(),
596 Event::Error => w.errie().set_bit(),
597 });
598 }
599
600 pub fn unlisten(&mut self, event: Event) {
604 self.spi.cr2().modify(|_, w| match event {
605 Event::Rxne => w.rxneie().clear_bit(),
606 Event::Txe => w.txeie().clear_bit(),
607 Event::Error => w.errie().clear_bit(),
608 });
609 }
610
611 #[inline]
613 pub fn is_tx_empty(&self) -> bool {
614 self.spi.sr().read().txe().bit_is_set()
615 }
616
617 #[inline]
619 pub fn is_rx_not_empty(&self) -> bool {
620 self.spi.sr().read().rxne().bit_is_set()
621 }
622
623 #[inline]
625 pub fn is_busy(&self) -> bool {
626 self.spi.sr().read().bsy().bit_is_set()
627 }
628
629 #[inline]
631 pub fn is_overrun(&self) -> bool {
632 self.spi.sr().read().ovr().bit_is_set()
633 }
634}
635
636impl<SPI: Instance, PULL> Spi<SPI, u8, PULL> {
637 pub fn frame_size_16bit(self) -> Spi<SPI, u16, PULL> {
639 self.spi.cr1().modify(|_, w| w.spe().clear_bit());
640 self.spi.cr1().modify(|_, w| w.dff().set_bit());
641 self.spi.cr1().modify(|_, w| w.spe().set_bit());
642 Spi {
643 inner: SpiInner::new(self.inner.spi),
644 pins: self.pins,
645 }
646 }
647}
648
649impl<SPI: Instance, Otype, PULL> SpiSlave<SPI, u8, Otype, PULL> {
650 pub fn frame_size_16bit(self) -> SpiSlave<SPI, u16, Otype, PULL> {
652 self.spi.cr1().modify(|_, w| w.spe().clear_bit());
653 self.spi.cr1().modify(|_, w| w.dff().set_bit());
654 self.spi.cr1().modify(|_, w| w.spe().set_bit());
655 SpiSlave {
656 inner: SpiInner::new(self.inner.spi),
657 pins: self.pins,
658 }
659 }
660}
661
662impl<SPI: Instance, PULL> Spi<SPI, u16, PULL> {
663 pub fn frame_size_8bit(self) -> Spi<SPI, u16, PULL> {
665 self.spi.cr1().modify(|_, w| w.spe().clear_bit());
666 self.spi.cr1().modify(|_, w| w.dff().clear_bit());
667 self.spi.cr1().modify(|_, w| w.spe().set_bit());
668 Spi {
669 inner: SpiInner::new(self.inner.spi),
670 pins: self.pins,
671 }
672 }
673}
674
675impl<SPI: Instance, Otype, PULL> SpiSlave<SPI, u16, Otype, PULL> {
676 pub fn frame_size_8bit(self) -> SpiSlave<SPI, u8, Otype, PULL> {
678 self.spi.cr1().modify(|_, w| w.spe().clear_bit());
679 self.spi.cr1().modify(|_, w| w.dff().clear_bit());
680 self.spi.cr1().modify(|_, w| w.spe().set_bit());
681 SpiSlave {
682 inner: SpiInner::new(self.inner.spi),
683 pins: self.pins,
684 }
685 }
686}
687
688impl<SPI, W> SpiInner<SPI, W>
689where
690 SPI: Instance,
691 W: FrameSize,
692{
693 pub(crate) fn check_read(&mut self) -> nb::Result<W, Error> {
694 let sr = self.spi.sr().read();
695
696 Err(if sr.ovr().bit_is_set() {
697 Error::Overrun.into()
698 } else if sr.modf().bit_is_set() {
699 Error::ModeFault.into()
700 } else if sr.crcerr().bit_is_set() {
701 Error::Crc.into()
702 } else if sr.rxne().bit_is_set() {
703 return Ok(W::read_data(&self.spi));
706 } else {
707 nb::Error::WouldBlock
708 })
709 }
710
711 pub(crate) fn check_send(&mut self, data: W) -> nb::Result<(), Error> {
712 let sr = self.spi.sr().read();
713
714 Err(if sr.modf().bit_is_set() {
716 Error::ModeFault.into()
717 } else if sr.crcerr().bit_is_set() {
718 Error::Crc.into()
719 } else if sr.txe().bit_is_set() {
720 data.write_data(&self.spi);
722 return Ok(());
723 } else {
724 nb::Error::WouldBlock
725 })
726 }
727
728 #[inline(always)]
729 pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
730 self.check_read()
732 }
733
734 #[inline(always)]
735 pub fn write_nonblocking(&mut self, data: W) -> nb::Result<(), Error> {
736 self.check_send(data)
738 }
739
740 #[inline(always)]
741 pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
742 self.spi_write(words)
743 }
744
745 pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
746 for word in words {
747 nb::block!(self.write_nonblocking(*word))?;
748 *word = nb::block!(self.read_nonblocking())?;
749 }
750
751 Ok(())
752 }
753
754 pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
755 if data.len() == buff.len() {
756 for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
757 nb::block!(self.write_nonblocking(d))?;
758 *b = nb::block!(self.read_nonblocking())?;
759 }
760 } else {
761 let mut iter_r = buff.iter_mut();
762 let mut iter_w = data.iter().cloned();
763 loop {
764 match (iter_r.next(), iter_w.next()) {
765 (Some(r), Some(w)) => {
766 nb::block!(self.write_nonblocking(w))?;
767 *r = nb::block!(self.read_nonblocking())?;
768 }
769 (Some(r), None) => {
770 nb::block!(self.write_nonblocking(W::default()))?;
771 *r = nb::block!(self.read_nonblocking())?;
772 }
773 (None, Some(w)) => {
774 nb::block!(self.write_nonblocking(w))?;
775 let _ = nb::block!(self.read_nonblocking())?;
776 }
777 (None, None) => break,
778 }
779 }
780 }
781
782 Ok(())
783 }
784
785 pub fn flush(&mut self) -> Result<(), Error> {
786 Ok(())
787 }
788
789 pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
790 for word in words {
792 nb::block!(self.check_send(W::default()))?;
793 *word = nb::block!(self.check_read())?;
794 }
795
796 Ok(())
797 }
798}
799
800pub type SpiTxDma<SPI, CHANNEL, PULL = Floating> = TxDma<Spi<SPI, u8, PULL>, CHANNEL>;
803pub type SpiRxDma<SPI, CHANNEL, PULL = Floating> = RxDma<Spi<SPI, u8, PULL>, CHANNEL>;
804pub type SpiRxTxDma<SPI, RXCHANNEL, TXCHANNEL, PULL = Floating> =
805 RxTxDma<Spi<SPI, u8, PULL>, RXCHANNEL, TXCHANNEL>;
806
807pub type SpiSlaveTxDma<SPI, CHANNEL, Otype, PULL = Floating> =
808 TxDma<SpiSlave<SPI, u8, Otype, PULL>, CHANNEL>;
809pub type SpiSlaveRxDma<SPI, CHANNEL, Otype, PULL = Floating> =
810 RxDma<SpiSlave<SPI, u8, Otype, PULL>, CHANNEL>;
811pub type SpiSlaveRxTxDma<SPI, RXCHANNEL, TXCHANNEL, Otype, PULL = Floating> =
812 RxTxDma<SpiSlave<SPI, u8, Otype, PULL>, RXCHANNEL, TXCHANNEL>;
813
814macro_rules! spi_dma {
815 (
816 $SPIi:ty,
817 rx: $RCi:ty,
818 tx: $TCi:ty,
819 $rxdma:ident,
820 $txdma:ident,
821 $rxtxdma:ident,
822 $slaverxdma:ident,
823 $slavetxdma:ident,
824 $slaverxtxdma:ident
825 ) => {
826 pub type $rxdma<PULL = Floating> = SpiRxDma<$SPIi, $RCi, PULL>;
827 pub type $txdma<PULL = Floating> = SpiTxDma<$SPIi, $TCi, PULL>;
828 pub type $rxtxdma<PULL = Floating> = SpiRxTxDma<$SPIi, $RCi, $TCi, PULL>;
829
830 impl<PULL> Transmit for SpiTxDma<$SPIi, $TCi, PULL> {
831 type TxChannel = $TCi;
832 type ReceivedWord = u8;
833 }
834
835 impl<PULL> Receive for SpiRxDma<$SPIi, $RCi, PULL> {
836 type RxChannel = $RCi;
837 type TransmittedWord = u8;
838 }
839
840 impl<PULL> Transmit for SpiRxTxDma<$SPIi, $RCi, $TCi, PULL> {
841 type TxChannel = $TCi;
842 type ReceivedWord = u8;
843 }
844
845 impl<PULL> Receive for SpiRxTxDma<$SPIi, $RCi, $TCi, PULL> {
846 type RxChannel = $RCi;
847 type TransmittedWord = u8;
848 }
849
850 impl<PULL> Spi<$SPIi, u8, PULL> {
851 pub fn with_tx_dma(self, channel: $TCi) -> SpiTxDma<$SPIi, $TCi, PULL> {
852 self.spi.cr2().modify(|_, w| w.txdmaen().set_bit());
853 SpiTxDma {
854 payload: self,
855 channel,
856 }
857 }
858 pub fn with_rx_dma(self, channel: $RCi) -> SpiRxDma<$SPIi, $RCi, PULL> {
859 self.spi.cr2().modify(|_, w| w.rxdmaen().set_bit());
860 SpiRxDma {
861 payload: self,
862 channel,
863 }
864 }
865 pub fn with_rx_tx_dma(
866 self,
867 rxchannel: $RCi,
868 txchannel: $TCi,
869 ) -> SpiRxTxDma<$SPIi, $RCi, $TCi, PULL> {
870 self.spi
871 .cr2()
872 .modify(|_, w| w.rxdmaen().set_bit().txdmaen().set_bit());
873 SpiRxTxDma {
874 payload: self,
875 rxchannel,
876 txchannel,
877 }
878 }
879 }
880
881 impl<PULL> SpiTxDma<$SPIi, $TCi, PULL> {
882 pub fn release(self) -> (Spi<$SPIi, u8, PULL>, $TCi) {
883 let SpiTxDma { payload, channel } = self;
884 payload.spi.cr2().modify(|_, w| w.txdmaen().clear_bit());
885 (payload, channel)
886 }
887 }
888
889 impl<PULL> SpiRxDma<$SPIi, $RCi, PULL> {
890 pub fn release(self) -> (Spi<$SPIi, u8, PULL>, $RCi) {
891 let SpiRxDma { payload, channel } = self;
892 payload.spi.cr2().modify(|_, w| w.rxdmaen().clear_bit());
893 (payload, channel)
894 }
895 }
896
897 impl<PULL> SpiRxTxDma<$SPIi, $RCi, $TCi, PULL> {
898 pub fn release(self) -> (Spi<$SPIi, u8, PULL>, $RCi, $TCi) {
899 let SpiRxTxDma {
900 payload,
901 rxchannel,
902 txchannel,
903 } = self;
904 payload
905 .spi
906 .cr2()
907 .modify(|_, w| w.rxdmaen().clear_bit().txdmaen().clear_bit());
908 (payload, rxchannel, txchannel)
909 }
910 }
911
912 impl<PULL> TransferPayload for SpiTxDma<$SPIi, $TCi, PULL> {
913 fn start(&mut self) {
914 self.channel.start();
915 }
916 fn stop(&mut self) {
917 self.channel.stop();
918 }
919 }
920
921 impl<PULL> TransferPayload for SpiRxDma<$SPIi, $RCi, PULL> {
922 fn start(&mut self) {
923 self.channel.start();
924 }
925 fn stop(&mut self) {
926 self.channel.stop();
927 }
928 }
929
930 impl<PULL> TransferPayload for SpiRxTxDma<$SPIi, $RCi, $TCi, PULL> {
931 fn start(&mut self) {
932 self.rxchannel.start();
933 self.txchannel.start();
934 }
935 fn stop(&mut self) {
936 self.txchannel.stop();
937 self.rxchannel.stop();
938 }
939 }
940
941 impl<B, PULL> crate::dma::ReadDma<B, u8> for SpiRxDma<$SPIi, $RCi, PULL>
942 where
943 B: WriteBuffer<Word = u8>,
944 {
945 fn read(mut self, mut buffer: B) -> Transfer<dma::W, B, Self> {
946 let (ptr, len) = unsafe { buffer.write_buffer() };
949 self.channel.set_peripheral_address(
950 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
951 false,
952 );
953 self.channel.set_memory_address(ptr as u32, true);
954 self.channel.set_transfer_length(len);
955
956 atomic::compiler_fence(Ordering::Release);
957 self.channel.ch().cr().modify(|_, w| {
958 w.mem2mem().clear_bit();
960 w.pl().medium();
962 w.msize().bits8();
964 w.psize().bits8();
966 w.circ().clear_bit();
968 w.dir().clear_bit()
970 });
971 self.start();
972
973 Transfer::w(buffer, self)
974 }
975 }
976
977 impl<B, PULL> crate::dma::WriteDma<B, u8> for SpiTxDma<$SPIi, $TCi, PULL>
978 where
979 B: ReadBuffer<Word = u8>,
980 {
981 fn write(mut self, buffer: B) -> Transfer<dma::R, B, Self> {
982 let (ptr, len) = unsafe { buffer.read_buffer() };
985 self.channel.set_peripheral_address(
986 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
987 false,
988 );
989 self.channel.set_memory_address(ptr as u32, true);
990 self.channel.set_transfer_length(len);
991
992 atomic::compiler_fence(Ordering::Release);
993 self.channel.ch().cr().modify(|_, w| {
994 w.mem2mem().clear_bit();
996 w.pl().medium();
998 w.msize().bits8();
1000 w.psize().bits8();
1002 w.circ().clear_bit();
1004 w.dir().set_bit()
1006 });
1007 self.start();
1008
1009 Transfer::r(buffer, self)
1010 }
1011 }
1012
1013 impl<RXB, TXB, PULL> crate::dma::ReadWriteDma<RXB, TXB, u8>
1014 for SpiRxTxDma<$SPIi, $RCi, $TCi, PULL>
1015 where
1016 RXB: WriteBuffer<Word = u8>,
1017 TXB: ReadBuffer<Word = u8>,
1018 {
1019 fn read_write(
1020 mut self,
1021 mut rxbuffer: RXB,
1022 txbuffer: TXB,
1023 ) -> Transfer<dma::W, (RXB, TXB), Self> {
1024 let (rxptr, rxlen) = unsafe { rxbuffer.write_buffer() };
1027 let (txptr, txlen) = unsafe { txbuffer.read_buffer() };
1028
1029 if rxlen != txlen {
1030 panic!("receive and send buffer lengths do not match!");
1031 }
1032
1033 self.rxchannel.set_peripheral_address(
1034 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1035 false,
1036 );
1037 self.rxchannel.set_memory_address(rxptr as u32, true);
1038 self.rxchannel.set_transfer_length(rxlen);
1039
1040 self.txchannel.set_peripheral_address(
1041 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1042 false,
1043 );
1044 self.txchannel.set_memory_address(txptr as u32, true);
1045 self.txchannel.set_transfer_length(txlen);
1046
1047 atomic::compiler_fence(Ordering::Release);
1048 self.rxchannel.ch().cr().modify(|_, w| {
1049 w.mem2mem().clear_bit();
1051 w.pl().medium();
1053 w.msize().bits8();
1055 w.psize().bits8();
1057 w.circ().clear_bit();
1059 w.dir().clear_bit()
1061 });
1062 self.txchannel.ch().cr().modify(|_, w| {
1063 w.mem2mem().clear_bit();
1065 w.pl().medium();
1067 w.msize().bits8();
1069 w.psize().bits8();
1071 w.circ().clear_bit();
1073 w.dir().set_bit()
1075 });
1076 self.start();
1077
1078 Transfer::w((rxbuffer, txbuffer), self)
1079 }
1080 }
1081
1082 pub type $slaverxdma<Otype = PushPull, PULL = Floating> =
1083 SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL>;
1084 pub type $slavetxdma<Otype = PushPull, PULL = Floating> =
1085 SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL>;
1086 pub type $slaverxtxdma<Otype = PushPull, PULL = Floating> =
1087 SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL>;
1088
1089 impl<Otype, PULL> Transmit for SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL> {
1090 type TxChannel = $TCi;
1091 type ReceivedWord = u8;
1092 }
1093
1094 impl<Otype, PULL> Receive for SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL> {
1095 type RxChannel = $RCi;
1096 type TransmittedWord = u8;
1097 }
1098
1099 impl<Otype, PULL> Transmit for SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL> {
1100 type TxChannel = $TCi;
1101 type ReceivedWord = u8;
1102 }
1103
1104 impl<Otype, PULL> Receive for SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL> {
1105 type RxChannel = $RCi;
1106 type TransmittedWord = u8;
1107 }
1108
1109 impl<Otype, PULL> SpiSlave<$SPIi, u8, Otype, PULL> {
1110 pub fn with_tx_dma(self, channel: $TCi) -> SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL> {
1111 self.spi.cr2().modify(|_, w| w.txdmaen().set_bit());
1112 SpiSlaveTxDma {
1113 payload: self,
1114 channel,
1115 }
1116 }
1117 pub fn with_rx_dma(self, channel: $RCi) -> SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL> {
1118 self.spi.cr2().modify(|_, w| w.rxdmaen().set_bit());
1119 SpiSlaveRxDma {
1120 payload: self,
1121 channel,
1122 }
1123 }
1124 pub fn with_rx_tx_dma(
1125 self,
1126 rxchannel: $RCi,
1127 txchannel: $TCi,
1128 ) -> SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL> {
1129 self.spi
1130 .cr2()
1131 .modify(|_, w| w.rxdmaen().set_bit().txdmaen().set_bit());
1132 SpiSlaveRxTxDma {
1133 payload: self,
1134 rxchannel,
1135 txchannel,
1136 }
1137 }
1138 }
1139
1140 impl<Otype, PULL> SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL> {
1141 pub fn release(self) -> (SpiSlave<$SPIi, u8, Otype, PULL>, $TCi) {
1142 let SpiSlaveTxDma { payload, channel } = self;
1143 payload.spi.cr2().modify(|_, w| w.txdmaen().clear_bit());
1144 (payload, channel)
1145 }
1146 }
1147
1148 impl<Otype, PULL> SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL> {
1149 pub fn release(self) -> (SpiSlave<$SPIi, u8, Otype, PULL>, $RCi) {
1150 let SpiSlaveRxDma { payload, channel } = self;
1151 payload.spi.cr2().modify(|_, w| w.rxdmaen().clear_bit());
1152 (payload, channel)
1153 }
1154 }
1155
1156 impl<Otype, PULL> SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL> {
1157 pub fn release(self) -> (SpiSlave<$SPIi, u8, Otype, PULL>, $RCi, $TCi) {
1158 let SpiSlaveRxTxDma {
1159 payload,
1160 rxchannel,
1161 txchannel,
1162 } = self;
1163 payload
1164 .spi
1165 .cr2()
1166 .modify(|_, w| w.rxdmaen().clear_bit().txdmaen().clear_bit());
1167 (payload, rxchannel, txchannel)
1168 }
1169 }
1170
1171 impl<Otype, PULL> TransferPayload for SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL> {
1172 fn start(&mut self) {
1173 self.channel.start();
1174 }
1175 fn stop(&mut self) {
1176 self.channel.stop();
1177 }
1178 }
1179
1180 impl<Otype, PULL> TransferPayload for SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL> {
1181 fn start(&mut self) {
1182 self.channel.start();
1183 }
1184 fn stop(&mut self) {
1185 self.channel.stop();
1186 }
1187 }
1188
1189 impl<Otype, PULL> TransferPayload for SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL> {
1190 fn start(&mut self) {
1191 self.rxchannel.start();
1192 self.txchannel.start();
1193 }
1194 fn stop(&mut self) {
1195 self.txchannel.stop();
1196 self.rxchannel.stop();
1197 }
1198 }
1199
1200 impl<B, Otype, PULL> crate::dma::ReadDma<B, u8> for SpiSlaveRxDma<$SPIi, $RCi, Otype, PULL>
1201 where
1202 B: WriteBuffer<Word = u8>,
1203 {
1204 fn read(mut self, mut buffer: B) -> Transfer<dma::W, B, Self> {
1205 let (ptr, len) = unsafe { buffer.write_buffer() };
1208 self.channel.set_peripheral_address(
1209 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1210 false,
1211 );
1212 self.channel.set_memory_address(ptr as u32, true);
1213 self.channel.set_transfer_length(len);
1214
1215 atomic::compiler_fence(Ordering::Release);
1216 self.channel.ch().cr().modify(|_, w| {
1217 w.mem2mem().clear_bit();
1219 w.pl().medium();
1221 w.msize().bits8();
1223 w.psize().bits8();
1225 w.circ().clear_bit();
1227 w.dir().clear_bit()
1229 });
1230 self.start();
1231
1232 Transfer::w(buffer, self)
1233 }
1234 }
1235
1236 impl<B, Otype, PULL> crate::dma::WriteDma<B, u8> for SpiSlaveTxDma<$SPIi, $TCi, Otype, PULL>
1237 where
1238 B: ReadBuffer<Word = u8>,
1239 {
1240 fn write(mut self, buffer: B) -> Transfer<dma::R, B, Self> {
1241 let (ptr, len) = unsafe { buffer.read_buffer() };
1244 self.channel.set_peripheral_address(
1245 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1246 false,
1247 );
1248 self.channel.set_memory_address(ptr as u32, true);
1249 self.channel.set_transfer_length(len);
1250
1251 atomic::compiler_fence(Ordering::Release);
1252 self.channel.ch().cr().modify(|_, w| {
1253 w.mem2mem().clear_bit();
1255 w.pl().medium();
1257 w.msize().bits8();
1259 w.psize().bits8();
1261 w.circ().clear_bit();
1263 w.dir().set_bit()
1265 });
1266 self.start();
1267
1268 Transfer::r(buffer, self)
1269 }
1270 }
1271
1272 impl<RXB, TXB, Otype, PULL> crate::dma::ReadWriteDma<RXB, TXB, u8>
1273 for SpiSlaveRxTxDma<$SPIi, $RCi, $TCi, Otype, PULL>
1274 where
1275 RXB: WriteBuffer<Word = u8>,
1276 TXB: ReadBuffer<Word = u8>,
1277 {
1278 fn read_write(
1279 mut self,
1280 mut rxbuffer: RXB,
1281 txbuffer: TXB,
1282 ) -> Transfer<dma::W, (RXB, TXB), Self> {
1283 let (rxptr, rxlen) = unsafe { rxbuffer.write_buffer() };
1286 let (txptr, txlen) = unsafe { txbuffer.read_buffer() };
1287
1288 if rxlen != txlen {
1289 panic!("receive and send buffer lengths do not match!");
1290 }
1291
1292 self.rxchannel.set_peripheral_address(
1293 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1294 false,
1295 );
1296 self.rxchannel.set_memory_address(rxptr as u32, true);
1297 self.rxchannel.set_transfer_length(rxlen);
1298
1299 self.txchannel.set_peripheral_address(
1300 unsafe { (*<$SPIi>::ptr()).dr().as_ptr() as u32 },
1301 false,
1302 );
1303 self.txchannel.set_memory_address(txptr as u32, true);
1304 self.txchannel.set_transfer_length(txlen);
1305
1306 atomic::compiler_fence(Ordering::Release);
1307 self.rxchannel.ch().cr().modify(|_, w| {
1308 w.mem2mem().clear_bit();
1310 w.pl().medium();
1312 w.msize().bits8();
1314 w.psize().bits8();
1316 w.circ().clear_bit();
1318 w.dir().clear_bit()
1320 });
1321 self.txchannel.ch().cr().modify(|_, w| {
1322 w.mem2mem().clear_bit();
1324 w.pl().medium();
1326 w.msize().bits8();
1328 w.psize().bits8();
1330 w.circ().clear_bit();
1332 w.dir().set_bit()
1334 });
1335 self.start();
1336
1337 Transfer::w((rxbuffer, txbuffer), self)
1338 }
1339 }
1340 };
1341}
1342
1343spi_dma!(
1344 pac::SPI1,
1345 rx: dma1::C2,
1346 tx: dma1::C3,
1347 Spi1RxDma,
1348 Spi1TxDma,
1349 Spi1RxTxDma,
1350 SpiSlave1RxDma,
1351 SpiSlave1TxDma,
1352 SpiSlave1RxTxDma
1353);
1354spi_dma!(
1355 pac::SPI2,
1356 rx: dma1::C4,
1357 tx: dma1::C5,
1358 Spi2RxDma,
1359 Spi2TxDma,
1360 Spi2RxTxDma,
1361 SpiSlave2RxDma,
1362 SpiSlave2TxDma,
1363 SpiSlave2RxTxDma
1364);
1365#[cfg(feature = "connectivity")]
1366spi_dma!(
1367 pac::SPI3,
1368 rx: dma2::C1,
1369 tx: dma2::C2,
1370 Spi3RxDma,
1371 Spi3TxDma,
1372 Spi3RxTxDma,
1373 SpiSlave3RxDma,
1374 SpiSlave3TxDma,
1375 SpiSlave3RxTxDma
1376);