{"record":{"id":"8064757ec0487e50","repo":"embassy-rs/embassy","slug":"dma-error-on-dma-0-channel-806475","errorCode":null,"errorMessage":"DMA: error on DMA_0 channel {}","messagePattern":"DMA: error on DMA_0 channel (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"embassy-rp/src/dma.rs","lineNumber":28,"sourceCode":"use embassy_sync::waitqueue::AtomicWaker;\nuse pac::dma::vals::DataSize;\n\nuse crate::interrupt::typelevel::Interrupt;\nuse crate::mode::{Async, Blocking, Mode};\nuse crate::pac::dma::vals;\nuse crate::{RegExt, interrupt, pac, peripherals};\n\n/// DMA interrupt handler.\npub struct InterruptHandler<T: ChannelInstance> {\n    _phantom: PhantomData<T>,\n}\n\nimpl<T: ChannelInstance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {\n    unsafe fn on_interrupt() {\n        let channel = T::number() as usize;\n        let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read();\n        if ctrl_trig.ahb_error() {\n            panic!(\"DMA: error on DMA_0 channel {}\", channel);\n        }\n\n        let ints0 = pac::DMA.ints(0).read();\n        if ints0 & (1 << channel) != 0 {\n            pac::DMA.ints(0).write_value(1 << channel);\n\n            CHANNEL_WAKERS[channel].wake();\n        }\n    }\n}\n\npub(crate) unsafe fn init() {\n    interrupt::DMA_IRQ_0.set_priority(interrupt::Priority::P3);\n}\n\n/// DMA channel driver.\npub struct Channel<'d, M: Mode> {\n    number: u8,","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-rp/src/dma.rs#L10-L46","documentation":"The DMA interrupt handler checks each channel's `ctrl_trig.ahb_error` flag and panics if the DMA transfer hit an AHB bus error (bad address, inaccessible peripheral memory, or FIFO underrun/overrun at the bus level). This indicates the transfer descriptor pointed at invalid or unserviced memory.","triggerScenarios":"A DMA channel configured with a read/write address that is invalid or becomes invalid mid-transfer (unmapped RAM region, peripheral FIFO not ready), triggering `ahb_error` when the IRQ fires; chained transfers with wrong ring/carrier addresses.","commonSituations":"DMA into/from a buffer moved or dropped while transfer is in flight (stack buffer, dangling pointer); using DMA with flash/XIP regions incorrectly; wrong DREQ selection causing FIFO underrun on a peripheral; buffer size crossing an address boundary the bus forbids.","solutions":["Verify the buffer passed to the DMA transfer outlives the transfer (use `'static`/owned buffers, not stack locals)","Check the read/write address and DREQ settings on channel `ch(channel)` configuration for the reported channel number","Reproduce with the channel number from the panic and inspect its `read_addr`/`trans_count` registers in a debugger","Ensure the peripheral is enabled/clocked before the DMA transfer starts","Handle errors gracefully by replacing the panic-based IRQ handler with one that logs and aborts the channel"],"exampleFix":"// before\nfn send(mut buf: [u8; 64]) { dma.write(buf.into(), ...).await; } // buf dies at fn end, DMA may fault\n// after\nasync fn send(dma: &mut DmaChannel, buf: &'static mut [u8; 64]) { dma.write(buf.into(), ...).await; } // static/lifetime-safe buffer\n","handlingStrategy":"type-guard","validationCode":"fn validate_dma_target(buf: &[u8]) -> Result<(), &'static str> {\n    if buf.as_ptr() as u32 >= 0x2000_0000 && buf.as_ptr() as u32 < 0x2004_2000 { Ok(()) } else { Err(\"DMA buffer must be in SRAM\") }\n}\n// Also ensure the buffer is 'static / owned for the transfer duration.\n","typeGuard":"fn is_sram_slice<T>(s: &[T]) -> bool {\n    let a = s.as_ptr() as usize;\n    (0x2000_0000..0x2004_2000).contains(&a)\n}\n","tryCatchPattern":null,"preventionTips":["Only hand DMA slices that live in SRAM and outlive the transfer","Use embassy-rp's typed buffer abstractions (owned/'static buffers) instead of raw pointers","Never start DMA before the target peripheral is enabled and clocked","Verify DREQ selection matches the peripheral to avoid FIFO faults"],"tags":["rust","embedded","rp2040","dma","bus-error","interrupt"],"backgroundTag":"internal-invariant-violation","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}