Skip to content

Commit

Permalink
static DMA ctrl block placement
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Jul 2, 2024
1 parent 01341ed commit 16d2856
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
17 changes: 11 additions & 6 deletions examples/simple/examples/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ use va416xx_hal::{
prelude::*,
};

// Place the DMA control block in SRAM1
const DMA_CTRL_BLOCK_ADDR: u32 = 0x2000_0000;
static DMA_DONE_FLAG: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));
static DMA_ACTIVE_FLAG: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));

// Place the DMA control block into SRAM1 statically. This section needs to be defined in
// memory.x
#[link_section = ".sram1"]
static mut DMA_CTRL_BLOCK: DmaCtrlBlock = DmaCtrlBlock::new();

#[entry]
fn main() -> ! {
rtt_init_print!();
Expand All @@ -35,10 +38,12 @@ fn main() -> ! {
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.unwrap();
let dma_ctrl_block =
DmaCtrlBlock::new_at_addr(DMA_CTRL_BLOCK_ADDR).expect("error creating DMA control block");
let dma = Dma::new(&mut dp.sysconfig, dp.dma, DmaCfg::default(), dma_ctrl_block)
.expect("error creating DMA");
// Safety: The DMA control block has an alignment rule of 128 and we constructed it directly
// statically.
let dma = Dma::new(&mut dp.sysconfig, dp.dma, DmaCfg::default(), unsafe {
core::ptr::addr_of_mut!(DMA_CTRL_BLOCK)
})
.expect("error creating DMA");
let (mut dma0, _, _, _) = dma.split();
let mut delay_ms = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);
let mut src_buf_8_bit: [u8; 65] = [0; 65];
Expand Down
48 changes: 33 additions & 15 deletions va416xx-hal/src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,22 +118,42 @@ pub struct DmaChannelControl {
padding: u32,
}

impl Default for DmaChannelControl {
fn default() -> Self {
impl DmaChannelControl {
const fn new() -> Self {
Self {
src_end_ptr: Default::default(),
dest_end_ptr: Default::default(),
src_end_ptr: 0,
dest_end_ptr: 0,
cfg: ChannelConfig(0),
padding: Default::default(),
padding: 0,
}
}
}
impl Default for DmaChannelControl {
fn default() -> Self {
Self::new()
}
}
#[repr(C)]
#[repr(align(128))]
pub struct DmaCtrlBlock {
pub pri: [DmaChannelControl; 4],
pub alt: [DmaChannelControl; 4],
}

impl DmaCtrlBlock {
pub const fn new() -> Self {
Self {
pri: [DmaChannelControl::new(); 4],
alt: [DmaChannelControl::new(); 4],
}
}
}
impl Default for DmaCtrlBlock {
fn default() -> Self {
Self::new()
}
}

impl DmaCtrlBlock {
/// This function creates a DMA control block at the specified memory address.
///
Expand All @@ -145,15 +165,7 @@ impl DmaCtrlBlock {
return Err(InvalidCtrlBlockAddr);
}
let ctrl_block_ptr = addr as *mut DmaCtrlBlock;
unsafe {
core::ptr::write(
ctrl_block_ptr,
DmaCtrlBlock {
pri: [DmaChannelControl::default(); 4],
alt: [DmaChannelControl::default(); 4],
},
)
}
unsafe { core::ptr::write(ctrl_block_ptr, DmaCtrlBlock::default()) }
Ok(ctrl_block_ptr)
}
}
Expand Down Expand Up @@ -388,7 +400,13 @@ impl DmaChannel {
impl Dma {
/// Create a new DMA instance.
///
/// You can use [DmaCtrlBlock::new_at_addr] to create the DMA control block at a specific address.
/// You can also place the [DmaCtrlBlock] statically using a global static mutable
/// instance and the [DmaCtrlBlock::new] const constructor This also allows to place the control
/// block in a memory section using the [link_section](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
/// attribute and then creating a mutable pointer to it using [core::ptr::addr_of_mut].
///
/// Alternatively, the [DmaCtrlBlock::new_at_addr] function can be used to create the DMA
/// control block at a specific address.
pub fn new(
syscfg: &mut pac::Sysconfig,
dma: pac::Dma,
Expand Down

0 comments on commit 16d2856

Please sign in to comment.