embassy-rs/embassy · critical
DMA: error on DMA_0 channel
Error message
DMA: error on DMA_0 channel {} What it means
In the LPC55 DMA interrupt handler, each channel with an error bit set in `errint0` causes an immediate panic naming the failing channel. DMA transfer errors (bus errors, invalid descriptors) on LPC55 are treated as unrecoverable by this driver rather than returned to the application. The panic aborts the firmware at the point of the interrupt.
Solutions
- Identify the failing channel from the panic message and audit what transfer that channel was running (addresses, lengths, peripheral).
- Validate the source/destination addresses and buffer sizes passed to the DMA transfer API before starting it.
- Ensure the source peripheral is powered/clocked and its DMA requests are correctly wired in your init code.
- Update embassy-nxp in case the driver has gained proper error handling (Result-returning transfers) since your version.
Example fix
// before let dma_channel = p.DMA0_CH0.into(); dma_channel.read(&mut weird_ptr as *mut u8, &mut buf).await; // invalid address -> bus error // after assert!(core::ptr::addr_of!(buf).is_aligned()); dma_channel.read(&mut peripheral_rx_addr, &mut buf).await; // valid mapped peripheral address
Defensive patterns
Strategy: validation
Validate before calling
// Before issuing a DMA transfer, validate addresses and lengths:
fn dma_transfer_ok(src: *const u8, dst: *mut u8, len: usize) -> bool {
!src.is_null() && !dst.is_null() && len > 0
&& (src as usize) >= 0x0000_0000 && (dst as usize) < 0x2000_0000
// plus peripheral-region checks per your memory map
} Try / catch
// The driver panics in the IRQ; errors cannot be caught at runtime. // Mitigate by pre-validating every transfer configuration before .await:
Prevention
- Validate DMA buffer addresses, alignment, and sizes against the LPC55 memory map before starting transfers.
- Ensure source peripherals are clocked and powered before DMA requests arrive.
- Keep DMA channel usage documented per channel so a panic message maps immediately to a code path.
When it happens
Trigger: A DMA transfer on DMA_0 encounters a hardware error (source/destination bus fault, misaligned or invalid transfer configuration, descriptor issue); the DMA0 IRQ fires, the handler scans `errint0` and finds the error bit for the channel.
Common situations: DMA-ing from/to a peripheral or memory region that is not accessible (wrong address, powered-down peripheral); buffer in uncacheable/invalid memory; race where the transfer is configured with a zero length or bad burst settings; hardware fault on the bus.
Related errors
- DMA data error
- DMA: error on DMA@ channel
- DMA: error on BDMA@ channel
- DMA: error on MDMA@ channel
- unrecognized rx error
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/c1d500d32738be9a.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-nxp/src/dma/lpc55.rs:25
use core::task::{Context, Poll};
use critical_section::Mutex;
use embassy_hal_internal::interrupt::InterruptExt;
use embassy_hal_internal::{PeripheralType, impl_peripheral};
use embassy_sync::waitqueue::AtomicWaker;
use crate::Peri;
#[cfg(feature = "rt")]
use crate::pac::interrupt;
use crate::pac::{SYSCON, *};
#[cfg(feature = "rt")]
#[interrupt]
fn DMA0() {
let inta = DMA0.inta0().read().ia();
for channel in 0..CHANNEL_COUNT {
if (DMA0.errint0().read().err() & (1 << channel)) != 0 {
panic!("DMA: error on DMA_0 channel {}", channel);
}
if (inta & (1 << channel)) != 0 {
CHANNEL_WAKERS[channel].wake();
DMA0.inta0().modify(|w| w.set_ia(1 << channel));
}
}
}
pub(crate) fn init() {
assert_eq!(core::mem::size_of::<DmaDescriptor>(), 16, "Descriptor must be 16 bytes");
assert_eq!(
core::mem::align_of::<DmaDescriptor>(),
16,
"Descriptor must be 16-byte aligned"
);
assert_eq!(
core::mem::align_of::<DmaDescriptorTable>(),View on GitHub (pinned to 463a07b963)