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
This commit is contained in:
parent
a3b3305b8e
commit
85ec9dd16f
@ -289,27 +289,31 @@ where
|
|||||||
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
|
||||||
|
|
||||||
match T::state().tx_done.poll_wait(cx) {
|
if T::state().tx_done.poll_wait(cx).is_pending() {
|
||||||
Poll::Pending if !uarte.tx_started() => {
|
let ptr = buf.as_ptr();
|
||||||
let uarte = &uarte.instance;
|
let len = buf.len();
|
||||||
let ptr = buf.as_ptr();
|
assert!(len <= EASY_DMA_SIZE);
|
||||||
let len = buf.len();
|
// TODO: panic if buffer is not in SRAM
|
||||||
assert!(len <= EASY_DMA_SIZE);
|
|
||||||
// TODO: panic if buffer is not in SRAM
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
uarte.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
|
uarte
|
||||||
uarte
|
.instance
|
||||||
.txd
|
.txd
|
||||||
.maxcnt
|
.ptr
|
||||||
.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
.write(|w| unsafe { w.ptr().bits(ptr as u32) });
|
||||||
|
uarte
|
||||||
|
.instance
|
||||||
|
.txd
|
||||||
|
.maxcnt
|
||||||
|
.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
||||||
|
|
||||||
trace!("starttx");
|
trace!("starttx");
|
||||||
uarte.tasks_starttx.write(|w| unsafe { w.bits(1) });
|
uarte.instance.tasks_starttx.write(|w| unsafe { w.bits(1) });
|
||||||
Poll::Pending
|
while !uarte.tx_started() {} // Make sure transmission has started
|
||||||
}
|
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending
|
||||||
Poll::Ready(_) => Poll::Ready(Ok(())),
|
} else {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,21 +356,26 @@ where
|
|||||||
|
|
||||||
match T::state().rx_done.poll_wait(cx) {
|
match T::state().rx_done.poll_wait(cx) {
|
||||||
Poll::Pending if !uarte.rx_started() => {
|
Poll::Pending if !uarte.rx_started() => {
|
||||||
let uarte = &uarte.instance;
|
|
||||||
|
|
||||||
let ptr = buf.as_ptr();
|
let ptr = buf.as_ptr();
|
||||||
let len = buf.len();
|
let len = buf.len();
|
||||||
assert!(len <= EASY_DMA_SIZE);
|
assert!(len <= EASY_DMA_SIZE);
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
uarte.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
|
|
||||||
uarte
|
uarte
|
||||||
|
.instance
|
||||||
|
.rxd
|
||||||
|
.ptr
|
||||||
|
.write(|w| unsafe { w.ptr().bits(ptr as u32) });
|
||||||
|
uarte
|
||||||
|
.instance
|
||||||
.rxd
|
.rxd
|
||||||
.maxcnt
|
.maxcnt
|
||||||
.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
||||||
|
|
||||||
trace!("startrx");
|
trace!("startrx");
|
||||||
uarte.tasks_startrx.write(|w| unsafe { w.bits(1) });
|
uarte.instance.tasks_startrx.write(|w| unsafe { w.bits(1) });
|
||||||
|
while !uarte.rx_started() {} // Make sure reception has started
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
|
Loading…
Reference in New Issue
Block a user