diff --git a/arch/common/sw_isr_common.c b/arch/common/sw_isr_common.c index 538c03603f2..2aa6202aaee 100644 --- a/arch/common/sw_isr_common.c +++ b/arch/common/sw_isr_common.c @@ -71,6 +71,43 @@ unsigned int get_parent_offset(unsigned int parent_irq, #endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ +unsigned int z_get_sw_isr_table_idx(unsigned int irq) +{ + unsigned int table_idx; + +#ifdef CONFIG_MULTI_LEVEL_INTERRUPTS + unsigned int level, parent_irq, parent_offset; + + level = irq_get_level(irq); + + if (level == 2U) { + parent_irq = irq_parent_level_2(irq); + parent_offset = get_parent_offset(parent_irq, + lvl2_irq_list, + CONFIG_NUM_2ND_LEVEL_AGGREGATORS); + table_idx = parent_offset + irq_from_level_2(irq); + } +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + else if (level == 3U) { + parent_irq = irq_parent_level_3(irq); + parent_offset = get_parent_offset(parent_irq, + lvl3_irq_list, + CONFIG_NUM_3RD_LEVEL_AGGREGATORS); + table_idx = parent_offset + irq_from_level_3(irq); + } +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + else { + table_idx = irq; + } + + table_idx -= CONFIG_GEN_IRQ_START_VECTOR; +#else + table_idx = irq - CONFIG_GEN_IRQ_START_VECTOR; +#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ + + return table_idx; +} + void z_isr_install(unsigned int irq, void (*routine)(const void *), const void *param) { @@ -85,37 +122,7 @@ void z_isr_install(unsigned int irq, void (*routine)(const void *), __ASSERT(!irq_is_enabled(irq), "IRQ %d is enabled", irq); #endif /* !CONFIG_GIC */ -#ifdef CONFIG_MULTI_LEVEL_INTERRUPTS - unsigned int level; - unsigned int parent_irq; - unsigned int parent_offset; - - level = irq_get_level(irq); - - if (level == 2U) { - parent_irq = irq_parent_level_2(irq); - parent_offset = get_parent_offset(parent_irq, - lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - table_idx = parent_offset + irq_from_level_2(irq); - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - parent_irq = irq_parent_level_3(irq); - parent_offset = get_parent_offset(parent_irq, - lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - table_idx = parent_offset + irq_from_level_3(irq); - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - else { - table_idx = irq; - } - - table_idx -= CONFIG_GEN_IRQ_START_VECTOR; -#else - table_idx = irq - CONFIG_GEN_IRQ_START_VECTOR; -#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ + table_idx = z_get_sw_isr_table_idx(irq); /* If dynamic IRQs are enabled, then the _sw_isr_table is in RAM and * can be modified diff --git a/include/zephyr/sw_isr_table.h b/include/zephyr/sw_isr_table.h index dd700fdfd46..bd301e47592 100644 --- a/include/zephyr/sw_isr_table.h +++ b/include/zephyr/sw_isr_table.h @@ -77,6 +77,16 @@ void z_shared_isr(const void *data); extern struct z_shared_isr_table_entry z_shared_sw_isr_table[]; #endif /* CONFIG_SHARED_INTERRUPTS */ +/** + * @brief Helper function used to compute the index in _sw_isr_table + * based on passed IRQ. + * + * @param irq IRQ number in its zephyr format + * + * @return corresponding index in _sw_isr_table + */ +unsigned int z_get_sw_isr_table_idx(unsigned int irq); + /** This interrupt gets put directly in the vector table */ #define ISR_FLAG_DIRECT BIT(0)