In addtion to 1023, the GICC_IAR register may return 1022 as a special value. Simply check for a valid interrupt vector for the dispatching.
Check the GICC_IAR again after the dispatch to quickly process a next interrupt without having to go through the interrupt prologue and epiloge. --- bsps/aarch64/include/dev/irq/arm-gic-arch.h | 12 ++++++---- bsps/arm/include/dev/irq/arm-gic-arch.h | 10 +++++---- bsps/shared/dev/irq/arm-gicv2.c | 25 ++++++++++++++++----- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/bsps/aarch64/include/dev/irq/arm-gic-arch.h b/bsps/aarch64/include/dev/irq/arm-gic-arch.h index f1b6fdc03d..94b832c2c5 100644 --- a/bsps/aarch64/include/dev/irq/arm-gic-arch.h +++ b/bsps/aarch64/include/dev/irq/arm-gic-arch.h @@ -46,14 +46,18 @@ extern "C" { #endif -static inline void arm_interrupt_handler_dispatch(rtems_vector_number vector) +static inline uint32_t arm_interrupt_enable_interrupts(void) { - uint32_t interrupt_level = _CPU_ISR_Get_level(); + uint32_t status = _CPU_ISR_Get_level(); /* Enable interrupts for nesting */ _CPU_ISR_Set_level(0); - bsp_interrupt_handler_dispatch(vector); + return status; +} + +static inline void arm_interrupt_restore_interrupts(uint32_t status) +{ /* Restore interrupts to previous level */ - _CPU_ISR_Set_level(interrupt_level); + _CPU_ISR_Set_level(status); } static inline void arm_interrupt_facility_set_exception_handler(void) diff --git a/bsps/arm/include/dev/irq/arm-gic-arch.h b/bsps/arm/include/dev/irq/arm-gic-arch.h index c9931be61a..f2ea76f22f 100644 --- a/bsps/arm/include/dev/irq/arm-gic-arch.h +++ b/bsps/arm/include/dev/irq/arm-gic-arch.h @@ -44,12 +44,14 @@ extern "C" { #endif -static inline void arm_interrupt_handler_dispatch(rtems_vector_number vector) +static inline uint32_t arm_interrupt_enable_interrupts(void) { - uint32_t psr = _ARMV4_Status_irq_enable(); - bsp_interrupt_handler_dispatch(vector); + return _ARMV4_Status_irq_enable(); +} - _ARMV4_Status_restore(psr); +static inline void arm_interrupt_restore_interrupts(uint32_t status) +{ + _ARMV4_Status_restore(status); } static inline void arm_interrupt_facility_set_exception_handler(void) diff --git a/bsps/shared/dev/irq/arm-gicv2.c b/bsps/shared/dev/irq/arm-gicv2.c index f1730cc2ea..48423c9e08 100644 --- a/bsps/shared/dev/irq/arm-gicv2.c +++ b/bsps/shared/dev/irq/arm-gicv2.c @@ -41,6 +41,14 @@ #include <bsp/irq-generic.h> #include <bsp/start.h> +/* + * The GIC architecture reserves interrupt ID numbers 1020 to 1023 for special + * purposes. + */ +#if BSP_INTERRUPT_VECTOR_COUNT >= 1020 +#error "BSP_INTERRUPT_VECTOR_COUNT is too large" +#endif + #define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE) #define PRIORITY_DEFAULT 127 @@ -75,12 +83,19 @@ void bsp_interrupt_dispatch(void) { volatile gic_cpuif *cpuif = GIC_CPUIF; - uint32_t icciar = cpuif->icciar; - rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar); - rtems_vector_number spurious = 1023; - if (vector != spurious) { - arm_interrupt_handler_dispatch(vector); + while (true) { + uint32_t icciar = cpuif->icciar; + rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar); + uint32_t status; + + if (!bsp_interrupt_is_valid_vector(vector)) { + break; + } + + status = arm_interrupt_enable_interrupts(); + bsp_interrupt_handler_dispatch_unchecked(vector); + arm_interrupt_restore_interrupts(status); cpuif->icceoir = icciar; } -- 2.35.3 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel