From 3f49a57b99e7fe5aafa73e70ed146d98b1ae174c Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 24 Feb 2025 22:54:30 -0700 Subject: libhw: rp2040_hwspi: Use interrupts instead of busy-polling --- libhw/rp2040_dma.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 libhw/rp2040_dma.c (limited to 'libhw/rp2040_dma.c') diff --git a/libhw/rp2040_dma.c b/libhw/rp2040_dma.c new file mode 100644 index 0000000..dfbf136 --- /dev/null +++ b/libhw/rp2040_dma.c @@ -0,0 +1,56 @@ +/* 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<