aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/spi/mod.rs112
-rw-r--r--embassy-stm32/src/spi/v1.rs103
-rw-r--r--embassy-stm32/src/spi/v2.rs110
-rw-r--r--embassy-stm32/src/spi/v3.rs182
4 files changed, 125 insertions, 382 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index f39fc746d..d3d78e2a8 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,6 +1,7 @@
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::{regs, vals}; 7use crate::pac::spi::{regs, vals};
@@ -9,6 +10,7 @@ use crate::rcc::RccPeripheral;
9use crate::time::Hertz; 10use crate::time::Hertz;
10use core::future::Future; 11use core::future::Future;
11use core::marker::PhantomData; 12use core::marker::PhantomData;
13use core::ptr;
12use embassy::util::Unborrow; 14use embassy::util::Unborrow;
13use embassy_hal_common::unborrow; 15use embassy_hal_common::unborrow;
14use embassy_traits::spi as traits; 16use embassy_traits::spi as traits;
@@ -403,11 +405,121 @@ fn check_error_flags(sr: regs::Sr) -> Result<(), Error> {
403 Ok(()) 405 Ok(())
404} 406}
405 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
406trait Word {} 442trait Word {}
407 443
408impl Word for u8 {} 444impl Word for u8 {}
409impl Word for u16 {} 445impl Word for u16 {}
410 446
447fn transfer_word<W: Word>(regs: &'static crate::pac::spi::Spi, tx_word: W) -> Result<W, Error> {
448 spin_until_tx_ready(regs)?;
449
450 unsafe {
451 ptr::write_volatile(regs.tx_ptr(), tx_word);
452
453 #[cfg(spi_v3)]
454 regs.cr1().modify(|reg| reg.set_cstart(true));
455 }
456
457 spin_until_rx_ready(regs)?;
458
459 let rx_word = unsafe { ptr::read_volatile(regs.rx_ptr()) };
460 return Ok(rx_word);
461}
462
463impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
464 type Error = Error;
465
466 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
467 self.set_word_size(WordSize::EightBit);
468 let regs = T::regs();
469
470 for word in words.iter() {
471 let _ = transfer_word(regs, *word)?;
472 }
473
474 Ok(())
475 }
476}
477
478impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
479 type Error = Error;
480
481 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
482 self.set_word_size(WordSize::EightBit);
483 let regs = T::regs();
484
485 for word in words.iter_mut() {
486 *word = transfer_word(regs, *word)?;
487 }
488
489 Ok(words)
490 }
491}
492
493impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
494 type Error = Error;
495
496 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
497 self.set_word_size(WordSize::SixteenBit);
498 let regs = T::regs();
499
500 for word in words.iter() {
501 let _ = transfer_word(regs, *word)?;
502 }
503
504 Ok(())
505 }
506}
507
508impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
509 type Error = Error;
510
511 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
512 self.set_word_size(WordSize::SixteenBit);
513 let regs = T::regs();
514
515 for word in words.iter_mut() {
516 *word = transfer_word(regs, *word)?;
517 }
518
519 Ok(words)
520 }
521}
522
411impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> { 523impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> {
412 type Error = Error; 524 type Error = Error;
413} 525}
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index efe7e468c..92449ea80 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -1,15 +1,10 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{
5 check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize,
6};
7use core::ptr;
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 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 10 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
@@ -155,99 +150,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
155 } 150 }
156 } 151 }
157} 152}
158
159impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
160 type Error = Error;
161
162 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
163 self.set_word_size(WordSize::EightBit);
164 let regs = T::regs();
165
166 for word in words.iter() {
167 write_word(regs, *word)?;
168 let _: u8 = read_word(regs)?;
169 }
170
171 Ok(())
172 }
173}
174
175impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
176 type Error = Error;
177
178 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
179 self.set_word_size(WordSize::EightBit);
180 let regs = T::regs();
181
182 for word in words.iter_mut() {
183 write_word(regs, *word)?;
184 *word = read_word(regs)?;
185 }
186
187 Ok(words)
188 }
189}
190
191impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
192 type Error = Error;
193
194 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
195 self.set_word_size(WordSize::SixteenBit);
196 let regs = T::regs();
197
198 for word in words.iter() {
199 write_word(regs, *word)?;
200 let _: u8 = read_word(regs)?;
201 }
202
203 Ok(())
204 }
205}
206
207impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
208 type Error = Error;
209
210 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
211 self.set_word_size(WordSize::SixteenBit);
212 let regs = T::regs();
213
214 for word in words.iter_mut() {
215 write_word(regs, *word)?;
216 *word = read_word(regs)?;
217 }
218
219 Ok(words)
220 }
221}
222
223use super::Word;
224
225fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
226 loop {
227 let sr = unsafe { regs.sr().read() };
228
229 check_error_flags(sr)?;
230
231 if sr.txe() {
232 unsafe {
233 ptr::write_volatile(regs.tx_ptr(), word);
234 }
235 return Ok(());
236 }
237 }
238}
239
240/// Read a single word blocking. Assumes word size have already been set.
241fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
242 loop {
243 let sr = unsafe { regs.sr().read() };
244
245 check_error_flags(sr)?;
246
247 if sr.rxne() {
248 unsafe {
249 return Ok(ptr::read_volatile(regs.rx_ptr()));
250 }
251 }
252 }
253}
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs
index e905a1b9c..de78676c2 100644
--- a/embassy-stm32/src/spi/v2.rs
+++ b/embassy-stm32/src/spi/v2.rs
@@ -1,14 +1,9 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{
5 check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize,
6};
7use core::ptr;
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 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
@@ -100,7 +95,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
100 Ok(()) 95 Ok(())
101 } 96 }
102 97
103 pub(super) async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> 98 pub(super) async fn read_write_dma_u8(
99 &mut self,
100 read: &mut [u8],
101 write: &[u8],
102 ) -> Result<(), Error>
104 where 103 where
105 Tx: TxDmaChannel<T>, 104 Tx: TxDmaChannel<T>,
106 Rx: RxDmaChannel<T>, 105 Rx: RxDmaChannel<T>,
@@ -170,100 +169,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
170 } 169 }
171 } 170 }
172} 171}
173
174use super::Word;
175
176/// Write a single word blocking. Assumes word size have already been set.
177fn write_word<W: Word>(regs: &'static crate::pac::spi::Spi, word: W) -> Result<(), Error> {
178 loop {
179 let sr = unsafe { regs.sr().read() };
180
181 check_error_flags(sr)?;
182
183 if sr.txe() {
184 unsafe {
185 ptr::write_volatile(regs.tx_ptr(), word);
186 }
187 return Ok(());
188 }
189 }
190}
191
192/// Read a single word blocking. Assumes word size have already been set.
193fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> {
194 loop {
195 let sr = unsafe { regs.sr().read() };
196
197 check_error_flags(sr)?;
198
199 if sr.rxne() {
200 unsafe {
201 return Ok(ptr::read_volatile(regs.rx_ptr()));
202 }
203 }
204 }
205}
206
207impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, Rx> {
208 type Error = Error;
209
210 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
211 self.set_word_size(WordSize::EightBit);
212 let regs = T::regs();
213
214 for word in words.iter() {
215 write_word(regs, *word)?;
216 let _: u8 = read_word(regs)?;
217 }
218
219 Ok(())
220 }
221}
222
223impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
224 type Error = Error;
225
226 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
227 self.set_word_size(WordSize::EightBit);
228 let regs = T::regs();
229
230 for word in words.iter_mut() {
231 write_word(regs, *word)?;
232 *word = read_word(regs)?;
233 }
234
235 Ok(words)
236 }
237}
238
239impl<'d, T: Instance, Rx> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, Rx> {
240 type Error = Error;
241
242 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
243 self.set_word_size(WordSize::SixteenBit);
244 let regs = T::regs();
245
246 for word in words.iter() {
247 write_word(regs, *word)?;
248 let _: u16 = read_word(regs)?;
249 }
250
251 Ok(())
252 }
253}
254
255impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
256 type Error = Error;
257
258 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
259 self.set_word_size(WordSize::SixteenBit);
260 let regs = T::regs();
261
262 for word in words.iter_mut() {
263 write_word(regs, *word)?;
264 *word = read_word(regs)?;
265 }
266
267 Ok(words)
268 }
269}
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index cbe2861e0..ef0f23063 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -1,15 +1,9 @@
1#![macro_use] 1#![macro_use]
2 2
3use crate::dma::NoDma;
4use crate::spi::{
5 check_error_flags, Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize,
6};
7use core::ptr;
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 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error> 9 pub(super) async fn write_dma_u8(&mut self, write: &[u8]) -> Result<(), Error>
@@ -105,7 +99,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
105 Ok(()) 99 Ok(())
106 } 100 }
107 101
108 pub(super) async fn read_write_dma_u8(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> 102 pub(super) async fn read_write_dma_u8(
103 &mut self,
104 read: &mut [u8],
105 write: &[u8],
106 ) -> Result<(), Error>
109 where 107 where
110 Tx: TxDmaChannel<T>, 108 Tx: TxDmaChannel<T>,
111 Rx: RxDmaChannel<T>, 109 Rx: RxDmaChannel<T>,
@@ -173,171 +171,3 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
173 } 171 }
174 } 172 }
175} 173}
176
177impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T, NoDma, NoDma> {
178 type Error = Error;
179
180 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
181 self.set_word_size(WordSize::EightBit);
182 let regs = T::regs();
183
184 for word in words.iter() {
185 while unsafe { !regs.sr().read().txp() } {
186 // spin
187 }
188 unsafe {
189 ptr::write_volatile(regs.tx_ptr(), *word);
190 regs.cr1().modify(|reg| reg.set_cstart(true));
191 }
192 loop {
193 let sr = unsafe { regs.sr().read() };
194 if sr.tifre() {
195 return Err(Error::Framing);
196 }
197 if sr.ovr() {
198 return Err(Error::Overrun);
199 }
200 if sr.crce() {
201 return Err(Error::Crc);
202 }
203 if !sr.txp() {
204 // loop waiting for TXE
205 continue;
206 }
207 break;
208 }
209 unsafe {
210 // discard read to prevent pverrun.
211 let _: u8 = ptr::read_volatile(T::regs().rx_ptr());
212 }
213 }
214
215 while unsafe { !regs.sr().read().txc() } {
216 // spin
217 }
218
219 Ok(())
220 }
221}
222
223impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T, NoDma, NoDma> {
224 type Error = Error;
225
226 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
227 self.set_word_size(WordSize::EightBit);
228 let regs = T::regs();
229
230 for word in words.iter_mut() {
231 unsafe {
232 regs.cr1().modify(|reg| {
233 reg.set_ssi(false);
234 });
235 }
236 while unsafe { !regs.sr().read().txp() } {
237 // spin
238 }
239 unsafe {
240 ptr::write_volatile(T::regs().tx_ptr(), *word);
241 regs.cr1().modify(|reg| reg.set_cstart(true));
242 }
243 loop {
244 let sr = unsafe { regs.sr().read() };
245
246 if sr.rxp() {
247 break;
248 }
249
250 check_error_flags(sr)?;
251 }
252 unsafe {
253 *word = ptr::read_volatile(T::regs().rx_ptr());
254 }
255 let sr = unsafe { regs.sr().read() };
256 check_error_flags(sr)?;
257 }
258
259 Ok(words)
260 }
261}
262
263impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T, NoDma, NoDma> {
264 type Error = Error;
265
266 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
267 self.set_word_size(WordSize::SixteenBit);
268 let regs = T::regs();
269
270 for word in words.iter() {
271 while unsafe { !regs.sr().read().txp() } {
272 // spin
273 }
274 unsafe {
275 let txdr = regs.txdr().ptr() as *mut u16;
276 ptr::write_volatile(txdr, *word);
277 regs.cr1().modify(|reg| reg.set_cstart(true));
278 }
279 loop {
280 let sr = unsafe { regs.sr().read() };
281
282 check_error_flags(sr)?;
283
284 if !sr.txp() {
285 // loop waiting for TXE
286 continue;
287 }
288 break;
289 }
290
291 unsafe {
292 let rxdr = regs.rxdr().ptr() as *const u8;
293 // discard read to prevent pverrun.
294 let _ = ptr::read_volatile(rxdr);
295 }
296 }
297
298 while unsafe { !regs.sr().read().txc() } {
299 // spin
300 }
301
302 Ok(())
303 }
304}
305
306impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T, NoDma, NoDma> {
307 type Error = Error;
308
309 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
310 self.set_word_size(WordSize::SixteenBit);
311 let regs = T::regs();
312
313 for word in words.iter_mut() {
314 while unsafe { !regs.sr().read().txp() } {
315 // spin
316 }
317 unsafe {
318 let txdr = regs.txdr().ptr() as *mut u16;
319 ptr::write_volatile(txdr, *word);
320 regs.cr1().modify(|reg| reg.set_cstart(true));
321 }
322
323 loop {
324 let sr = unsafe { regs.sr().read() };
325
326 if sr.rxp() {
327 break;
328 }
329
330 check_error_flags(sr)?;
331 }
332
333 unsafe {
334 let rxdr = regs.rxdr().ptr() as *const u16;
335 *word = ptr::read_volatile(rxdr);
336 }
337 let sr = unsafe { regs.sr().read() };
338 check_error_flags(sr)?;
339 }
340
341 Ok(words)
342 }
343}