From 6680ef22fa4b46adb4cda46d6cdbc9dac39dc78c Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 8 Dec 2025 17:58:00 +0100 Subject: Clean up examples, move interrupts to be more fully managed --- embassy-mcxa/src/dma.rs | 58 +++++-------- embassy-mcxa/src/lib.rs | 35 -------- examples/mcxa/src/bin/adc_interrupt.rs | 4 +- examples/mcxa/src/bin/adc_polling.rs | 2 +- examples/mcxa/src/bin/dma_channel_link.rs | 21 +---- examples/mcxa/src/bin/dma_interleave_transfer.rs | 58 +++++-------- examples/mcxa/src/bin/dma_mem_to_mem.rs | 81 ++++-------------- examples/mcxa/src/bin/dma_memset.rs | 97 ++++------------------ examples/mcxa/src/bin/dma_ping_pong_transfer.rs | 5 +- examples/mcxa/src/bin/dma_scatter_gather.rs | 3 +- .../mcxa/src/bin/dma_scatter_gather_builder.rs | 16 +--- examples/mcxa/src/bin/dma_wrap_transfer.rs | 16 +--- examples/mcxa/src/bin/i2c-async.rs | 2 +- examples/mcxa/src/bin/i2c-scan-blocking.rs | 2 +- examples/mcxa/src/bin/lpuart_buffered.rs | 2 +- examples/mcxa/src/bin/lpuart_dma.rs | 11 +-- examples/mcxa/src/bin/lpuart_ring_buffer.rs | 8 -- 17 files changed, 93 insertions(+), 328 deletions(-) diff --git a/embassy-mcxa/src/dma.rs b/embassy-mcxa/src/dma.rs index b3ea94dbf..07500e9a2 100644 --- a/embassy-mcxa/src/dma.rs +++ b/embassy-mcxa/src/dma.rs @@ -618,16 +618,9 @@ impl DmaChannel { /// Note: DMA is initialized during `hal::init()` via `dma::init()`. #[inline] pub fn new(_ch: embassy_hal_internal::Peri<'_, C>) -> Self { - Self { - _ch: core::marker::PhantomData, + unsafe { + cortex_m::peripheral::NVIC::unmask(C::INTERRUPT); } - } - - /// Wrap a DMA channel token directly (for internal use). - /// - /// Note: DMA is initialized during `hal::init()` via `dma::init()`. - #[inline] - pub fn from_token(_ch: C) -> Self { Self { _ch: core::marker::PhantomData, } @@ -740,7 +733,8 @@ impl DmaChannel { #[inline] fn set_even_transfer_size(t: &'static pac::edma_0_tcd0::Tcd, sz: WordSize) { let hw_size = sz.to_hw_size(); - t.tcd_attr().write(|w| unsafe { w.ssize().bits(hw_size).dsize().bits(hw_size) } ); + t.tcd_attr() + .write(|w| unsafe { w.ssize().bits(hw_size).dsize().bits(hw_size) }); } #[inline] @@ -1068,7 +1062,7 @@ impl DmaChannel { // Addresses Self::set_source_ptr(t, buf.as_ptr()); - t.tcd_daddr().write(|w| w.daddr().bits(peri_addr as u32)); + Self::set_dest_ptr(t, peri_addr); // Offsets: Source increments, Dest fixed Self::set_source_increment(t, size); @@ -2357,7 +2351,7 @@ impl ScatterGatherBuilder { // Reset channel state - clear DONE, disable requests, clear errors // This ensures the channel is in a clean state before loading the TCD - Self::reset_channel_state(t); + DmaChannel::::reset_channel_state(t); // Memory barrier to ensure channel state is reset before loading TCD cortex_m::asm::dsb(); @@ -2441,38 +2435,28 @@ pub unsafe fn on_interrupt(ch_index: usize) { } // ============================================================================ -// Type-level Interrupt Handlers for bind_interrupts! macro +// Type-level Interrupt Handlers // ============================================================================ /// Macro to generate DMA channel interrupt handlers. -/// -/// This generates handler structs that implement the `Handler` trait for use -/// with the `bind_interrupts!` macro. macro_rules! impl_dma_interrupt_handler { - ($name:ident, $irq:ident, $ch:expr) => { - /// Interrupt handler for DMA channel. - /// - /// Use this with the `bind_interrupts!` macro: - /// ```ignore - /// bind_interrupts!(struct Irqs { - #[doc = concat!(" ", stringify!($irq), " => dma::", stringify!($name), ";")] - /// }); - /// ``` - pub struct $name; - - impl crate::interrupt::typelevel::Handler for $name { - unsafe fn on_interrupt() { + ($irq:ident, $ch:expr) => { + #[interrupt] + fn $irq() { + unsafe { on_interrupt($ch); } } }; } -impl_dma_interrupt_handler!(DmaCh0InterruptHandler, DMA_CH0, 0); -impl_dma_interrupt_handler!(DmaCh1InterruptHandler, DMA_CH1, 1); -impl_dma_interrupt_handler!(DmaCh2InterruptHandler, DMA_CH2, 2); -impl_dma_interrupt_handler!(DmaCh3InterruptHandler, DMA_CH3, 3); -impl_dma_interrupt_handler!(DmaCh4InterruptHandler, DMA_CH4, 4); -impl_dma_interrupt_handler!(DmaCh5InterruptHandler, DMA_CH5, 5); -impl_dma_interrupt_handler!(DmaCh6InterruptHandler, DMA_CH6, 6); -impl_dma_interrupt_handler!(DmaCh7InterruptHandler, DMA_CH7, 7); +use crate::pac::interrupt; + +impl_dma_interrupt_handler!(DMA_CH0, 0); +impl_dma_interrupt_handler!(DMA_CH1, 1); +impl_dma_interrupt_handler!(DMA_CH2, 2); +impl_dma_interrupt_handler!(DMA_CH3, 3); +impl_dma_interrupt_handler!(DMA_CH4, 4); +impl_dma_interrupt_handler!(DMA_CH5, 5); +impl_dma_interrupt_handler!(DMA_CH6, 6); +impl_dma_interrupt_handler!(DMA_CH7, 7); diff --git a/embassy-mcxa/src/lib.rs b/embassy-mcxa/src/lib.rs index 23cda7511..724f99234 100644 --- a/embassy-mcxa/src/lib.rs +++ b/embassy-mcxa/src/lib.rs @@ -400,41 +400,6 @@ pub fn init(cfg: crate::config::Config) -> Peripherals { peripherals } -// /// Optional hook called by cortex-m-rt before RAM init. -// /// We proactively mask and clear all NVIC IRQs to avoid wedges from stale state -// /// left by soft resets/debug sessions. -// /// -// /// NOTE: Manual VTOR setup is required for RAM execution. The cortex-m-rt 'set-vtor' -// /// feature is incompatible with our setup because it expects __vector_table to be -// /// defined differently than how our RAM-based linker script arranges it. -// #[no_mangle] -// pub unsafe extern "C" fn __pre_init() { -// // Set the VTOR to point to the interrupt vector table in RAM -// // This is required since code runs from RAM on this MCU -// crate::interrupt::vtor_set_ram_vector_base(0x2000_0000 as *const u32); - -// // Mask and clear pending for all NVIC lines (0..127) to avoid stale state across runs. -// let nvic = &*cortex_m::peripheral::NVIC::PTR; -// for i in 0..4 { -// // 4 words x 32 = 128 IRQs -// nvic.icer[i].write(0xFFFF_FFFF); -// nvic.icpr[i].write(0xFFFF_FFFF); -// } -// // Do NOT touch peripheral registers here: clocks may be off and accesses can fault. -// crate::interrupt::clear_default_handler_snapshot(); -// } - -/// Internal helper to dispatch a type-level interrupt handler. -#[inline(always)] -#[doc(hidden)] -pub unsafe fn __handle_interrupt() -where - T: crate::interrupt::typelevel::Interrupt, - H: crate::interrupt::typelevel::Handler, -{ - H::on_interrupt(); -} - /// Macro to bind interrupts to handlers, similar to embassy-imxrt. /// /// Example: diff --git a/examples/mcxa/src/bin/adc_interrupt.rs b/examples/mcxa/src/bin/adc_interrupt.rs index c88b1fe8d..83d8046b3 100644 --- a/examples/mcxa/src/bin/adc_interrupt.rs +++ b/examples/mcxa/src/bin/adc_interrupt.rs @@ -4,13 +4,13 @@ use embassy_executor::Spawner; use embassy_mcxa_examples::init_adc_pins; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; -use hal::clocks::PoweredClock; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; +use hal::clocks::PoweredClock; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; use hal::pac::adc1::tctrl::Tcmd; -use hal::{InterruptExt, bind_interrupts}; +use hal::{bind_interrupts, InterruptExt}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; bind_interrupts!(struct Irqs { diff --git a/examples/mcxa/src/bin/adc_polling.rs b/examples/mcxa/src/bin/adc_polling.rs index 07c50f224..ddf3f586b 100644 --- a/examples/mcxa/src/bin/adc_polling.rs +++ b/examples/mcxa/src/bin/adc_polling.rs @@ -4,8 +4,8 @@ use embassy_executor::Spawner; use embassy_mcxa_examples::init_adc_pins; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; -use hal::clocks::PoweredClock; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; +use hal::clocks::PoweredClock; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; diff --git a/examples/mcxa/src/bin/dma_channel_link.rs b/examples/mcxa/src/bin/dma_channel_link.rs index f7ab5d8fd..2d757a636 100644 --- a/examples/mcxa/src/bin/dma_channel_link.rs +++ b/examples/mcxa/src/bin/dma_channel_link.rs @@ -16,13 +16,14 @@ #![no_std] #![no_main] +use core::fmt::Write as _; + use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaCh1InterruptHandler, DmaCh2InterruptHandler, DmaChannel}; +use embassy_mcxa::dma::DmaChannel; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; +use embassy_mcxa::pac; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; // Buffers static mut SRC_BUFFER: [u32; 4] = [1, 2, 3, 4]; @@ -30,14 +31,6 @@ static mut DEST_BUFFER0: [u32; 4] = [0; 4]; static mut DEST_BUFFER1: [u32; 4] = [0; 4]; static mut DEST_BUFFER2: [u32; 4] = [0; 4]; -// Bind DMA channel interrupts using Embassy-style macro -// The standard handlers call on_interrupt() which wakes wakers and clears flags -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; - DMA_CH1 => DmaCh1InterruptHandler; - DMA_CH2 => DmaCh2InterruptHandler; -}); - /// Helper to print a buffer to UART fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); @@ -84,12 +77,6 @@ async fn main(_spawner: Spawner) { .normal_operation() }); - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH1); - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH2); - } - let config = Config { baudrate_bps: 115_200, ..Default::default() diff --git a/examples/mcxa/src/bin/dma_interleave_transfer.rs b/examples/mcxa/src/bin/dma_interleave_transfer.rs index 98e301a7c..03441fc32 100644 --- a/examples/mcxa/src/bin/dma_interleave_transfer.rs +++ b/examples/mcxa/src/bin/dma_interleave_transfer.rs @@ -10,29 +10,25 @@ #![no_std] #![no_main] +use core::fmt::Write as _; + use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel}; +use embassy_mcxa::dma::DmaChannel; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; +use static_cell::ConstStaticCell; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; - -// Bind DMA channel 0 interrupt using Embassy-style macro -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; -}); const BUFFER_LENGTH: usize = 16; const HALF_BUFF_LENGTH: usize = BUFFER_LENGTH / 2; // Buffers in RAM -static mut SRC_BUFFER: [u32; HALF_BUFF_LENGTH] = [0; HALF_BUFF_LENGTH]; -static mut DEST_BUFFER: [u32; BUFFER_LENGTH] = [0; BUFFER_LENGTH]; +static SRC_BUFFER: ConstStaticCell<[u32; HALF_BUFF_LENGTH]> = ConstStaticCell::new([0; HALF_BUFF_LENGTH]); +static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); /// Helper to print a buffer to UART -fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { - write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); +fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf: &[u32]) { + write!(tx, "{:?}", buf).ok(); } #[embassy_executor::main] @@ -49,11 +45,6 @@ async fn main(_spawner: Spawner) { defmt::info!("DMA interleave transfer example starting..."); - // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL) - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - } - let config = Config { baudrate_bps: 115_200, ..Default::default() @@ -66,17 +57,16 @@ async fn main(_spawner: Spawner) { .unwrap(); // Initialize buffers - unsafe { - SRC_BUFFER = [1, 2, 3, 4, 5, 6, 7, 8]; - DEST_BUFFER = [0; BUFFER_LENGTH]; - } + let src = SRC_BUFFER.take(); + *src = [1, 2, 3, 4, 5, 6, 7, 8]; + let dst = DEST_BUFFER.take(); tx.blocking_write(b"Source Buffer: ").unwrap(); - print_buffer(&mut tx, core::ptr::addr_of!(SRC_BUFFER) as *const u32, HALF_BUFF_LENGTH); + print_buffer(&mut tx, src); tx.blocking_write(b"\r\n").unwrap(); tx.blocking_write(b"Destination Buffer (before): ").unwrap(); - print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH); + print_buffer(&mut tx, dst); tx.blocking_write(b"\r\n").unwrap(); tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n") @@ -109,10 +99,8 @@ async fn main(_spawner: Spawner) { t.ch_int().write(|w| w.int().clear_bit_by_one()); // Source/destination addresses - t.tcd_saddr() - .write(|w| w.saddr().bits(core::ptr::addr_of_mut!(SRC_BUFFER) as u32)); - t.tcd_daddr() - .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DEST_BUFFER) as u32)); + t.tcd_saddr().write(|w| w.saddr().bits(src.as_ptr() as u32)); + t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32)); // Custom offsets for interleaving t.tcd_soff().write(|w| w.soff().bits(4)); // src: +4 bytes per read @@ -156,21 +144,15 @@ async fn main(_spawner: Spawner) { tx.blocking_write(b"\r\nEDMA interleave transfer example finish.\r\n\r\n") .unwrap(); tx.blocking_write(b"Destination Buffer (after): ").unwrap(); - print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH); + print_buffer(&mut tx, dst); tx.blocking_write(b"\r\n\r\n").unwrap(); // Verify: Even indices should match SRC_BUFFER[i/2], odd indices should be 0 let mut mismatch = false; - unsafe { - for i in 0..BUFFER_LENGTH { - if i % 2 == 0 { - if DEST_BUFFER[i] != SRC_BUFFER[i / 2] { - mismatch = true; - } - } else if DEST_BUFFER[i] != 0 { - mismatch = true; - } - } + let diter = dst.chunks_exact(2); + let siter = src.iter(); + for (ch, src) in diter.zip(siter) { + mismatch |= !matches!(ch, [a, 0] if a == src); } if mismatch { diff --git a/examples/mcxa/src/bin/dma_mem_to_mem.rs b/examples/mcxa/src/bin/dma_mem_to_mem.rs index b78745464..b20068b79 100644 --- a/examples/mcxa/src/bin/dma_mem_to_mem.rs +++ b/examples/mcxa/src/bin/dma_mem_to_mem.rs @@ -15,17 +15,9 @@ use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel, TransferOptions}; -use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; +use embassy_mcxa::dma::{DmaChannel, TransferOptions}; use static_cell::ConstStaticCell; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; - -// Bind DMA channel 0 interrupt using Embassy-style macro -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; -}); const BUFFER_LENGTH: usize = 4; @@ -34,12 +26,6 @@ static SRC_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new( static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); static MEMSET_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); -/// Helper to print a buffer as [v1, v2, v3, v4] to UART -/// Takes a raw pointer to avoid warnings about shared references to mutable statics -fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: &[u32; BUFFER_LENGTH]) { - write!(tx, "{:?}", buf_ptr).ok(); -} - #[embassy_executor::main] async fn main(_spawner: Spawner) { // Small delay to allow probe-rs to attach after reset @@ -54,37 +40,15 @@ async fn main(_spawner: Spawner) { defmt::info!("DMA memory-to-memory example starting..."); - // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL) - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - } - - // Create UART for debug output - let config = Config { - baudrate_bps: 115_200, - ..Default::default() - }; - - let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap(); - let (mut tx, _rx) = lpuart.split(); - - tx.blocking_write(b"EDMA memory to memory example begin.\r\n\r\n") - .unwrap(); + defmt::info!("EDMA memory to memory example begin."); let src = SRC_BUFFER.take(); let dst = DEST_BUFFER.take(); let mst = MEMSET_BUFFER.take(); - tx.blocking_write(b"Source Buffer: ").unwrap(); - print_buffer(&mut tx, src); - tx.blocking_write(b"\r\n").unwrap(); - - tx.blocking_write(b"Destination Buffer (before): ").unwrap(); - print_buffer(&mut tx, dst); - tx.blocking_write(b"\r\n").unwrap(); - - tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n") - .unwrap(); + 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); @@ -109,19 +73,13 @@ async fn main(_spawner: Spawner) { let transfer = dma_ch0.mem_to_mem(src, dst, options); transfer.await; - tx.blocking_write(b"DMA mem-to-mem transfer complete!\r\n\r\n").unwrap(); - tx.blocking_write(b"Destination Buffer (after): ").unwrap(); - print_buffer(&mut tx, dst); - tx.blocking_write(b"\r\n").unwrap(); + defmt::info!("DMA mem-to-mem transfer complete!"); + defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); // Verify data - let mut mismatch = src != dst; - - if mismatch { - tx.blocking_write(b"FAIL: mem_to_mem mismatch!\r\n").unwrap(); + if src != dst { defmt::error!("FAIL: mem_to_mem mismatch!"); } else { - tx.blocking_write(b"PASS: mem_to_mem verified.\r\n\r\n").unwrap(); defmt::info!("PASS: mem_to_mem verified."); } @@ -134,36 +92,27 @@ async fn main(_spawner: Spawner) { // - Incrementing destination address // - Uses the same Transfer future pattern - tx.blocking_write(b"--- Demonstrating memset() feature ---\r\n\r\n") - .unwrap(); + defmt::info!("--- Demonstrating memset() feature ---"); - tx.blocking_write(b"Memset Buffer (before): ").unwrap(); - print_buffer(&mut tx, mst); - tx.blocking_write(b"\r\n").unwrap(); + defmt::info!("Memset Buffer (before): {=[?]}", mst.as_slice()); // Fill buffer with a pattern value using DMA memset let pattern: u32 = 0xDEADBEEF; - tx.blocking_write(b"Filling with pattern 0xDEADBEEF...\r\n").unwrap(); + 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(); - tx.blocking_write(b"DMA memset complete!\r\n\r\n").unwrap(); - tx.blocking_write(b"Memset Buffer (after): ").unwrap(); - print_buffer(&mut tx, mst); - tx.blocking_write(b"\r\n").unwrap(); + defmt::info!("DMA memset complete!"); + defmt::info!("Memset Buffer (after): {=[?]}", mst.as_slice()); // Verify memset result - let memset_ok = mst.iter().all(|&v| v == pattern); - - if !memset_ok { - tx.blocking_write(b"FAIL: memset mismatch!\r\n").unwrap(); + if !mst.iter().all(|&v| v == pattern) { defmt::error!("FAIL: memset mismatch!"); } else { - tx.blocking_write(b"PASS: memset verified.\r\n\r\n").unwrap(); defmt::info!("PASS: memset verified."); } - tx.blocking_write(b"=== All DMA tests complete ===\r\n").unwrap(); + defmt::info!("=== All DMA tests complete ==="); } diff --git a/examples/mcxa/src/bin/dma_memset.rs b/examples/mcxa/src/bin/dma_memset.rs index bc4e78701..d7b03e91b 100644 --- a/examples/mcxa/src/bin/dma_memset.rs +++ b/examples/mcxa/src/bin/dma_memset.rs @@ -12,27 +12,15 @@ use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel}; -use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; +use embassy_mcxa::dma::DmaChannel; +use static_cell::ConstStaticCell; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; - -// Bind DMA channel 0 interrupt using Embassy-style macro -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; -}); const BUFFER_LENGTH: usize = 4; // Buffers in RAM -static mut PATTERN: u32 = 0; -static mut DEST_BUFFER: [u32; BUFFER_LENGTH] = [0; BUFFER_LENGTH]; - -/// Helper to print a buffer to UART -fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { - write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); -} +static PATTERN: u32 = 0xDEADBEEF; +static DEST_BUFFER: ConstStaticCell<[u32; BUFFER_LENGTH]> = ConstStaticCell::new([0; BUFFER_LENGTH]); #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -47,48 +35,14 @@ async fn main(_spawner: Spawner) { let p = hal::init(cfg); defmt::info!("DMA memset example starting..."); - - // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL) - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - } - - let config = Config { - baudrate_bps: 115_200, - ..Default::default() - }; - - let lpuart = Lpuart::new_blocking(p.LPUART2, p.P2_2, p.P2_3, config).unwrap(); - let (mut tx, _rx) = lpuart.split(); - - tx.blocking_write(b"EDMA memset example begin.\r\n\r\n").unwrap(); + defmt::info!("EDMA memset example begin."); // Initialize buffers - unsafe { - PATTERN = 0xDEADBEEF; - DEST_BUFFER = [0; BUFFER_LENGTH]; - } - - tx.blocking_write(b"Pattern value: 0x").unwrap(); - // Print pattern in hex - unsafe { - let hex_chars = b"0123456789ABCDEF"; - let mut hex_buf = [0u8; 8]; - let mut val = PATTERN; - for i in (0..8).rev() { - hex_buf[i] = hex_chars[(val & 0xF) as usize]; - val >>= 4; - } - tx.blocking_write(&hex_buf).ok(); - } - tx.blocking_write(b"\r\n").unwrap(); - - tx.blocking_write(b"Destination Buffer (before): ").unwrap(); - print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH); - tx.blocking_write(b"\r\n").unwrap(); - - tx.blocking_write(b"Configuring DMA with Embassy-style API...\r\n") - .unwrap(); + let pat = &PATTERN; + let dst = DEST_BUFFER.take(); + defmt::info!("Pattern Value: {=u32}", pat); + defmt::info!("Destination Buffer (before): {=[?]}", dst.as_slice()); + defmt::info!("Configuring DMA with Embassy-style API..."); // Create DMA channel using Embassy-style API let dma_ch0 = DmaChannel::new(p.DMA_CH0); @@ -116,11 +70,9 @@ async fn main(_spawner: Spawner) { t.ch_int().write(|w| w.int().clear_bit_by_one()); // Source address (pattern) - fixed - t.tcd_saddr() - .write(|w| w.saddr().bits(core::ptr::addr_of_mut!(PATTERN) as u32)); + t.tcd_saddr().write(|w| w.saddr().bits(pat as *const _ as u32)); // Destination address - increments - t.tcd_daddr() - .write(|w| w.daddr().bits(core::ptr::addr_of_mut!(DEST_BUFFER) as u32)); + t.tcd_daddr().write(|w| w.daddr().bits(dst.as_mut_ptr() as u32)); // Source offset = 0 (stays fixed), Dest offset = 4 (increments) t.tcd_soff().write(|w| w.soff().bits(0)); @@ -147,7 +99,7 @@ async fn main(_spawner: Spawner) { cortex_m::asm::dsb(); - tx.blocking_write(b"Triggering transfer...\r\n").unwrap(); + defmt::info!("Triggering transfer..."); dma_ch0.trigger_start(); } @@ -159,32 +111,15 @@ async fn main(_spawner: Spawner) { dma_ch0.clear_done(); } - tx.blocking_write(b"\r\nEDMA memset example finish.\r\n\r\n").unwrap(); - tx.blocking_write(b"Destination Buffer (after): ").unwrap(); - print_buffer(&mut tx, core::ptr::addr_of!(DEST_BUFFER) as *const u32, BUFFER_LENGTH); - tx.blocking_write(b"\r\n\r\n").unwrap(); + defmt::info!("EDMA memset example finish."); + defmt::info!("Destination Buffer (after): {=[?]}", dst.as_slice()); // Verify: All elements should equal PATTERN - let mut mismatch = false; - unsafe { - #[allow(clippy::needless_range_loop)] - for i in 0..BUFFER_LENGTH { - if DEST_BUFFER[i] != PATTERN { - mismatch = true; - break; - } - } - } + let mismatch = dst.iter().any(|i| *i != *pat); if mismatch { - tx.blocking_write(b"FAIL: Mismatch detected!\r\n").unwrap(); defmt::error!("FAIL: Mismatch detected!"); } else { - tx.blocking_write(b"PASS: Data verified.\r\n").unwrap(); defmt::info!("PASS: Data verified."); } - - loop { - cortex_m::asm::wfe(); - } } diff --git a/examples/mcxa/src/bin/dma_ping_pong_transfer.rs b/examples/mcxa/src/bin/dma_ping_pong_transfer.rs index 728e4d408..58f643b80 100644 --- a/examples/mcxa/src/bin/dma_ping_pong_transfer.rs +++ b/examples/mcxa/src/bin/dma_ping_pong_transfer.rs @@ -23,15 +23,15 @@ #![no_std] #![no_main] +use core::fmt::Write as _; use core::sync::atomic::{AtomicBool, Ordering}; use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{self, DmaCh1InterruptHandler, DmaChannel, Tcd, TransferOptions}; +use embassy_mcxa::dma::{self, DmaChannel, Tcd, TransferOptions}; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; use embassy_mcxa::{bind_interrupts, pac}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; // Source and destination buffers for Approach 1 (scatter/gather) static mut SRC: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; @@ -85,7 +85,6 @@ impl embassy_mcxa::interrupt::typelevel::Handler PingPongDmaHandler; - DMA_CH1 => DmaCh1InterruptHandler; }); /// Helper to print a buffer to UART diff --git a/examples/mcxa/src/bin/dma_scatter_gather.rs b/examples/mcxa/src/bin/dma_scatter_gather.rs index ea553b843..3e34e95b1 100644 --- a/examples/mcxa/src/bin/dma_scatter_gather.rs +++ b/examples/mcxa/src/bin/dma_scatter_gather.rs @@ -12,6 +12,7 @@ #![no_std] #![no_main] +use core::fmt::Write as _; use core::sync::atomic::{AtomicBool, Ordering}; use embassy_executor::Spawner; @@ -20,7 +21,6 @@ use embassy_mcxa::dma::{self, DmaChannel, Tcd}; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; use embassy_mcxa::{bind_interrupts, pac}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; // Source and destination buffers static mut SRC: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; @@ -73,7 +73,6 @@ bind_interrupts!(struct Irqs { DMA_CH0 => ScatterGatherDmaHandler; }); - /// Helper to print a buffer to UART fn print_buffer(tx: &mut LpuartTx<'_, Blocking>, buf_ptr: *const u32, len: usize) { write!(tx, "{:?}", unsafe { core::slice::from_raw_parts(buf_ptr, len) }).ok(); diff --git a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs index 29c54ca42..d0f9ae9c4 100644 --- a/examples/mcxa/src/bin/dma_scatter_gather_builder.rs +++ b/examples/mcxa/src/bin/dma_scatter_gather_builder.rs @@ -20,18 +20,13 @@ #![no_std] #![no_main] +use core::fmt::Write as _; + use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel, ScatterGatherBuilder}; +use embassy_mcxa::dma::{DmaChannel, ScatterGatherBuilder}; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; - -// Bind DMA channel 0 interrupt -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; -}); // Source buffers (multiple segments) static mut SRC1: [u32; 4] = [0x11111111, 0x22222222, 0x33333333, 0x44444444]; @@ -62,11 +57,6 @@ async fn main(_spawner: Spawner) { defmt::info!("DMA Scatter-Gather Builder example starting..."); - // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL) - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - } - // Create UART for debug output let config = Config { baudrate_bps: 115_200, diff --git a/examples/mcxa/src/bin/dma_wrap_transfer.rs b/examples/mcxa/src/bin/dma_wrap_transfer.rs index 7fea4bf76..acfd29f08 100644 --- a/examples/mcxa/src/bin/dma_wrap_transfer.rs +++ b/examples/mcxa/src/bin/dma_wrap_transfer.rs @@ -10,18 +10,13 @@ #![no_std] #![no_main] +use core::fmt::Write as _; + use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaChannel}; +use embassy_mcxa::dma::DmaChannel; use embassy_mcxa::lpuart::{Blocking, Config, Lpuart, LpuartTx}; -use embassy_mcxa::{bind_interrupts, pac}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -use core::fmt::Write as _; - -// Bind DMA channel 0 interrupt using Embassy-style macro -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; -}); // Source buffer: 4 words (16 bytes), aligned to 16 bytes for modulo #[repr(align(16))] @@ -49,11 +44,6 @@ async fn main(_spawner: Spawner) { defmt::info!("DMA wrap transfer example starting..."); - // Enable DMA interrupt (DMA clock/reset/init is handled automatically by HAL) - unsafe { - cortex_m::peripheral::NVIC::unmask(pac::Interrupt::DMA_CH0); - } - let config = Config { baudrate_bps: 115_200, ..Default::default() diff --git a/examples/mcxa/src/bin/i2c-async.rs b/examples/mcxa/src/bin/i2c-async.rs index edcfd5f22..47b5f3cbe 100644 --- a/examples/mcxa/src/bin/i2c-async.rs +++ b/examples/mcxa/src/bin/i2c-async.rs @@ -6,8 +6,8 @@ use embassy_time::Timer; use hal::bind_interrupts; use hal::clocks::config::Div8; use hal::config::Config; -use hal::i2c::InterruptHandler; use hal::i2c::controller::{self, I2c, Speed}; +use hal::i2c::InterruptHandler; use hal::peripherals::LPI2C3; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; diff --git a/examples/mcxa/src/bin/i2c-scan-blocking.rs b/examples/mcxa/src/bin/i2c-scan-blocking.rs index 0197f9b1d..4e203597b 100644 --- a/examples/mcxa/src/bin/i2c-scan-blocking.rs +++ b/examples/mcxa/src/bin/i2c-scan-blocking.rs @@ -2,8 +2,8 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa::Input; use embassy_mcxa::gpio::Pull; +use embassy_mcxa::Input; use embassy_time::Timer; use hal::clocks::config::Div8; use hal::config::Config; diff --git a/examples/mcxa/src/bin/lpuart_buffered.rs b/examples/mcxa/src/bin/lpuart_buffered.rs index 47b56b7c7..420589d00 100644 --- a/examples/mcxa/src/bin/lpuart_buffered.rs +++ b/examples/mcxa/src/bin/lpuart_buffered.rs @@ -3,8 +3,8 @@ use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::lpuart::Config; use embassy_mcxa::lpuart::buffered::BufferedLpuart; +use embassy_mcxa::lpuart::Config; use embassy_mcxa::{bind_interrupts, lpuart}; use embedded_io_async::Write; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; diff --git a/examples/mcxa/src/bin/lpuart_dma.rs b/examples/mcxa/src/bin/lpuart_dma.rs index 34d343452..cc86f6a40 100644 --- a/examples/mcxa/src/bin/lpuart_dma.rs +++ b/examples/mcxa/src/bin/lpuart_dma.rs @@ -12,17 +12,9 @@ use embassy_executor::Spawner; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaCh1InterruptHandler}; use embassy_mcxa::lpuart::{Config, LpuartDma}; -use embassy_mcxa::bind_interrupts; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -// Bind DMA channel interrupts using Embassy-style macro -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; - DMA_CH1 => DmaCh1InterruptHandler; -}); - #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut cfg = hal::config::Config::default(); @@ -40,7 +32,8 @@ async fn main(_spawner: Spawner) { // Create UART instance with DMA channels let mut lpuart = LpuartDma::new( - p.LPUART2, p.P2_2, // TX pin + p.LPUART2, // Instance + p.P2_2, // TX pin p.P2_3, // RX pin p.DMA_CH0, // TX DMA channel p.DMA_CH1, // RX DMA channel diff --git a/examples/mcxa/src/bin/lpuart_ring_buffer.rs b/examples/mcxa/src/bin/lpuart_ring_buffer.rs index b707e20f8..be7fd4534 100644 --- a/examples/mcxa/src/bin/lpuart_ring_buffer.rs +++ b/examples/mcxa/src/bin/lpuart_ring_buffer.rs @@ -19,19 +19,11 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa::bind_interrupts; use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::dma::{DmaCh0InterruptHandler, DmaCh1InterruptHandler}; use embassy_mcxa::lpuart::{Config, LpuartDma, LpuartTxDma}; use static_cell::ConstStaticCell; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -// Bind DMA channel interrupts -bind_interrupts!(struct Irqs { - DMA_CH0 => DmaCh0InterruptHandler; - DMA_CH1 => DmaCh1InterruptHandler; -}); - // Ring buffer for RX - power of 2 is ideal for modulo efficiency static RX_RING_BUFFER: ConstStaticCell<[u8; 64]> = ConstStaticCell::new([0; 64]); -- cgit