1use crate::gpio::gpioa::{PA11, PA12, PA5, PA6, PA7};
2use crate::gpio::gpiob::{PB13, PB14, PB15, PB3, PB4, PB5};
3use crate::gpio::gpioc::{PC10, PC11, PC12};
4use crate::gpio::{Floating, Input};
5use crate::rcc::Rcc;
6use crate::stm32::{SPI1, SPI2, SPI3};
7use crate::time::Hertz;
8use core::ptr;
9use hal;
10use nb;
11
12pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
13
14#[derive(Debug)]
16pub enum Error {
17 Overrun,
19 ModeFault,
21 Crc,
23 #[doc(hidden)]
24 _Extensible,
25}
26
27pub trait Pins<SPI> {}
28pub trait PinSck<SPI> {}
29pub trait PinMiso<SPI> {}
30pub trait PinMosi<SPI> {}
31
32impl<SPI, SCK, MISO, MOSI> Pins<SPI> for (SCK, MISO, MOSI)
33where
34 SCK: PinSck<SPI>,
35 MISO: PinMiso<SPI>,
36 MOSI: PinMosi<SPI>,
37{
38}
39
40pub struct NoSck;
42pub struct NoMiso;
44pub struct NoMosi;
46
47macro_rules! pins {
48 ($($SPIX:ty: SCK: [$($SCK:ty),*] MISO: [$($MISO:ty),*] MOSI: [$($MOSI:ty),*])+) => {
49 $(
50 $(
51 impl PinSck<$SPIX> for $SCK {}
52 )*
53 $(
54 impl PinMiso<$SPIX> for $MISO {}
55 )*
56 $(
57 impl PinMosi<$SPIX> for $MOSI {}
58 )*
59 )+
60 }
61}
62
63pins! {
64 SPI1:
65 SCK: [
66 NoSck,
67 PA5<Input<Floating>>,
68 PB3<Input<Floating>>
69 ]
70 MISO: [
71 NoMiso,
72 PA6<Input<Floating>>,
73 PA11<Input<Floating>>,
74 PB4<Input<Floating>>
75 ]
76 MOSI: [
77 NoMosi,
78 PA7<Input<Floating>>,
79 PA12<Input<Floating>>,
80 PB5<Input<Floating>>
81 ]
82
83 SPI2:
84 SCK: [
85 NoSck,
86 PB13<Input<Floating>>
87 ]
88 MISO: [
89 NoMiso,
90 PB14<Input<Floating>>
91 ]
92 MOSI: [
93 NoMosi,
94 PB15<Input<Floating>>
95 ]
96
97 SPI3:
98 SCK: [
99 NoSck,
100 PB3<Input<Floating>>,
101 PC10<Input<Floating>>
102 ]
103 MISO: [
104 NoMiso,
105 PB4<Input<Floating>>,
106 PC11<Input<Floating>>
107 ]
108 MOSI: [
109 NoMosi,
110 PB5<Input<Floating>>,
111 PC12<Input<Floating>>
112 ]
113}
114
115#[derive(Debug)]
116pub struct Spi<SPI, PINS> {
117 spi: SPI,
118 pins: PINS,
119}
120
121pub trait SpiExt<SPI>: Sized {
122 fn spi<PINS, T>(self, pins: PINS, mode: Mode, freq: T, rcc: &mut Rcc) -> Spi<SPI, PINS>
123 where
124 PINS: Pins<SPI>,
125 T: Into<Hertz>;
126}
127
128macro_rules! spi {
129 ($($SPIX:ident: ($spiX:ident, $apbXenr:ident, $spiXen:ident, $pclkX:ident),)+) => {
130 $(
131 impl<PINS> Spi<$SPIX, PINS> {
132 pub fn $spiX<T>(
133 spi: $SPIX,
134 pins: PINS,
135 mode: Mode,
136 freq: T,
137 rcc: &mut Rcc
138 ) -> Self
139 where
140 PINS: Pins<$SPIX>,
141 T: Into<Hertz>
142 {
143 rcc.rb.$apbXenr.modify(|_, w| w.$spiXen().set_bit());
145
146 spi.cr2.write(|w| w.ssoe().clear_bit());
148
149 let spi_freq = freq.into().0;
150 let apb_freq = rcc.clocks.$pclkX().0;
151 let br = match apb_freq / spi_freq {
152 0 => unreachable!(),
153 1..=2 => 0b000,
154 3..=5 => 0b001,
155 6..=11 => 0b010,
156 12..=23 => 0b011,
157 24..=47 => 0b100,
158 48..=95 => 0b101,
159 96..=191 => 0b110,
160 _ => 0b111,
161 };
162
163 #[allow(unused)]
171 spi.cr1.write(|w| unsafe {
172 w.cpha()
173 .bit(mode.phase == Phase::CaptureOnSecondTransition)
174 .cpol()
175 .bit(mode.polarity == Polarity::IdleHigh)
176 .mstr()
177 .set_bit()
178 .br()
179 .bits(br)
180 .lsbfirst()
181 .clear_bit()
182 .ssm()
183 .set_bit()
184 .ssi()
185 .set_bit()
186 .rxonly()
187 .clear_bit()
188 .dff()
189 .clear_bit()
190 .bidimode()
191 .clear_bit()
192 .spe()
193 .set_bit()
194 });
195
196 Spi { spi, pins }
197 }
198
199 pub fn free(self) -> ($SPIX, PINS) {
200 (self.spi, self.pins)
201 }
202 }
203
204 impl SpiExt<$SPIX> for $SPIX {
205 fn spi<PINS, T>(self, pins: PINS, mode: Mode, freq: T, rcc: &mut Rcc) -> Spi<$SPIX, PINS>
206 where
207 PINS: Pins<$SPIX>,
208 T: Into<Hertz>
209 {
210 Spi::$spiX(self, pins, mode, freq, rcc)
211 }
212 }
213
214 impl<PINS> hal::spi::FullDuplex<u8> for Spi<$SPIX, PINS> {
215 type Error = Error;
216
217 fn read(&mut self) -> nb::Result<u8, Error> {
218 let sr = self.spi.sr.read();
219
220 Err(if sr.ovr().bit_is_set() {
221 nb::Error::Other(Error::Overrun)
222 } else if sr.modf().bit_is_set() {
223 nb::Error::Other(Error::ModeFault)
224 } else if sr.crcerr().bit_is_set() {
225 nb::Error::Other(Error::Crc)
226 } else if sr.rxne().bit_is_set() {
227 return Ok(unsafe {
230 ptr::read_volatile(&self.spi.dr as *const _ as *const u8)
231 });
232 } else {
233 nb::Error::WouldBlock
234 })
235 }
236
237 fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
238 let sr = self.spi.sr.read();
239
240 Err(if sr.ovr().bit_is_set() {
241 nb::Error::Other(Error::Overrun)
242 } else if sr.modf().bit_is_set() {
243 nb::Error::Other(Error::ModeFault)
244 } else if sr.crcerr().bit_is_set() {
245 nb::Error::Other(Error::Crc)
246 } else if sr.txe().bit_is_set() {
247 unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
249 return Ok(());
250 } else {
251 nb::Error::WouldBlock
252 })
253 }
254
255 }
256
257 impl<PINS> ::hal::blocking::spi::transfer::Default<u8> for Spi<$SPIX, PINS> {}
258
259 impl<PINS> ::hal::blocking::spi::write::Default<u8> for Spi<$SPIX, PINS> {}
260 )+
261 }
262}
263
264spi! {
265 SPI1: (spi1, apb2enr, spi1en, apb2_clk),
266 SPI2: (spi2, apb1enr, spi2en, apb1_clk),
267 SPI3: (spi3, apb1enr, spi3en, apb1_clk),
268}