From d2cda57e9d6a6dedecf7f581c4e4e960d9fdd877 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 12 Mar 2026 10:50:19 +1100 Subject: [PATCH] rp2/rp2_dma: Disable DMA IRQ before clearing handler function. Both the overall IRQ line and the per-channel IRQ, for good measure. Otherwise, soft reset will remove the handler before the finaliser for the DMA object(s) run and trigger IRQs if the channel is still active. Closes #18765 This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- ports/rp2/rp2_dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/rp2/rp2_dma.c b/ports/rp2/rp2_dma.c index 471cf24ea..bb935f3b4 100644 --- a/ports/rp2/rp2_dma.c +++ b/ports/rp2/rp2_dma.c @@ -427,6 +427,9 @@ static mp_obj_t rp2_dma_close(mp_obj_t self_in) { uint8_t channel = self->channel; if (channel != CHANNEL_CLOSED) { + // Disable channel IRQ + dma_channel_set_irq0_enabled(channel, false); + // Reset this channel's registers to their default values (zeros). dma_channel_config config = { .ctrl = 0 }; dma_channel_configure(channel, &config, NULL, NULL, 0, false); @@ -441,7 +444,6 @@ static mp_obj_t rp2_dma_close(mp_obj_t self_in) { if (irq) { irq->parent = MP_OBJ_NULL; irq->handler = MP_OBJ_NULL; - dma_channel_set_irq0_enabled(channel, false); } dma_channel_unclaim(channel); self->channel = CHANNEL_CLOSED; @@ -479,7 +481,8 @@ void rp2_dma_init(void) { } void rp2_dma_deinit(void) { - // Remove our interrupt handler. + // Disable and remove our interrupt handler. + irq_set_enabled(DMA_IRQ_0, false); irq_remove_handler(DMA_IRQ_0, rp2_dma_irq_handler); }