stm32f4xx_hal/
spi.rs

1use core::marker::PhantomData;
2use core::ops::{Deref, DerefMut};
3
4use crate::dma::traits::{DMASet, PeriAddress};
5use crate::dma::{MemoryToPeripheral, PeripheralToMemory};
6use crate::gpio::{self, NoPin};
7use crate::pac;
8
9/// Clock polarity
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub enum Polarity {
12    /// Clock signal low when idle
13    IdleLow,
14    /// Clock signal high when idle
15    IdleHigh,
16}
17
18/// Clock phase
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub enum Phase {
21    /// Data in "captured" on the first clock transition
22    CaptureOnFirstTransition,
23    /// Data in "captured" on the second clock transition
24    CaptureOnSecondTransition,
25}
26
27/// SPI mode
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct Mode {
30    /// Clock polarity
31    pub polarity: Polarity,
32    /// Clock phase
33    pub phase: Phase,
34}
35
36mod hal_02;
37mod hal_1;
38
39use crate::pac::spi1;
40use crate::rcc;
41
42use crate::rcc::Clocks;
43use enumflags2::BitFlags;
44use fugit::HertzU32 as Hertz;
45
46/// SPI error
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[derive(Debug, Eq, PartialEq, Copy, Clone)]
49#[non_exhaustive]
50pub enum Error {
51    /// Overrun occurred
52    Overrun,
53    /// Mode fault occurred
54    ModeFault,
55    /// CRC error
56    Crc,
57}
58
59/// A filler type for when the SCK pin is unnecessary
60pub type NoSck = NoPin;
61/// A filler type for when the Miso pin is unnecessary
62pub type NoMiso = NoPin;
63/// A filler type for when the Mosi pin is unnecessary
64pub type NoMosi = NoPin;
65
66/// SPI interrupt events
67#[enumflags2::bitflags]
68#[cfg_attr(feature = "defmt", derive(defmt::Format))]
69#[derive(Debug, Eq, PartialEq, Copy, Clone)]
70#[repr(u16)]
71pub enum Event {
72    /// An error occurred.
73    ///
74    /// This bit controls the generation of an interrupt
75    /// when an error condition occurs
76    /// (OVR, CRCERR, MODF, FRE in SPI mode,
77    /// and UDR, OVR, FRE in I2S mode)
78    Error = 1 << 5,
79    /// New data has been received
80    ///
81    /// RX buffer not empty interrupt enable
82    RxNotEmpty = 1 << 6,
83    /// Data can be sent
84    ///
85    /// Tx buffer empty interrupt enable
86    TxEmpty = 1 << 7,
87}
88
89/// SPI status flags
90#[enumflags2::bitflags]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92#[derive(Debug, Eq, PartialEq, Copy, Clone)]
93#[repr(u16)]
94pub enum Flag {
95    /// Receive buffer not empty
96    RxNotEmpty = 1 << 0,
97    /// Transmit buffer empty
98    TxEmpty = 1 << 1,
99    /// CRC error flag
100    CrcError = 1 << 4,
101    /// Mode fault
102    ModeFault = 1 << 5,
103    /// Overrun flag
104    Overrun = 1 << 6,
105    /// Busy flag
106    Busy = 1 << 7,
107    /// Frame Error
108    FrameError = 1 << 8,
109}
110
111/// SPI clearable flags
112#[enumflags2::bitflags]
113#[cfg_attr(feature = "defmt", derive(defmt::Format))]
114#[derive(Debug, Eq, PartialEq, Copy, Clone)]
115#[repr(u32)]
116pub enum CFlag {
117    /// CRC error flag
118    CrcError = 1 << 4,
119}
120
121/// Normal mode - RX and TX pins are independent
122#[allow(non_upper_case_globals)]
123pub const TransferModeNormal: bool = false;
124/// Bidirectional (Half-Duplex) mode - use TX pin as RX then spi receive data
125#[allow(non_upper_case_globals)]
126pub const TransferModeBidi: bool = true;
127
128pub trait FrameSize: Copy + Default {
129    const DFF: bool;
130    #[doc(hidden)]
131    fn read_data(spi: &spi1::RegisterBlock) -> Self;
132    #[doc(hidden)]
133    fn write_data(self, spi: &spi1::RegisterBlock);
134}
135
136impl FrameSize for u8 {
137    const DFF: bool = false;
138    fn read_data(spi: &spi1::RegisterBlock) -> Self {
139        spi.dr8().read().dr().bits()
140    }
141    fn write_data(self, spi: &spi1::RegisterBlock) {
142        spi.dr8().write(|w| w.dr().set(self))
143    }
144}
145
146impl FrameSize for u16 {
147    const DFF: bool = true;
148    fn read_data(spi: &spi1::RegisterBlock) -> Self {
149        spi.dr().read().dr().bits()
150    }
151    fn write_data(self, spi: &spi1::RegisterBlock) {
152        spi.dr().write(|w| w.dr().set(self))
153    }
154}
155
156/// The bit format to send the data in
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
158pub enum BitFormat {
159    /// Least significant bit first
160    LsbFirst,
161    /// Most significant bit first
162    MsbFirst,
163}
164
165#[derive(Debug)]
166pub struct Inner<SPI: Instance> {
167    spi: SPI,
168}
169
170/// Spi in Master mode
171#[derive(Debug)]
172pub struct Spi<SPI: Instance, const BIDI: bool = false, W = u8> {
173    inner: Inner<SPI>,
174    pins: (SPI::Sck, SPI::Miso, SPI::Mosi),
175    _operation: PhantomData<W>,
176}
177
178impl<SPI: Instance, const BIDI: bool, W> Deref for Spi<SPI, BIDI, W> {
179    type Target = Inner<SPI>;
180    fn deref(&self) -> &Self::Target {
181        &self.inner
182    }
183}
184
185impl<SPI: Instance, const BIDI: bool, W> DerefMut for Spi<SPI, BIDI, W> {
186    fn deref_mut(&mut self) -> &mut Self::Target {
187        &mut self.inner
188    }
189}
190
191/// Spi in Slave mode
192#[derive(Debug)]
193pub struct SpiSlave<SPI: Instance, const BIDI: bool = false, W = u8> {
194    inner: Inner<SPI>,
195    pins: (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>),
196    _operation: PhantomData<W>,
197}
198
199impl<SPI: Instance, const BIDI: bool, W> Deref for SpiSlave<SPI, BIDI, W> {
200    type Target = Inner<SPI>;
201    fn deref(&self) -> &Self::Target {
202        &self.inner
203    }
204}
205
206impl<SPI: Instance, const BIDI: bool, W> DerefMut for SpiSlave<SPI, BIDI, W> {
207    fn deref_mut(&mut self) -> &mut Self::Target {
208        &mut self.inner
209    }
210}
211
212// Implemented by all SPI instances
213pub trait Instance:
214    crate::Sealed
215    + crate::Ptr<RB = spi1::RegisterBlock>
216    + Deref<Target = Self::RB>
217    + rcc::Enable
218    + rcc::Reset
219    + rcc::BusClock
220    + gpio::alt::SpiCommon
221{
222}
223
224// Implemented by all SPI instances
225macro_rules! spi {
226    ($SPI:ty: $Spi:ident, $SpiSlave:ident) => {
227        pub type $Spi<const BIDI: bool = false, W = u8> = Spi<$SPI, BIDI, W>;
228        pub type $SpiSlave<const BIDI: bool = false, W = u8> = SpiSlave<$SPI, BIDI, W>;
229
230        impl Instance for $SPI {}
231
232        impl crate::Ptr for $SPI {
233            type RB = spi1::RegisterBlock;
234            fn ptr() -> *const Self::RB {
235                Self::ptr()
236            }
237        }
238    };
239}
240
241spi! { pac::SPI1: Spi1, SpiSlave1 }
242spi! { pac::SPI2: Spi2, SpiSlave2 }
243
244#[cfg(feature = "spi3")]
245spi! { pac::SPI3: Spi3, SpiSlave3 }
246
247#[cfg(feature = "spi4")]
248spi! { pac::SPI4: Spi4, SpiSlave4 }
249
250#[cfg(feature = "spi5")]
251spi! { pac::SPI5: Spi5, SpiSlave5 }
252
253#[cfg(feature = "spi6")]
254spi! { pac::SPI6: Spi6, SpiSlave6 }
255
256pub trait SpiExt: Sized + Instance {
257    fn spi(
258        self,
259        pins: (
260            impl Into<Self::Sck>,
261            impl Into<Self::Miso>,
262            impl Into<Self::Mosi>,
263        ),
264        mode: impl Into<Mode>,
265        freq: Hertz,
266        clocks: &Clocks,
267    ) -> Spi<Self, false, u8>;
268
269    fn spi_bidi(
270        self,
271        pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
272        mode: impl Into<Mode>,
273        freq: Hertz,
274        clocks: &Clocks,
275    ) -> Spi<Self, true, u8>
276    where
277        NoPin: Into<Self::Miso>;
278
279    fn spi_slave(
280        self,
281        pins: (
282            impl Into<Self::Sck>,
283            impl Into<Self::Miso>,
284            impl Into<Self::Mosi>,
285            Option<Self::Nss>,
286        ),
287        mode: impl Into<Mode>,
288    ) -> SpiSlave<Self, false, u8>;
289
290    fn spi_bidi_slave(
291        self,
292        pins: (
293            impl Into<Self::Sck>,
294            impl Into<Self::Miso>,
295            Option<Self::Nss>,
296        ),
297        mode: impl Into<Mode>,
298    ) -> SpiSlave<Self, true, u8>
299    where
300        NoPin: Into<Self::Mosi>;
301}
302
303impl<SPI: Instance> SpiExt for SPI {
304    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master Normal mode.
305    ///
306    /// # Note
307    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
308    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
309    fn spi(
310        self,
311        pins: (
312            impl Into<Self::Sck>,
313            impl Into<Self::Miso>,
314            impl Into<Self::Mosi>,
315        ),
316        mode: impl Into<Mode>,
317        freq: Hertz,
318        clocks: &Clocks,
319    ) -> Spi<Self, false, u8> {
320        Spi::new(self, pins, mode, freq, clocks)
321    }
322    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master BIDI mode.
323    ///
324    /// # Note
325    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
326    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
327    fn spi_bidi(
328        self,
329        pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
330        mode: impl Into<Mode>,
331        freq: Hertz,
332        clocks: &Clocks,
333    ) -> Spi<Self, true, u8>
334    where
335        NoPin: Into<Self::Miso>,
336    {
337        Spi::new_bidi(self, pins, mode, freq, clocks)
338    }
339    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave Normal 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_slave(
345        self,
346        pins: (
347            impl Into<Self::Sck>,
348            impl Into<Self::Miso>,
349            impl Into<Self::Mosi>,
350            Option<Self::Nss>,
351        ),
352        mode: impl Into<Mode>,
353    ) -> SpiSlave<Self, false, u8> {
354        SpiSlave::new(self, pins, mode)
355    }
356    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave BIDI mode.
357    ///
358    /// # Note
359    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
360    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
361    fn spi_bidi_slave(
362        self,
363        pins: (
364            impl Into<Self::Sck>,
365            impl Into<Self::Miso>,
366            Option<Self::Nss>,
367        ),
368        mode: impl Into<Mode>,
369    ) -> SpiSlave<Self, true, u8>
370    where
371        NoPin: Into<Self::Mosi>,
372    {
373        SpiSlave::new_bidi(self, pins, mode)
374    }
375}
376
377impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
378    pub fn init(self) -> Self {
379        self.spi.cr1().modify(|_, w| {
380            // bidimode: 2-line or 1-line unidirectional
381            w.bidimode().bit(BIDI);
382            w.bidioe().bit(BIDI);
383            // data frame size
384            w.dff().bit(W::DFF);
385            // spe: enable the SPI bus
386            w.spe().set_bit()
387        });
388
389        self
390    }
391}
392
393impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
394    pub fn init(self) -> Self {
395        self.spi.cr1().modify(|_, w| {
396            // bidimode: 2-line or 1-line unidirectional
397            w.bidimode().bit(BIDI);
398            w.bidioe().bit(BIDI);
399            // data frame size
400            w.dff().bit(W::DFF);
401            // spe: enable the SPI bus
402            w.spe().set_bit()
403        });
404
405        self
406    }
407}
408
409impl<SPI: Instance, W: FrameSize> Spi<SPI, false, W> {
410    pub fn to_bidi_transfer_mode(self) -> Spi<SPI, true, W> {
411        self.into_mode()
412    }
413}
414
415impl<SPI: Instance, W: FrameSize> Spi<SPI, true, W> {
416    pub fn to_normal_transfer_mode(self) -> Spi<SPI, false, W> {
417        self.into_mode()
418    }
419}
420
421impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, false, W> {
422    pub fn to_bidi_transfer_mode(self) -> SpiSlave<SPI, true, W> {
423        self.into_mode()
424    }
425}
426
427impl<SPI: Instance, W: FrameSize> SpiSlave<SPI, true, W> {
428    pub fn to_normal_transfer_mode(self) -> SpiSlave<SPI, false, W> {
429        self.into_mode()
430    }
431}
432
433impl<SPI, const BIDI: bool> Spi<SPI, BIDI, u8>
434where
435    SPI: Instance,
436{
437    /// Converts from 8bit dataframe to 16bit.
438    pub fn frame_size_16bit(self) -> Spi<SPI, BIDI, u16> {
439        self.into_mode()
440    }
441}
442
443impl<SPI, const BIDI: bool> Spi<SPI, BIDI, u16>
444where
445    SPI: Instance,
446{
447    /// Converts from 16bit dataframe to 8bit.
448    pub fn frame_size_8bit(self) -> Spi<SPI, BIDI, u8> {
449        self.into_mode()
450    }
451}
452
453impl<SPI, const BIDI: bool> SpiSlave<SPI, BIDI, u8>
454where
455    SPI: Instance,
456{
457    /// Converts from 8bit dataframe to 16bit.
458    pub fn frame_size_16bit(self) -> SpiSlave<SPI, BIDI, u16> {
459        self.into_mode()
460    }
461}
462
463impl<SPI, const BIDI: bool> SpiSlave<SPI, BIDI, u16>
464where
465    SPI: Instance,
466{
467    /// Converts from 16bit dataframe to 8bit.
468    pub fn frame_size_8bit(self) -> SpiSlave<SPI, BIDI, u8> {
469        self.into_mode()
470    }
471}
472
473impl<SPI: Instance> Spi<SPI, false, u8> {
474    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master Normal mode.
475    ///
476    /// # Note
477    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
478    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
479    pub fn new(
480        spi: SPI,
481        pins: (
482            impl Into<SPI::Sck>,
483            impl Into<SPI::Miso>,
484            impl Into<SPI::Mosi>,
485        ),
486        mode: impl Into<Mode>,
487        freq: Hertz,
488        clocks: &Clocks,
489    ) -> Self {
490        unsafe {
491            SPI::enable_unchecked();
492            SPI::reset_unchecked();
493        }
494
495        let pins = (pins.0.into(), pins.1.into(), pins.2.into());
496
497        Self::_new(spi, pins)
498            .pre_init(mode.into(), freq, SPI::clock(clocks))
499            .init()
500    }
501}
502
503impl<SPI: Instance> Spi<SPI, true, u8> {
504    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Master BIDI mode.
505    ///
506    /// # Note
507    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
508    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
509    pub fn new_bidi(
510        spi: SPI,
511        pins: (impl Into<SPI::Sck>, impl Into<SPI::Mosi>),
512        mode: impl Into<Mode>,
513        freq: Hertz,
514        clocks: &Clocks,
515    ) -> Self
516    where
517        NoPin: Into<SPI::Miso>,
518    {
519        unsafe {
520            SPI::enable_unchecked();
521            SPI::reset_unchecked();
522        }
523
524        let pins = (pins.0.into(), NoPin::new().into(), pins.1.into());
525
526        Self::_new(spi, pins)
527            .pre_init(mode.into(), freq, SPI::clock(clocks))
528            .init()
529    }
530}
531
532impl<SPI: Instance> SpiSlave<SPI, false, u8> {
533    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave Normal mode.
534    ///
535    /// # Note
536    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
537    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
538    pub fn new(
539        spi: SPI,
540        pins: (
541            impl Into<SPI::Sck>,
542            impl Into<SPI::Miso>,
543            impl Into<SPI::Mosi>,
544            Option<SPI::Nss>,
545        ),
546        mode: impl Into<Mode>,
547    ) -> Self {
548        unsafe {
549            SPI::enable_unchecked();
550            SPI::reset_unchecked();
551        }
552
553        let pins = (pins.0.into(), pins.1.into(), pins.2.into(), pins.3);
554
555        Self::_new(spi, pins).pre_init(mode.into()).init()
556    }
557}
558
559impl<SPI: Instance> SpiSlave<SPI, true, u8> {
560    /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave BIDI mode.
561    ///
562    /// # Note
563    /// Depending on `freq` you may need to set GPIO speed for `pins` (the `Speed::Low` is default for GPIO) before create `Spi` instance.
564    /// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
565    pub fn new_bidi(
566        spi: SPI,
567        pins: (impl Into<SPI::Sck>, impl Into<SPI::Miso>, Option<SPI::Nss>),
568        mode: impl Into<Mode>,
569    ) -> Self
570    where
571        NoPin: Into<SPI::Mosi>,
572    {
573        unsafe {
574            SPI::enable_unchecked();
575            SPI::reset_unchecked();
576        }
577
578        let pins = (pins.0.into(), pins.1.into(), NoPin::new().into(), pins.2);
579
580        Self::_new(spi, pins).pre_init(mode.into()).init()
581    }
582}
583
584impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
585    #[allow(clippy::type_complexity)]
586    pub fn release(self) -> (SPI, (SPI::Sck, SPI::Miso, SPI::Mosi)) {
587        (self.inner.spi, self.pins)
588    }
589}
590
591impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
592    #[allow(clippy::type_complexity)]
593    pub fn release(self) -> (SPI, (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>)) {
594        (self.inner.spi, self.pins)
595    }
596}
597
598impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
599    fn _new(spi: SPI, pins: (SPI::Sck, SPI::Miso, SPI::Mosi)) -> Self {
600        Self {
601            inner: Inner::new(spi),
602            pins,
603            _operation: PhantomData,
604        }
605    }
606
607    /// Convert the spi to another mode.
608    fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> Spi<SPI, BIDI2, W2> {
609        let mut spi = Spi::_new(self.inner.spi, self.pins);
610        spi.enable(false);
611        spi.init()
612    }
613}
614
615impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
616    fn _new(spi: SPI, pins: (SPI::Sck, SPI::Miso, SPI::Mosi, Option<SPI::Nss>)) -> Self {
617        Self {
618            inner: Inner::new(spi),
619            pins,
620            _operation: PhantomData,
621        }
622    }
623
624    /// Convert the spi to another mode.
625    fn into_mode<const BIDI2: bool, W2: FrameSize>(self) -> SpiSlave<SPI, BIDI2, W2> {
626        let mut spi = SpiSlave::_new(self.inner.spi, self.pins);
627        spi.enable(false);
628        spi.init()
629    }
630}
631
632impl<SPI: Instance, const BIDI: bool, W> Spi<SPI, BIDI, W> {
633    /// Pre initializing the SPI bus.
634    fn pre_init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self {
635        // disable SS output
636        self.spi.cr2().write(|w| w.ssoe().clear_bit());
637
638        let br = match clock.raw() / freq.raw() {
639            0 => unreachable!(),
640            1..=2 => 0b000,
641            3..=5 => 0b001,
642            6..=11 => 0b010,
643            12..=23 => 0b011,
644            24..=47 => 0b100,
645            48..=95 => 0b101,
646            96..=191 => 0b110,
647            _ => 0b111,
648        };
649
650        self.spi.cr1().write(|w| {
651            w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
652            w.cpol().bit(mode.polarity == Polarity::IdleHigh);
653            // mstr: master configuration
654            w.mstr().set_bit();
655            w.br().set(br);
656            // lsbfirst: MSB first
657            w.lsbfirst().clear_bit();
658            // ssm: enable software slave management (NSS pin free for other uses)
659            w.ssm().set_bit();
660            // ssi: set nss high
661            w.ssi().set_bit();
662            w.rxonly().clear_bit();
663            // dff: 8 bit frames
664            w.dff().clear_bit()
665        });
666
667        self
668    }
669}
670
671impl<SPI: Instance, const BIDI: bool, W> SpiSlave<SPI, BIDI, W> {
672    /// Pre initializing the SPI bus.
673    fn pre_init(self, mode: Mode) -> Self {
674        self.spi.cr1().write(|w| {
675            w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition);
676            w.cpol().bit(mode.polarity == Polarity::IdleHigh);
677            // mstr: slave configuration
678            w.mstr().clear_bit();
679            w.br().set(0);
680            // lsbfirst: MSB first
681            w.lsbfirst().clear_bit();
682            // ssm: enable software slave management (NSS pin free for other uses)
683            w.ssm().bit(self.pins.3.is_none());
684            // ssi: set nss high = master mode
685            w.ssi().set_bit();
686            w.rxonly().clear_bit();
687            // dff: 8 bit frames
688            w.dff().clear_bit()
689        });
690
691        self
692    }
693
694    /// Set the slave select bit programmatically.
695    #[inline]
696    pub fn set_internal_nss(&mut self, value: bool) {
697        self.spi.cr1().modify(|_, w| w.ssi().bit(value));
698    }
699}
700
701impl<SPI: Instance> Inner<SPI> {
702    fn new(spi: SPI) -> Self {
703        Self { spi }
704    }
705
706    /// Enable/disable spi
707    pub fn enable(&mut self, enable: bool) {
708        self.spi.cr1().modify(|_, w| {
709            // spe: enable the SPI bus
710            w.spe().bit(enable)
711        });
712    }
713
714    /// Select which frame format is used for data transfers
715    pub fn bit_format(&mut self, format: BitFormat) {
716        self.spi
717            .cr1()
718            .modify(|_, w| w.lsbfirst().bit(format == BitFormat::LsbFirst));
719    }
720
721    /// Return `true` if the TXE flag is set, i.e. new data to transmit
722    /// can be written to the SPI.
723    #[inline]
724    pub fn is_tx_empty(&self) -> bool {
725        self.spi.sr().read().txe().bit_is_set()
726    }
727
728    /// Return `true` if the RXNE flag is set, i.e. new data has been received
729    /// and can be read from the SPI.
730    #[inline]
731    pub fn is_rx_not_empty(&self) -> bool {
732        self.spi.sr().read().rxne().bit_is_set()
733    }
734
735    /// Return `true` if the MODF flag is set, i.e. the SPI has experienced a
736    /// Master Mode Fault. (see chapter 28.3.10 of the STM32F4 Reference Manual)
737    #[inline]
738    pub fn is_modf(&self) -> bool {
739        self.spi.sr().read().modf().bit_is_set()
740    }
741
742    /// Returns true if the transfer is in progress
743    #[inline]
744    pub fn is_busy(&self) -> bool {
745        self.spi.sr().read().bsy().bit_is_set()
746    }
747
748    /// Return `true` if the OVR flag is set, i.e. new data has been received
749    /// while the receive data register was already filled.
750    #[inline]
751    pub fn is_overrun(&self) -> bool {
752        self.spi.sr().read().ovr().bit_is_set()
753    }
754
755    #[inline]
756    fn bidi_output(&mut self) {
757        self.spi.cr1().modify(|_, w| w.bidioe().set_bit());
758    }
759
760    #[inline]
761    fn bidi_input(&mut self) {
762        self.spi.cr1().modify(|_, w| w.bidioe().set_bit());
763    }
764
765    fn read_data_reg<W: FrameSize>(&mut self) -> W {
766        W::read_data(&self.spi)
767    }
768
769    fn write_data_reg<W: FrameSize>(&mut self, data: W) {
770        data.write_data(&self.spi)
771    }
772
773    #[inline(always)]
774    fn check_read<W: FrameSize>(&mut self) -> nb::Result<W, Error> {
775        let sr = self.spi.sr().read();
776
777        Err(if sr.ovr().bit_is_set() {
778            Error::Overrun.into()
779        } else if sr.modf().bit_is_set() {
780            Error::ModeFault.into()
781        } else if sr.crcerr().bit_is_set() {
782            Error::Crc.into()
783        } else if sr.rxne().bit_is_set() {
784            return Ok(self.read_data_reg());
785        } else {
786            nb::Error::WouldBlock
787        })
788    }
789
790    #[inline(always)]
791    fn check_send<W: FrameSize>(&mut self, byte: W) -> nb::Result<(), Error> {
792        let sr = self.spi.sr().read();
793
794        Err(if sr.ovr().bit_is_set() {
795            // Read from the DR to clear the OVR bit
796            let _ = self.spi.dr().read();
797            Error::Overrun.into()
798        } else if sr.modf().bit_is_set() {
799            // Write to CR1 to clear MODF
800            self.spi.cr1().modify(|_r, w| w);
801            Error::ModeFault.into()
802        } else if sr.crcerr().bit_is_set() {
803            // Clear the CRCERR bit
804            self.spi.sr().modify(|_r, w| w.crcerr().clear_bit());
805            Error::Crc.into()
806        } else if sr.txe().bit_is_set() {
807            self.write_data_reg(byte);
808            return Ok(());
809        } else {
810            nb::Error::WouldBlock
811        })
812    }
813
814    fn spi_write<const BIDI: bool, W: FrameSize>(
815        &mut self,
816        words: impl IntoIterator<Item = W>,
817    ) -> Result<(), Error> {
818        if BIDI {
819            self.bidi_output();
820            for word in words.into_iter() {
821                nb::block!(self.check_send(word))?;
822            }
823        } else {
824            for word in words.into_iter() {
825                nb::block!(self.check_send(word))?;
826                nb::block!(self.check_read::<W>())?;
827            }
828        }
829
830        Ok(())
831    }
832
833    fn listen_event(&mut self, disable: Option<BitFlags<Event>>, enable: Option<BitFlags<Event>>) {
834        self.spi.cr2().modify(|r, w| unsafe {
835            w.bits({
836                let mut bits = r.bits();
837                if let Some(d) = disable {
838                    bits &= !d.bits();
839                }
840                if let Some(e) = enable {
841                    bits |= e.bits();
842                }
843                bits
844            })
845        });
846    }
847}
848
849impl<SPI: Instance> crate::Listen for Inner<SPI> {
850    type Event = Event;
851
852    fn listen(&mut self, event: impl Into<BitFlags<Self::Event>>) {
853        self.listen_event(None, Some(event.into()));
854    }
855
856    fn listen_only(&mut self, event: impl Into<BitFlags<Self::Event>>) {
857        self.listen_event(Some(BitFlags::ALL), Some(event.into()));
858    }
859
860    fn unlisten(&mut self, event: impl Into<BitFlags<Self::Event>>) {
861        self.listen_event(Some(event.into()), None);
862    }
863}
864
865impl<SPI: Instance> crate::ClearFlags for Inner<SPI> {
866    type Flag = CFlag;
867    fn clear_flags(&mut self, flags: impl Into<BitFlags<Self::Flag>>) {
868        if flags.into().contains(CFlag::CrcError) {
869            self.spi
870                .sr()
871                .write(|w| unsafe { w.bits(0xffff).crcerr().clear_bit() })
872        }
873    }
874}
875
876impl<SPI: Instance> crate::ReadFlags for Inner<SPI> {
877    type Flag = Flag;
878    fn flags(&self) -> BitFlags<Self::Flag> {
879        BitFlags::from_bits_truncate(self.spi.sr().read().bits())
880    }
881}
882
883// Spi DMA
884
885impl<SPI: Instance, const BIDI: bool> Spi<SPI, BIDI, u8> {
886    pub fn use_dma(self) -> DmaBuilder<SPI> {
887        DmaBuilder {
888            spi: self.inner.spi,
889        }
890    }
891}
892
893impl<SPI: Instance, const BIDI: bool> SpiSlave<SPI, BIDI, u8> {
894    pub fn use_dma(self) -> DmaBuilder<SPI> {
895        DmaBuilder {
896            spi: self.inner.spi,
897        }
898    }
899}
900
901pub struct DmaBuilder<SPI> {
902    spi: SPI,
903}
904
905pub struct Tx<SPI> {
906    spi: PhantomData<SPI>,
907}
908
909pub struct Rx<SPI> {
910    spi: PhantomData<SPI>,
911}
912
913impl<SPI: Instance> DmaBuilder<SPI> {
914    pub fn tx(self) -> Tx<SPI> {
915        self.spi.cr2().modify(|_, w| w.txdmaen().enabled());
916        Tx { spi: PhantomData }
917    }
918
919    pub fn rx(self) -> Rx<SPI> {
920        self.spi.cr2().modify(|_, w| w.rxdmaen().enabled());
921        Rx { spi: PhantomData }
922    }
923
924    pub fn txrx(self) -> (Tx<SPI>, Rx<SPI>) {
925        self.spi.cr2().modify(|_, w| {
926            w.txdmaen().enabled();
927            w.rxdmaen().enabled()
928        });
929        (Tx { spi: PhantomData }, Rx { spi: PhantomData })
930    }
931}
932
933unsafe impl<SPI: Instance> PeriAddress for Rx<SPI> {
934    #[inline(always)]
935    fn address(&self) -> u32 {
936        unsafe { (*SPI::ptr()).dr().as_ptr() as u32 }
937    }
938
939    type MemSize = u8;
940}
941
942unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, PeripheralToMemory> for Rx<SPI> where
943    SPI: DMASet<STREAM, CHANNEL, PeripheralToMemory>
944{
945}
946
947unsafe impl<SPI: Instance> PeriAddress for Tx<SPI> {
948    #[inline(always)]
949    fn address(&self) -> u32 {
950        unsafe { (*SPI::ptr()).dr().as_ptr() as u32 }
951    }
952
953    type MemSize = u8;
954}
955
956unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeripheral> for Tx<SPI> where
957    SPI: DMASet<STREAM, CHANNEL, MemoryToPeripheral>
958{
959}
960
961macro_rules! spi_transfer {
962    ($Spi: ident) => {
963        impl<SPI: Instance, const BIDI: bool, W: FrameSize> $Spi<SPI, BIDI, W> {
964            pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
965                if BIDI {
966                    self.bidi_input();
967                }
968                self.check_read()
969            }
970
971            pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
972                if BIDI {
973                    self.bidi_output();
974                }
975                self.check_send(byte)
976            }
977
978            pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
979                for word in words {
980                    nb::block!(self.write_nonblocking(*word))?;
981                    *word = nb::block!(self.read_nonblocking())?;
982                }
983
984                Ok(())
985            }
986
987            pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
988                if data.len() == buff.len() {
989                    for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
990                        nb::block!(self.write_nonblocking(d))?;
991                        *b = nb::block!(self.read_nonblocking())?;
992                    }
993                } else {
994                    let mut iter_r = buff.iter_mut();
995                    let mut iter_w = data.iter().cloned();
996                    loop {
997                        match (iter_r.next(), iter_w.next()) {
998                            (Some(r), Some(w)) => {
999                                nb::block!(self.write_nonblocking(w))?;
1000                                *r = nb::block!(self.read_nonblocking())?;
1001                            }
1002                            (Some(r), None) => {
1003                                nb::block!(self.write_nonblocking(W::default()))?;
1004                                *r = nb::block!(self.read_nonblocking())?;
1005                            }
1006                            (None, Some(w)) => {
1007                                nb::block!(self.write_nonblocking(w))?;
1008                                let _ = nb::block!(self.read_nonblocking())?;
1009                            }
1010                            (None, None) => break,
1011                        }
1012                    }
1013                }
1014
1015                Ok(())
1016            }
1017
1018            pub fn flush(&mut self) -> Result<(), Error> {
1019                Ok(())
1020            }
1021
1022            pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
1023                self.spi_write::<BIDI, W>(words.iter().copied())
1024            }
1025
1026            pub fn write_iter(&mut self, words: impl IntoIterator<Item = W>) -> Result<(), Error> {
1027                self.spi_write::<BIDI, W>(words)
1028            }
1029
1030            pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
1031                if BIDI {
1032                    self.bidi_input();
1033                    for word in words {
1034                        *word = nb::block!(self.check_read())?;
1035                    }
1036                } else {
1037                    for word in words {
1038                        nb::block!(self.check_send(W::default()))?;
1039                        *word = nb::block!(self.check_read())?;
1040                    }
1041                }
1042
1043                Ok(())
1044            }
1045        }
1046    };
1047}
1048
1049spi_transfer!(Spi);
1050spi_transfer!(SpiSlave);