aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Kröger <[email protected]>2021-01-03 12:09:51 +0100
committerTimo Kröger <[email protected]>2021-01-04 22:55:40 +0100
commit85ec9dd16fb5649900722228e46e9c68370901a6 (patch)
tree759856b65a30ae1f7451f358254147e49ff04286
parenta3b3305b8e9afbedde58e6c44c112335b25fa176 (diff)
uarte: Be on safe side with potentially racy code
The PS does not specify how many cycles it takes for a STARTXX task to generate a XXSTARTED event. I think it is instantaneous but let’s be on the safe side for the following sequence: 1. poll() starttx 2. drop() txstarted not yet set, but future gets dropped 3. txstarted set by hardware, peripheral enabled after it was dropped
-rw-r--r--embassy-nrf/src/uarte.rs55
1 files changed, 32 insertions, 23 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 80c31b671..156dbbefd 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -289,27 +289,31 @@ where
289 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 289 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
290 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; 290 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
291 291
292 match T::state().tx_done.poll_wait(cx) { 292 if T::state().tx_done.poll_wait(cx).is_pending() {
293 Poll::Pending if !uarte.tx_started() => { 293 let ptr = buf.as_ptr();
294 let uarte = &uarte.instance; 294 let len = buf.len();
295 let ptr = buf.as_ptr(); 295 assert!(len <= EASY_DMA_SIZE);
296 let len = buf.len(); 296 // TODO: panic if buffer is not in SRAM
297 assert!(len <= EASY_DMA_SIZE);
298 // TODO: panic if buffer is not in SRAM
299 297
300 compiler_fence(Ordering::SeqCst); 298 compiler_fence(Ordering::SeqCst);
301 uarte.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 299 uarte
302 uarte 300 .instance
303 .txd 301 .txd
304 .maxcnt 302 .ptr
305 .write(|w| unsafe { w.maxcnt().bits(len as _) }); 303 .write(|w| unsafe { w.ptr().bits(ptr as u32) });
304 uarte
305 .instance
306 .txd
307 .maxcnt
308 .write(|w| unsafe { w.maxcnt().bits(len as _) });
306 309
307 trace!("starttx"); 310 trace!("starttx");
308 uarte.tasks_starttx.write(|w| unsafe { w.bits(1) }); 311 uarte.instance.tasks_starttx.write(|w| unsafe { w.bits(1) });
309 Poll::Pending 312 while !uarte.tx_started() {} // Make sure transmission has started
310 } 313
311 Poll::Pending => Poll::Pending, 314 Poll::Pending
312 Poll::Ready(_) => Poll::Ready(Ok(())), 315 } else {
316 Poll::Ready(Ok(()))
313 } 317 }
314 } 318 }
315} 319}
@@ -352,21 +356,26 @@ where
352 356
353 match T::state().rx_done.poll_wait(cx) { 357 match T::state().rx_done.poll_wait(cx) {
354 Poll::Pending if !uarte.rx_started() => { 358 Poll::Pending if !uarte.rx_started() => {
355 let uarte = &uarte.instance;
356
357 let ptr = buf.as_ptr(); 359 let ptr = buf.as_ptr();
358 let len = buf.len(); 360 let len = buf.len();
359 assert!(len <= EASY_DMA_SIZE); 361 assert!(len <= EASY_DMA_SIZE);
360 362
361 compiler_fence(Ordering::SeqCst); 363 compiler_fence(Ordering::SeqCst);
362 uarte.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
363 uarte 364 uarte
365 .instance
366 .rxd
367 .ptr
368 .write(|w| unsafe { w.ptr().bits(ptr as u32) });
369 uarte
370 .instance
364 .rxd 371 .rxd
365 .maxcnt 372 .maxcnt
366 .write(|w| unsafe { w.maxcnt().bits(len as _) }); 373 .write(|w| unsafe { w.maxcnt().bits(len as _) });
367 374
368 trace!("startrx"); 375 trace!("startrx");
369 uarte.tasks_startrx.write(|w| unsafe { w.bits(1) }); 376 uarte.instance.tasks_startrx.write(|w| unsafe { w.bits(1) });
377 while !uarte.rx_started() {} // Make sure reception has started
378
370 Poll::Pending 379 Poll::Pending
371 } 380 }
372 Poll::Pending => Poll::Pending, 381 Poll::Pending => Poll::Pending,