diff options
| author | Timo Kröger <[email protected]> | 2021-01-03 12:09:51 +0100 |
|---|---|---|
| committer | Timo Kröger <[email protected]> | 2021-01-04 22:55:40 +0100 |
| commit | 85ec9dd16fb5649900722228e46e9c68370901a6 (patch) | |
| tree | 759856b65a30ae1f7451f358254147e49ff04286 | |
| parent | a3b3305b8e9afbedde58e6c44c112335b25fa176 (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.rs | 55 |
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, |
