From 16d2856fb2a054b00947dc87701e8a5b7442d002 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 3 Jul 2024 00:01:33 +0200 Subject: [PATCH] static DMA ctrl block placement --- examples/simple/examples/dma.rs | 17 +++++++----- va416xx-hal/src/dma.rs | 48 ++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/examples/simple/examples/dma.rs b/examples/simple/examples/dma.rs index f437f08..de4d87f 100644 --- a/examples/simple/examples/dma.rs +++ b/examples/simple/examples/dma.rs @@ -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> = Mutex::new(Cell::new(false)); static DMA_ACTIVE_FLAG: Mutex> = 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!(); @@ -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]; diff --git a/va416xx-hal/src/dma.rs b/va416xx-hal/src/dma.rs index 62cdd9d..2a295f9 100644 --- a/va416xx-hal/src/dma.rs +++ b/va416xx-hal/src/dma.rs @@ -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. /// @@ -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) } } @@ -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,