Add more options to DMA
This commit is contained in:
parent
2d224cf6a0
commit
34b5175d2c
@ -9,7 +9,7 @@ use crate::interrupt;
|
|||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::dma::{regs, vals};
|
use crate::pac::dma::{regs, vals};
|
||||||
|
|
||||||
use super::{Request, Word, WordSize};
|
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||||
|
|
||||||
impl From<WordSize> for vals::Size {
|
impl From<WordSize> for vals::Size {
|
||||||
fn from(raw: WordSize) -> Self {
|
fn from(raw: WordSize) -> Self {
|
||||||
@ -21,6 +21,26 @@ impl From<WordSize> for vals::Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Burst> for vals::Burst {
|
||||||
|
fn from(burst: Burst) -> Self {
|
||||||
|
match burst {
|
||||||
|
Burst::Single => vals::Burst::SINGLE,
|
||||||
|
Burst::Incr4 => vals::Burst::INCR4,
|
||||||
|
Burst::Incr8 => vals::Burst::INCR8,
|
||||||
|
Burst::Incr16 => vals::Burst::INCR16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FlowControl> for vals::Pfctrl {
|
||||||
|
fn from(flow: FlowControl) -> Self {
|
||||||
|
match flow {
|
||||||
|
FlowControl::Dma => vals::Pfctrl::DMA,
|
||||||
|
FlowControl::Peripheral => vals::Pfctrl::PERIPHERAL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT],
|
ch_wakers: [AtomicWaker; DMA_CHANNEL_COUNT],
|
||||||
}
|
}
|
||||||
@ -49,7 +69,7 @@ pub(crate) unsafe fn init() {
|
|||||||
foreach_dma_channel! {
|
foreach_dma_channel! {
|
||||||
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||||
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W) {
|
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
let (ptr, len) = super::slice_ptr_parts(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -61,6 +81,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -68,7 +89,7 @@ foreach_dma_channel! {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) {
|
unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W, options: TransferOptions) {
|
||||||
let buf = [repeated];
|
let buf = [repeated];
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -80,6 +101,7 @@ foreach_dma_channel! {
|
|||||||
count,
|
count,
|
||||||
false,
|
false,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -87,7 +109,7 @@ foreach_dma_channel! {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W]) {
|
unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *const W, buf: *mut [W], options: TransferOptions) {
|
||||||
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
let (ptr, len) = super::slice_ptr_parts_mut(buf);
|
||||||
low_level_api::start_transfer(
|
low_level_api::start_transfer(
|
||||||
pac::$dma_peri,
|
pac::$dma_peri,
|
||||||
@ -99,6 +121,7 @@ foreach_dma_channel! {
|
|||||||
len,
|
len,
|
||||||
true,
|
true,
|
||||||
vals::Size::from(W::bits()),
|
vals::Size::from(W::bits()),
|
||||||
|
options,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
<Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS,
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
@ -146,6 +169,7 @@ mod low_level_api {
|
|||||||
mem_len: usize,
|
mem_len: usize,
|
||||||
incr_mem: bool,
|
incr_mem: bool,
|
||||||
data_size: vals::Size,
|
data_size: vals::Size,
|
||||||
|
options: TransferOptions,
|
||||||
#[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,
|
||||||
) {
|
) {
|
||||||
@ -180,6 +204,10 @@ mod low_level_api {
|
|||||||
#[cfg(dma_v2)]
|
#[cfg(dma_v2)]
|
||||||
w.set_chsel(request);
|
w.set_chsel(request);
|
||||||
|
|
||||||
|
w.set_pburst(options.pburst.into());
|
||||||
|
w.set_mburst(options.mburst.into());
|
||||||
|
w.set_pfctrl(options.flow_ctrl.into());
|
||||||
|
|
||||||
w.set_en(true);
|
w.set_en(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ pub(crate) mod sealed {
|
|||||||
request: Request,
|
request: Request,
|
||||||
buf: *const [W],
|
buf: *const [W],
|
||||||
reg_addr: *mut W,
|
reg_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Starts this channel for writing a word repeatedly.
|
/// Starts this channel for writing a word repeatedly.
|
||||||
@ -58,6 +59,7 @@ pub(crate) mod sealed {
|
|||||||
repeated: W,
|
repeated: W,
|
||||||
count: usize,
|
count: usize,
|
||||||
reg_addr: *mut W,
|
reg_addr: *mut W,
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Starts this channel for reading a stream of words.
|
/// Starts this channel for reading a stream of words.
|
||||||
@ -71,6 +73,7 @@ pub(crate) mod sealed {
|
|||||||
request: Request,
|
request: Request,
|
||||||
reg_addr: *const W,
|
reg_addr: *const W,
|
||||||
buf: *mut [W],
|
buf: *mut [W],
|
||||||
|
options: TransferOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Requests the channel to stop.
|
/// Requests the channel to stop.
|
||||||
@ -126,6 +129,43 @@ impl Word for u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Burst {
|
||||||
|
/// Single transfer
|
||||||
|
Single,
|
||||||
|
/// Incremental burst of 4 beats
|
||||||
|
Incr4,
|
||||||
|
/// Incremental burst of 8 beats
|
||||||
|
Incr8,
|
||||||
|
/// Incremental burst of 16 beats
|
||||||
|
Incr16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FlowControl {
|
||||||
|
/// Flow control by DMA
|
||||||
|
Dma,
|
||||||
|
/// Flow control by peripheral
|
||||||
|
Peripheral,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TransferOptions {
|
||||||
|
/// Peripheral burst transfer configuration
|
||||||
|
pub pburst: Burst,
|
||||||
|
/// Memory burst transfer configuration
|
||||||
|
pub mburst: Burst,
|
||||||
|
/// Flow control configuration
|
||||||
|
pub flow_ctrl: FlowControl,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TransferOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pburst: Burst::Single,
|
||||||
|
mburst: Burst::Single,
|
||||||
|
flow_ctrl: FlowControl::Dma,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod transfers {
|
mod transfers {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -139,7 +179,7 @@ mod transfers {
|
|||||||
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_read::<W>(request, reg_addr, buf) };
|
unsafe { channel.start_read::<W>(request, reg_addr, buf, Default::default()) };
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
@ -154,7 +194,7 @@ mod transfers {
|
|||||||
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
assert!(buf.len() > 0 && buf.len() <= 0xFFFF);
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_write::<W>(request, buf, reg_addr) };
|
unsafe { channel.start_write::<W>(request, buf, reg_addr, Default::default()) };
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
@ -169,7 +209,15 @@ mod transfers {
|
|||||||
) -> impl Future<Output = ()> + 'a {
|
) -> impl Future<Output = ()> + 'a {
|
||||||
unborrow!(channel);
|
unborrow!(channel);
|
||||||
|
|
||||||
unsafe { channel.start_write_repeated::<W>(request, repeated, count, reg_addr) };
|
unsafe {
|
||||||
|
channel.start_write_repeated::<W>(
|
||||||
|
request,
|
||||||
|
repeated,
|
||||||
|
count,
|
||||||
|
reg_addr,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
Transfer::new(channel)
|
Transfer::new(channel)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user