/* * Copyright (c) 2024 Baumer Electric AG * * SPDX-License-Identifier: Apache-2.0 */ /** * @brief Assembler-hooks specific to Nuclei's Extended Core Interrupt Controller */ #include GTEXT(__soc_handle_irq) /* * In an ECLIC, pending interrupts don't have to be cleared by hand. * In vectored mode, interrupts are cleared automatically. * In non-vectored mode, interrupts are cleared when writing the mnxti register (done in * __soc_handle_all_irqs). * Thus this function can directly return. */ SECTION_FUNC(exception.other, __soc_handle_irq) ret GTEXT(__soc_handle_all_irqs) #ifdef CONFIG_TRACING /* imports */ GTEXT(sys_trace_isr_enter) GTEXT(sys_trace_isr_exit) #endif /* * This function services and clears all pending interrupts for an ECLIC in non-vectored mode. */ SECTION_FUNC(exception.other, __soc_handle_all_irqs) addi sp, sp, -16 sw ra, 0(sp) /* Read and clear mnxti to get highest current interrupt and enable interrupts. Will return * original interrupt if no others appear. */ csrrci a0, 0x345, MSTATUS_IEN beqz a0, irq_done /* Check if original interrupt vanished. */ irq_loop: #ifdef CONFIG_TRACING_ISR call sys_trace_isr_enter #endif /* Call corresponding registered function in _sw_isr_table. a0 is offset in pointer with * the mtvt, sw irq table is 2-pointer wide -> shift by one. */ csrr t0, 0x307 /* mtvt */ sub a0, a0, t0 la t0, _sw_isr_table slli a0, a0, (1) add t0, t0, a0 /* Load argument in a0 register */ lw a0, 0(t0) /* Load ISR function address in register t1 */ lw t1, RV_REGSIZE(t0) /* Call ISR function */ jalr ra, t1, 0 #ifdef CONFIG_TRACING_ISR call sys_trace_isr_exit #endif /* Read and clear mnxti to get highest current interrupt and enable interrupts. */ csrrci a0, 0x345, MSTATUS_IEN bnez a0, irq_loop irq_done: lw ra, 0(sp) addi sp, sp, 16 ret