1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
//! DMA memory-to-memory transfer example for MCXA276.
//!
//! This example demonstrates using DMA to copy data between memory buffers
//! using the Embassy-style async API with type-safe transfers.
//!
//! # Embassy-style features demonstrated:
//! - `TransferOptions` for configuration
//! - Type-safe `mem_to_mem<u32>()` method with async `.await`
//! - `Transfer` Future that can be `.await`ed
//! - `Word` trait for automatic transfer width detection
//! - `memset()` method for filling memory with a pattern
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_mcxa::clocks::config::Div8;
use embassy_mcxa::dma::{DmaChannel, TransferOptions};
use static_cell::ConstStaticCell;
use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
const BUFFER_LENGTH: usize = 4;
// Buffers in RAM (static mut is automatically placed in .bss/.data)
static SRC_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([1, 2, 3, 4]);
static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
static MEMSET_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
// Small delay to allow probe-rs to attach after reset
for _ in 0..100_000 {
cortex_m::asm::nop();
}
let mut cfg = hal::config::Config::default();
cfg.clock_cfg.sirc.fro_12m_enabled = true;
cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
let p = hal::init(cfg);
defmt::info!("DMA memory-to-memory example starting...");
defmt::info!("EDMA memory to memory example begin.");
let src = SRC_BUFFER.take();
let dst = DEST_BUFFER.take();
let mst = MEMSET_BUFFER.take();
defmt::info!("Source Buffer: {=[?]}", src.as_slice());
defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
defmt::info!("Configuring DMA with Embassy-style API...");
// Create DMA channel
let dma_ch0 = DmaChannel::new(p.DMA_CH0);
// Configure transfer options (Embassy-style)
// TransferOptions defaults to: complete_transfer_interrupt = true
let options = TransferOptions::default();
// =========================================================================
// Part 1: Embassy-style async API demonstration (mem_to_mem)
// =========================================================================
//
// Use the new type-safe `mem_to_mem<u32>()` method:
// - Automatically determines transfer width from buffer element type (u32)
// - Returns a `Transfer` future that can be `.await`ed
// - Uses TransferOptions for consistent configuration
//
// Using async `.await` - the executor can run other tasks while waiting!
// Perform type-safe memory-to-memory transfer using Embassy-style async API
// Using async `.await` - the executor can run other tasks while waiting!
let transfer = dma_ch0.mem_to_mem(src, dst, options).unwrap();
transfer.await.unwrap();
defmt::info!("DMA mem-to-mem transfer complete!");
defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
// Verify data
if src != dst {
defmt::error!("FAIL: mem_to_mem mismatch!");
} else {
defmt::info!("PASS: mem_to_mem verified.");
}
// =========================================================================
// Part 2: memset() demonstration
// =========================================================================
//
// The `memset()` method fills a buffer with a pattern value:
// - Fixed source address (pattern is read repeatedly)
// - Incrementing destination address
// - Uses the same Transfer future pattern
defmt::info!("--- Demonstrating memset() feature ---");
defmt::info!("Memset Buffer (before): {=[?]}", mst.as_slice());
// Fill buffer with a pattern value using DMA memset
let pattern: u32 = 0xDEADBEEF;
defmt::info!("Filling with pattern 0xDEADBEEF...");
// Using blocking_wait() for demonstration - also shows non-async usage
let transfer = dma_ch0.memset(&pattern, mst, options);
transfer.blocking_wait();
defmt::info!("DMA memset complete!");
defmt::info!("Memset Buffer (after): {=[?]}", mst.as_slice());
// Verify memset result
if !mst.iter().all(|&v| v == pattern) {
defmt::error!("FAIL: memset mismatch!");
} else {
defmt::info!("PASS: memset verified.");
}
defmt::info!("=== All DMA tests complete ===");
}
|