mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 06:40:47 +00:00

* esp-wifi uses global allocator, esp-alloc supports multiple regions * CHANGELOG.md * Apply suggestions * Use `alloc` when linting esp-wifi * Make coex example build for ESP32 * Re-enable some wifi examples for ESP32-S2 * Optionally depend on `esp-alloc` (by default) * Rename INSTANCE -> HEAP
154 lines
4.6 KiB
Rust
154 lines
4.6 KiB
Rust
//! Uses DMA to copy psram to internal memory.
|
|
|
|
//% FEATURES: esp-hal/log opsram-2m aligned
|
|
//% CHIPS: esp32s3
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
use aligned::{Aligned, A64};
|
|
use esp_alloc as _;
|
|
use esp_backtrace as _;
|
|
use esp_hal::{
|
|
delay::Delay,
|
|
dma::{Dma, DmaPriority, Mem2Mem},
|
|
dma_descriptors_chunk_size,
|
|
prelude::*,
|
|
};
|
|
use log::{error, info};
|
|
extern crate alloc;
|
|
|
|
const DATA_SIZE: usize = 1024 * 10;
|
|
const CHUNK_SIZE: usize = 4032; // size is aligned to 64 bytes
|
|
|
|
macro_rules! dma_buffer_aligned {
|
|
($size:expr, $align:ty) => {{
|
|
static mut BUFFER: Aligned<$align, [u8; $size]> = Aligned([0; $size]);
|
|
unsafe { &mut *BUFFER }
|
|
}};
|
|
}
|
|
|
|
macro_rules! dma_alloc_buffer {
|
|
($size:expr, $align:expr) => {{
|
|
let layout = core::alloc::Layout::from_size_align($size, $align).unwrap();
|
|
unsafe {
|
|
let ptr = alloc::alloc::alloc(layout);
|
|
if ptr.is_null() {
|
|
error!("make_buffers: alloc failed");
|
|
alloc::alloc::handle_alloc_error(layout);
|
|
}
|
|
core::slice::from_raw_parts_mut(ptr, $size)
|
|
}
|
|
}};
|
|
}
|
|
|
|
fn init_heap(psram: impl esp_hal::peripheral::Peripheral<P = esp_hal::peripherals::PSRAM>) {
|
|
esp_hal::psram::init_psram(psram);
|
|
info!(
|
|
"init_heap: start: 0x{:0x}",
|
|
esp_hal::psram::psram_vaddr_start()
|
|
);
|
|
unsafe {
|
|
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
|
|
esp_hal::psram::psram_vaddr_start() as *mut u8,
|
|
esp_hal::psram::PSRAM_BYTES,
|
|
esp_alloc::MemoryCapability::External.into(),
|
|
));
|
|
}
|
|
}
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
esp_println::logger::init_logger(log::LevelFilter::Info);
|
|
|
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
|
|
|
init_heap(peripherals.PSRAM);
|
|
let delay = Delay::new();
|
|
|
|
let mut extram_buffer: &mut [u8] = dma_alloc_buffer!(DATA_SIZE, 64);
|
|
let mut intram_buffer = dma_buffer_aligned!(DATA_SIZE, A64);
|
|
let (rx_descriptors, tx_descriptors) = dma_descriptors_chunk_size!(DATA_SIZE, CHUNK_SIZE);
|
|
|
|
let dma = Dma::new(peripherals.DMA);
|
|
let channel = dma.channel0.configure(false, DmaPriority::Priority0);
|
|
let dma_peripheral = peripherals.SPI2;
|
|
|
|
let mut mem2mem = Mem2Mem::new_with_chunk_size(
|
|
channel,
|
|
dma_peripheral,
|
|
rx_descriptors,
|
|
tx_descriptors,
|
|
CHUNK_SIZE,
|
|
)
|
|
.unwrap();
|
|
|
|
for i in 0..core::mem::size_of_val(extram_buffer) {
|
|
extram_buffer[i] = (i % 256) as u8;
|
|
intram_buffer[i] = 255 - extram_buffer[i];
|
|
}
|
|
|
|
info!(" ext2int: Starting transfer of {} bytes", DATA_SIZE);
|
|
match mem2mem.start_transfer(&mut intram_buffer, &extram_buffer) {
|
|
Ok(dma_wait) => {
|
|
info!("Transfer started");
|
|
dma_wait.wait().unwrap();
|
|
info!("Transfer completed, comparing buffer");
|
|
let mut error = false;
|
|
for i in 0..core::mem::size_of_val(extram_buffer) {
|
|
if intram_buffer[i] != extram_buffer[i] {
|
|
error!(
|
|
"Error: extram_buffer[{}] = {}, intram_buffer[{}] = {}",
|
|
i, extram_buffer[i], i, intram_buffer[i]
|
|
);
|
|
error = true;
|
|
break;
|
|
}
|
|
}
|
|
if !error {
|
|
info!("Buffers are equal");
|
|
}
|
|
info!("Done");
|
|
}
|
|
Err(e) => {
|
|
error!("start_transfer: Error: {:?}", e);
|
|
}
|
|
}
|
|
|
|
for i in 0..core::mem::size_of_val(extram_buffer) {
|
|
intram_buffer[i] = (i % 256) as u8;
|
|
extram_buffer[i] = 255 - intram_buffer[i];
|
|
}
|
|
|
|
info!(" int2ext: Starting transfer of {} bytes", DATA_SIZE);
|
|
match mem2mem.start_transfer(&mut extram_buffer, &intram_buffer) {
|
|
Ok(dma_wait) => {
|
|
info!("Transfer started");
|
|
dma_wait.wait().unwrap();
|
|
info!("Transfer completed, comparing buffer");
|
|
let mut error = false;
|
|
for i in 0..core::mem::size_of_val(extram_buffer) {
|
|
if intram_buffer[i] != extram_buffer[i] {
|
|
error!(
|
|
"Error: extram_buffer[{}] = {}, intram_buffer[{}] = {}",
|
|
i, extram_buffer[i], i, intram_buffer[i]
|
|
);
|
|
error = true;
|
|
break;
|
|
}
|
|
}
|
|
if !error {
|
|
info!("Buffers are equal");
|
|
}
|
|
info!("Done");
|
|
}
|
|
Err(e) => {
|
|
error!("start_transfer: Error: {:?}", e);
|
|
}
|
|
}
|
|
|
|
loop {
|
|
delay.delay(2.secs());
|
|
}
|
|
}
|