aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-09-23 11:14:16 +0000
committerGitHub <[email protected]>2023-09-23 11:14:16 +0000
commit1e80fd81f7ccc8cd48d4f9e373395222c3394c6e (patch)
tree96ece93b25608b63163b0bfadd6f1a51b528e13b
parent52e269edbb5bddfc9d9101d07903a0266367007f (diff)
parent6f83acc010786d89400426c3395f871ac7199d32 (diff)
Merge pull request #1939 from nilfit/spim-anomaly-109
spim: Fix nRF52832 SPIM with polling executors
-rw-r--r--embassy-nrf/Cargo.toml5
-rw-r--r--embassy-nrf/src/spim.rs82
2 files changed, 56 insertions, 31 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index eee927211..3c706b473 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -51,7 +51,7 @@ nrf52805 = ["nrf52805-pac", "_nrf52"]
51nrf52810 = ["nrf52810-pac", "_nrf52"] 51nrf52810 = ["nrf52810-pac", "_nrf52"]
52nrf52811 = ["nrf52811-pac", "_nrf52"] 52nrf52811 = ["nrf52811-pac", "_nrf52"]
53nrf52820 = ["nrf52820-pac", "_nrf52"] 53nrf52820 = ["nrf52820-pac", "_nrf52"]
54nrf52832 = ["nrf52832-pac", "_nrf52"] 54nrf52832 = ["nrf52832-pac", "_nrf52", "_nrf52832_anomaly_109"]
55nrf52833 = ["nrf52833-pac", "_nrf52", "_gpio-p1"] 55nrf52833 = ["nrf52833-pac", "_nrf52", "_gpio-p1"]
56nrf52840 = ["nrf52840-pac", "_nrf52", "_gpio-p1"] 56nrf52840 = ["nrf52840-pac", "_nrf52", "_gpio-p1"]
57nrf5340-app-s = ["_nrf5340-app", "_s"] 57nrf5340-app-s = ["_nrf5340-app", "_s"]
@@ -90,6 +90,9 @@ _ppi = []
90_dppi = [] 90_dppi = []
91_gpio-p1 = [] 91_gpio-p1 = []
92 92
93# Errata workarounds
94_nrf52832_anomaly_109 = []
95
93[dependencies] 96[dependencies]
94embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } 97embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
95embassy-sync = { version = "0.3.0", path = "../embassy-sync" } 98embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 99a195a6e..4828af43e 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -68,30 +68,14 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
68 let r = T::regs(); 68 let r = T::regs();
69 let s = T::state(); 69 let s = T::state();
70 70
71 #[cfg(feature = "nrf52832")] 71 #[cfg(feature = "_nrf52832_anomaly_109")]
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 }
@@ -222,8 +206,7 @@ impl<'d, T: Instance> Spim<'d, T> {
222 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); 206 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
223 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) }); 207 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });
224 208
225 // ANOMALY 109 workaround 209 #[cfg(feature = "_nrf52832_anomaly_109")]
226 #[cfg(feature = "nrf52832")]
227 { 210 {
228 let s = T::state(); 211 let s = T::state();
229 212
@@ -254,6 +237,9 @@ impl<'d, T: Instance> Spim<'d, T> {
254 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { 237 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
255 self.prepare(rx, tx)?; 238 self.prepare(rx, tx)?;
256 239
240 #[cfg(feature = "_nrf52832_anomaly_109")]
241 while let Poll::Pending = self.nrf52832_dma_workaround_status() {}
242
257 // Wait for 'end' event. 243 // Wait for 'end' event.
258 while T::regs().events_end.read().bits() == 0 {} 244 while T::regs().events_end.read().bits() == 0 {}
259 245
@@ -278,9 +264,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> { 264 async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
279 self.prepare(rx, tx)?; 265 self.prepare(rx, tx)?;
280 266
267 #[cfg(feature = "_nrf52832_anomaly_109")]
268 poll_fn(|cx| {
269 let s = T::state();
270
271 s.waker.register(cx.waker());
272
273 self.nrf52832_dma_workaround_status()
274 })
275 .await;
276
281 // Wait for 'end' event. 277 // Wait for 'end' event.
282 poll_fn(|cx| { 278 poll_fn(|cx| {
283 T::state().end_waker.register(cx.waker()); 279 T::state().waker.register(cx.waker());
284 if T::regs().events_end.read().bits() != 0 { 280 if T::regs().events_end.read().bits() != 0 {
285 return Poll::Ready(()); 281 return Poll::Ready(());
286 } 282 }
@@ -371,6 +367,32 @@ impl<'d, T: Instance> Spim<'d, T> {
371 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> { 367 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
372 self.async_inner_from_ram(&mut [], data).await 368 self.async_inner_from_ram(&mut [], data).await
373 } 369 }
370
371 #[cfg(feature = "_nrf52832_anomaly_109")]
372 fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> {
373 let r = T::regs();
374 if r.events_started.read().bits() != 0 {
375 let s = T::state();
376
377 // Handle the first "fake" transmission
378 r.events_started.reset();
379 r.events_end.reset();
380
381 // Update DMA registers with correct rx/tx buffer sizes
382 r.rxd
383 .maxcnt
384 .write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) });
385 r.txd
386 .maxcnt
387 .write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) });
388
389 r.intenset.write(|w| w.end().set());
390 // ... and start actual, hopefully glitch-free transmission
391 r.tasks_start.write(|w| unsafe { w.bits(1) });
392 return Poll::Ready(());
393 }
394 Poll::Pending
395 }
374} 396}
375 397
376impl<'d, T: Instance> Drop for Spim<'d, T> { 398impl<'d, T: Instance> Drop for Spim<'d, T> {
@@ -395,7 +417,7 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
395} 417}
396 418
397pub(crate) mod sealed { 419pub(crate) mod sealed {
398 #[cfg(feature = "nrf52832")] 420 #[cfg(feature = "_nrf52832_anomaly_109")]
399 use core::sync::atomic::AtomicU8; 421 use core::sync::atomic::AtomicU8;
400 422
401 use embassy_sync::waitqueue::AtomicWaker; 423 use embassy_sync::waitqueue::AtomicWaker;
@@ -403,20 +425,20 @@ pub(crate) mod sealed {
403 use super::*; 425 use super::*;
404 426
405 pub struct State { 427 pub struct State {
406 pub end_waker: AtomicWaker, 428 pub waker: AtomicWaker,
407 #[cfg(feature = "nrf52832")] 429 #[cfg(feature = "_nrf52832_anomaly_109")]
408 pub rx: AtomicU8, 430 pub rx: AtomicU8,
409 #[cfg(feature = "nrf52832")] 431 #[cfg(feature = "_nrf52832_anomaly_109")]
410 pub tx: AtomicU8, 432 pub tx: AtomicU8,
411 } 433 }
412 434
413 impl State { 435 impl State {
414 pub const fn new() -> Self { 436 pub const fn new() -> Self {
415 Self { 437 Self {
416 end_waker: AtomicWaker::new(), 438 waker: AtomicWaker::new(),
417 #[cfg(feature = "nrf52832")] 439 #[cfg(feature = "_nrf52832_anomaly_109")]
418 rx: AtomicU8::new(0), 440 rx: AtomicU8::new(0),
419 #[cfg(feature = "nrf52832")] 441 #[cfg(feature = "_nrf52832_anomaly_109")]
420 tx: AtomicU8::new(0), 442 tx: AtomicU8::new(0),
421 } 443 }
422 } 444 }