#![allow(clippy::transmute_ptr_to_ptr)]
#![deny(warnings)]
#![no_main]
#![no_std]
use core::{mem, mem::MaybeUninit};
use cortex_m_rt::entry;
#[macro_use]
mod utilities;
use stm32h7xx_hal::{pac, prelude::*};
use stm32h7xx_hal::dma::{
mdma::{MdmaConfig, MdmaIncrement, MdmaSize, StreamsTuple},
traits::Direction,
MemoryToMemory, Transfer,
};
use log::info;
#[link_section = ".axisram.buffers"]
static mut SOURCE_BUFFER: MaybeUninit<[u32; 200]> = MaybeUninit::uninit();
#[entry]
fn main() -> ! {
utilities::logger::init();
let dp = pac::Peripherals::take().unwrap();
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = example_power!(pwr).freeze();
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc
.sys_ck(100.MHz())
.hclk(50.MHz())
.freeze(pwrcfg, &dp.SYSCFG);
info!("");
info!("stm32h7xx-hal example - Memory to TCM with Master DMA");
info!("");
let source_buffer: &'static mut [u32; 200] = {
let buf: &mut [MaybeUninit<u32>; 200] =
unsafe { mem::transmute(&mut SOURCE_BUFFER) };
for value in buf.iter_mut() {
unsafe {
value.as_mut_ptr().write(0x11223344u32);
}
}
unsafe { mem::transmute(buf) }
};
let mut target_buffer: [u32; 200] = [0; 200];
let streams = StreamsTuple::new(dp.MDMA, ccdr.peripheral.MDMA);
let config = MdmaConfig::default()
.destination_increment(MdmaIncrement::Increment)
.source_increment(MdmaIncrement::Increment);
let mut transfer: Transfer<_, _, MemoryToMemory<u32>, _, _> = {
let target: &'static mut [u32; 200] =
unsafe { mem::transmute(&mut target_buffer) };
Transfer::init_master(
streams.0,
MemoryToMemory::new(),
target, Some(source_buffer), config,
)
};
assert_eq!(transfer.get_block_length(), 800);
assert_eq!(transfer.get_buffer_length(), 128);
transfer.start(|_| {});
while !transfer.get_transfer_complete_flag() {}
let (stream, _mem2mem, _target, source_buffer_opt) = transfer.free();
let source_buffer = source_buffer_opt.unwrap();
for a in target_buffer.iter() {
assert_eq!(*a, 0x11223344);
}
info!("Example 1: Memory to TCM DMA completed successfully");
*source_buffer = [0xAABBCCDD; 200];
let mut target_buffer: [u32; 20] = [0; 20];
let config = MdmaConfig::default()
.source_increment(MdmaIncrement::Increment)
.destination_increment(MdmaIncrement::IncrementWithOffset(
MdmaSize::DoubleWord,
))
.half_word_endianness_exchange(true);
let mut transfer: Transfer<_, _, MemoryToMemory<u32>, _, _> = {
let target: &'static mut [u32; 20] =
unsafe { mem::transmute(&mut target_buffer) };
Transfer::init_master(
stream,
MemoryToMemory::new(),
&mut target[..], Some(&mut source_buffer[..]), config,
)
};
assert_eq!(transfer.get_block_length(), 40);
transfer.start(|_| {});
while !transfer.get_transfer_complete_flag() {}
assert_eq!(
target_buffer,
[
0xCCDDAABB, 0, 0xCCDDAABB, 0, 0xCCDDAABB, 0, 0xCCDDAABB, 0,
0xCCDDAABB, 0, 0xCCDDAABB, 0, 0xCCDDAABB, 0, 0xCCDDAABB, 0,
0xCCDDAABB, 0, 0xCCDDAABB, 0,
]
);
info!(
"Example 2: Memory to TCM DMA with endianess and offset completed successfully"
);
let mut source_buffer_tcm = [1u8, 2];
let source_buffer: &'static mut [u8] =
unsafe { mem::transmute(&mut source_buffer_tcm[..]) };
let mut target_buffer = [0u8; 17];
let config = MdmaConfig::default().destination_increment(
MdmaIncrement::IncrementWithOffset(MdmaSize::DoubleWord),
);
let mut transfer: Transfer<_, _, MemoryToMemory<u8>, _, _> = {
Transfer::init_master(
streams.1,
MemoryToMemory::new(),
unsafe { mem::transmute(&mut target_buffer[..]) }, Some(source_buffer), config,
)
};
transfer.start(|_| {});
while !transfer.get_transfer_complete_flag() {}
assert_eq!(transfer.get_block_length(), 0);
assert_eq!(source_buffer_tcm, [1, 2]);
assert_eq!(
target_buffer,
[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]
);
info!("Example 3: TCM to TCM DMA with offset completed successfully");
loop {
cortex_m::asm::nop()
}
}