{"record":{"id":"55eec77c9886e8bc","repo":"embassy-rs/embassy","slug":"failed-to-find-dma-interrupt-for-channel","errorCode":null,"errorMessage":"failed to find dma interrupt for channel {}","messagePattern":"failed to find dma interrupt for channel (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/build.rs","lineNumber":2684,"sourceCode":"        let stop_mode = dma_peri\n            .rcc\n            .as_ref()\n            .map(|rcc| rcc.stop_mode.clone())\n            .unwrap_or_default();\n\n        let stop_mode = match stop_mode {\n            StopMode::Standby => quote! { Standby },\n            StopMode::Stop2 => quote! { Stop2 },\n            StopMode::Stop1 => quote! { Stop1 },\n        };\n\n        let name = format_ident!(\"{}\", ch.name);\n\n        // Get the interrupt type for this DMA channel\n        let irq_name = dma_ch_to_irq\n            .get(ch.name)\n            .and_then(|v| v.first())\n            .unwrap_or_else(|| panic!(\"failed to find dma interrupt for channel {}\", ch.name));\n        let irq_ident = format_ident!(\"{}\", irq_name);\n        let irq_type = quote!(crate::interrupt::typelevel::#irq_ident);\n\n        #[cfg(feature = \"_dual-core\")]\n        let irq_pac = quote!(crate::pac::Interrupt::#irq_ident);\n\n        g.extend(quote!(dma_channel_impl!(#name, #irq_type);));\n\n        if ch.supports_2d.unwrap_or(false) {\n            g.extend(quote!(dma_channel_2d_impl!(#name);));\n        }\n\n        let dma = format_ident!(\"{}\", ch.dma);\n        let ch_num = ch.channel as usize;\n        let bi = dma_peri.registers.as_ref().unwrap();\n\n        if ch.supports_2d.unwrap_or(false) && bi.kind == \"gpdma\" {\n            has_gpdma_2d = true;","sourceCodeStart":2666,"sourceCodeEnd":2702,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/build.rs#L2666-L2702","documentation":"While generating DMA channel traits, build.rs maps each DMA channel to its interrupt (IRQ) name via a `dma_ch_to_irq` lookup built from chip metadata. If a DMA channel has no associated interrupt entry, the script panics naming the channel. It indicates a gap in the chip's interrupt/DMA metadata, so the channel can't be wired to an interrupt handler.","triggerScenarios":"Building with DMA for a chip whose metadata lists a DMA/GPDMA/LPDMA channel without any matching interrupt in the interrupt table, so `.get(ch.name).and_then(|v| v.first())` is None.","commonSituations":"Newly added STM32 parts with incomplete DMA-to-IRQ metadata; channels shared across cores (dual-core parts) where the mapping wasn't populated.","solutions":["Check embassy-stm32's per-chip metadata and add the missing DMA-channel-to-interrupt mapping.","Verify you're on the latest embassy-stm32 — the chip's metadata may have been fixed upstream.","As a workaround, use a different DMA channel whose interrupt mapping exists."],"exampleFix":"// metadata: ch \"GPDMA1_CHANNEL7\" has no IRQ entry\n// before (chip data): { name: \"GPDMA1_CHANNEL7\", ... } // no irq\n// after: add \"GPDMA1_CHANNEL7\" => [\"GPDMA1_CHANNEL7\"] to the dma irq mapping","handlingStrategy":"validation","validationCode":"// check the chip's DMA channel -> IRQ mapping exists before using that channel\n// in embassy-stm32 data: dma_ch_to_irq must contain ch.name","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use DMA channels known to be wired to interrupts on your chip.","Update embassy-stm32 when adding support for a new MCU to pick up metadata fixes.","Validate per-chip metadata (channel/interrupt tables) when onboarding a new STM32 part."],"tags":["dma","interrupt","build-script","metadata"],"backgroundTag":"resource-not-found","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"}