diff options
Diffstat (limited to 'examples/mcxa/src')
| -rw-r--r-- | examples/mcxa/src/bin/dma_scatter_gather_builder.rs | 168 |
1 files changed, 57 insertions, 111 deletions
diff --git a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs index d0f9ae9c4..ba8682cee 100644 --- a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs +++ b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs | |||
| @@ -25,23 +25,18 @@ use core::fmt::Write as _; | |||
| 25 | use embassy_executor::Spawner; | 25 | use embassy_executor::Spawner; |
| 26 | use embassy_mcxa::clocks::config::Div8; | 26 | use embassy_mcxa::clocks::config::Div8; |
| 27 | use embassy_mcxa::dma::{DmaChannel, ScatterGatherBuilder}; | 27 | use embassy_mcxa::dma::{DmaChannel, ScatterGatherBuilder}; |
| 28 | use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; | 28 | use static_cell::ConstStaticCell; |
| 29 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 29 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 30 | 30 | ||
| 31 | // Source buffers (multiple segments) | 31 | // Source buffers (multiple segments) |
| 32 | static mut SRC1: [u32; 4] = [0x11111111, 0x22222222, 0x33333333, 0x44444444]; | 32 | static SRC1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x11111111, 0x22222222, 0x33333333, 0x44444444]); |
| 33 | static mut SRC2: [u32; 4] = [0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD]; | 33 | static SRC2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD]); |
| 34 | static mut SRC3: [u32; 4] = [0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210]; | 34 | static SRC3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210]); |
| 35 | 35 | ||
| 36 | // Destination buffers (one per segment) | 36 | // Destination buffers (one per segment) |
| 37 | static mut DST1: [u32; 4] = [0; 4]; | 37 | static DST1: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); |
| 38 | static mut DST2: [u32; 4] = [0; 4]; | 38 | static DST2: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); |
| 39 | static mut DST3: [u32; 4] = [0; 4]; | 39 | static DST3: ConstStaticCell<[u32; 4]> = ConstStaticCell::new([0; 4]); |
| 40 | |||
| 41 | /// Helper to print a buffer to UART | ||
| 42 | fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { | ||
| 43 | write!(tx, "{:08X?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); | ||
| 44 | } | ||
| 45 | 40 | ||
| 46 | #[embassy_executor::main] | 41 | #[embassy_executor::main] |
| 47 | async fn main(_spawner: Spawner) { | 42 | async fn main(_spawner: Spawner) { |
| @@ -57,47 +52,30 @@ async fn main(_spawner: Spawner) { | |||
| 57 | 52 | ||
| 58 | defmt::info!("DMA Scatter-Gather Builder example starting..."); | 53 | defmt::info!("DMA Scatter-Gather Builder example starting..."); |
| 59 | 54 | ||
| 60 | // Create UART for debug output | 55 | defmt::info!("DMA Scatter-Gather Builder Example"); |
| 61 | let config = Config { | 56 | defmt::info!("==================================="); |
| 62 | baudrate_bps: 115_200, | 57 | let src1 = SRC1.take(); |
| 63 | ..Default::default() | 58 | let src2 = SRC2.take(); |
| 64 | }; | 59 | let src3 = SRC3.take(); |
| 65 | 60 | let dst1 = DST1.take(); | |
| 66 | let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap(); | 61 | let dst2 = DST2.take(); |
| 67 | let (mut tx, _rx) = lpuart.split(); | 62 | let dst3 = DST3.take(); |
| 68 | |||
| 69 | tx.blocking_write(b"DMA Scatter-Gather Builder Example\r\n").unwrap(); | ||
| 70 | tx.blocking_write(b"===================================\r\n\r\n") | ||
| 71 | .unwrap(); | ||
| 72 | 63 | ||
| 73 | // Show source buffers | 64 | // Show source buffers |
| 74 | tx.blocking_write(b"Source buffers:\r\n").unwrap(); | 65 | defmt::info!("Source buffers:"); |
| 75 | tx.blocking_write(b" SRC1: ").unwrap(); | 66 | defmt::info!(" SRC1: {=[?]}", src1.as_slice()); |
| 76 | print_buffer(&mut tx, core::ptr::addr_of!(SRC1) as *const u32, 4); | 67 | defmt::info!(" SRC2: {=[?]}", src2.as_slice()); |
| 77 | tx.blocking_write(b"\r\n").unwrap(); | 68 | defmt::info!(" SRC3: {=[?]}", src3.as_slice()); |
| 78 | tx.blocking_write(b" SRC2: ").unwrap(); | 69 | |
| 79 | print_buffer(&mut tx, core::ptr::addr_of!(SRC2) as *const u32, 4); | 70 | defmt::info!("Destination buffers (before):"); |
| 80 | tx.blocking_write(b"\r\n").unwrap(); | 71 | defmt::info!(" DST1: {=[?]}", dst1.as_slice()); |
| 81 | tx.blocking_write(b" SRC3: ").unwrap(); | 72 | defmt::info!(" DST2: {=[?]}", dst2.as_slice()); |
| 82 | print_buffer(&mut tx, core::ptr::addr_of!(SRC3) as *const u32, 4); | 73 | defmt::info!(" DST3: {=[?]}", dst3.as_slice()); |
| 83 | tx.blocking_write(b"\r\n\r\n").unwrap(); | ||
| 84 | |||
| 85 | tx.blocking_write(b"Destination buffers (before):\r\n").unwrap(); | ||
| 86 | tx.blocking_write(b" DST1: ").unwrap(); | ||
| 87 | print_buffer(&mut tx, core::ptr::addr_of!(DST1) as *const u32, 4); | ||
| 88 | tx.blocking_write(b"\r\n").unwrap(); | ||
| 89 | tx.blocking_write(b" DST2: ").unwrap(); | ||
| 90 | print_buffer(&mut tx, core::ptr::addr_of!(DST2) as *const u32, 4); | ||
| 91 | tx.blocking_write(b"\r\n").unwrap(); | ||
| 92 | tx.blocking_write(b" DST3: ").unwrap(); | ||
| 93 | print_buffer(&mut tx, core::ptr::addr_of!(DST3) as *const u32, 4); | ||
| 94 | tx.blocking_write(b"\r\n\r\n").unwrap(); | ||
| 95 | 74 | ||
| 96 | // Create DMA channel | 75 | // Create DMA channel |
| 97 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); | 76 | let dma_ch0 = DmaChannel::new(p.DMA_CH0); |
| 98 | 77 | ||
| 99 | tx.blocking_write(b"Building scatter-gather chain with builder API...\r\n") | 78 | defmt::info!("Building scatter-gather chain with builder API..."); |
| 100 | .unwrap(); | ||
| 101 | 79 | ||
| 102 | // ========================================================================= | 80 | // ========================================================================= |
| 103 | // ScatterGatherBuilder API demonstration | 81 | // ScatterGatherBuilder API demonstration |
| @@ -112,27 +90,24 @@ async fn main(_spawner: Spawner) { | |||
| 112 | let mut builder = ScatterGatherBuilder::<u32>::new(); | 90 | let mut builder = ScatterGatherBuilder::<u32>::new(); |
| 113 | 91 | ||
| 114 | // Add three transfer segments - the builder handles TCD linking automatically | 92 | // Add three transfer segments - the builder handles TCD linking automatically |
| 115 | unsafe { | 93 | builder.add_transfer(src1, dst1); |
| 116 | let src1 = &*core::ptr::addr_of!(SRC1); | 94 | builder.add_transfer(src2, dst2); |
| 117 | let dst1 = &mut *core::ptr::addr_of_mut!(DST1); | 95 | builder.add_transfer(src3, dst3); |
| 118 | builder.add_transfer(src1, dst1); | 96 | |
| 119 | } | 97 | defmt::info!("Added 3 transfer segments to chain."); |
| 120 | 98 | defmt::info!("Starting scatter-gather transfer with .await..."); | |
| 121 | unsafe { | 99 | |
| 122 | let src2 = &*core::ptr::addr_of!(SRC2); | 100 | // TODO START |
| 123 | let dst2 = &mut *core::ptr::addr_of_mut!(DST2); | 101 | defmt::info!("Destination buffers (after):"); |
| 124 | builder.add_transfer(src2, dst2); | 102 | defmt::info!(" DST1: {=[?]}", dst1.as_slice()); |
| 125 | } | 103 | defmt::info!(" DST2: {=[?]}", dst2.as_slice()); |
| 126 | 104 | defmt::info!(" DST3: {=[?]}", dst3.as_slice()); | |
| 127 | unsafe { | 105 | // TODO: If we want to make the `builder.build()` below safe, the above prints SHOULD NOT |
| 128 | let src3 = &*core::ptr::addr_of!(SRC3); | 106 | // compile. We need to make sure that the lifetime of the builder reflects that it is |
| 129 | let dst3 = &mut *core::ptr::addr_of_mut!(DST3); | 107 | // "consuming" the slices until the builder is dropped, since we can access them to print here, |
| 130 | builder.add_transfer(src3, dst3); | 108 | // that means that the borrow checker isn't enforcing that yet. |
| 131 | } | 109 | todo!("ABOVE CODE SHOULDN'T COMPILE"); |
| 132 | 110 | // TODO END | |
| 133 | tx.blocking_write(b"Added 3 transfer segments to chain.\r\n").unwrap(); | ||
| 134 | tx.blocking_write(b"Starting scatter-gather transfer with .await...\r\n\r\n") | ||
| 135 | .unwrap(); | ||
| 136 | 111 | ||
| 137 | // Build and execute the scatter-gather chain | 112 | // Build and execute the scatter-gather chain |
| 138 | // The build() method: | 113 | // The build() method: |
| @@ -145,60 +120,31 @@ async fn main(_spawner: Spawner) { | |||
| 145 | transfer.blocking_wait(); | 120 | transfer.blocking_wait(); |
| 146 | } | 121 | } |
| 147 | 122 | ||
| 148 | tx.blocking_write(b"Scatter-gather transfer complete!\r\n\r\n").unwrap(); | 123 | defmt::info!("Scatter-gather transfer complete!"); |
| 149 | 124 | ||
| 150 | // Show results | 125 | // Show results |
| 151 | tx.blocking_write(b"Destination buffers (after):\r\n").unwrap(); | 126 | defmt::info!("Destination buffers (after):"); |
| 152 | tx.blocking_write(b" DST1: ").unwrap(); | 127 | defmt::info!(" DST1: {=[?]}", dst1.as_slice()); |
| 153 | print_buffer(&mut tx, core::ptr::addr_of!(DST1) as *const u32, 4); | 128 | defmt::info!(" DST2: {=[?]}", dst2.as_slice()); |
| 154 | tx.blocking_write(b"\r\n").unwrap(); | 129 | defmt::info!(" DST3: {=[?]}", dst3.as_slice()); |
| 155 | tx.blocking_write(b" DST2: ").unwrap(); | 130 | |
| 156 | print_buffer(&mut tx, core::ptr::addr_of!(DST2) as *const u32, 4); | 131 | let comps = [ |
| 157 | tx.blocking_write(b"\r\n").unwrap(); | 132 | (src1, dst1), |
| 158 | tx.blocking_write(b" DST3: ").unwrap(); | 133 | (src2, dst2), |
| 159 | print_buffer(&mut tx, core::ptr::addr_of!(DST3) as *const u32, 4); | 134 | (src3, dst3), |
| 160 | tx.blocking_write(b"\r\n\r\n").unwrap(); | 135 | ]; |
| 161 | 136 | ||
| 162 | // Verify all three segments | 137 | // Verify all three segments |
| 163 | let mut all_ok = true; | 138 | let mut all_ok = true; |
| 164 | unsafe { | 139 | for (src, dst) in comps { |
| 165 | let src1 = core::ptr::addr_of!(SRC1) as *const u32; | 140 | all_ok &= src == dst; |
| 166 | let dst1 = core::ptr::addr_of!(DST1) as *const u32; | ||
| 167 | for i in 0..4 { | ||
| 168 | if *src1.add(i) != *dst1.add(i) { | ||
| 169 | all_ok = false; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | let src2 = core::ptr::addr_of!(SRC2) as *const u32; | ||
| 174 | let dst2 = core::ptr::addr_of!(DST2) as *const u32; | ||
| 175 | for i in 0..4 { | ||
| 176 | if *src2.add(i) != *dst2.add(i) { | ||
| 177 | all_ok = false; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | let src3 = core::ptr::addr_of!(SRC3) as *const u32; | ||
| 182 | let dst3 = core::ptr::addr_of!(DST3) as *const u32; | ||
| 183 | for i in 0..4 { | ||
| 184 | if *src3.add(i) != *dst3.add(i) { | ||
| 185 | all_ok = false; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | 141 | } |
| 189 | 142 | ||
| 190 | if all_ok { | 143 | if all_ok { |
| 191 | tx.blocking_write(b"PASS: All segments verified!\r\n").unwrap(); | ||
| 192 | defmt::info!("PASS: All segments verified!"); | 144 | defmt::info!("PASS: All segments verified!"); |
| 193 | } else { | 145 | } else { |
| 194 | tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap(); | ||
| 195 | defmt::error!("FAIL: Mismatch detected!"); | 146 | defmt::error!("FAIL: Mismatch detected!"); |
| 196 | } | 147 | } |
| 197 | 148 | ||
| 198 | tx.blocking_write(b"\r\n=== Scatter-Gather Builder example complete ===\r\n") | 149 | defmt::info!("=== Scatter-Gather Builder example complete ==="); |
| 199 | .unwrap(); | ||
| 200 | |||
| 201 | loop { | ||
| 202 | cortex_m::asm::wfe(); | ||
| 203 | } | ||
| 204 | } | 150 | } |
