stm32f7x7_hal/
spi.rs

1//! Serial Peripheral Interface (SPI) bus
2use core::ptr;
3use core::ops::Deref;
4
5use embedded_hal::spi;
6pub use embedded_hal::spi::{Mode, Phase, Polarity};
7use nb;
8
9use crate::stm32::{spi1, SPI1, SPI2, SPI3, SPI4, SPI5, SPI6, RCC};
10
11use crate::gpio::{
12    gpioa::{PA1, PA5, PA6, PA7, PA9, PA10, PA11, PA12},
13    gpiob::{PB0, PB2, PB3, PB4, PB5, PB8, PB10, PB12, PB13, PB14, PB15},
14    gpioc::{PC1, PC2, PC3, PC7, PC10, PC11, PC12},
15    gpiod::{PD0, PD3, PD6},
16    gpioe::{PE2, PE5, PE6, PE12, PE13, PE14},
17    gpiof::{PF7, PF8, PF9, PF11},
18    gpiog::{PG11, PG12, PG13, PG14},
19    gpioh::{PH6, PH7},
20    gpioi::{PI1, PI2, PI3},
21};
22
23use crate::gpio::{Alternate, AF5, AF6, AF7};
24
25use crate::rcc::Clocks;
26use crate::time::Hertz;
27
28/// SPI error
29#[derive(Debug)]
30pub enum Error {
31    /// Overrun occurred
32    Overrun,
33    /// Mode fault occurred
34    ModeFault,
35    /// CRC error
36    Crc,
37    #[doc(hidden)]
38    _Extensible,
39}
40
41pub trait Pins<SPI> {}
42pub trait PinSck<SPI> {}
43pub trait PinMiso<SPI> {}
44pub trait PinMosi<SPI> {}
45
46impl<SPI, SCK, MISO, MOSI> Pins<SPI> for (SCK, MISO, MOSI)
47where
48    SCK: PinSck<SPI>,
49    MISO: PinMiso<SPI>,
50    MOSI: PinMosi<SPI>,
51{}
52
53/// A filler type for when the SCK pin is unnecessary
54pub struct NoSck;
55/// A filler type for when the Miso pin is unnecessary
56pub struct NoMiso;
57/// A filler type for when the Mosi pin is unnecessary
58pub struct NoMosi;
59
60macro_rules! pins {
61    ($($SPIX:ty: SCK: [$($SCK:ty),*] MISO: [$($MISO:ty),*] MOSI: [$($MOSI:ty),*])+) => {
62        $(
63            $(
64                impl PinSck<$SPIX> for $SCK {}
65            )*
66            $(
67                impl PinMiso<$SPIX> for $MISO {}
68            )*
69            $(
70                impl PinMosi<$SPIX> for $MOSI {}
71            )*
72        )+
73    }
74}
75
76pins! {
77    SPI1:
78        SCK: [
79            NoSck,
80            PA5<Alternate<AF5>>,
81            PB3<Alternate<AF5>>
82        ]
83        MISO: [
84            NoMiso,
85            PA6<Alternate<AF5>>,
86            PB4<Alternate<AF5>>
87        ]
88        MOSI: [
89            NoMosi,
90            PA7<Alternate<AF5>>,
91            PB5<Alternate<AF5>>
92        ]
93
94    SPI2:
95        SCK: [
96            NoSck,
97            PB10<Alternate<AF5>>,
98            PB13<Alternate<AF5>>
99        ]
100        MISO: [
101            NoMiso,
102            PB14<Alternate<AF5>>,
103            PC2<Alternate<AF5>>
104        ]
105        MOSI: [
106            NoMosi,
107            PB15<Alternate<AF5>>,
108            PC3<Alternate<AF5>>
109        ]
110}
111
112pins! {
113    SPI3:
114        SCK: [
115            NoSck,
116            PB3<Alternate<AF6>>,
117            PC10<Alternate<AF6>>
118        ]
119        MISO: [
120            NoMiso,
121            PB4<Alternate<AF6>>,
122            PC11<Alternate<AF6>>
123        ]
124        MOSI: [
125            NoMosi,
126            PB5<Alternate<AF6>>,
127            PC12<Alternate<AF6>>
128        ]
129}
130
131pins! {
132    SPI2:
133        SCK: [PD3<Alternate<AF5>>]
134        MISO: []
135        MOSI: []
136    SPI3:
137        SCK: []
138        MISO: []
139        MOSI: [PD6<Alternate<AF5>>]
140    SPI4:
141        SCK: [
142            NoSck,
143            PE2<Alternate<AF5>>,
144            PE12<Alternate<AF5>>
145        ]
146        MISO: [
147            NoMiso,
148            PE5<Alternate<AF5>>,
149            PE13<Alternate<AF5>>
150        ]
151        MOSI: [
152            NoMosi,
153            PE6<Alternate<AF5>>,
154            PE14<Alternate<AF5>>
155        ]
156}
157
158pins! {
159    SPI2:
160        SCK: [PI1<Alternate<AF5>>]
161        MISO: [PI2<Alternate<AF5>>]
162        MOSI: [PI3<Alternate<AF5>>]
163}
164
165pins! {
166    SPI2:
167        SCK: [PC7<Alternate<AF5>>]
168        MISO: []
169        MOSI: []
170}
171
172pins! {
173    SPI5:
174        SCK: [
175            NoSck,
176            PB0<Alternate<AF6>>
177        ]
178        MISO: [
179            NoMiso,
180            PA12<Alternate<AF6>>
181        ]
182        MOSI: [
183            NoMosi,
184            PA10<Alternate<AF6>>,
185            PB8<Alternate<AF6>>
186        ]
187}
188
189pins! {
190    SPI3:
191        SCK: [PB12<Alternate<AF7>>]
192        MISO: []
193        MOSI: []
194    SPI4:
195        SCK: [PB13<Alternate<AF6>>]
196        MISO: [PA11<Alternate<AF6>>]
197        MOSI: [PA1<Alternate<AF5>>]
198    SPI5:
199        SCK: [
200            PE2<Alternate<AF6>>,
201            PE12<Alternate<AF6>>
202        ]
203        MISO: [
204            PE5<Alternate<AF6>>,
205            PE13<Alternate<AF6>>
206        ]
207        MOSI: [
208            PE6<Alternate<AF6>>,
209            PE14<Alternate<AF6>>
210        ]
211}
212
213pins! {
214    SPI2:
215        SCK: [PA9<Alternate<AF5>>]
216        MISO: [PA12<Alternate<AF5>>]
217        MOSI: [PA10<Alternate<AF5>>]
218}
219
220pins! {
221    SPI5:
222        SCK: [
223            PF7<Alternate<AF5>>,
224            PH6<Alternate<AF5>>
225        ]
226        MISO: [
227            PF8<Alternate<AF5>>,
228            PH7<Alternate<AF5>>
229        ]
230        MOSI: [
231            PF9<Alternate<AF5>>,
232            PF11<Alternate<AF5>>
233        ]
234
235    SPI6:
236        SCK: [
237            NoSck,
238            PG13<Alternate<AF5>>
239        ]
240        MISO: [
241            NoMiso,
242            PG12<Alternate<AF5>>
243        ]
244        MOSI: [
245            NoMosi,
246            PG14<Alternate<AF5>>
247        ]
248}
249
250pins! {
251    SPI2:
252        SCK: []
253        MISO: []
254        MOSI: [PC1<Alternate<AF7>>]
255
256    SPI3:
257        SCK: []
258        MISO: []
259        MOSI: [
260            PB0<Alternate<AF7>>,
261            PB2<Alternate<AF7>>,
262            PD0<Alternate<AF6>>
263        ]
264
265    SPI4:
266        SCK: [PG11<Alternate<AF6>>]
267        MISO: [
268            PG12<Alternate<AF6>>,
269            PD0<Alternate<AF5>>
270        ]
271        MOSI: [PG13<Alternate<AF6>>]
272}
273
274pins! {
275    SPI2:
276        SCK: []
277        MISO: []
278        MOSI: [PC1<Alternate<AF5>>]
279}
280
281/// Interrupt events
282pub enum Event {
283    /// New data has been received
284    Rxne,
285    /// Data can be sent
286    Txe,
287    /// An error occurred
288    Error,
289}
290
291#[derive(Debug)]
292pub struct Spi<SPI, PINS> {
293    spi: SPI,
294    pins: PINS,
295}
296
297impl<PINS> Spi<SPI1, PINS> {
298    pub fn spi1(spi: SPI1, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
299    where
300        PINS: Pins<SPI1>
301    {
302        // NOTE(unsafe) This executes only during initialisation
303        let rcc = unsafe { &(*RCC::ptr()) };
304
305        // Enable clock for SPI
306        rcc.apb2enr.modify(|_, w| w.spi1en().set_bit());
307
308        Spi { spi, pins }.init(mode, freq, clocks.pclk2())
309    }
310}
311
312impl<PINS> Spi<SPI2, PINS> {
313    pub fn spi2(spi: SPI2, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
314    where
315        PINS: Pins<SPI2>
316    {
317        // NOTE(unsafe) This executes only during initialisation
318        let rcc = unsafe { &(*RCC::ptr()) };
319
320        // Enable clock for SPI
321        rcc.apb1enr.modify(|_, w| w.spi2en().set_bit());
322
323        Spi { spi, pins }.init(mode, freq, clocks.pclk1())
324    }
325}
326
327impl<PINS> Spi<SPI3, PINS> {
328    pub fn spi3(spi: SPI3, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
329    where
330        PINS: Pins<SPI3>
331    {
332        // NOTE(unsafe) This executes only during initialisation
333        let rcc = unsafe { &(*RCC::ptr()) };
334
335        // Enable clock for SPI
336        rcc.apb1enr.modify(|_, w| w.spi3en().set_bit());
337
338        Spi { spi, pins }.init(mode, freq, clocks.pclk1())
339    }
340}
341
342impl<PINS> Spi<SPI4, PINS> {
343    pub fn spi4(spi: SPI4, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
344    where
345        PINS: Pins<SPI4>
346    {
347        // NOTE(unsafe) This executes only during initialisation
348        let rcc = unsafe { &(*RCC::ptr()) };
349
350        // Enable clock for SPI
351        rcc.apb2enr.modify(|_, w| w.spi4en().set_bit());
352
353        Spi { spi, pins }.init(mode, freq, clocks.pclk2())
354    }
355}
356
357impl<PINS> Spi<SPI5, PINS> {
358    pub fn spi5(spi: SPI5, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
359    where
360        PINS: Pins<SPI5>
361    {
362        // NOTE(unsafe) This executes only during initialisation
363        let rcc = unsafe { &(*RCC::ptr()) };
364
365        // Enable clock for SPI
366        rcc.apb2enr.modify(|_, w| w.spi5en().set_bit());
367
368        Spi { spi, pins }.init(mode, freq, clocks.pclk2())
369    }
370}
371
372impl<PINS> Spi<SPI6, PINS> {
373    pub fn spi6(spi: SPI6, pins: PINS, mode: Mode, freq: Hertz, clocks: Clocks) -> Self
374    where
375        PINS: Pins<SPI6>
376    {
377        // NOTE(unsafe) This executes only during initialisation
378        let rcc = unsafe { &(*RCC::ptr()) };
379
380        // Enable clock for SPI
381        rcc.apb2enr.modify(|_, w| w.spi6en().set_bit());
382
383        Spi { spi, pins }.init(mode, freq, clocks.pclk2())
384    }
385}
386
387impl<SPI, PINS> Spi<SPI, PINS>
388where
389    SPI: Deref<Target = spi1::RegisterBlock>,
390{
391    pub fn init(self, mode: Mode, freq: Hertz, clock: Hertz) -> Self
392    {
393        // disable the SPI peripheral
394        self.spi.cr1.write(|w| w.spe().clear_bit());
395    
396        // disable SS output
397        self.spi.cr2.write(|w| w.ssoe().clear_bit());
398
399        let br = match clock.0 / freq.0 {
400            0 => unreachable!(),
401            1...2 => 0b000,
402            3...5 => 0b001,
403            6...11 => 0b010,
404            12...23 => 0b011,
405            24...47 => 0b100,
406            48...95 => 0b101,
407            96...191 => 0b110,
408            _ => 0b111,
409        };
410
411        // ds: 8 bit frames (0b111)
412        // frxth: event is generated for FIFO level >= 1/4 (8-bit)
413        self.spi.cr2.write(|w| { unsafe { w
414            .ds()
415            .bits(0b111)
416            .frxth()
417            .set_bit()
418        }});
419        
420        // mstr: master configuration
421        // lsbfirst: MSB first
422        // ssm: enable software slave management (NSS pin free for other uses)
423        // ssi: set nss high = master mode
424        // bidimode: 2-line unidirectional
425        // spe: enable the SPI bus
426        self.spi.cr1.write(|w| { w
427            .cpha()
428            .bit(mode.phase == Phase::CaptureOnSecondTransition)
429            .cpol()
430            .bit(mode.polarity == Polarity::IdleHigh)
431            .mstr()
432            .set_bit()
433            .br()
434            .bits(br)
435            .lsbfirst()
436            .clear_bit()
437            .ssm()
438            .set_bit()
439            .ssi()
440            .set_bit()
441            .rxonly()
442            .clear_bit()
443            .bidimode()
444            .clear_bit()
445            .bidioe()
446            .clear_bit()
447            .spe()
448            .set_bit()
449        });
450
451        self
452    }
453
454    /// Enable interrupts for the given `event`:
455    ///  - Received data ready to be read (RXNE)
456    ///  - Transmit data register empty (TXE)
457    ///  - Transfer error
458    pub fn listen(&mut self, event: Event) {
459        match event {
460            Event::Rxne  => self.spi.cr2.modify(|_, w| { w.rxneie().set_bit() }),
461            Event::Txe   => self.spi.cr2.modify(|_, w| { w.txeie().set_bit() }),
462            Event::Error => self.spi.cr2.modify(|_, w| { w.errie().set_bit() }),
463        }
464    }
465
466    /// Disable interrupts for the given `event`:
467    ///  - Received data ready to be read (RXNE)
468    ///  - Transmit data register empty (TXE)
469    ///  - Transfer error
470    pub fn unlisten(&mut self, event: Event) {
471        match event {
472            Event::Rxne  => self.spi.cr2.modify(|_, w| { w.rxneie().clear_bit() }),
473            Event::Txe   => self.spi.cr2.modify(|_, w| { w.txeie().clear_bit() }),
474            Event::Error => self.spi.cr2.modify(|_, w| { w.errie().clear_bit() }),
475        }
476    }
477
478    /// Return `true` if the TXE flag is set, i.e. new data to transmit
479    /// can be written to the SPI.
480    pub fn is_txe(&self) -> bool {
481        self.spi.sr.read().txe().bit_is_set()
482    }
483
484    /// Return `true` if the RXNE flag is set, i.e. new data has been received
485    /// and can be read from the SPI.
486    pub fn is_rxne(&self) -> bool {
487        self.spi.sr.read().rxne().bit_is_set()
488    }
489
490    /// Return `true` if the MODF flag is set, i.e. the SPI has experienced a
491    /// Master Mode Fault. (see chapter 28.3.10 of the STM32F4 Reference Manual)
492    pub fn is_modf(&self) -> bool {
493        self.spi.sr.read().modf().bit_is_set()
494    }
495
496    /// Return `true` if the OVR flag is set, i.e. new data has been received
497    /// while the receive data register was already filled.
498    pub fn is_ovr(&self) -> bool {
499        self.spi.sr.read().ovr().bit_is_set()
500    }
501
502    pub fn free(self) -> (SPI, PINS) {
503        (self.spi, self.pins)
504    }
505}
506
507impl<SPI, PINS> spi::FullDuplex<u8> for Spi<SPI, PINS>
508where
509    SPI: Deref<Target = spi1::RegisterBlock>,
510{
511    type Error = Error;
512
513    fn read(&mut self) -> nb::Result<u8, Error> {
514        let sr = self.spi.sr.read();
515
516        Err(if sr.ovr().bit_is_set() {
517            nb::Error::Other(Error::Overrun)
518        } else if sr.modf().bit_is_set() {
519            nb::Error::Other(Error::ModeFault)
520        } else if sr.crcerr().bit_is_set() {
521            nb::Error::Other(Error::Crc)
522        } else if sr.rxne().bit_is_set() {
523            // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
524            // reading a half-word)
525            return Ok(unsafe {
526                ptr::read_volatile(&self.spi.dr as *const _ as *const u8)
527            });
528        } else {
529            nb::Error::WouldBlock
530        })
531    }
532
533    fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
534        let sr = self.spi.sr.read();
535
536        Err(if sr.ovr().bit_is_set() {
537            nb::Error::Other(Error::Overrun)
538        } else if sr.modf().bit_is_set() {
539            nb::Error::Other(Error::ModeFault)
540        } else if sr.crcerr().bit_is_set() {
541            nb::Error::Other(Error::Crc)
542        } else if sr.txe().bit_is_set() {
543            // NOTE(write_volatile) see note above
544            unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
545            return Ok(());
546        } else {
547            nb::Error::WouldBlock
548        })
549    }
550}
551
552impl<SPI, PINS> embedded_hal::blocking::spi::transfer::Default<u8> for Spi<SPI, PINS>
553where
554    SPI: Deref<Target = spi1::RegisterBlock>,
555{}
556
557impl<SPI, PINS> embedded_hal::blocking::spi::write::Default<u8> for Spi<SPI, PINS>
558where
559    SPI: Deref<Target = spi1::RegisterBlock>,
560{}
561
562
563
564