aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-07 06:30:29 +0000
committerGitHub <[email protected]>2021-12-07 06:30:29 +0000
commit56bcc824e093aef3d523adc3ac6f3fe7db9c347f (patch)
treef66884f697286ace5a4726d9e7c1fa40d8f57589
parent2e6c3b22b887f5fc377b1549c1a36cf24ac4acf8 (diff)
parent79baa041184d8837a26c9e4b07230b1cdd8cb5b3 (diff)
Merge #523
523: Incrementally merge STM32 SPI versions, Part 2 r=Dirbaio a=GrantM11235 Co-authored-by: Grant Miller <[email protected]>
-rw-r--r--embassy-stm32/src/spi/mod.rs174
-rw-r--r--embassy-stm32/src/spi/v1.rs178
-rw-r--r--embassy-stm32/src/spi/v2.rs169
-rw-r--r--embassy-stm32/src/spi/v3.rs264
4 files changed, 197 insertions, 588 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 80a05aac6..5d919f923 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,15 +1,19 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma; 3use crate::dma;
4use crate::dma::NoDma;
4use crate::gpio::sealed::{AFType, Pin}; 5use crate::gpio::sealed::{AFType, Pin};
5use crate::gpio::{AnyPin, NoPin, OptionalPin}; 6use crate::gpio::{AnyPin, NoPin, OptionalPin};
6use crate::pac::spi::vals; 7use crate::pac::spi::{regs, vals};
7use crate::peripherals; 8use crate::peripherals;
8use crate::rcc::RccPeripheral; 9use crate::rcc::RccPeripheral;
9use crate::time::Hertz; 10use crate::time::Hertz;
11use core::future::Future;
10use core::marker::PhantomData; 12use core::marker::PhantomData;
13use core::ptr;
11use embassy::util::Unborrow; 14use embassy::util::Unborrow;
12use embassy_hal_common::unborrow; 15use embassy_hal_common::unborrow;
16use embassy_traits::spi as traits;
13 17
14#[cfg_attr(spi_v1, path = "v1.rs")] 18#[cfg_attr(spi_v1, path = "v1.rs")]
15#[cfg_attr(spi_f1, path = "v1.rs")] 19#[cfg_attr(spi_f1, path = "v1.rs")]
@@ -374,6 +378,174 @@ impl RegsExt for crate::pac::spi::Spi {
374 } 378 }
375} 379}
376 380
381fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
382 if sr.ovr() {
383 return Err(Error::Overrun);
384 }
385 #[cfg(not(any(spi_f1, spi_v3)))]
386 if sr.fre() {
387 return Err(Error::Framing);
388 }
389 #[cfg(spi_v3)]
390 if sr.tifre() {
391 return Err(Error::Framing);
392 }
393 if sr.modf() {
394 return Err(Error::ModeFault);
395 }
396 #[cfg(not(spi_v3))]
397 if sr.crcerr() {
398 return Err(Error::Crc);
399 }
400 #[cfg(spi_v3)]
401 if sr.crce() {
402 return Err(Error::Crc);
403 }
404
405 Ok(())
406}
407
408fn spin_until_tx_ready(regs: &'static crate::pac::spi::Spi) -> Result<(), Error> {
409 loop {
410 let sr = unsafe { regs.sr().read() };
411
412 check_error_flags(sr)?;
413
414 #[cfg(not(spi_v3))]
415 if sr.txe() {
416 return Ok(());
417 }
418 #[cfg(spi_v3)]
419 if sr.txp() {
420 return Ok(());
421 }
422 }
423}
424
425fn spin_until_rx_ready(regs: &'static crate::pac::spi::Spi) -> Result<(), Error> {
426 loop {
427 let sr = unsafe { regs.sr().read() };
428
429 check_error_flags(sr)?;
430
431 #[cfg(not(spi_v3))]
432 if sr.rxne() {
433 return Ok(());
434 }
435 #[cfg(spi_v3)]
436 if sr.rxp() {
437 return Ok(());
438 }
439 }
440}
441
442trait Word {
443 const WORDSIZE: WordSize;
444}
445
446impl Word for u8 {
447 const WORDSIZE: WordSize = WordSize::EightBit;
448}
449impl Word for u16 {
450 const WORDSIZE: WordSize = WordSize::SixteenBit;
451}
452
453fn transfer_word<W: Word>(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Result<W, Error> {
454 spin_until_tx_ready(regs)?;
455
456 unsafe {
457 ptr::write_volatile(regs.tx_ptr(), tx_word);
458
459 #[cfg(spi_v3)]
460 regs.cr1().modify(|reg| reg.set_cstart(true));
461 }
462
463 spin_until_rx_ready(regs)?;
464
465 let rx_word = unsafe { ptr::read_volatile(regs.rx_ptr()) };
466 return Ok(rx_word);
467}
468
469// Note: It is not possible to impl these traits generically in embedded-hal 0.2 due to a conflict with
470// some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289
471macro_rules! impl_blocking {
472 ($w:ident) => {
473 impl<'d, T: Instance> embedded_hal::blocking::spi::Write<$w> for Spi<'d, T, NoDma, NoDma> {
474 type Error = Error;
475
476 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
477 self.set_word_size($w::WORDSIZE);
478 let regs = T::regs();
479
480 for word in words.iter() {
481 let _ = transfer_word(regs, *word)?;
482 }
483
484 Ok(())
485 }
486 }
487
488 impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<$w>
489 for Spi<'d, T, NoDma, NoDma>
490 {
491 type Error = Error;
492
493 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
494 self.set_word_size($w::WORDSIZE);
495 let regs = T::regs();
496
497 for word in words.iter_mut() {
498 *word = transfer_word(regs, *word)?;
499 }
500
501 Ok(words)
502 }
503 }
504 };
505}
506
507impl_blocking!(u8);
508impl_blocking!(u16);
509
510impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
511 type Error = Error;
512}
513
514impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
515 #[rustfmt::skip]
516 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
517
518 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
519 self.write_dma_u8(data)
520 }
521}
522
523impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
524 for Spi<'d, T, Tx, Rx>
525{
526 #[rustfmt::skip]
527 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
528
529 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
530 self.read_dma_u8(data)
531 }
532}
533
534impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDuplex<u8>
535 for Spi<'d, T, Tx, Rx>
536{
537 #[rustfmt::skip]
538 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
539
540 fn read_write<'a>(
541 &'a mut self,
542 read: &'a mut [u8],
543 write: &'a [u8],
544 ) -> Self::WriteReadFuture<'a> {
545 self.read_write_dma_u8(read, write)
546 }
547}
548
377pub(crate) mod sealed { 549pub(crate) mod sealed {
378 use super::*; 550 use super::*;
379 551
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index 255bd950a..92449ea80 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -1,19 +1,13 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
5use core::future::Future;
6use core::ptr;
7use embassy_traits::spi as traits;
8pub use embedded_hal::blocking; 3pub use embedded_hal::blocking;
9pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 4pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
10use futures::future::join3; 5use futures::future::join3;
11 6
12use super::Spi; 7use super::*;
13 8
14impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 9impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
15 #[allow(unused)] 10 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
16 async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
17 where 11 where
18 Tx: TxDmaChannel<T>, 12 Tx: TxDmaChannel<T>,
19 { 13 {
@@ -41,8 +35,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
41 Ok(()) 35 Ok(())
42 } 36 }
43 37
44 #[allow(unused)] 38 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
45 async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
46 where 39 where
47 Tx: TxDmaChannel<T>, 40 Tx: TxDmaChannel<T>,
48 Rx: RxDmaChannel<T>, 41 Rx: RxDmaChannel<T>,
@@ -94,8 +87,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
94 Ok(()) 87 Ok(())
95 } 88 }
96 89
97 #[allow(unused)] 90 pub(super) async fn read_write_dma_u8(
98 async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> 91 &mut self,
92 read: &mut [u8],
93 write: &[u8],
94 ) -> Result<(), Error>
99 where 95 where
100 Tx: TxDmaChannel<T>, 96 Tx: TxDmaChannel<T>,
101 Rx: RxDmaChannel<T>, 97 Rx: RxDmaChannel<T>,
@@ -154,161 +150,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
154 } 150 }
155 } 151 }
156} 152}
157
158impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
159 type Error = Error;
160
161 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
162 self.set_word_size(WordSize::EightBit);
163 let regs = T::regs();
164
165 for word in words.iter() {
166 write_word(regs, *word)?;
167 let _: u8 = read_word(regs)?;
168 }
169
170 Ok(())
171 }
172}
173
174impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
175 type Error = Error;
176
177 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
178 self.set_word_size(WordSize::EightBit);
179 let regs = T::regs();
180
181 for word in words.iter_mut() {
182 write_word(regs, *word)?;
183 *word = read_word(regs)?;
184 }
185
186 Ok(words)
187 }
188}
189
190impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
191 type Error = Error;
192
193 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
194 self.set_word_size(WordSize::SixteenBit);
195 let regs = T::regs();
196
197 for word in words.iter() {
198 write_word(regs, *word)?;
199 let _: u8 = read_word(regs)?;
200 }
201
202 Ok(())
203 }
204}
205
206impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
207 type Error = Error;
208
209 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
210 self.set_word_size(WordSize::SixteenBit);
211 let regs = T::regs();
212
213 for word in words.iter_mut() {
214 write_word(regs, *word)?;
215 *word = read_word(regs)?;
216 }
217
218 Ok(words)
219 }
220}
221
222impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
223 type Error = super::Error;
224}
225
226impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
227 #[rustfmt::skip]
228 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
229
230 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
231 self.write_dma_u8(data)
232 }
233}
234
235impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
236 for Spi<'d, T, Tx, Rx>
237{
238 #[rustfmt::skip]
239 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
240
241 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
242 self.read_dma_u8(data)
243 }
244}
245
246impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDuplex<u8>
247 for Spi<'d, T, Tx, Rx>
248{
249 #[rustfmt::skip]
250 type WriteReadFuture<'a> where Self: 'a = impl Future<Output=Result<(), Self::Error>> + 'a;
251
252 fn read_write<'a>(
253 &'a mut self,
254 read: &'a mut [u8],
255 write: &'a [u8],
256 ) -> Self::WriteReadFuture<'a> {
257 self.read_write_dma_u8(read, write)
258 }
259}
260
261trait Word {}
262
263impl Word for u8 {}
264impl Word for u16 {}
265
266fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
267 loop {
268 let sr = unsafe { regs.sr().read() };
269 if sr.ovr() {
270 return Err(Error::Overrun);
271 }
272 #[cfg(not(spi_f1))]
273 if sr.fre() {
274 return Err(Error::Framing);
275 }
276 if sr.modf() {
277 return Err(Error::ModeFault);
278 }
279 if sr.crcerr() {
280 return Err(Error::Crc);
281 }
282 if sr.txe() {
283 unsafe {
284 ptr::write_volatile(regs.tx_ptr(), word);
285 }
286 return Ok(());
287 }
288 }
289}
290
291/// Read a single word blocking. Assumes word size have already been set.
292fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
293 loop {
294 let sr = unsafe { regs.sr().read() };
295 if sr.ovr() {
296 return Err(Error::Overrun);
297 }
298 #[cfg(not(spi_f1))]
299 if sr.fre() {
300 return Err(Error::Framing);
301 }
302 if sr.modf() {
303 return Err(Error::ModeFault);
304 }
305 if sr.crcerr() {
306 return Err(Error::Crc);
307 }
308 if sr.rxne() {
309 unsafe {
310 return Ok(ptr::read_volatile(regs.rx_ptr()));
311 }
312 }
313 }
314}
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs
index b1fae4bdc..de78676c2 100644
--- a/embassy-stm32/src/spi/v2.rs
+++ b/embassy-stm32/src/spi/v2.rs
@@ -1,18 +1,12 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
5use core::future::Future;
6use core::ptr;
7use embassy_traits::spi as traits;
8pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 3pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
9use futures::future::{join, join3}; 4use futures::future::{join, join3};
10 5
11use super::Spi; 6use super::*;
12 7
13impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
14 #[allow(unused)] 9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
15 async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
16 where 10 where
17 Tx: TxDmaChannel<T>, 11 Tx: TxDmaChannel<T>,
18 { 12 {
@@ -49,8 +43,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
49 Ok(()) 43 Ok(())
50 } 44 }
51 45
52 #[allow(unused)] 46 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
53 async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
54 where 47 where
55 Tx: TxDmaChannel<T>, 48 Tx: TxDmaChannel<T>,
56 Rx: RxDmaChannel<T>, 49 Rx: RxDmaChannel<T>,
@@ -102,8 +95,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
102 Ok(()) 95 Ok(())
103 } 96 }
104 97
105 #[allow(unused)] 98 pub(super) async fn read_write_dma_u8(
106 async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> 99 &mut self,
100 read: &mut [u8],
101 write: &[u8],
102 ) -> Result<(), Error>
107 where 103 where
108 Tx: TxDmaChannel<T>, 104 Tx: TxDmaChannel<T>,
109 Rx: RxDmaChannel<T>, 105 Rx: RxDmaChannel<T>,
@@ -173,152 +169,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
173 } 169 }
174 } 170 }
175} 171}
176
177trait Word {}
178
179impl Word for u8 {}
180impl Word for u16 {}
181
182/// Write a single word blocking. Assumes word size have already been set.
183fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
184 loop {
185 let sr = unsafe { regs.sr().read() };
186 if sr.ovr() {
187 return Err(Error::Overrun);
188 } else if sr.fre() {
189 return Err(Error::Framing);
190 } else if sr.modf() {
191 return Err(Error::ModeFault);
192 } else if sr.crcerr() {
193 return Err(Error::Crc);
194 } else if sr.txe() {
195 unsafe {
196 ptr::write_volatile(regs.tx_ptr(), word);
197 }
198 return Ok(());
199 }
200 }
201}
202
203/// Read a single word blocking. Assumes word size have already been set.
204fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
205 loop {
206 let sr = unsafe { regs.sr().read() };
207 if sr.ovr() {
208 return Err(Error::Overrun);
209 } else if sr.modf() {
210 return Err(Error::ModeFault);
211 } else if sr.fre() {
212 return Err(Error::Framing);
213 } else if sr.crcerr() {
214 return Err(Error::Crc);
215 } else if sr.rxne() {
216 unsafe {
217 return Ok(ptr::read_volatile(regs.rx_ptr()));
218 }
219 }
220 }
221}
222
223impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, Rx> {
224 type Error = Error;
225
226 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
227 self.set_word_size(WordSize::EightBit);
228 let regs = T::regs();
229
230 for word in words.iter() {
231 write_word(regs, *word)?;
232 let _: u8 = read_word(regs)?;
233 }
234
235 Ok(())
236 }
237}
238
239impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
240 type Error = Error;
241
242 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
243 self.set_word_size(WordSize::EightBit);
244 let regs = T::regs();
245
246 for word in words.iter_mut() {
247 write_word(regs, *word)?;
248 *word = read_word(regs)?;
249 }
250
251 Ok(words)
252 }
253}
254
255impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, Rx> {
256 type Error = Error;
257
258 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
259 self.set_word_size(WordSize::SixteenBit);
260 let regs = T::regs();
261
262 for word in words.iter() {
263 write_word(regs, *word)?;
264 let _: u16 = read_word(regs)?;
265 }
266
267 Ok(())
268 }
269}
270
271impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
272 type Error = Error;
273
274 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
275 self.set_word_size(WordSize::SixteenBit);
276 let regs = T::regs();
277
278 for word in words.iter_mut() {
279 write_word(regs, *word)?;
280 *word = read_word(regs)?;
281 }
282
283 Ok(words)
284 }
285}
286
287impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
288 type Error = super::Error;
289}
290
291impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
292 #[rustfmt::skip]
293 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
294
295 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
296 self.write_dma_u8(data)
297 }
298}
299
300impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
301 for Spi<'d, T, Tx, Rx>
302{
303 #[rustfmt::skip]
304 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
305
306 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
307 self.read_dma_u8(data)
308 }
309}
310
311impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDuplex<u8>
312 for Spi<'d, T, Tx, Rx>
313{
314 #[rustfmt::skip]
315 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
316
317 fn read_write<'a>(
318 &'a mut self,
319 read: &'a mut [u8],
320 write: &'a [u8],
321 ) -> Self::WriteReadFuture<'a> {
322 self.read_write_dma_u8(read, write)
323 }
324}
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index 052924db0..ef0f23063 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -1,19 +1,12 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize};
5use core::future::Future;
6use core::ptr;
7use embassy_traits::spi as traits;
8pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 3pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
9
10use futures::future::join3; 4use futures::future::join3;
11 5
12use super::Spi; 6use super::*;
13 7
14impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { 8impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
15 #[allow(unused)] 9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
16 async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
17 where 10 where
18 Tx: TxDmaChannel<T>, 11 Tx: TxDmaChannel<T>,
19 { 12 {
@@ -53,8 +46,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
53 Ok(()) 46 Ok(())
54 } 47 }
55 48
56 #[allow(unused)] 49 pub(super) async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
57 async fn read_dma_u8(&mut self, read: &mut [u8]) -> Result<(), Error>
58 where 50 where
59 Tx: TxDmaChannel<T>, 51 Tx: TxDmaChannel<T>,
60 Rx: RxDmaChannel<T>, 52 Rx: RxDmaChannel<T>,
@@ -107,8 +99,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
107 Ok(()) 99 Ok(())
108 } 100 }
109 101
110 #[allow(unused)] 102 pub(super) async fn read_write_dma_u8(
111 async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> 103 &mut self,
104 read: &mut [u8],
105 write: &[u8],
106 ) -> Result<(), Error>
112 where 107 where
113 Tx: TxDmaChannel<T>, 108 Tx: TxDmaChannel<T>,
114 Rx: RxDmaChannel<T>, 109 Rx: RxDmaChannel<T>,
@@ -176,246 +171,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
176 } 171 }
177 } 172 }
178} 173}
179
180impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
181 type Error = Error;
182
183 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
184 self.set_word_size(WordSize::EightBit);
185 let regs = T::regs();
186
187 for word in words.iter() {
188 while unsafe { !regs.sr().read().txp() } {
189 // spin
190 }
191 unsafe {
192 ptr::write_volatile(regs.tx_ptr(), *word);
193 regs.cr1().modify(|reg| reg.set_cstart(true));
194 }
195 loop {
196 let sr = unsafe { regs.sr().read() };
197 if sr.tifre() {
198 return Err(Error::Framing);
199 }
200 if sr.ovr() {
201 return Err(Error::Overrun);
202 }
203 if sr.crce() {
204 return Err(Error::Crc);
205 }
206 if !sr.txp() {
207 // loop waiting for TXE
208 continue;
209 }
210 break;
211 }
212 unsafe {
213 // discard read to prevent pverrun.
214 let _: u8 = ptr::read_volatile(T::regs().rx_ptr());
215 }
216 }
217
218 while unsafe { !regs.sr().read().txc() } {
219 // spin
220 }
221
222 Ok(())
223 }
224}
225
226impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
227 type Error = Error;
228
229 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
230 self.set_word_size(WordSize::EightBit);
231 let regs = T::regs();
232
233 for word in words.iter_mut() {
234 unsafe {
235 regs.cr1().modify(|reg| {
236 reg.set_ssi(false);
237 });
238 }
239 while unsafe { !regs.sr().read().txp() } {
240 // spin
241 }
242 unsafe {
243 ptr::write_volatile(T::regs().tx_ptr(), *word);
244 regs.cr1().modify(|reg| reg.set_cstart(true));
245 }
246 loop {
247 let sr = unsafe { regs.sr().read() };
248
249 if sr.rxp() {
250 break;
251 }
252 if sr.tifre() {
253 return Err(Error::Framing);
254 }
255 if sr.ovr() {
256 return Err(Error::Overrun);
257 }
258 if sr.crce() {
259 return Err(Error::Crc);
260 }
261 }
262 unsafe {
263 *word = ptr::read_volatile(T::regs().rx_ptr());
264 }
265 let sr = unsafe { regs.sr().read() };
266 if sr.tifre() {
267 return Err(Error::Framing);
268 }
269 if sr.ovr() {
270 return Err(Error::Overrun);
271 }
272 if sr.crce() {
273 return Err(Error::Crc);
274 }
275 }
276
277 Ok(words)
278 }
279}
280
281impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
282 type Error = Error;
283
284 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
285 self.set_word_size(WordSize::SixteenBit);
286 let regs = T::regs();
287
288 for word in words.iter() {
289 while unsafe { !regs.sr().read().txp() } {
290 // spin
291 }
292 unsafe {
293 let txdr = regs.txdr().ptr() as *mut u16;
294 ptr::write_volatile(txdr, *word);
295 regs.cr1().modify(|reg| reg.set_cstart(true));
296 }
297 loop {
298 let sr = unsafe { regs.sr().read() };
299 if sr.tifre() {
300 return Err(Error::Framing);
301 }
302 if sr.ovr() {
303 return Err(Error::Overrun);
304 }
305 if sr.crce() {
306 return Err(Error::Crc);
307 }
308 if !sr.txp() {
309 // loop waiting for TXE
310 continue;
311 }
312 break;
313 }
314
315 unsafe {
316 let rxdr = regs.rxdr().ptr() as *const u8;
317 // discard read to prevent pverrun.
318 let _ = ptr::read_volatile(rxdr);
319 }
320 }
321
322 while unsafe { !regs.sr().read().txc() } {
323 // spin
324 }
325
326 Ok(())
327 }
328}
329
330impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
331 type Error = Error;
332
333 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
334 self.set_word_size(WordSize::SixteenBit);
335 let regs = T::regs();
336
337 for word in words.iter_mut() {
338 while unsafe { !regs.sr().read().txp() } {
339 // spin
340 }
341 unsafe {
342 let txdr = regs.txdr().ptr() as *mut u16;
343 ptr::write_volatile(txdr, *word);
344 regs.cr1().modify(|reg| reg.set_cstart(true));
345 }
346
347 loop {
348 let sr = unsafe { regs.sr().read() };
349
350 if sr.rxp() {
351 break;
352 }
353 if sr.tifre() {
354 return Err(Error::Framing);
355 }
356 if sr.ovr() {
357 return Err(Error::Overrun);
358 }
359 if sr.crce() {
360 return Err(Error::Crc);
361 }
362 }
363
364 unsafe {
365 let rxdr = regs.rxdr().ptr() as *const u16;
366 *word = ptr::read_volatile(rxdr);
367 }
368 let sr = unsafe { regs.sr().read() };
369 if sr.tifre() {
370 return Err(Error::Framing);
371 }
372 if sr.ovr() {
373 return Err(Error::Overrun);
374 }
375 if sr.crce() {
376 return Err(Error::Crc);
377 }
378 }
379
380 Ok(words)
381 }
382}
383
384impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
385 type Error = super::Error;
386}
387
388impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx> traits::Write<u8> for Spi<'d, T, Tx, Rx> {
389 #[rustfmt::skip]
390 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
391
392 fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
393 self.write_dma_u8(data)
394 }
395}
396
397impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::Read<u8>
398 for Spi<'d, T, Tx, Rx>
399{
400 #[rustfmt::skip]
401 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
402
403 fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
404 self.read_dma_u8(data)
405 }
406}
407
408impl<'d, T: Instance, Tx: TxDmaChannel<T>, Rx: RxDmaChannel<T>> traits::FullDuplex<u8>
409 for Spi<'d, T, Tx, Rx>
410{
411 #[rustfmt::skip]
412 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
413
414 fn read_write<'a>(
415 &'a mut self,
416 read: &'a mut [u8],
417 write: &'a [u8],
418 ) -> Self::WriteReadFuture<'a> {
419 self.read_write_dma_u8(read, write)
420 }
421}