LogEtComUSB/lib/sd_driver/dma_interrupts.c

86 lines
2.7 KiB
C

#include "hw_config.h"
#include "sd_card.h"
//
#include "dma_interrupts.h"
static void dma_irq_handler(const uint DMA_IRQ_num, io_rw_32 *dma_hw_ints_p) {
// Iterate through all of the SD cards
for (size_t i = 0; i < sd_get_num(); ++i) {
sd_card_t *sd_card_p = sd_get_by_num(i);
if (!sd_card_p)
continue;
uint irq_num = 0, channel = 0;
if (SD_IF_SDIO == sd_card_p->type) {
irq_num = sd_card_p->sdio_if_p->DMA_IRQ_num;
channel = sd_card_p->sdio_if_p->state.SDIO_DMA_CHB;
}
// Is this channel requesting interrupt?
if (irq_num == DMA_IRQ_num && (*dma_hw_ints_p & (1 << channel))) {
*dma_hw_ints_p = 1 << channel; // Clear it.
if (SD_IF_SDIO == sd_card_p->type) {
sdio_irq_handler(sd_card_p);
}
}
}
}
static void __not_in_flash_func(dma_irq_handler_0)() {
dma_irq_handler(DMA_IRQ_0, &dma_hw->ints0);
}
static void __not_in_flash_func(dma_irq_handler_1)() {
dma_irq_handler(DMA_IRQ_1, &dma_hw->ints1);
}
/* Adding the interrupt request handler
Only add it once.
Otherwise, space is wasted in irq_add_shared_handler's table.
Also, each core maintains its own table of interrupt vectors,
and we don't want both cores to call the IRQ handler.
*/
typedef struct ih_added_rec_t {
uint num;
bool added;
} ih_added_rec_t;
static ih_added_rec_t ih_added_recs[] = {
{DMA_IRQ_0, false},
{DMA_IRQ_1, false}};
static bool is_handler_added(const uint num) {
for (size_t i = 0; i < count_of(ih_added_recs); ++i)
if (num == ih_added_recs[i].num)
return ih_added_recs[i].added;
return false;
}
static void mark_handler_added(const uint num) {
size_t i;
for (i = 0; i < count_of(ih_added_recs); ++i)
if (num == ih_added_recs[i].num) {
ih_added_recs[i].added = true;
break;
}
myASSERT(i < count_of(ih_added_recs));
}
void dma_irq_add_handler(const uint num, bool exclusive) {
if (!is_handler_added(num)) {
static void (*irq_handler)();
switch (num) {
case DMA_IRQ_0:
irq_handler = dma_irq_handler_0;
break;
case DMA_IRQ_1:
irq_handler = dma_irq_handler_1;
break;
default:
myASSERT(false);
}
if (exclusive) {
irq_set_exclusive_handler(num, *irq_handler);
} else {
irq_add_shared_handler(
num, *irq_handler,
PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
}
irq_set_enabled(num, true); // Enable IRQ in NVIC
mark_handler_added(num);
}
}