static DMA ctrl block placement
All checks were successful
Rust/va416xx-rs/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2024-07-03 00:01:33 +02:00
parent 01341edc91
commit 16d2856fb2
Signed by: muellerr
GPG Key ID: A649FB78196E3849
2 changed files with 44 additions and 21 deletions

View File

@ -17,11 +17,14 @@ use va416xx_hal::{
prelude::*, 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_DONE_FLAG: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));
static DMA_ACTIVE_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] #[entry]
fn main() -> ! { fn main() -> ! {
rtt_init_print!(); rtt_init_print!();
@ -35,9 +38,11 @@ fn main() -> ! {
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ) .xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig) .freeze(&mut dp.sysconfig)
.unwrap(); .unwrap();
let dma_ctrl_block = // Safety: The DMA control block has an alignment rule of 128 and we constructed it directly
DmaCtrlBlock::new_at_addr(DMA_CTRL_BLOCK_ADDR).expect("error creating DMA control block"); // statically.
let dma = Dma::new(&mut dp.sysconfig, dp.dma, DmaCfg::default(), dma_ctrl_block) let dma = Dma::new(&mut dp.sysconfig, dp.dma, DmaCfg::default(), unsafe {
core::ptr::addr_of_mut!(DMA_CTRL_BLOCK)
})
.expect("error creating DMA"); .expect("error creating DMA");
let (mut dma0, _, _, _) = dma.split(); let (mut dma0, _, _, _) = dma.split();
let mut delay_ms = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks); let mut delay_ms = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);

View File

@ -118,22 +118,42 @@ pub struct DmaChannelControl {
padding: u32, padding: u32,
} }
impl DmaChannelControl {
const fn new() -> Self {
Self {
src_end_ptr: 0,
dest_end_ptr: 0,
cfg: ChannelConfig(0),
padding: 0,
}
}
}
impl Default for DmaChannelControl { impl Default for DmaChannelControl {
fn default() -> Self { fn default() -> Self {
Self { Self::new()
src_end_ptr: Default::default(),
dest_end_ptr: Default::default(),
cfg: ChannelConfig(0),
padding: Default::default(),
}
} }
} }
#[repr(C)] #[repr(C)]
#[repr(align(128))]
pub struct DmaCtrlBlock { pub struct DmaCtrlBlock {
pub pri: [DmaChannelControl; 4], pub pri: [DmaChannelControl; 4],
pub alt: [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 { impl DmaCtrlBlock {
/// This function creates a DMA control block at the specified memory address. /// This function creates a DMA control block at the specified memory address.
/// ///
@ -145,15 +165,7 @@ impl DmaCtrlBlock {
return Err(InvalidCtrlBlockAddr); return Err(InvalidCtrlBlockAddr);
} }
let ctrl_block_ptr = addr as *mut DmaCtrlBlock; let ctrl_block_ptr = addr as *mut DmaCtrlBlock;
unsafe { unsafe { core::ptr::write(ctrl_block_ptr, DmaCtrlBlock::default()) }
core::ptr::write(
ctrl_block_ptr,
DmaCtrlBlock {
pri: [DmaChannelControl::default(); 4],
alt: [DmaChannelControl::default(); 4],
},
)
}
Ok(ctrl_block_ptr) Ok(ctrl_block_ptr)
} }
} }
@ -388,7 +400,13 @@ impl DmaChannel {
impl Dma { impl Dma {
/// Create a new DMA instance. /// 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( pub fn new(
syscfg: &mut pac::Sysconfig, syscfg: &mut pac::Sysconfig,
dma: pac::Dma, dma: pac::Dma,