/* libhw/rp2040_dma.c - Utilities for sharing the DMA IRQs * * Copyright (C) 2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include #include /* for irq_set_exclusive_handler() */ #include "rp2040_dma.h" struct dmairq_handler_entry { dmairq_handler_t fn; void *arg; }; struct dmairq_handler_entry dmairq_handlers[NUM_DMA_CHANNELS] = {0}; bool dmairq_initialized[NUM_DMA_IRQS] = {0}; static void dmairq_handler(void) { enum dmairq irq = __get_current_exception() - VTABLE_FIRST_IRQ; size_t irq_idx = irq - DMAIRQ_0; assert(irq_idx < NUM_DMA_IRQS); uint32_t regval = dma_hw->irq_ctrl[irq_idx].ints; for (uint channel = 0; channel < NUM_DMA_CHANNELS; channel++) { if (regval & 1u<fn) handler->fn(handler->arg, irq, channel); } } /* acknowledge irq */ dma_hw->intr = regval; } void dmairq_set_and_enable_exclusive_handler(enum dmairq irq, uint channel, dmairq_handler_t fn, void *arg) { assert(irq == DMAIRQ_0 || irq == DMAIRQ_1); assert(channel < NUM_DMA_CHANNELS); assert(fn); assert(dmairq_handlers[channel].fn == NULL); dmairq_handlers[channel].fn = fn; dmairq_handlers[channel].arg = arg; size_t irq_idx = irq - DMAIRQ_0; hw_set_bits(&dma_hw->irq_ctrl[irq_idx].inte, 1u<