Merge pull request #304 from bobmcwhirter/async_move_dma_transfer

The `async move` portion of @thalesfragoso's i2c PR.
This commit is contained in:
Thales 2021-07-20 13:07:28 -03:00 committed by GitHub
commit cec2654854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 28 deletions

View File

@ -38,7 +38,7 @@ impl State {
static STATE: State = State::new(); static STATE: State = State::new();
#[allow(unused)] #[allow(unused)]
pub(crate) async unsafe fn do_transfer( pub(crate) unsafe fn do_transfer(
dma: pac::bdma::Dma, dma: pac::bdma::Dma,
channel_number: u8, channel_number: u8,
state_number: u8, state_number: u8,
@ -49,7 +49,7 @@ pub(crate) async unsafe fn do_transfer(
mem_len: usize, mem_len: usize,
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
#[cfg(dmamux)] dmamux_ch_num: u8, #[cfg(dmamux)] dmamux_ch_num: u8,
) { ) -> impl Future<Output = ()> {
// ndtr is max 16 bits. // ndtr is max 16 bits.
assert!(mem_len <= 0xFFFF); assert!(mem_len <= 0xFFFF);
@ -59,7 +59,7 @@ pub(crate) async unsafe fn do_transfer(
// Generate a DMB here to flush the store buffer (M7) before enabling the DMA // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
STATE.ch_status[state_number as usize].store(CH_STATUS_NONE, Ordering::Release); STATE.ch_status[state_number as usize].store(CH_STATUS_NONE, Ordering::Release);
let on_drop = OnDrop::new(|| unsafe { let on_drop = OnDrop::new(move || unsafe {
ch.cr().modify(|w| { ch.cr().modify(|w| {
w.set_tcie(false); w.set_tcie(false);
w.set_teie(false); w.set_teie(false);
@ -95,17 +95,20 @@ pub(crate) async unsafe fn do_transfer(
w.set_en(true); w.set_en(true);
}); });
let res = poll_fn(|cx| { async move {
STATE.ch_wakers[state_number as usize].register(cx.waker()); let res = poll_fn(|cx| {
match STATE.ch_status[state_number as usize].load(Ordering::Acquire) { STATE.ch_wakers[state_number as usize].register(cx.waker());
CH_STATUS_NONE => Poll::Pending, match STATE.ch_status[state_number as usize].load(Ordering::Acquire) {
x => Poll::Ready(x), CH_STATUS_NONE => Poll::Pending,
} x => Poll::Ready(x),
}) }
.await; })
.await;
// TODO handle error // TODO handle error
assert!(res == CH_STATUS_COMPLETED); assert!(res == CH_STATUS_COMPLETED);
drop(on_drop)
}
} }
macro_rules! dma_num { macro_rules! dma_num {

View File

@ -1,7 +1,7 @@
use core::future::Future;
use core::task::Poll; use core::task::Poll;
use atomic_polyfill::{AtomicU8, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};
use core::future::Future;
use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::interrupt::{Interrupt, InterruptExt};
use embassy::util::{AtomicWaker, OnDrop}; use embassy::util::{AtomicWaker, OnDrop};
use futures::future::poll_fn; use futures::future::poll_fn;
@ -39,7 +39,7 @@ static STATE: State = State::new();
//async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) { //async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) {
#[allow(unused)] #[allow(unused)]
pub(crate) async unsafe fn do_transfer( pub(crate) unsafe fn do_transfer(
dma: pac::dma::Dma, dma: pac::dma::Dma,
channel_number: u8, channel_number: u8,
state_number: u8, state_number: u8,
@ -50,7 +50,7 @@ pub(crate) async unsafe fn do_transfer(
mem_len: usize, mem_len: usize,
#[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
#[cfg(dmamux)] dmamux_ch_num: u8, #[cfg(dmamux)] dmamux_ch_num: u8,
) { ) -> impl Future<Output = ()> {
// ndtr is max 16 bits. // ndtr is max 16 bits.
assert!(mem_len <= 0xFFFF); assert!(mem_len <= 0xFFFF);
@ -60,7 +60,7 @@ pub(crate) async unsafe fn do_transfer(
let ch = dma.st(channel_number as _); let ch = dma.st(channel_number as _);
let on_drop = OnDrop::new(|| unsafe { let on_drop = OnDrop::new(move || unsafe {
ch.cr().modify(|w| { ch.cr().modify(|w| {
w.set_tcie(false); w.set_tcie(false);
w.set_teie(false); w.set_teie(false);
@ -100,18 +100,21 @@ pub(crate) async unsafe fn do_transfer(
}); });
} }
let res = poll_fn(|cx| { async move {
let n = channel_number as usize; let res = poll_fn(|cx| {
STATE.ch_wakers[n].register(cx.waker()); let n = channel_number as usize;
match STATE.ch_status[n].load(Ordering::Acquire) { STATE.ch_wakers[n].register(cx.waker());
CH_STATUS_NONE => Poll::Pending, match STATE.ch_status[n].load(Ordering::Acquire) {
x => Poll::Ready(x), CH_STATUS_NONE => Poll::Pending,
} x => Poll::Ready(x),
}) }
.await; })
.await;
// TODO handle error // TODO handle error
assert!(res == CH_STATUS_COMPLETED); assert!(res == CH_STATUS_COMPLETED);
drop(on_drop)
}
} }
macro_rules! dma_num { macro_rules! dma_num {