/** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "pico/stdlib.h" #include "pico/test.h" #include "pico/time.h" #include "hardware/irq.h" #include "hardware/dma.h" #include "hardware/structs/scb.h" PICOTEST_MODULE_NAME("IRQ", "IRQ Handler test"); extern void __unhandled_user_irq(void); static bool remove_handler1_in_dma; static bool remove_handler2_in_dma; static bool remove_handler3_in_dma; static dma_channel_config config; #define MAX_FIRE_COUNT 4 static int fire_count; static int fired[MAX_FIRE_COUNT]; static uint32_t dma_to = 0; static uint32_t dma_from = 0xaaaa5555; int record_fire(int which) { PICOTEST_CHECK(fire_count < MAX_FIRE_COUNT, "too many firings"); fired[fire_count++] = which; return 0; } void __isr handler1(void) { record_fire(1); dma_channel_acknowledge_irq0(0); if (remove_handler1_in_dma) { irq_remove_handler(DMA_IRQ_0, handler1); remove_handler1_in_dma = false; } } void __isr handler2(void) { record_fire(2); dma_channel_acknowledge_irq0(0); if (remove_handler2_in_dma) { irq_remove_handler(DMA_IRQ_0, handler2); remove_handler2_in_dma = false; } } void __isr handler3(void) { record_fire(3); dma_channel_acknowledge_irq0(0); if (remove_handler3_in_dma) { irq_remove_handler(DMA_IRQ_0, handler3); remove_handler3_in_dma = false; } } static inline irq_handler_t *get_vtable(void) { return (irq_handler_t *) scb_hw->vtor; } int dma_check(int expected, ...) { if (expected == 0) { // doing the DMA if there are no IRQ handlers will cause a hard fault, so we just check we are pointing at the handler which does this. PICOTEST_CHECK_AND_ABORT(get_vtable()[16 + DMA_IRQ_0] == __unhandled_user_irq, "Expected there to be no IRQ handlers"); return 0; } fire_count = 0; dma_channel_configure(0, &config, &dma_to, &dma_from, 1, true); sleep_ms(100); va_list args; va_start(args, expected); bool ok = expected == fire_count; for(int i=0;ok && i