stm32/gpdma: fix race condition when resetting channel when done.
This commit is contained in:
parent
dee8c71a2d
commit
44b7fe45e2
1 changed files with 9 additions and 2 deletions
|
@ -190,6 +190,10 @@ mod low_level_api {
|
||||||
fence(Ordering::SeqCst);
|
fence(Ordering::SeqCst);
|
||||||
|
|
||||||
let ch = dma.ch(channel_number as _);
|
let ch = dma.ch(channel_number as _);
|
||||||
|
|
||||||
|
// Reset ch
|
||||||
|
ch.cr().write(|w| w.set_reset(true));
|
||||||
|
|
||||||
ch.llr().write(|_| {}); // no linked list
|
ch.llr().write(|_| {}); // no linked list
|
||||||
ch.tr1().write(|w| {
|
ch.tr1().write(|w| {
|
||||||
w.set_sdw(data_size.into());
|
w.set_sdw(data_size.into());
|
||||||
|
@ -252,7 +256,7 @@ mod low_level_api {
|
||||||
/// Gets the running status of the channel
|
/// Gets the running status of the channel
|
||||||
pub unsafe fn is_running(dma: Gpdma, ch: u8) -> bool {
|
pub unsafe fn is_running(dma: Gpdma, ch: u8) -> bool {
|
||||||
let ch = dma.ch(ch as _);
|
let ch = dma.ch(ch as _);
|
||||||
!ch.sr().read().idlef()
|
!ch.sr().read().tcf()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the total remaining transfers for the channel
|
/// Gets the total remaining transfers for the channel
|
||||||
|
@ -291,7 +295,10 @@ mod low_level_api {
|
||||||
}
|
}
|
||||||
|
|
||||||
if sr.suspf() || sr.tcf() {
|
if sr.suspf() || sr.tcf() {
|
||||||
ch.cr().write(|w| w.set_reset(true));
|
// disable all xxIEs to prevent the irq from firing again.
|
||||||
|
ch.cr().write(|_| {});
|
||||||
|
|
||||||
|
// Wake the future. It'll look at tcf and see it's set.
|
||||||
STATE.channels[state_index].waker.wake();
|
STATE.channels[state_index].waker.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue