diff options
| author | Nils Fitinghoff <[email protected]> | 2023-09-22 16:12:57 +0300 |
|---|---|---|
| committer | Nils Fitinghoff <[email protected]> | 2023-09-22 17:02:21 +0200 |
| commit | 2b7b7a917d0fc5917cb968c52bd19d710675f540 (patch) | |
| tree | 999bab6f3f7f82aa55966f52ebdab2cd27db3048 /embassy-nrf | |
| parent | f1488864ebee3daebdc2cc6ed3ccdf7014fa67b2 (diff) | |
spim: Fix SPIM with polling executors
Co-authored-by: Priit Laes <[email protected]>
Diffstat (limited to 'embassy-nrf')
| -rw-r--r-- | embassy-nrf/src/spim.rs | 67 |
1 files changed, 45 insertions, 22 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 99a195a6e..a0d2c8eb1 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -69,29 +69,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 69 | let s = T::state(); | 69 | let s = T::state(); |
| 70 | 70 | ||
| 71 | #[cfg(feature = "nrf52832")] | 71 | #[cfg(feature = "nrf52832")] |
| 72 | // NRF32 Anomaly 109 workaround... NRF52832 | 72 | if r.events_started.read().bits() != 0 { |
| 73 | if r.intenset.read().started().is_enabled() && r.events_started.read().bits() != 0 { | 73 | s.waker.wake(); |
| 74 | // Handle the first "fake" transmission | ||
| 75 | r.events_started.reset(); | ||
| 76 | r.events_end.reset(); | ||
| 77 | |||
| 78 | // Update DMA registers with correct rx/tx buffer sizes | ||
| 79 | r.rxd | ||
| 80 | .maxcnt | ||
| 81 | .write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) }); | ||
| 82 | r.txd | ||
| 83 | .maxcnt | ||
| 84 | .write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) }); | ||
| 85 | |||
| 86 | // Disable interrupt for STARTED event... | ||
| 87 | r.intenclr.write(|w| w.started().clear()); | 74 | r.intenclr.write(|w| w.started().clear()); |
| 88 | // ... and start actual, hopefully glitch-free transmission | ||
| 89 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | ||
| 90 | return; | ||
| 91 | } | 75 | } |
| 92 | 76 | ||
| 93 | if r.events_end.read().bits() != 0 { | 77 | if r.events_end.read().bits() != 0 { |
| 94 | s.end_waker.wake(); | 78 | s.waker.wake(); |
| 95 | r.intenclr.write(|w| w.end().clear()); | 79 | r.intenclr.write(|w| w.end().clear()); |
| 96 | } | 80 | } |
| 97 | } | 81 | } |
| @@ -254,6 +238,9 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 254 | fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 238 | fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 255 | self.prepare(rx, tx)?; | 239 | self.prepare(rx, tx)?; |
| 256 | 240 | ||
| 241 | #[cfg(feature = "nrf52832")] | ||
| 242 | while let Poll::Pending = self.nrf52832_dma_workaround_status() {} | ||
| 243 | |||
| 257 | // Wait for 'end' event. | 244 | // Wait for 'end' event. |
| 258 | while T::regs().events_end.read().bits() == 0 {} | 245 | while T::regs().events_end.read().bits() == 0 {} |
| 259 | 246 | ||
| @@ -278,9 +265,19 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 278 | async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 265 | async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 279 | self.prepare(rx, tx)?; | 266 | self.prepare(rx, tx)?; |
| 280 | 267 | ||
| 268 | #[cfg(feature = "nrf52832")] | ||
| 269 | poll_fn(|cx| { | ||
| 270 | let s = T::state(); | ||
| 271 | |||
| 272 | s.waker.register(cx.waker()); | ||
| 273 | |||
| 274 | self.nrf52832_dma_workaround_status() | ||
| 275 | }) | ||
| 276 | .await; | ||
| 277 | |||
| 281 | // Wait for 'end' event. | 278 | // Wait for 'end' event. |
| 282 | poll_fn(|cx| { | 279 | poll_fn(|cx| { |
| 283 | T::state().end_waker.register(cx.waker()); | 280 | T::state().waker.register(cx.waker()); |
| 284 | if T::regs().events_end.read().bits() != 0 { | 281 | if T::regs().events_end.read().bits() != 0 { |
| 285 | return Poll::Ready(()); | 282 | return Poll::Ready(()); |
| 286 | } | 283 | } |
| @@ -371,6 +368,32 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 371 | pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> { | 368 | pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> { |
| 372 | self.async_inner_from_ram(&mut [], data).await | 369 | self.async_inner_from_ram(&mut [], data).await |
| 373 | } | 370 | } |
| 371 | |||
| 372 | #[cfg(feature = "nrf52832")] | ||
| 373 | fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> { | ||
| 374 | let r = T::regs(); | ||
| 375 | if r.events_started.read().bits() != 0 { | ||
| 376 | let s = T::state(); | ||
| 377 | |||
| 378 | // Handle the first "fake" transmission | ||
| 379 | r.events_started.reset(); | ||
| 380 | r.events_end.reset(); | ||
| 381 | |||
| 382 | // Update DMA registers with correct rx/tx buffer sizes | ||
| 383 | r.rxd | ||
| 384 | .maxcnt | ||
| 385 | .write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) }); | ||
| 386 | r.txd | ||
| 387 | .maxcnt | ||
| 388 | .write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) }); | ||
| 389 | |||
| 390 | r.intenset.write(|w| w.end().set()); | ||
| 391 | // ... and start actual, hopefully glitch-free transmission | ||
| 392 | r.tasks_start.write(|w| unsafe { w.bits(1) }); | ||
| 393 | return Poll::Ready(()); | ||
| 394 | } | ||
| 395 | Poll::Pending | ||
| 396 | } | ||
| 374 | } | 397 | } |
| 375 | 398 | ||
| 376 | impl<'d, T: Instance> Drop for Spim<'d, T> { | 399 | impl<'d, T: Instance> Drop for Spim<'d, T> { |
| @@ -403,7 +426,7 @@ pub(crate) mod sealed { | |||
| 403 | use super::*; | 426 | use super::*; |
| 404 | 427 | ||
| 405 | pub struct State { | 428 | pub struct State { |
| 406 | pub end_waker: AtomicWaker, | 429 | pub waker: AtomicWaker, |
| 407 | #[cfg(feature = "nrf52832")] | 430 | #[cfg(feature = "nrf52832")] |
| 408 | pub rx: AtomicU8, | 431 | pub rx: AtomicU8, |
| 409 | #[cfg(feature = "nrf52832")] | 432 | #[cfg(feature = "nrf52832")] |
| @@ -413,7 +436,7 @@ pub(crate) mod sealed { | |||
| 413 | impl State { | 436 | impl State { |
| 414 | pub const fn new() -> Self { | 437 | pub const fn new() -> Self { |
| 415 | Self { | 438 | Self { |
| 416 | end_waker: AtomicWaker::new(), | 439 | waker: AtomicWaker::new(), |
| 417 | #[cfg(feature = "nrf52832")] | 440 | #[cfg(feature = "nrf52832")] |
| 418 | rx: AtomicU8::new(0), | 441 | rx: AtomicU8::new(0), |
| 419 | #[cfg(feature = "nrf52832")] | 442 | #[cfg(feature = "nrf52832")] |
