aboutsummaryrefslogtreecommitdiff
path: root/examples/mcxa/src/bin/dma_wrap_transfer.rs
diff options
context:
space:
mode:
authorRaul Alimbekov <[email protected]>2025-12-16 09:05:22 +0300
committerGitHub <[email protected]>2025-12-16 09:05:22 +0300
commitc9a04b4b732b7a3b696eb8223664c1a7942b1875 (patch)
tree6dbe5c02e66eed8d8762f13f95afd24f8db2b38c /examples/mcxa/src/bin/dma_wrap_transfer.rs
parentcde24a3ef1117653ba5ed4184102b33f745782fb (diff)
parent5ae6e060ec1c90561719aabdc29d5b6e7b8b0a82 (diff)
Merge branch 'main' into main
Diffstat (limited to 'examples/mcxa/src/bin/dma_wrap_transfer.rs')
-rw-r--r--examples/mcxa/src/bin/dma_wrap_transfer.rs184
1 files changed, 184 insertions, 0 deletions
diff --git a/examples/mcxa/src/bin/dma_wrap_transfer.rs b/examples/mcxa/src/bin/dma_wrap_transfer.rs
new file mode 100644
index 000000000..acfd29f08
--- /dev/null
+++ b/examples/mcxa/src/bin/dma_wrap_transfer.rs
@@ -0,0 +1,184 @@
1//! DMA wrap transfer example for MCXA276.
2//!
3//! This example demonstrates using DMA with modulo addressing to wrap around
4//! a source buffer, effectively repeating the source data in the destination.
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 core::fmt::Write as _;
14
15use embassy_executor::Spawner;
16use embassy_mcxa::clocks::config::Div8;
17use embassy_mcxa::dma::DmaChannel;
18use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx};
19use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
20
21// Source buffer: 4 words (16 bytes), aligned to 16 bytes for modulo
22#[repr(align(16))]
23struct AlignedSrc([u32; 4]);
24
25static mut SRC: AlignedSrc = AlignedSrc([0; 4]);
26static mut DST: [u32; 8] = [0; 8];
27
28/// Helper to print a buffer to UART
29fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) {
30 write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok();
31}
32
33#[embassy_executor::main]
34async fn main(_spawner: Spawner) {
35 // Small delay to allow probe-rs to attach after reset
36 for _ in 0..100_000 {
37 cortex_m::asm::nop();
38 }
39
40 let mut cfg = hal::config::Config::default();
41 cfg.clock_cfg.sirc.fro_12m_enabled = true;
42 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
43 let p = hal::init(cfg);
44
45 defmt::info!("DMA wrap transfer example starting...");
46
47 let config = Config {
48 baudrate_bps: 115_200,
49 ..Default::default()
50 };
51
52 let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap();
53 let (mut tx, _rx) = lpuart.split();
54
55 tx.blocking_write(b"EDMA wrap transfer example begin.\r\n\r\n").unwrap();
56
57 // Initialize buffers
58 unsafe {
59 SRC.0 = [1, 2, 3, 4];
60 DST = [0; 8];
61 }
62
63 tx.blocking_write(b"Source Buffer: ").unwrap();
64 print_buffer(&mut tx, unsafe { core::ptr::addr_of!(SRC.0) } as *const u32, 4);
65 tx.blocking_write(b"\r\n").unwrap();
66
67 tx.blocking_write(b"Destination Buffer (before): ").unwrap();
68 print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8);
69 tx.blocking_write(b"\r\n").unwrap();
70
71 tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n")
72 .unwrap();
73
74 // Create DMA channel using Embassy-style API
75 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
76
77 // Configure wrap transfer using direct TCD access:
78 // SRC is 16 bytes (4 * u32). We want to transfer 32 bytes (8 * u32).
79 // SRC modulo is 16 bytes (2^4 = 16) - wraps source address.
80 // DST modulo is 0 (disabled).
81 // This causes the source address to wrap around after 16 bytes,
82 // effectively repeating the source data.
83 unsafe {
84 let t = dma_ch0.tcd();
85
86 // Reset channel state
87 t.ch_csr().write(|w| {
88 w.erq()
89 .disable()
90 .earq()
91 .disable()
92 .eei()
93 .no_error()
94 .ebw()
95 .disable()
96 .done()
97 .clear_bit_by_one()
98 });
99 t.ch_es().write(|w| w.bits(0));
100 t.ch_int().write(|w| w.int().clear_bit_by_one());
101
102 // Source/destination addresses
103 t.tcd_saddr()
104 .write(|w| w.saddr().bits(core::ptr::addr_of!(SRC.0) as u32));
105 t.tcd_daddr()
106 .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DST) as u32));
107
108 // Offsets: both increment by 4 bytes
109 t.tcd_soff().write(|w| w.soff().bits(4));
110 t.tcd_doff().write(|w| w.doff().bits(4));
111
112 // Attributes: 32-bit transfers (size = 2)
113 // SMOD = 4 (2^4 = 16 byte modulo for source), DMOD = 0 (disabled)
114 t.tcd_attr().write(|w| {
115 w.ssize()
116 .bits(2)
117 .dsize()
118 .bits(2)
119 .smod()
120 .bits(4) // Source modulo: 2^4 = 16 bytes
121 .dmod()
122 .bits(0) // Dest modulo: disabled
123 });
124
125 // Transfer 32 bytes total in one minor loop
126 let nbytes = 32u32;
127 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
128
129 // Source wraps via modulo, no adjustment needed
130 t.tcd_slast_sda().write(|w| w.slast_sda().bits(0));
131 // Reset dest address after major loop
132 t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32));
133
134 // Major loop count = 1
135 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
136 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
137
138 // Enable interrupt on major loop completion
139 t.tcd_csr().write(|w| w.intmajor().set_bit());
140
141 cortex_m::asm::dsb();
142
143 tx.blocking_write(b"Triggering transfer...\r\n").unwrap();
144 dma_ch0.trigger_start();
145 }
146
147 // Wait for completion using channel helper method
148 while !dma_ch0.is_done() {
149 cortex_m::asm::nop();
150 }
151 unsafe {
152 dma_ch0.clear_done();
153 }
154
155 tx.blocking_write(b"\r\nEDMA wrap transfer example finish.\r\n\r\n")
156 .unwrap();
157 tx.blocking_write(b"Destination Buffer (after): ").unwrap();
158 print_buffer(&mut tx, core::ptr::addr_of!(DST) as *const u32, 8);
159 tx.blocking_write(b"\r\n\r\n").unwrap();
160
161 // Verify: DST should be [1, 2, 3, 4, 1, 2, 3, 4]
162 let expected = [1u32, 2, 3, 4, 1, 2, 3, 4];
163 let mut mismatch = false;
164 unsafe {
165 for i in 0..8 {
166 if DST[i] != expected[i] {
167 mismatch = true;
168 break;
169 }
170 }
171 }
172
173 if mismatch {
174 tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap();
175 defmt::error!("FAIL: Mismatch detected!");
176 } else {
177 tx.blocking_write(b"PASS: Data verified.\r\n").unwrap();
178 defmt::info!("PASS: Data verified.");
179 }
180
181 loop {
182 cortex_m::asm::wfe();
183 }
184}