diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-12-07 06:30:29 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-12-07 06:30:29 +0000 |
| commit | 56bcc824e093aef3d523adc3ac6f3fe7db9c347f (patch) | |
| tree | f66884f697286ace5a4726d9e7c1fa40d8f57589 | |
| parent | 2e6c3b22b887f5fc377b1549c1a36cf24ac4acf8 (diff) | |
| parent | 79baa041184d8837a26c9e4b07230b1cdd8cb5b3 (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.rs | 174 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v1.rs | 178 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v2.rs | 169 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v3.rs | 264 |
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 | ||
| 3 | use crate::dma; | 3 | use crate::dma; |
| 4 | use crate::dma::NoDma; | ||
| 4 | use crate::gpio::sealed::{AFType, Pin}; | 5 | use crate::gpio::sealed::{AFType, Pin}; |
| 5 | use crate::gpio::{AnyPin, NoPin, OptionalPin}; | 6 | use crate::gpio::{AnyPin, NoPin, OptionalPin}; |
| 6 | use crate::pac::spi::vals; | 7 | use crate::pac::spi::{regs, vals}; |
| 7 | use crate::peripherals; | 8 | use crate::peripherals; |
| 8 | use crate::rcc::RccPeripheral; | 9 | use crate::rcc::RccPeripheral; |
| 9 | use crate::time::Hertz; | 10 | use crate::time::Hertz; |
| 11 | use core::future::Future; | ||
| 10 | use core::marker::PhantomData; | 12 | use core::marker::PhantomData; |
| 13 | use core::ptr; | ||
| 11 | use embassy::util::Unborrow; | 14 | use embassy::util::Unborrow; |
| 12 | use embassy_hal_common::unborrow; | 15 | use embassy_hal_common::unborrow; |
| 16 | use 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 | ||
| 381 | fn 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 | |||
| 408 | fn 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 | |||
| 425 | fn 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 | |||
| 442 | trait Word { | ||
| 443 | const WORDSIZE: WordSize; | ||
| 444 | } | ||
| 445 | |||
| 446 | impl Word for u8 { | ||
| 447 | const WORDSIZE: WordSize = WordSize::EightBit; | ||
| 448 | } | ||
| 449 | impl Word for u16 { | ||
| 450 | const WORDSIZE: WordSize = WordSize::SixteenBit; | ||
| 451 | } | ||
| 452 | |||
| 453 | fn 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 | ||
| 471 | macro_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 | |||
| 507 | impl_blocking!(u8); | ||
| 508 | impl_blocking!(u16); | ||
| 509 | |||
| 510 | impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> { | ||
| 511 | type Error = Error; | ||
| 512 | } | ||
| 513 | |||
| 514 | impl<'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 | |||
| 523 | impl<'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 | |||
| 534 | impl<'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 | |||
| 377 | pub(crate) mod sealed { | 549 | pub(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 | ||
| 3 | use crate::dma::NoDma; | ||
| 4 | use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; | ||
| 5 | use core::future::Future; | ||
| 6 | use core::ptr; | ||
| 7 | use embassy_traits::spi as traits; | ||
| 8 | pub use embedded_hal::blocking; | 3 | pub use embedded_hal::blocking; |
| 9 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 4 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 10 | use futures::future::join3; | 5 | use futures::future::join3; |
| 11 | 6 | ||
| 12 | use super::Spi; | 7 | use super::*; |
| 13 | 8 | ||
| 14 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 9 | impl<'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 | |||
| 158 | impl<'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 | |||
| 174 | impl<'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 | |||
| 190 | impl<'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 | |||
| 206 | impl<'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 | |||
| 222 | impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> { | ||
| 223 | type Error = super::Error; | ||
| 224 | } | ||
| 225 | |||
| 226 | impl<'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 | |||
| 235 | impl<'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 | |||
| 246 | impl<'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 | |||
| 261 | trait Word {} | ||
| 262 | |||
| 263 | impl Word for u8 {} | ||
| 264 | impl Word for u16 {} | ||
| 265 | |||
| 266 | fn 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. | ||
| 292 | fn 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 | ||
| 3 | use crate::dma::NoDma; | ||
| 4 | use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; | ||
| 5 | use core::future::Future; | ||
| 6 | use core::ptr; | ||
| 7 | use embassy_traits::spi as traits; | ||
| 8 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 3 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 9 | use futures::future::{join, join3}; | 4 | use futures::future::{join, join3}; |
| 10 | 5 | ||
| 11 | use super::Spi; | 6 | use super::*; |
| 12 | 7 | ||
| 13 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 8 | impl<'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 | |||
| 177 | trait Word {} | ||
| 178 | |||
| 179 | impl Word for u8 {} | ||
| 180 | impl Word for u16 {} | ||
| 181 | |||
| 182 | /// Write a single word blocking. Assumes word size have already been set. | ||
| 183 | fn 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. | ||
| 204 | fn 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 | |||
| 223 | impl<'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 | |||
| 239 | impl<'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 | |||
| 255 | impl<'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 | |||
| 271 | impl<'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 | |||
| 287 | impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> { | ||
| 288 | type Error = super::Error; | ||
| 289 | } | ||
| 290 | |||
| 291 | impl<'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 | |||
| 300 | impl<'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 | |||
| 311 | impl<'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 | ||
| 3 | use crate::dma::NoDma; | ||
| 4 | use crate::spi::{Error, Instance, RegsExt, RxDmaChannel, TxDmaChannel, WordSize}; | ||
| 5 | use core::future::Future; | ||
| 6 | use core::ptr; | ||
| 7 | use embassy_traits::spi as traits; | ||
| 8 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 3 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 9 | |||
| 10 | use futures::future::join3; | 4 | use futures::future::join3; |
| 11 | 5 | ||
| 12 | use super::Spi; | 6 | use super::*; |
| 13 | 7 | ||
| 14 | impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | 8 | impl<'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 | |||
| 180 | impl<'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 | |||
| 226 | impl<'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 | |||
| 281 | impl<'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 | |||
| 330 | impl<'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 | |||
| 384 | impl<'d, T: Instance, Tx, Rx> traits::Spi<u8> for Spi<'d, T, Tx, Rx> { | ||
| 385 | type Error = super::Error; | ||
| 386 | } | ||
| 387 | |||
| 388 | impl<'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 | |||
| 397 | impl<'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 | |||
| 408 | impl<'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 | } | ||
