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