aboutsummaryrefslogtreecommitdiff
path: root/examples/mcxa/src/bin/dma_memset.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/mcxa/src/bin/dma_memset.rs')
-rw-r--r--examples/mcxa/src/bin/dma_memset.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/examples/mcxa/src/bin/dma_memset.rs b/examples/mcxa/src/bin/dma_memset.rs
new file mode 100644
index 000000000..95e365e47
--- /dev/null
+++ b/examples/mcxa/src/bin/dma_memset.rs
@@ -0,0 +1,218 @@
1//! DMA memset example for MCXA276.
2//!
3//! This example demonstrates using DMA to fill a buffer with a repeated pattern.
4//! The source address stays fixed while the destination increments.
5//!
6//! # Embassy-style features demonstrated:
7//! - `DmaChannel::is_done()` and `clear_done()` helper methods
8//! - No need to pass register block around
9
10#![no_std]
11#![no_main]
12
13use embassy_executor::Spawner;
14use embassy_mcxa::clocks::config::Div8;
15use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel};
16use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx};
17use embassy_mcxa::{bind_interrupts, pac};
18use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
19
20// Bind DMA channel 0 interrupt using Embassy-style macro
21bind_interrupts!(struct Irqs {
22 DMA_CH0 => DmaCh0InterruptHandler;
23});
24
25const BUFFER_LENGTH: usize = 4;
26
27// Buffers in RAM
28static mut PATTERN: u32 = 0;
29static mut DEST_BUFFER: [u32; BUFFER_LENGTH] = [0; BUFFER_LENGTH];
30
31/// Helper to write a u32 as decimal ASCII to UART
32fn write_u32(tx: &mut LpuartTx<'_, Blocking>, val: u32) {
33 let mut buf = [0u8; 10];
34 let mut n = val;
35 let mut i = buf.len();
36
37 if n == 0 {
38 tx.blocking_write(b"0").ok();
39 return;
40 }
41
42 while n > 0 {
43 i -= 1;
44 buf[i] = b'0' + (n % 10) as u8;
45 n /= 10;
46 }
47
48 tx.blocking_write(&buf[i..]).ok();
49}
50
51/// Helper to print a buffer to UART
52fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) {
53 tx.blocking_write(b"[").ok();
54 unsafe {
55 for i in 0..len {
56 write_u32(tx, *buf_ptr.add(i));
57 if i < len - 1 {
58 tx.blocking_write(b", ").ok();
59 }
60 }
61 }
62 tx.blocking_write(b"]").ok();
63}
64
65#[embassy_executor::main]
66async fn main(_spawner: Spawner) {
67 // Small delay to allow probe-rs to attach after reset
68 for _ in 0..100_000 {
69 cortex_m::asm::nop();
70 }
71
72 let mut cfg = hal::config::Config::default();
73 cfg.clock_cfg.sirc.fro_12m_enabled = true;
74 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
75 let p = hal::init(cfg);
76
77 defmt::info!("DMA memset example starting...");
78
79 // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL)
80 unsafe {
81 cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0);
82 }
83
84 let config = Config {
85 baudrate_bps: 115_200,
86 ..Default::default()
87 };
88
89 let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap();
90 let (mut tx, _rx) = lpuart.split();
91
92 tx.blocking_write(b"EDMA memset example begin.\r\n\r\n").unwrap();
93
94 // Initialize buffers
95 unsafe {
96 PATTERN = 0xDEADBEEF;
97 DEST_BUFFER = [0; BUFFER_LENGTH];
98 }
99
100 tx.blocking_write(b"Pattern value: 0x").unwrap();
101 // Print pattern in hex
102 unsafe {
103 let hex_chars = b"0123456789ABCDEF";
104 let mut hex_buf = [0u8; 8];
105 let mut val = PATTERN;
106 for i in (0..8).rev() {
107 hex_buf[i] = hex_chars[(val & 0xF) as usize];
108 val >>= 4;
109 }
110 tx.blocking_write(&hex_buf).ok();
111 }
112 tx.blocking_write(b"\r\n").unwrap();
113
114 tx.blocking_write(b"Destination Buffer (before): ").unwrap();
115 print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH);
116 tx.blocking_write(b"\r\n").unwrap();
117
118 tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n")
119 .unwrap();
120
121 // Create DMA channel using Embassy-style API
122 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
123
124 // Configure memset transfer using direct TCD access:
125 // Source stays fixed (soff = 0, reads same pattern repeatedly)
126 // Destination increments (doff = 4)
127 unsafe {
128 let t = dma_ch0.tcd();
129
130 // Reset channel state
131 t.ch_csr().write(|w| {
132 w.erq()
133 .disable()
134 .earq()
135 .disable()
136 .eei()
137 .no_error()
138 .ebw()
139 .disable()
140 .done()
141 .clear_bit_by_one()
142 });
143 t.ch_es().write(|w| w.bits(0));
144 t.ch_int().write(|w| w.int().clear_bit_by_one());
145
146 // Source address (pattern) - fixed
147 t.tcd_saddr()
148 .write(|w| w.saddr().bits(core::ptr::addr_of_mut!(PATTERN) as u32));
149 // Destination address - increments
150 t.tcd_daddr()
151 .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DEST_BUFFER) as u32));
152
153 // Source offset = 0 (stays fixed), Dest offset = 4 (increments)
154 t.tcd_soff().write(|w| w.soff().bits(0));
155 t.tcd_doff().write(|w| w.doff().bits(4));
156
157 // Attributes: 32-bit transfers (size = 2)
158 t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2));
159
160 // Transfer entire buffer in one minor loop
161 let nbytes = (BUFFER_LENGTH * 4) as u32;
162 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
163
164 // Source doesn't need adjustment (stays fixed)
165 t.tcd_slast_sda().write(|w| w.slast_sda().bits(0));
166 // Reset dest address after major loop
167 t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32));
168
169 // Major loop count = 1
170 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
171 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
172
173 // Enable interrupt on major loop completion
174 t.tcd_csr().write(|w| w.intmajor().set_bit());
175
176 cortex_m::asm::dsb();
177
178 tx.blocking_write(b"Triggering transfer...\r\n").unwrap();
179 dma_ch0.trigger_start();
180 }
181
182 // Wait for completion using channel helper method
183 while !dma_ch0.is_done() {
184 cortex_m::asm::nop();
185 }
186 unsafe {
187 dma_ch0.clear_done();
188 }
189
190 tx.blocking_write(b"\r\nEDMA memset example finish.\r\n\r\n").unwrap();
191 tx.blocking_write(b"Destination Buffer (after): ").unwrap();
192 print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH);
193 tx.blocking_write(b"\r\n\r\n").unwrap();
194
195 // Verify: All elements should equal PATTERN
196 let mut mismatch = false;
197 unsafe {
198 #[allow(clippy::needless_range_loop)]
199 for i in 0..BUFFER_LENGTH {
200 if DEST_BUFFER[i] != PATTERN {
201 mismatch = true;
202 break;
203 }
204 }
205 }
206
207 if mismatch {
208 tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap();
209 defmt::error!("FAIL: Mismatch detected!");
210 } else {
211 tx.blocking_write(b"PASS: Data verified.\r\n").unwrap();
212 defmt::info!("PASS: Data verified.");
213 }
214
215 loop {
216 cortex_m::asm::wfe();
217 }
218}