embassy-rs/embassy · critical
DMA: link transfer error on DMA@
Error message
DMA: link transfer error on DMA@{:08x} channel {} What it means
The GPDMA channel IRQ handler found the link transfer error flag (ULEF) set: an error occurred while fetching or executing a linked-list item (LLI). The linked-list descriptor address was invalid or the LLI itself was corrupted/unreachable. The driver panics because linked-list state can no longer be trusted.
Solutions
- Place linked-list items in DMA-accessible, writable RAM (not flash/DTCM)
- Ensure LLI descriptors have required alignment and outlive the transfer
- Verify each LLI's next-address field (la/pa) points to a valid item or terminates correctly
- Update embassy-stm32 if using the linked-list API, as this area is under active development
Example fix
// before
fn build(x: &[u8]) -> Transfer { let lli = LLi::new(...); Transfer::new(lli) } // lli dropped
// after
static mut LLI: LLiState = LLiState::new(); // keep descriptor alive in RAM
fn build(x: &[u8]) -> Transfer { Transfer::new(unsafe { &mut LLI }) } Defensive patterns
Strategy: validation
Validate before calling
fn lli_valid(lli_addr: u32, item_size: usize) -> bool {
lli_addr != 0 && lli_addr % core::mem::align_of::<LLiState>() as u32 == 0
// must be in DMA-reachable RAM, e.g. SRAM region
&& (0x2000_0000..0x2004_0000).contains(&lli_addr)
&& core::mem::size_of::<LLiState>() == item_size
} Prevention
- Keep linked-list items in static, DMA-reachable RAM for the transfer's lifetime
- Never drop or move LLi descriptors while the channel is running
- Ensure LLI next-pointer fields point to valid, aligned items or terminate properly
- Use the latest embassy-stm32; the linked-list API is still evolving
When it happens
Trigger: Using linked-list mode (DMA linked-list/ring APIs) where an LLI points to invalid memory, an unaligned descriptor, or a descriptor in DMA-inaccessible memory; LLI struct modified while the channel runs.
Common situations: Building custom linked-list item chains with embassy's gpdma linked-list API and placing items in flash or DTCM; forgetting to keep LLiState items alive (dropped stack descriptors).
Related errors
- DMA transfers may not be larger than 65535 bytes.
- DMA: data transfer error on DMA@
- DMA: user settings error on DMA@
- Boot prepare error
- DMA data error
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/6932a34a99c985db.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/dma/gpdma/mod.rs:576
let ch = info.dma.ch(info.num);
let sr = ch.sr().read();
if sr.dtef() {
panic!(
"DMA: data transfer error on DMA@{:08x} channel {}",
info.dma.cast().as_ptr() as u32,
info.num
);
}
if sr.usef() {
panic!(
"DMA: user settings error on DMA@{:08x} channel {}",
info.dma.cast().as_ptr() as u32,
info.num
);
}
if sr.ulef() {
panic!(
"DMA: link transfer error on DMA@{:08x} channel {}",
info.dma.cast().as_ptr() as u32,
info.num
);
}
if sr.htf() {
ch.fcr().write(|w| w.set_htf(true));
}
if sr.tcf() {
ch.fcr().write(|w| w.set_tcf(true));
let lli_count = state.lli_state.count.load(Ordering::Acquire);
let complete = if lli_count > 0 {
let next_lli_index = state.lli_state.index.load(Ordering::Acquire) + 1;
let complete = next_lli_index >= lli_count;
View on GitHub (pinned to 463a07b963)