aboutsummaryrefslogtreecommitdiff
path: root/examples/mcxa/src/bin/raw_dma_memset.rs
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-12-09 15:52:12 +0100
committerJames Munns <[email protected]>2025-12-09 15:52:12 +0100
commite962f5568a9f6433dcd6ad3e41d3faabb8b7c552 (patch)
tree0bcf67cbd0d53039580042b856e1b9dd58a528aa /examples/mcxa/src/bin/raw_dma_memset.rs
parent4386b39e2516c453966d894b4fd265fae9d82c1a (diff)
Clean up remaining examples, move some to "raw" examples
Diffstat (limited to 'examples/mcxa/src/bin/raw_dma_memset.rs')
-rw-r--r--examples/mcxa/src/bin/raw_dma_memset.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/examples/mcxa/src/bin/raw_dma_memset.rs b/examples/mcxa/src/bin/raw_dma_memset.rs
new file mode 100644
index 000000000..7b3c06ffa
--- /dev/null
+++ b/examples/mcxa/src/bin/raw_dma_memset.rs
@@ -0,0 +1,129 @@
1//! DMA memset example for MCXA276.
2//!
3//! NOTE: this is a "raw dma" example! It exists as a proof of concept, as we don't have
4//! a high-level and safe API for. It should not be taken as typical, recommended, or
5//! stable usage!
6//!
7//! This example demonstrates using DMA to fill a buffer with a repeated pattern.
8//! The source address stays fixed while the destination increments.
9//!
10//! # Embassy-style features demonstrated:
11//! - `DmaChannel::is_done()` and `clear_done()` helper methods
12//! - No need to pass register block around
13
14#![no_std]
15#![no_main]
16
17use embassy_executor::Spawner;
18use embassy_mcxa::clocks::config::Div8;
19use embassy_mcxa::dma::DmaChannel;
20use static_cell::ConstStaticCell;
21use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
22
23const BUFFER_LENGTH: usize = 4;
24
25// Buffers in RAM
26static PATTERN: u32 = 0xDEADBEEF;
27static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]);
28
29#[embassy_executor::main]
30async fn main(_spawner: Spawner) {
31 // Small delay to allow probe-rs to attach after reset
32 for _ in 0..100_000 {
33 cortex_m::asm::nop();
34 }
35
36 let mut cfg = hal::config::Config::default();
37 cfg.clock_cfg.sirc.fro_12m_enabled = true;
38 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
39 let p = hal::init(cfg);
40
41 defmt::info!("DMA memset example starting...");
42 defmt::info!("EDMA memset example begin.");
43
44 // Initialize buffers
45 let pat = &PATTERN;
46 let dst = DEST_BUFFER.take();
47 defmt::info!("Pattern Value: {=u32}", pat);
48 defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice());
49 defmt::info!("Configuring DMA with Embassy-style API...");
50
51 // Create DMA channel using Embassy-style API
52 let dma_ch0 = DmaChannel::new(p.DMA_CH0);
53
54 // Configure memset transfer using direct TCD access:
55 // Source stays fixed (soff = 0, reads same pattern repeatedly)
56 // Destination increments (doff = 4)
57 unsafe {
58 let t = dma_ch0.tcd();
59
60 // Reset channel state
61 t.ch_csr().write(|w| {
62 w.erq()
63 .disable()
64 .earq()
65 .disable()
66 .eei()
67 .no_error()
68 .ebw()
69 .disable()
70 .done()
71 .clear_bit_by_one()
72 });
73 t.ch_es().write(|w| w.bits(0));
74 t.ch_int().write(|w| w.int().clear_bit_by_one());
75
76 // Source address (pattern) - fixed
77 t.tcd_saddr().write(|w| w.saddr().bits(pat as *const _ as u32));
78 // Destination address - increments
79 t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32));
80
81 // Source offset = 0 (stays fixed), Dest offset = 4 (increments)
82 t.tcd_soff().write(|w| w.soff().bits(0));
83 t.tcd_doff().write(|w| w.doff().bits(4));
84
85 // Attributes: 32-bit transfers (size = 2)
86 t.tcd_attr().write(|w| w.ssize().bits(2).dsize().bits(2));
87
88 // Transfer entire buffer in one minor loop
89 let nbytes = (BUFFER_LENGTH * 4) as u32;
90 t.tcd_nbytes_mloffno().write(|w| w.nbytes().bits(nbytes));
91
92 // Source doesn't need adjustment (stays fixed)
93 t.tcd_slast_sda().write(|w| w.slast_sda().bits(0));
94 // Reset dest address after major loop
95 t.tcd_dlast_sga().write(|w| w.dlast_sga().bits(-(nbytes as i32) as u32));
96
97 // Major loop count = 1
98 t.tcd_biter_elinkno().write(|w| w.biter().bits(1));
99 t.tcd_citer_elinkno().write(|w| w.citer().bits(1));
100
101 // Enable interrupt on major loop completion
102 t.tcd_csr().write(|w| w.intmajor().set_bit());
103
104 cortex_m::asm::dsb();
105
106 defmt::info!("Triggering transfer...");
107 dma_ch0.trigger_start();
108 }
109
110 // Wait for completion using channel helper method
111 while !dma_ch0.is_done() {
112 cortex_m::asm::nop();
113 }
114 unsafe {
115 dma_ch0.clear_done();
116 }
117
118 defmt::info!("EDMA memset example finish.");
119 defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice());
120
121 // Verify: All elements should equal PATTERN
122 let mismatch = dst.iter().any(|i| *i != *pat);
123
124 if mismatch {
125 defmt::error!("FAIL: Mismatch detected!");
126 } else {
127 defmt::info!("PASS: Data verified.");
128 }
129}