1use core::ptr;
4
5use crate::pac::{RCC, SPI1, SPI2, SPI3};
6use hal::spi::{FullDuplex, Mode, Phase, Polarity};
7use nb;
8
9use crate::gpio::{AltFn, PullType, AF5, AF6};
10use crate::gpio::{HighSpeed, PinMode, PushPull};
11use crate::gpio::{PA5, PA6, PA7};
12use crate::gpio::{PB13, PB14, PB15, PB3, PB4, PB5};
13use crate::gpio::{PC10, PC11, PC12};
14use crate::rcc::Clocks;
15use crate::time::Hertz;
16
17#[derive(Debug)]
19pub enum Error {
20 Overrun,
22 ModeFault,
24 Crc,
26 #[doc(hidden)]
27 _Extensible,
28}
29
30pub struct Spi<SPI, PINS> {
32 spi: SPI,
33 pins: PINS,
34}
35
36pub trait SpiExt<SPI, ISCK, IMISO, IMOSI, SCK, MISO, MOSI> {
38 fn spi<F>(self,
44 pins: (ISCK, IMISO, IMOSI),
45 mode: Mode,
46 freq: F,
47 clocks: Clocks)
48 -> Spi<SPI, (SCK, MISO, MOSI)>
49 where F: Into<Hertz<u32>>;
50}
51
52#[cfg_attr(rustfmt, rustfmt_skip)]
53macro_rules! spi {
54 ($SPIX:ident,
55 $apbenr:ident,
56 $apbrstr:ident,
57 $spiXen:ident,
58 $spiXrst:ident,
59 $pclkX:ident,
60 $afn:ident,
61 $speed:ident,
62 sck: [$($sck: ident, )+],
63 miso: $miso: tt,
64 mosi: $mosi: tt
65 ) => {
66 spi!{
67 $SPIX,
68 $apbenr,
69 $apbrstr,
70 $spiXen,
71 $spiXrst,
72 $pclkX,
73 $afn,
74 $speed,
75 [$(
76 ($sck, $miso, ),
77 )+],
78 $mosi
79 }
80 };
81 ($SPIX:ident,
82 $apbenr:ident,
83 $apbrstr:ident,
84 $spiXen:ident,
85 $spiXrst:ident,
86 $pclkX:ident,
87 $afn:ident,
88 $speed:ident,
89 [$(($sck: ident,
90 [$($miso: ident, )+], ),
91 )+],
92 $mosi: tt
93 ) => {
94 spi!{
95 $SPIX,
96 $apbenr,
97 $apbrstr,
98 $spiXen,
99 $spiXrst,
100 $pclkX,
101 $afn,
102 $speed,
103 [$(
104 ($sck,
105 [$(
106 ($miso, $mosi),
107 )+]),
108 )+]
109 }
110 };
111 ($SPIX:ident,
112 $apbenr:ident,
113 $apbrstr:ident,
114 $spiXen:ident,
115 $spiXrst:ident,
116 $pclkX:ident,
117 $afn:ident,
118 $speed:ident,
119 [$(($sck: ident,
120 [$(($miso: ident, [$($mosi: ident,)+]), )+]
121 ), )+]
122 ) => {
123 $(
124 $(
125 $(
126 impl<PT: PullType, PM: PinMode>
127 SpiExt<$SPIX,
128 $sck<PT, PM>,
129 $miso<PT, PM>,
130 $mosi<PT, PM>,
131 $sck<PT, AltFn<$afn, PushPull, $speed>>,
132 $miso<PT, AltFn<$afn, PushPull, $speed>>,
133 $mosi<PT, AltFn<$afn, PushPull, $speed>>> for $SPIX
134 {
135 fn spi<F>(
136 self,
137 pins: ($sck<PT, PM>, $miso<PT, PM>, $mosi<PT, PM>),
138 mode: Mode,
139 freq: F,
140 clocks: Clocks)
141 -> Spi<$SPIX,
142 ($sck<PT, AltFn<$afn, PushPull, $speed>>,
143 $miso<PT, AltFn<$afn, PushPull, $speed>>,
144 $mosi<PT, AltFn<$afn, PushPull, $speed>>)>
145 where F: Into<Hertz<u32>>
146 {
147 let outpins = (pins.0.alternating($afn).output_speed($speed),
148 pins.1.alternating($afn).output_speed($speed),
149 pins.2.alternating($afn).output_speed($speed));
150 let apbenr = unsafe { &(*RCC::ptr()).$apbenr };
151 let apbrstr = unsafe { &(*RCC::ptr()).$apbrstr };
152 apbenr.modify(|_, w| w.$spiXen().enabled());
154 apbrstr.modify(|_, w| w.$spiXrst().set_bit());
155 apbrstr.modify(|_, w| w.$spiXrst().clear_bit());
156
157 self.cr2.write(|w| unsafe {
162 w.frxth()
163 .set_bit()
164 .ds()
165 .bits(0b111)
166 .ssoe()
167 .clear_bit()
168 });
169
170 let br = match clocks.$pclkX().0 / freq.into().0 {
171 0 => unreachable!(),
172 1..=2 => 0b000,
173 3..=5 => 0b001,
174 6..=11 => 0b010,
175 12..=23 => 0b011,
176 24..=39 => 0b100,
177 40..=95 => 0b101,
178 96..=191 => 0b110,
179 _ => 0b111,
180 };
181
182 self.cr1.write(|w|
193 w.cpha()
194 .bit(mode.phase
195 == Phase::CaptureOnSecondTransition)
196 .cpol()
197 .bit(mode.polarity == Polarity::IdleHigh)
198 .mstr()
199 .set_bit()
200 .br()
201 .bits(br)
202 .spe()
203 .set_bit()
204 .lsbfirst()
205 .clear_bit()
206 .ssi()
207 .set_bit()
208 .ssm()
209 .set_bit()
210 .crcen()
211 .clear_bit()
212 .bidimode()
213 .clear_bit()
214 );
215
216 Spi { spi: self,
217 pins: outpins, }
218 }
219 }
220 )+
221 )+
222 )+
223
224 impl<SCK, MISO, MOSI> Spi<$SPIX, (SCK, MISO, MOSI)> {
225 pub fn free(self) -> ($SPIX, (SCK, MISO, MOSI)) {
227 (self.spi, self.pins)
228 }
229 }
230
231 impl<PINS> FullDuplex<u8> for Spi<$SPIX, PINS> {
232 type Error = Error;
233
234 fn read(&mut self) -> nb::Result<u8, Error> {
235 let sr = self.spi.sr.read();
236
237 Err(if sr.ovr().bit_is_set() {
238 nb::Error::Other(Error::Overrun)
239 } else if sr.modf().bit_is_set() {
240 nb::Error::Other(Error::ModeFault)
241 } else if sr.crcerr().bit_is_set() {
242 nb::Error::Other(Error::Crc)
243 } else if sr.rxne().bit_is_set() {
244 return Ok(unsafe {
247 ptr::read_volatile(&self.spi.dr as *const _
248 as *const u8)
249 });
250 } else {
251 nb::Error::WouldBlock
252 })
253 }
254
255 fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
256 let sr = self.spi.sr.read();
257
258 Err(if sr.ovr().bit_is_set() {
259 nb::Error::Other(Error::Overrun)
260 } else if sr.modf().bit_is_set() {
261 nb::Error::Other(Error::ModeFault)
262 } else if sr.crcerr().bit_is_set() {
263 nb::Error::Other(Error::Crc)
264 } else if sr.txe().bit_is_set() {
265 unsafe {
267 ptr::write_volatile(&self.spi.dr as *const _ as *mut u8,
268 byte)
269 }
270 return Ok(());
271 } else {
272 nb::Error::WouldBlock
273 })
274 }
275 }
276
277 impl<PINS> ::hal::blocking::spi::transfer::Default<u8>
278 for Spi<$SPIX, PINS>
279 {}
280
281 impl<PINS> ::hal::blocking::spi::write::Default<u8>
282 for Spi<$SPIX, PINS>
283 {}
284 };
285}
286
287spi!(SPI1,
290 apb2enr,
291 apb2rstr,
292 spi1en,
293 spi1rst,
294 pclk2,
295 AF5,
296 HighSpeed,
297 sck: [PA5, PB3,],
298 miso: [PA6, PB4,],
299 mosi: [PA7, PB5,]);
300
301spi!(SPI2,
302 apb1enr,
303 apb1rstr,
304 spi2en,
305 spi2rst,
306 pclk1,
307 AF5,
308 HighSpeed,
309 sck: [PB13,],
310 miso: [PB14,],
311 mosi: [PB15,]);
312spi!(SPI3,
313 apb1enr,
314 apb1rstr,
315 spi3en,
316 spi3rst,
317 pclk1,
318 AF6,
319 HighSpeed,
320 sck: [PB3, PC10,],
321 miso: [PB4, PC11,],
322 mosi: [PB5, PC12,]);