1#![allow(missing_docs)]
2
3use core::{future::poll_fn, marker::PhantomData, ops::RangeInclusive, task::Poll};
13
14use embassy_futures::join::join;
15use embassy_hal_internal::{Peri, PeripheralType, interrupt::InterruptExt as _};
16use embassy_sync::waitqueue::AtomicWaker;
17use embedded_hal_1::spi::{ErrorType, MODE_0, Mode};
18
19#[cfg(dmac)]
20use crate::dmac::{Channel as DmacChannel, DmacInterruptHandler};
21#[cfg(dtc)]
22use crate::dtc::{Channel as DtcChannel, DtcInterruptHandler, Instance as DtcInstance};
23use crate::{
24 event_link::IcuInterrupt as _,
25 gpio::{Basic, Flex, Pin, PortFunction},
26 interrupt::{
27 self,
28 typelevel::{Handler as InterruptHandler, Interrupt as InterruptType},
29 },
30 module_stop::ModuleStop,
31 pac::{
32 self,
33 spi::vals::{Brdv, Bysw, Cpha, Cpol, Lsbf, Moifv, Spb, Spbyt, Splw, Spms},
34 },
35};
36
37const VALID_CLOCK_DIVIDER: RangeInclusive<u32> = 2..=4096;
38
39pub struct ErrorInterruptHandler<I: Instance> {
40 _phantom: PhantomData<I>,
41}
42
43pub struct RxInterruptHandler<I: Instance> {
44 _phantom: PhantomData<I>,
45}
46
47pub struct TeInterruptHandler<I: Instance> {
48 _phantom: PhantomData<I>,
49}
50
51pub struct TxInterruptHandler<I: Instance> {
52 _phantom: PhantomData<I>,
53}
54
55impl<I: Instance, ErrInt: InterruptType> InterruptHandler<ErrInt> for ErrorInterruptHandler<I> {
56 unsafe fn on_interrupt() {
57 error!("{}ErrInt", I::PERIPHERAL);
58 }
59}
60
61impl<I: Instance, RxInt: InterruptType> InterruptHandler<RxInt> for RxInterruptHandler<I> {
62 unsafe fn on_interrupt() {
63 trace!("{}RxInt", I::PERIPHERAL);
64 RxInt::IRQ.icu_unpend();
65 I::rx_waker().wake();
66 }
67}
68
69impl<I: Instance, TeInt: InterruptType> InterruptHandler<TeInt> for TeInterruptHandler<I> {
70 unsafe fn on_interrupt() {
71 trace!("{}TeInt", I::PERIPHERAL);
72 TeInt::IRQ.icu_unpend();
73 I::te_waker().wake();
74 }
75}
76
77impl<I: Instance, TxInt: InterruptType> InterruptHandler<TxInt> for TxInterruptHandler<I> {
78 unsafe fn on_interrupt() {
79 trace!("{}TxInt", I::PERIPHERAL);
80 TxInt::IRQ.icu_unpend();
81 I::tx_waker().wake();
82 }
83}
84
85#[derive(Debug)]
86#[cfg_attr(feature = "defmt", derive(defmt::Format))]
87struct ClockConfig {
88 pub rate: u32,
89 pub error: u32,
90 pub spbr: u8,
91 pub brdv: u8,
92}
93
94#[allow(private_bounds)]
95pub trait TransferMode: SealedTransferMode {}
96trait SealedTransferMode {}
97
98#[cfg(dmac)]
99pub struct Dma<'d> {
100 rx_dma: DmacChannel<'d>,
101 tx_dma: DmacChannel<'d>,
102}
103
104#[cfg(dtc)]
105pub struct Dtc<D1: DtcInstance, D2: DtcInstance> {
106 rx_dtc: DtcChannel<D1>,
107 tx_dtc: DtcChannel<D2>,
108}
109
110pub struct Blocking {}
111
112#[allow(private_bounds)]
114pub struct Spi<'d, I: Instance, W: Word, M: TransferMode> {
115 _instance: PhantomData<&'d I>,
116 _miso: Flex<'d, Basic>,
117 _mosi: Flex<'d, Basic>,
118 _sck: Flex<'d, Basic>,
119 _cs: Option<Flex<'d, Basic>>,
120 _word: PhantomData<W>,
121 bit_order: BitOrder,
122 io_mode: M,
123}
124
125#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130#[derive(Copy, Clone, PartialEq)]
131pub enum ChipSelectPolarity {
132 ActiveHigh,
134
135 ActiveLow,
137}
138
139#[cfg_attr(feature = "defmt", derive(defmt::Format))]
144#[derive(Copy, Clone, PartialEq)]
145pub enum BitOrder {
146 #[allow(missing_docs)]
147 Lsb0,
148 #[allow(missing_docs)]
149 Msb0,
150}
151
152#[cfg_attr(feature = "defmt", derive(defmt::Format))]
153#[derive(Copy, Clone, PartialEq)]
154pub enum Endian {
155 #[allow(missing_docs)]
156 Big,
157 #[allow(missing_docs)]
158 Little,
159}
160
161#[cfg_attr(feature = "defmt", derive(defmt::Format))]
162#[derive(Copy, Clone, PartialEq)]
163pub enum MosiIdle {
165 Last,
167
168 Low,
170
171 High,
173}
174
175#[non_exhaustive]
177#[derive(Copy, Clone)]
178pub struct Config {
179 #[allow(missing_docs)]
180 pub bit_order: BitOrder,
181
182 #[allow(missing_docs)]
183 pub endian: Endian,
184
185 pub mode: Mode,
187
188 pub bit_rate: u32,
190
191 #[allow(missing_docs)]
192 pub cs_polarity: ChipSelectPolarity,
193
194 #[allow(missing_docs)]
195 pub mosi_idle: MosiIdle,
196}
197
198#[allow(private_bounds)]
203#[cfg(feature = "defmt")]
204pub trait Word: SealedWord + Copy + defmt::Format {}
205
206#[allow(private_bounds)]
211#[cfg(not(feature = "defmt"))]
212pub trait Word: SealedWord + Copy {}
213
214pub(crate) trait SealedWord {
215 const BYTE_ACCESS: Spbyt;
216 const WORD_LENGTH: Splw;
217 const BIT_LENGTH: Spb;
218
219 fn read(peri: &mut crate::pac::spi::Spi, bit_order: BitOrder) -> Self;
220 fn write(peri: &mut crate::pac::spi::Spi, word: Self, bit_order: BitOrder);
221}
222
223impl Word for u8 {}
224impl SealedWord for u8 {
225 const BYTE_ACCESS: Spbyt = Spbyt::Byte;
226 const WORD_LENGTH: Splw = Splw::HalfWord;
227 const BIT_LENGTH: Spb = Spb::_8bits;
228
229 #[inline(always)]
230 fn read(peri: &mut crate::pac::spi::Spi, bit_order: BitOrder) -> Self {
231 let by = peri.spdr_by().read();
232 if bit_order == BitOrder::Lsb0 {
233 by.reverse_bits()
234 } else {
235 by
236 }
237 }
238
239 #[inline(always)]
240 fn write(peri: &mut crate::pac::spi::Spi, word: Self, bit_order: BitOrder) {
241 if bit_order == BitOrder::Lsb0 {
242 peri.spdr_by().write_value(word.reverse_bits());
243 } else {
244 peri.spdr_by().write_value(word);
245 }
246 }
247}
248
249impl Word for u16 {}
250impl SealedWord for u16 {
251 const BYTE_ACCESS: Spbyt = Spbyt::Word;
252 const WORD_LENGTH: Splw = Splw::HalfWord;
253 const BIT_LENGTH: Spb = Spb::_16bits;
254
255 #[inline(always)]
256 fn read(peri: &mut crate::pac::spi::Spi, bit_order: BitOrder) -> Self {
257 let ha = peri.spdr_ha().read();
258 if bit_order == BitOrder::Lsb0 {
259 ha.reverse_bits()
260 } else {
261 ha
262 }
263 }
264
265 #[inline(always)]
266 fn write(peri: &mut crate::pac::spi::Spi, word: Self, bit_order: BitOrder) {
267 if bit_order == BitOrder::Lsb0 {
268 let word = ((word & 0x00FF) as u8).reverse_bits() as u16
269 | ((((word & 0xFF00) >> 8) as u8).reverse_bits() as u16) << 8;
270 peri.spdr_ha().write_value(word);
271 } else {
272 peri.spdr().write_value(word as u32);
273 }
274 }
275}
276
277impl Word for u32 {}
278impl SealedWord for u32 {
279 const BYTE_ACCESS: Spbyt = Spbyt::Word;
280 const WORD_LENGTH: Splw = Splw::Word;
281 const BIT_LENGTH: Spb = Spb::_32bits;
282
283 #[inline(always)]
284 fn read(peri: &mut crate::pac::spi::Spi, bit_order: BitOrder) -> Self {
285 let word = peri.spdr().read();
286 if bit_order == BitOrder::Lsb0 {
287 word.reverse_bits()
288 } else {
289 word
290 }
291 }
292
293 #[inline(always)]
294 fn write(peri: &mut crate::pac::spi::Spi, word: Self, bit_order: BitOrder) {
295 if bit_order == BitOrder::Lsb0 {
296 peri.spdr().write_value(word.reverse_bits());
297 } else {
298 peri.spdr().write_value(word);
299 }
300 }
301}
302
303#[allow(private_bounds)]
305pub trait Instance: SealedInstance + ModuleStop + PeripheralType + 'static + Send {
306 const RX_EVENT: crate::event_link::InterruptEvent;
307 const TX_EVENT: crate::event_link::InterruptEvent;
308 const TE_EVENT: crate::event_link::InterruptEvent;
309 const ERROR_EVENT: crate::event_link::InterruptEvent;
310
311 fn tx_waker() -> &'static AtomicWaker;
313 fn te_waker() -> &'static AtomicWaker;
314 fn rx_waker() -> &'static AtomicWaker;
315}
316
317pub(crate) trait SealedInstance {
318 #[cfg(feature = "defmt")]
319 const PERIPHERAL: &'static str;
320 #[cfg(not(feature = "defmt"))]
321 const PERIPHERAL: () = ();
322
323 fn regs() -> pac::spi::Spi;
324}
325
326#[allow(private_bounds)]
328pub trait MisoPin<I: Instance>: SealedMisoPin<I> {}
329
330pub(crate) trait SealedMisoPin<I: SealedInstance>: Pin + PeripheralType {
331 const PERIPHERAL_FUNC: PortFunction;
332
333 #[inline(always)]
334 fn set_pfunc(&self) {
335 self.set_as_pf(Self::PERIPHERAL_FUNC);
336 }
337}
338
339#[allow(private_bounds)]
341pub trait MosiPin<I: Instance>: SealedMosiPin<I> {}
342
343pub(crate) trait SealedMosiPin<I: SealedInstance>: Pin + PeripheralType {
344 const PERIPHERAL_FUNC: PortFunction;
345
346 #[inline(always)]
347 fn set_pfunc(&self) {
348 self.set_as_pf(Self::PERIPHERAL_FUNC);
349 }
350}
351
352#[allow(private_bounds)]
354pub trait SckPin<I: Instance>: SealedSckPin<I> {}
355
356pub(crate) trait SealedSckPin<I: SealedInstance>: Pin + PeripheralType {
357 const PERIPHERAL_FUNC: PortFunction;
358
359 #[inline(always)]
360 fn set_pfunc(&self) {
361 self.set_as_pf(Self::PERIPHERAL_FUNC);
362 }
363}
364
365#[allow(private_bounds)]
367pub trait CsPin<I: Instance>: SealedCsPin<I> {}
368
369pub(crate) trait SealedCsPin<I: SealedInstance>: Pin + PeripheralType {
370 const PERIPHERAL_FUNC: PortFunction;
371
372 #[inline(always)]
373 fn set_pfunc(&self) {
374 self.set_as_pf(Self::PERIPHERAL_FUNC);
375 }
376}
377
378macro_rules! miso_pin {
379 ($instance:ident, $pin:ident, $pfunc:ident) => {
380 impl crate::spi::MisoPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
381 impl crate::spi::SealedMisoPin<crate::peripherals::$instance> for crate::peripherals::$pin {
382 const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
383 }
384 };
385}
386pub(crate) use miso_pin;
387
388macro_rules! mosi_pin {
389 ($instance:ident, $pin:ident, $pfunc:ident) => {
390 impl crate::spi::MosiPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
391 impl crate::spi::SealedMosiPin<crate::peripherals::$instance> for crate::peripherals::$pin {
392 const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
393 }
394 };
395}
396pub(crate) use mosi_pin;
397
398macro_rules! sck_pin {
399 ($instance:ident, $pin:ident, $pfunc:ident) => {
400 impl crate::spi::SckPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
401 impl crate::spi::SealedSckPin<crate::peripherals::$instance> for crate::peripherals::$pin {
402 const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
403 }
404 };
405}
406pub(crate) use sck_pin;
407
408macro_rules! cs_pin {
409 ($instance:ident, $pin:ident, $pfunc:ident) => {
410 impl crate::spi::CsPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
411 impl crate::spi::SealedCsPin<crate::peripherals::$instance> for crate::peripherals::$pin {
412 const PERIPHERAL_FUNC: crate::gpio::PortFunction = crate::gpio::PortFunction::$pfunc;
413 }
414 };
415}
416pub(crate) use cs_pin;
417
418macro_rules! instance_impl {
419 ($instance:ident, $error_int:ident, $te_int:ident, $tx_int:ident, $rx_int:ident) => {
420 paste::paste! {
421 impl Instance for crate::peripherals::$instance {
422 const RX_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$rx_int;
423 const TX_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$tx_int;
424 const TE_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$te_int;
425 const ERROR_EVENT: crate::event_link::InterruptEvent = crate::event_link::InterruptEvent::$error_int;
426
427 #[inline(always)]
429 fn tx_waker() -> &'static AtomicWaker{
430 static TX_WAKER: AtomicWaker = AtomicWaker::new();
431 &TX_WAKER
432 }
433
434 #[inline(always)]
436 fn te_waker() -> &'static AtomicWaker{
437 static TE_WAKER: AtomicWaker = AtomicWaker::new();
438 &TE_WAKER
439 }
440
441 #[inline(always)]
442 fn rx_waker() -> &'static AtomicWaker{
443 static RX_WAKER: AtomicWaker = AtomicWaker::new();
444 &RX_WAKER
445 }
446 }
447
448 impl SealedInstance for crate::peripherals::$instance {
449
450 #[cfg(feature = "defmt")]
451 const PERIPHERAL: &'static str = concat!(stringify!($instance), ": ");
452
453 #[inline(always)]
454 fn regs() -> crate::pac::spi::Spi {
455 crate::pac::$instance
456 }
457 }
458 }
459 };
460}
461
462instance_impl!(SPI0, Spi0Eri, Spi0Tei, Spi0Txi, Spi0Rxi);
463instance_impl!(SPI1, Spi1Eri, Spi1Tei, Spi1Txi, Spi1Rxi);
464
465fn calc_dividers(rate: u32) -> Result<ClockConfig, ()> {
466 let clocks = crate::clock::clock_status();
467 let clk = clocks.peripheral_a;
468
469 let target = rate;
470
471 let mut divider = (clk / target).to_MHz();
474
475 if !VALID_CLOCK_DIVIDER.contains(÷r) {
476 return Err(());
477 }
478
479 divider -= 1;
480
481 let mut options: [Option<(u32, u32, u32, u32)>; 4] = [None; 4];
482
483 for n in 0..=3 {
484 let spbr = divider / (2 << n);
485 let act = (clk / (2 * (spbr + 1) * (2_u32.pow(n)))).to_Hz();
486 let diff = target.abs_diff(act);
487 if spbr <= 255 {
488 options[n as usize] = Some((n, spbr, diff, act));
489 }
490 }
491
492 if !options.iter().any(|o| o.is_some()) {
493 return Err(());
494 }
495
496 let best = options[0].unwrap();
497
498 Ok(ClockConfig {
499 error: best.2,
500 spbr: best.1 as u8,
501 brdv: best.0 as u8,
502 rate,
503 })
504}
505
506impl TransferMode for Blocking {}
507impl SealedTransferMode for Blocking {}
508
509#[cfg(dmac)]
510impl<'d> TransferMode for Dma<'d> {}
511#[cfg(dmac)]
512impl<'d> SealedTransferMode for Dma<'d> {}
513
514#[cfg(dtc)]
515impl<Rx: DtcInstance, Tx: DtcInstance> TransferMode for Dtc<Rx, Tx> {}
516#[cfg(dtc)]
517impl<Rx: DtcInstance, Tx: DtcInstance> SealedTransferMode for Dtc<Rx, Tx> {}
518
519impl<'d, I: Instance, W: Word> Spi<'d, I, W, Blocking> {
520 pub fn new_blocking(
522 spi: Peri<'d, I>,
523 sck: Peri<'d, impl SckPin<I>>,
524 mosi: Peri<'d, impl MosiPin<I>>,
525 miso: Peri<'d, impl MisoPin<I>>,
526 cs: Peri<'d, impl CsPin<I>>,
527 config: Config,
528 ) -> Self {
529 cs.set_pfunc();
530 Self::new_inner(
531 spi,
532 sck,
533 mosi,
534 miso,
535 Some(Flex::new(cs)),
536 config,
537 Blocking {},
538 )
539 }
540
541 #[inline(always)]
546 pub fn blocking_write(&mut self, bytes: &[W]) -> Result<(), SpiError> {
547 let mut spi = I::regs();
548
549 for byte in bytes.iter() {
550 while !spi.spsr().read().sptef() {}
551 W::write(&mut spi, *byte, self.bit_order);
552 }
553
554 Ok(())
555 }
556
557 pub fn blocking_setup(&mut self) {
559 let spi = I::regs();
560 spi.spcr2().write(|r| r.set_spiie(false));
561 spi.spcr().modify(|r| {
562 r.set_sptie(false);
563 r.set_sprie(false);
564 r.set_speie(false);
565 r.set_spe(true);
566 });
567 }
568
569 pub fn blocking_shutdown(&mut self) {
571 let spi = I::regs();
572
573 spi.spcr().modify(|r| r.set_spe(false));
575 }
576
577 pub fn blocking_transfer(&mut self, input: &mut [W], output: &[W]) -> Result<(), SpiError> {
582 #[cfg(feature = "strict-assert")]
583 assert_eq!(input.len(), output.len());
584
585 let mut spi = I::regs();
586
587 for (obyte, ibyte) in output.iter().zip(input.iter_mut()) {
588 while !spi.spsr().read().sptef() {}
589 W::write(&mut spi, *obyte, self.bit_order);
590
591 while !spi.spsr().read().sprf() {}
592 let word = W::read(&mut spi, self.bit_order);
593 *ibyte = word;
594
595 if spi.spsr().read().ovrf() {
596 return Err(SpiError::Overrun);
597 }
598 }
599
600 Ok(())
601 }
602
603 #[inline(always)]
608 pub fn blocking_read(&mut self, buf: &mut [W]) -> Result<(), SpiError> {
609 let mut spi = I::regs();
610
611 let mut ret = Ok(());
612
613 for byte in buf.iter_mut() {
614 while !spi.spsr().read().sprf() {}
615 let datum = W::read(&mut spi, self.bit_order);
616 *byte = datum;
617 if spi.spsr().read().ovrf() {
618 ret = Err(SpiError::Overrun);
619 break;
620 }
621 }
622
623 ret
624 }
625}
626
627#[cfg(dmac)]
628impl<'d, I: Instance, W: Word + crate::dmac::Word> Spi<'d, I, W, Dma<'d>> {
629 #[allow(clippy::too_many_arguments)]
631 pub fn new_dma<
632 TeInt: InterruptType,
633 RxInt: InterruptType,
634 TxInt: InterruptType,
635 RxDmaInstance: crate::dmac::Instance,
636 TxDmaInstance: crate::dmac::Instance,
637 >(
638 spi: Peri<'d, I>,
639 sck: Peri<'d, impl SckPin<I>>,
640 mosi: Peri<'d, impl MosiPin<I>>,
641 miso: Peri<'d, impl MisoPin<I>>,
642 cs: Peri<'d, impl CsPin<I>>,
643 config: Config,
644 rx_dmac: Peri<'d, RxDmaInstance>,
645 tx_dmac: Peri<'d, TxDmaInstance>,
646 irqs: impl interrupt::typelevel::Binding<TeInt, TeInterruptHandler<I>>
647 + interrupt::typelevel::Binding<TxInt, DmacInterruptHandler<TxDmaInstance>>
648 + interrupt::typelevel::Binding<RxInt, DmacInterruptHandler<RxDmaInstance>>
649 + Clone
650 + 'd,
651 ) -> Self {
652 unsafe {
655 TeInt::IRQ.enable();
656 TeInt::IRQ.icu_enable(I::TE_EVENT);
657 }
658
659 let rx_dma = DmacChannel::new(rx_dmac, irqs);
660 let tx_dma = DmacChannel::new(tx_dmac, irqs);
661 let dma = Dma { rx_dma, tx_dma };
662
663 cs.set_pfunc();
664 Self::new_inner(spi, sck, mosi, miso, Some(Flex::new(cs)), config, dma)
665 }
666
667 pub async fn dma_write(&mut self, words: &[W]) -> Result<(), SpiError> {
668 let spi = I::regs();
669
670 spi.spcr().modify(|r| {
671 r.set_sptie(true);
672 r.set_sprie(false);
673 r.set_speie(false);
674 });
675 spi.spcr2().modify(|r| r.set_spiie(false));
676
677 let tx = self
678 .io_mode
679 .tx_dma
680 .write::<W>(words, spi.spdr().as_ptr() as *mut _, I::TX_EVENT);
681
682 spi.spcr().modify(|r| r.set_spe(true));
683
684 tx.await;
685
686 spi.spcr2().modify(|r| r.set_spiie(true));
687 poll_fn(|ctx| {
688 I::te_waker().register(ctx.waker());
689 if spi.spsr().read().sptef() {
690 Poll::Ready(())
691 } else {
692 Poll::Pending
693 }
694 })
695 .await;
696
697 spi.spcr().modify(|r| {
698 r.set_sptie(false);
699 r.set_spe(false);
700 });
701 spi.spcr2().modify(|r| r.set_spiie(false));
702
703 Ok(())
704 }
705
706 pub async fn dma_transfer(&mut self, input: &mut [W], output: &[W]) -> Result<(), SpiError> {
707 #[cfg(feature = "strict-assert")]
708 assert_eq!(input.len(), output.len());
709
710 let spi = I::regs();
711
712 spi.spcr().modify(|r| {
713 r.set_sptie(true);
714 r.set_sprie(true);
715 r.set_speie(false);
716 });
717 spi.spcr2().modify(|r| r.set_spiie(false));
718
719 let tx = self
720 .io_mode
721 .tx_dma
722 .write::<W>(output, spi.spdr().as_ptr() as *mut _, I::TX_EVENT);
723 let rx = self
724 .io_mode
725 .rx_dma
726 .read::<W>(spi.spdr().as_ptr() as *const _, input, I::RX_EVENT);
727
728 spi.spcr().modify(|r| r.set_spe(true));
729
730 join(tx, rx).await;
731
732 spi.spcr2().modify(|r| r.set_spiie(true));
733 poll_fn(|ctx| {
734 I::te_waker().register(ctx.waker());
735 if spi.spsr().read().sptef() {
736 Poll::Ready(())
737 } else {
738 Poll::Pending
739 }
740 })
741 .await;
742
743 spi.spcr().modify(|r| {
744 r.set_sptie(false);
745 r.set_sprie(false);
746 r.set_speie(false);
747 r.set_spe(false);
748 });
749 spi.spcr2().modify(|r| r.set_spiie(false));
750
751 spi.spcr().modify(|r| r.set_spe(false));
752
753 Ok(())
754 }
755}
756
757#[cfg(dtc)]
758impl<'d, I: Instance, W: Word + crate::dtc::Word, Rx: DtcInstance, Tx: DtcInstance>
759 Spi<'d, I, W, Dtc<Rx, Tx>>
760{
761 #[allow(clippy::too_many_arguments)]
762 pub fn new_dtc<TeInt: InterruptType>(
763 spi: Peri<'d, I>,
764 sck: Peri<'d, impl SckPin<I>>,
765 mosi: Peri<'d, impl MosiPin<I>>,
766 miso: Peri<'d, impl MisoPin<I>>,
767 cs: Peri<'d, impl CsPin<I>>,
768 config: Config,
769 rx_dtc: Peri<'d, Rx>,
770 tx_dtc: Peri<'d, Tx>,
771 irqs: impl interrupt::typelevel::Binding<TeInt, TeInterruptHandler<I>>
772 + interrupt::typelevel::Binding<Rx::Int, DtcInterruptHandler<Rx>>
773 + interrupt::typelevel::Binding<Tx::Int, DtcInterruptHandler<Tx>>
774 + Clone
775 + 'd,
776 ) -> Self {
777 unsafe {
779 TeInt::IRQ.enable();
781 TeInt::IRQ.icu_enable(I::TE_EVENT);
782 };
783
784 let rx_dtc = DtcChannel::new(rx_dtc, irqs);
785 let tx_dtc = DtcChannel::new(tx_dtc, irqs);
786 let dtc = Dtc { rx_dtc, tx_dtc };
787
788 cs.set_pfunc();
789 Self::new_inner(spi, sck, mosi, miso, Some(Flex::new(cs)), config, dtc)
790 }
791
792 pub async fn dtc_write(&mut self, words: &[W]) -> Result<(), SpiError> {
793 let spi = I::regs();
794
795 spi.spcr().modify(|r| {
796 r.set_sptie(true);
797 r.set_sprie(false);
798 r.set_speie(false);
799 });
800 spi.spcr2().modify(|r| r.set_spiie(false));
801
802 let tx = unsafe {
803 self.io_mode
804 .tx_dtc
805 .write(words, spi.spdr().as_ptr() as *mut _, I::TX_EVENT, false)
806 };
807
808 spi.spcr().modify(|r| r.set_spe(true));
809
810 tx.await.or(Err(SpiError::Dma))?;
811
812 spi.spcr2().modify(|r| r.set_spiie(true));
813 poll_fn(|ctx| {
814 I::te_waker().register(ctx.waker());
815 if spi.spsr().read().sptef() {
816 Poll::Ready(())
817 } else {
818 Poll::Pending
819 }
820 })
821 .await;
822
823 spi.spcr().modify(|r| {
824 r.set_sptie(false);
825 r.set_spe(false);
826 });
827 spi.spcr2().modify(|r| r.set_spiie(false));
828
829 Ok(())
830 }
831
832 pub async fn dtc_transfer(&mut self, input: &mut [W], output: &[W]) -> Result<(), SpiError> {
833 #[cfg(feature = "strict-assert")]
834 assert_eq!(input.len(), output.len());
835
836 let spi = I::regs();
837
838 spi.spcr().modify(|r| {
839 r.set_sptie(true);
840 r.set_sprie(true);
841 r.set_speie(false);
842 });
843 spi.spcr2().modify(|r| r.set_spiie(false));
844
845 let tx = unsafe {
846 self.io_mode
847 .tx_dtc
848 .write(output, spi.spdr().as_ptr() as *mut _, I::TX_EVENT, false)
849 };
850 let rx = unsafe {
851 self.io_mode
852 .rx_dtc
853 .read(spi.spdr().as_ptr() as *mut _, input, I::RX_EVENT, false)
854 };
855
856 spi.spcr().modify(|r| r.set_spe(true));
857
858 let (tx_result, rx_result) = join(tx, rx).await;
859 tx_result.or(Err(SpiError::Dma))?;
860 rx_result.or(Err(SpiError::Dma))?;
861
862 spi.spcr2().modify(|r| r.set_spiie(true));
863 poll_fn(|ctx| {
864 I::te_waker().register(ctx.waker());
865 if spi.spsr().read().sptef() {
866 Poll::Ready(())
867 } else {
868 Poll::Pending
869 }
870 })
871 .await;
872
873 spi.spcr().modify(|r| {
874 r.set_sptie(false);
875 r.set_sprie(false);
876 r.set_speie(false);
877 r.set_spe(false);
878 });
879 spi.spcr2().modify(|r| r.set_spiie(false));
880
881 spi.spcr().modify(|r| r.set_spe(false));
882
883 Ok(())
884 }
885}
886
887impl<'d, I: Instance, W: Word, M: TransferMode> Spi<'d, I, W, M> {
888 fn new_inner(
889 spi: Peri<'d, I>,
890 sck: Peri<'d, impl SckPin<I>>,
891 mosi: Peri<'d, impl MosiPin<I>>,
892 miso: Peri<'d, impl MisoPin<I>>,
893 cs: Option<Flex<'d, Basic>>,
894 config: Config,
895 io_mode: M,
896 ) -> Self {
897 let _ = spi;
898
899 I::start_module();
900
901 sck.set_pfunc();
902 mosi.set_pfunc();
903 miso.set_pfunc();
904
905 let spi = I::regs();
906
907 spi.spcr().modify(|r| r.set_spe(false));
908
909 spi.spcr().modify(|r| {
910 r.set_txmd(false);
911 r.set_mstr(true);
912 r.set_modfen(false);
913 r.set_spms(Spms::Spi);
914 });
915
916 let polarity = match config.mode.polarity {
917 embedded_hal_1::spi::Polarity::IdleLow => Cpol::Low,
918 embedded_hal_1::spi::Polarity::IdleHigh => Cpol::High,
919 };
920
921 let phase = match config.mode.phase {
922 embedded_hal_1::spi::Phase::CaptureOnFirstTransition => Cpha::SampleShift,
923 embedded_hal_1::spi::Phase::CaptureOnSecondTransition => Cpha::ShiftSample,
924 };
925
926 let bit_order = match config.bit_order {
927 BitOrder::Lsb0 => Lsbf::Lsb0,
928 BitOrder::Msb0 => Lsbf::Msb0,
929 };
930
931 let endian = match config.endian {
932 Endian::Big => Bysw::Big,
933 Endian::Little => Bysw::Little,
934 };
935
936 let (moifv, moife) = match config.mosi_idle {
937 MosiIdle::Last => (Moifv::Low, true),
938 MosiIdle::Low => (Moifv::Low, false),
939 MosiIdle::High => (Moifv::High, false),
940 };
941
942 debug!(
943 "{}polarity={}, phase={}, bit_order={}, endian={}",
944 I::PERIPHERAL,
945 polarity,
946 phase,
947 bit_order,
948 endian,
949 );
950
951 spi.spcmd0().modify(|r| {
952 r.set_cpol(polarity);
953 r.set_cpha(phase);
954 r.set_lsbf(bit_order);
955 });
956
957 spi.sppcr().write(|r| {
959 r.set_moifv(moifv);
960 r.set_moife(moife);
961 });
962
963 let dividers = calc_dividers(config.bit_rate).unwrap();
967 debug!("{}{}", I::PERIPHERAL, dividers);
968 let spbr = dividers.spbr;
969 let brdv = Brdv::from_bits(dividers.brdv);
970
971 spi.spbr().write_value(spbr);
972 spi.spdcr().modify(|r| r.set_spbyt(W::BYTE_ACCESS));
973 spi.spdcr2().modify(|r| r.set_bysw(endian));
974 spi.spdcr().modify(|r| r.set_splw(W::WORD_LENGTH));
975 spi.spcmd0().modify(|r| {
976 r.set_brdv(brdv);
977 r.set_spb(W::BIT_LENGTH);
978 });
979
980 Self {
981 _instance: PhantomData,
982 _cs: cs,
983 _miso: Flex::new(miso),
984 _mosi: Flex::new(mosi),
985 _sck: Flex::new(sck),
986 _word: PhantomData,
987 bit_order: config.bit_order,
988 io_mode,
989 }
990 }
991}
992
993impl<'d, I: Instance, W: Word, M: TransferMode> Drop for Spi<'d, I, W, M> {
994 fn drop(&mut self) {
995 I::stop_module();
996 }
997}
998
999impl Default for Config {
1000 fn default() -> Self {
1001 Self {
1002 bit_order: BitOrder::Msb0,
1003 mode: MODE_0,
1004 bit_rate: 1_000_000,
1005 cs_polarity: ChipSelectPolarity::ActiveLow,
1006 endian: Endian::Big,
1007 mosi_idle: MosiIdle::High,
1008 }
1009 }
1010}
1011
1012#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1014#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1015pub enum SpiError {
1016 Dma,
1017 Overrun,
1018 Unknown,
1019}
1020
1021impl core::fmt::Display for SpiError {
1022 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1023 match self {
1024 SpiError::Dma => write!(f, "DMAC/DTC"),
1025 SpiError::Overrun => write!(f, "Overrun"),
1026 SpiError::Unknown => write!(f, "Unknown"),
1027 }
1028 }
1029}
1030
1031impl core::error::Error for SpiError {}
1032
1033impl embedded_hal_1::spi::Error for SpiError {
1034 fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
1035 match *self {
1036 SpiError::Dma => embedded_hal_1::spi::ErrorKind::Other,
1037 SpiError::Overrun => embedded_hal_1::spi::ErrorKind::Overrun,
1038 SpiError::Unknown => embedded_hal_1::spi::ErrorKind::Other,
1039 }
1040 }
1041}
1042
1043impl<'d, I: Instance, W: Word + 'static, M: TransferMode> ErrorType for Spi<'d, I, W, M> {
1044 type Error = SpiError;
1045}
1046
1047impl<'d, I: Instance, W: Word + 'static> embedded_hal_1::spi::SpiBus<W>
1048 for Spi<'d, I, W, Blocking>
1049{
1050 #[inline]
1051 fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
1052 self.blocking_setup();
1053 self.blocking_read(words)?;
1054 self.blocking_shutdown();
1055 Ok(())
1056 }
1057
1058 #[inline]
1059 fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
1060 self.blocking_setup();
1061 self.blocking_write(words)?;
1062 self.blocking_shutdown();
1063 Ok(())
1064 }
1065
1066 #[inline]
1067 fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> {
1068 self.blocking_setup();
1069 self.blocking_transfer(read, write)?;
1070 self.blocking_shutdown();
1071 Ok(())
1072 }
1073
1074 fn transfer_in_place(&mut self, _words: &mut [W]) -> Result<(), Self::Error> {
1075 unimplemented!()
1076 }
1077
1078 fn flush(&mut self) -> Result<(), Self::Error> {
1079 Ok(())
1080 }
1081}
1082
1083#[cfg(dmac)]
1084impl<'d, I: Instance, W: Word + crate::dmac::Word + 'static> embedded_hal_async::spi::SpiBus<W>
1085 for Spi<'d, I, W, Dma<'d>>
1086{
1087 async fn read(&mut self, _words: &mut [W]) -> Result<(), Self::Error> {
1088 todo!()
1089 }
1090
1091 async fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
1092 self.dma_write(words).await
1093 }
1094
1095 async fn transfer(&mut self, input: &mut [W], output: &[W]) -> Result<(), Self::Error> {
1096 self.dma_transfer(input, output).await
1097 }
1098
1099 async fn transfer_in_place(&mut self, _words: &mut [W]) -> Result<(), Self::Error> {
1100 todo!()
1101 }
1102
1103 async fn flush(&mut self) -> Result<(), Self::Error> {
1104 Ok(())
1105 }
1106}