n32g4xx_hal/
spi.rs

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/// Clock polarity
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum Polarity {
14    /// Clock signal low when idle
15    IdleLow,
16    /// Clock signal high when idle
17    IdleHigh,
18}
19
20/// Clock phase
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Phase {
23    /// Data in "captured" on the first clock transition
24    CaptureOnFirstTransition,
25    /// Data in "captured" on the second clock transition
26    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/// SPI mode
38#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub struct Mode {
40    /// Clock polarity
41    pub polarity: Polarity,
42    /// Clock phase
43    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/// SPI error
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58#[derive(Debug, Eq, PartialEq, Copy, Clone)]
59#[non_exhaustive]
60pub enum Error {
61    /// Overrun occurred
62    Overrun,
63    /// Mode fault occurred
64    ModeFault,
65    /// CRC error
66    Crc,
67}
68
69/// A filler type for when the SCK pin is unnecessary
70pub type NoSck = NoPin;
71/// A filler type for when the Miso pin is unnecessary
72pub type NoMiso = NoPin;
73/// A filler type for when the Mosi pin is unnecessary
74pub type NoMosi = NoPin;
75
76/// SPI interrupt events
77#[enumflags2::bitflags]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79#[derive(Debug, Eq, PartialEq, Copy, Clone)]
80#[repr(u32)]
81pub enum Event {
82    /// An error occurred.
83    ///
84    /// This bit controls the generation of an interrupt
85    /// when an error condition occurs
86    /// (OVR, CRCERR, MODF, FRE in SPI mode,
87    /// and UDR, OVR, FRE in I2S mode)
88    Error = 1 << 5,
89    /// New data has been received
90    ///
91    /// RX buffer not empty interrupt enable
92    RxNotEmpty = 1 << 6,
93    /// Data can be sent
94    ///
95    /// Tx buffer empty interrupt enable
96    TxEmpty = 1 << 7,
97}
98
99/// SPI status flags
100#[enumflags2::bitflags]
101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
102#[derive(Debug, Eq, PartialEq, Copy, Clone)]
103#[repr(u32)]
104pub enum Flag {
105    /// Receive buffer not empty
106    RxNotEmpty = 1 << 0,
107    /// Transmit buffer empty
108    TxEmpty = 1 << 1,
109    /// CRC error flag
110    CrcError = 1 << 4,
111    /// Mode fault
112    ModeFault = 1 << 5,
113    /// Overrun flag
114    Overrun = 1 << 6,
115    /// Busy flag
116    Busy = 1 << 7,
117    /// Frame Error
118    FrameError = 1 << 8,
119}
120
121/// SPI clearable flags
122#[enumflags2::bitflags]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
124#[derive(Debug, Eq, PartialEq, Copy, Clone)]
125#[repr(u32)]
126pub enum CFlag {
127    /// CRC error flag
128    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/// The bit format to send the data in
144#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145pub enum BitFormat {
146    /// Least significant bit first
147    LsbFirst,
148    /// Most significant bit first
149    MsbFirst,
150}
151
152#[derive(Debug)]
153pub struct Inner<SPI: Instance> {
154    spi: SPI,
155}
156
157/// Spi in Master mode
158#[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/// Spi in Slave mode
179#[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
199// Implemented by all SPI instances
200pub 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
212// Implemented by all SPI instances
213macro_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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master Normal mode.
300    ///
301    /// # Note
302    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
303    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
304    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master XFER_MODE mode.
318    ///
319    /// # Note
320    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
321    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
322    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        /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master XFER_MODE mode.
340    ///
341    /// # Note
342    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
343    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
344    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave Normal mode.
362    ///
363    /// # Note
364    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
365    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
366    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave XFER_MODE mode.
383    ///
384    /// # Note
385    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
386    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
387    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            // bidimode: 2-line or 1-line unidirectional
407            w.bidirmode().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
408            w.bidiroen().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
409            // data frame size
410            w.datff().bit(W::DFF);
411            // spe: enable the SPI bus
412            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            // bidimode: 2-line or 1-line unidirectional
423            w.bidirmode().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
424            w.bidiroen().bit(XFER_MODE == TransferMode::TransferModeBidirectional);
425            // data frame size
426            w.datff().bit(W::DFF);
427            // spe: enable the SPI bus
428            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    /// Converts from 8bit dataframe to 16bit.
464    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    /// Converts from 16bit dataframe to 8bit.
474    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    /// Converts from 8bit dataframe to 16bit.
484    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    /// Converts from 16bit dataframe to 8bit.
494    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master Normal mode.
501    ///
502    /// # Note
503    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
504    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
505    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master XFER_MODE mode.
530    ///
531    /// # Note
532    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
533    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
534    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master XFER_MODE mode.
560    ///
561    /// # Note
562    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
563    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
564    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave Normal mode.
589    ///
590    /// # Note
591    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
592    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
593    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    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave XFER_MODE mode.
620    ///
621    /// # Note
622    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
623    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
624    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    /// Convert the spi to another mode.
667    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    /// Convert the spi to another mode.
684    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    /// Pre initializing the SPI bus.
693    fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self {
694        // disable SS output
695        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            // mstr: master configuration
713            w.msel().set_bit();
714            unsafe { w.br().bits(br) };
715            // lsbfirst: MSB first
716            w.lsbff().clear_bit();
717            // ssm: enable software slave management (NSS pin free for other uses)
718            w.ssmen().set_bit();
719            // ssi: set nss high
720            w.ssel().set_bit();
721            w.ronly().bit(XFER_MODE == TransferMode::TransferModeRecieveOnly);
722            // dff: 8 bit frames
723            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    /// Pre initializing the SPI bus.
732    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            // mstr: slave configuration
737            w.msel().clear_bit();
738            unsafe { w.br().bits(0) };
739            // lsbfirst: MSB first
740            w.lsbff().clear_bit();
741            // ssm: enable software slave management (NSS pin free for other uses)
742            w.ssmen().bit(self.pins.3.is_none());
743            // ssi: set nss high = master mode
744            w.ssel().set_bit();
745            w.ronly().clear_bit();
746            // dff: 8 bit frames
747            w.datff().clear_bit()
748        });
749
750        self
751    }
752
753    /// Set the slave select bit programmatically.
754    #[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    /// Enable/disable spi
766    pub fn enable(&mut self, enable: bool) {
767        self.spi.ctrl1().modify(|_, w| {
768            // spe: enable the SPI bus
769            w.spien().bit(enable)
770        });
771    }
772
773    /// Select which frame format is used for data transfers
774    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    /// Return `true` if the TXE flag is set, i.e. new data to transmit
781    /// can be written to the SPI.
782    #[inline]
783    pub fn is_tx_empty(&self) -> bool {
784        self.spi.sts().read().te().bit_is_set()
785    }
786
787    /// Return `true` if the RXNE flag is set, i.e. new data has been received
788    /// and can be read from the SPI.
789    #[inline]
790    pub fn is_rx_not_empty(&self) -> bool {
791        self.spi.sts().read().rne().bit_is_set()
792    }
793
794    /// Return `true` if the MODF flag is set, i.e. the SPI has experienced a
795    /// Master Mode Fault. (see chapter 28.3.10 of the STM32F4 Reference Manual)
796    #[inline]
797    pub fn is_modf(&self) -> bool {
798        self.spi.sts().read().moderr().bit_is_set()
799    }
800
801    /// Returns true if the transfer is in progress
802    #[inline]
803    pub fn is_busy(&self) -> bool {
804        self.spi.sts().read().busy().bit_is_set()
805    }
806
807    /// Return `true` if the OVR flag is set, i.e. new data has been received
808    /// while the receive data register was already filled.
809    #[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        // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
826        // reading a half-word)
827        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        // NOTE(write_volatile) see note above
832        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            // Read from the DR to clear the OVR bit
860            let _ = self.spi.dat().read();
861            Error::Overrun.into()
862        } else if sr.moderr().bit_is_set() {
863            // Write to CR1 to clear MODF
864            self.spi.ctrl1().modify(|_r, w| w);
865            Error::ModeFault.into()
866        } else if sr.crcerr().bit_is_set() {
867            // Clear the CRCERR bit
868            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
927// Spi DMA
928
929impl<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                // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
1297                // until the end of the transfer.
1298                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                        // memory to memory mode disabled
1310                        .mem2mem()
1311                        .disabled()
1312                        // medium channel priority level
1313                        .priolvl()
1314                        .medium()
1315                        // 8-bit memory size
1316                        .msize()
1317                        .bits8()
1318                        // 8-bit peripheral size
1319                        .psize()
1320                        .bits8()
1321                        // circular mode disabled
1322                        .circ()
1323                        .disabled()
1324                        // write to memory
1325                        .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                // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
1341                // until the end of the transfer.
1342                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                        // memory to memory mode disabled
1354                        .mem2mem()
1355                        .disabled()
1356                        // medium channel priority level
1357                        .priolvl()
1358                        .medium()
1359                        // 8-bit memory size
1360                        .msize()
1361                        .bits8()
1362                        // 8-bit peripheral size
1363                        .psize()
1364                        .bits8()
1365                        // circular mode disabled
1366                        .circ()
1367                        .disabled()
1368                        // read from memory
1369                        .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                // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
1390                // until the end of the transfer.
1391                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                        // memory to memory mode disabled
1416                        .mem2mem()
1417                        .disabled()
1418                        // medium channel priority level
1419                        .priolvl()
1420                        .medium()
1421                        // 8-bit memory size
1422                        .msize()
1423                        .bits8()
1424                        // 8-bit peripheral size
1425                        .psize()
1426                        .bits8()
1427                        // circular mode disabled
1428                        .circ()
1429                        .disabled()
1430                        // write to memory
1431                        .dir()
1432                        .from_peripheral()
1433                });
1434                self.txchannel.st().chcfg().modify(|_, w| {
1435                    w
1436                        // memory to memory mode disabled
1437                        .mem2mem()
1438                        .disabled()
1439                        // medium channel priority level
1440                        .priolvl()
1441                        .medium()
1442                        // 8-bit memory size
1443                        .msize()
1444                        .bits8()
1445                        // 8-bit peripheral size
1446                        .psize()
1447                        .bits8()
1448                        // circular mode disabled
1449                        .circ()
1450                        .disabled()
1451                        // read from memory
1452                        .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);