diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 6ceabb0d9d..89bf09e1e9 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -18,10 +18,10 @@ #include "sdkconfig.h" - .equ SAVE_REGS, 32 - .equ CONTEXT_SIZE, (SAVE_REGS * 4) - .equ panic_from_exception, xt_unhandled_exception - .equ panic_from_isr, panicHandler + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) + .equ panic_from_exception, xt_unhandled_exception + .equ panic_from_isr, panicHandler /* Macro which first allocates space on the stack to save general * purpose registers, and then save them. GP register is excluded. @@ -61,8 +61,8 @@ .endm .macro save_mepc - csrr t0, mepc - sw t0, RV_STK_MEPC(sp) + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) .endm /* Restore the general purpose registers (excluding gp) from the context on @@ -102,51 +102,51 @@ .endm .macro restore_mepc - lw t0, RV_STK_MEPC(sp) - csrw mepc, t0 + lw t0, RV_STK_MEPC(sp) + csrw mepc, t0 .endm - .global rtos_int_enter - .global rtos_int_exit - .global _global_interrupt_handler + .global rtos_int_enter + .global rtos_int_exit + .global _global_interrupt_handler - .section .exception_vectors.text - /* This is the vector table. MTVEC points here. - * - * Use 4-byte intructions here. 1 instruction = 1 entry of the table. - * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, - * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. - * - * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU - * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). - */ + .section .exception_vectors.text + /* This is the vector table. MTVEC points here. + * + * Use 4-byte intructions here. 1 instruction = 1 entry of the table. + * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, + * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. + * + * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU + * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). + */ - .balign 0x100 - .global _vector_table - .type _vector_table, @function + .balign 0x100 + .global _vector_table + .type _vector_table, @function _vector_table: - .option push - .option norvc - j _panic_handler /* exception handler, entry 0 */ - .rept (ETS_T1_WDT_INUM - 1) - j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */ - .endr - j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/ + .option push + .option norvc + j _panic_handler /* exception handler, entry 0 */ + .rept (ETS_T1_WDT_INUM - 1) + j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */ + .endr + j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/ j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/ #ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE j _panic_handler /* Call panic handler for ETS_MEMPROT_ERR_INUM interrupt (soc-level panic)*/ - .rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM) - #else - .rept (ETS_MAX_INUM - ETS_CACHEERR_INUM) - #endif - j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */ - .endr + .rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM) + #else + .rept (ETS_MAX_INUM - ETS_CACHEERR_INUM) + #endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE + j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */ + .endr - .option pop - .size _vector_table, .-_vector_table + .option pop + .size _vector_table, .-_vector_table - /* Exception handler.*/ - .type _panic_handler, @function + /* Exception handler.*/ + .type _panic_handler, @function _panic_handler: /* Allocate space on the stack and store general purpose registers */ save_general_regs RV_STK_FRMSZ @@ -154,44 +154,44 @@ _panic_handler: /* As gp register is not saved by the macro, save it here */ sw gp, RV_STK_GP(sp) - /* Same goes for the SP value before trapping */ - addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */ - sw t0, RV_STK_SP(sp) + /* Same goes for the SP value before trapping */ + addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */ - /* Save CSRs */ - csrr t0, mepc - sw t0, RV_STK_MEPC(sp) - csrr t0, mstatus - sw t0, RV_STK_MSTATUS(sp) - csrr t0, mtvec - sw t0, RV_STK_MTVEC(sp) - csrr t0, mtval - sw t0, RV_STK_MTVAL(sp) - csrr t0, mhartid - sw t0, RV_STK_MHARTID(sp) + /* Save CSRs */ + sw t0, RV_STK_SP(sp) + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) + csrr t0, mstatus + sw t0, RV_STK_MSTATUS(sp) + csrr t0, mtvec + sw t0, RV_STK_MTVEC(sp) + csrr t0, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) - /* Call panic_from_exception(sp) or panic_from_isr(sp) - * depending on whether we have a pseudo excause or not. - * If mcause's highest bit is 1, then an interrupt called this routine, - * so we have a pseudo excause. Else, it is due to a exception, we don't - * have an pseudo excause */ - mv a0, sp - csrr a1, mcause - /* Branches instructions don't accept immediates values, so use t1 to - * store our comparator */ - li t0, 0x80000000 - bgeu a1, t0, _call_panic_handler - sw a1, RV_STK_MCAUSE(sp) + /* Call panic_from_exception(sp) or panic_from_isr(sp) + * depending on whether we have a pseudo excause or not. + * If mcause's highest bit is 1, then an interrupt called this routine, + * so we have a pseudo excause. Else, it is due to a exception, we don't + * have an pseudo excause */ + mv a0, sp + csrr a1, mcause + /* Branches instructions don't accept immediates values, so use t1 to + * store our comparator */ + li t0, 0x80000000 + bgeu a1, t0, _call_panic_handler + sw a1, RV_STK_MCAUSE(sp) jal panic_from_exception /* We arrive here if the exception handler has returned. */ j _return_from_exception _call_panic_handler: - /* Remove highest bit from mcause (a1) register and save it in the - * structure */ - not t0, t0 - and a1, a1, t0 - sw a1, RV_STK_MCAUSE(sp) + /* Remove highest bit from mcause (a1) register and save it in the + * structure */ + not t0, t0 + and a1, a1, t0 + sw a1, RV_STK_MCAUSE(sp) jal panic_from_isr /* We arrive here if the exception handler has returned. This means that @@ -208,18 +208,19 @@ _return_from_exception: mret .size _panic_handler, .-_panic_handler - /* This is the interrupt handler. - * It saves the registers on the stack, - * prepares for interrupt nesting, - * re-enables the interrupts, - * then jumps to the C dispatcher in interrupt.c. - */ - .global _interrupt_handler - .type _interrupt_handler, @function + /* This is the interrupt handler. + * It saves the registers on the stack, + * prepares for interrupt nesting, + * re-enables the interrupts, + * then jumps to the C dispatcher in interrupt.c. + */ + .global _interrupt_handler + .type _interrupt_handler, @function _interrupt_handler: - /* entry */ - save_general_regs - save_mepc + /* Start by saving the general purpose registers and the PC value before + * the interrupt happened. */ + save_general_regs + save_mepc /* Though it is not necessary we save GP and SP here. * SP is necessary to help GDB to properly unwind @@ -232,80 +233,84 @@ _interrupt_handler: /* Save SP */ sw t0, RV_STK_SP(sp) - /* Before doing anythig preserve the stack pointer */ - /* It will be saved in current TCB, if needed */ - mv a0, sp - call rtos_int_enter + /* Before doing anythig preserve the stack pointer */ + /* It will be saved in current TCB, if needed */ + mv a0, sp + call rtos_int_enter + /* If this is a non-nested interrupt, SP now points to the interrupt stack */ - /* Before dispatch c handler, restore interrupt to enable nested intr */ - csrr s1, mcause - csrr s2, mstatus + /* Before dispatch c handler, restore interrupt to enable nested intr */ + csrr s1, mcause + csrr s2, mstatus - /* Save the interrupt threshold level */ - la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG - lw s3, 0(t0) + /* Save the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + lw s3, 0(t0) - /* Increase interrupt threshold level */ - li t2, 0x7fffffff - and t1, s1, t2 /* t1 = mcause & mask */ - slli t1, t1, 2 /* t1 = mcause * 4 */ - la t2, INTC_INT_PRIO_REG(0) - add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ - lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ - addi t2, t2, 1 /* t2 = t2 +1 */ - sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ - fence + /* Increase interrupt threshold level */ + li t2, 0x7fffffff + and t1, s1, t2 /* t1 = mcause & mask */ + slli t1, t1, 2 /* t1 = mcause * 4 */ + la t2, INTC_INT_PRIO_REG(0) + add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ + lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ + addi t2, t2, 1 /* t2 = t2 +1 */ + sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ + fence - li t0, 0x8 - csrrs t0, mstatus, t0 + li t0, 0x8 + csrrs t0, mstatus, t0 + /* MIE set. Nested interrupts can now occur */ - #ifdef CONFIG_PM_TRACE - li a0, 0 /* = ESP_PM_TRACE_IDLE */ - #if SOC_CPU_CORES_NUM == 1 - li a1, 0 /* No need to check core ID on single core hardware */ - #else - csrr a1, mhartid - #endif - la t0, esp_pm_trace_exit - jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ - #endif + #ifdef CONFIG_PM_TRACE + li a0, 0 /* = ESP_PM_TRACE_IDLE */ + #if SOC_CPU_CORES_NUM == 1 + li a1, 0 /* No need to check core ID on single core hardware */ + #else + csrr a1, mhartid + #endif + la t0, esp_pm_trace_exit + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif - #ifdef CONFIG_PM_ENABLE - la t0, esp_pm_impl_isr_hook - jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ - #endif + #ifdef CONFIG_PM_ENABLE + la t0, esp_pm_impl_isr_hook + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif - /* call the C dispatcher */ - mv a0, sp /* argument 1, stack pointer */ - mv a1, s1 /* argument 2, interrupt number (mcause) */ - /* mask off the interrupt flag of mcause */ - li t0, 0x7fffffff - and a1, a1, t0 - jal _global_interrupt_handler + /* call the C dispatcher */ + mv a0, sp /* argument 1, stack pointer */ + mv a1, s1 /* argument 2, interrupt number (mcause) */ + /* mask off the interrupt flag of mcause */ + li t0, 0x7fffffff + and a1, a1, t0 + jal _global_interrupt_handler - /* After dispatch c handler, disable interrupt to make freertos make context switch */ + /* After dispatch c handler, disable interrupt to make freertos make context switch */ - li t0, 0x8 - csrrc t0, mstatus, t0 + li t0, 0x8 + csrrc t0, mstatus, t0 + /* MIE cleared. Nested interrupts are disabled */ - /* restore the interrupt threshold level */ - la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG - sw s3, 0(t0) - fence + /* restore the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + sw s3, 0(t0) + fence - /* Yield to the next task is needed: */ - mv a0, sp - call rtos_int_exit + /* Yield to the next task is needed: */ + mv a0, sp + call rtos_int_exit + /* If this is a non-nested interrupt, context switch called, SP now points to back to task stack. */ - /* The next (or current) stack pointer is returned in a0 */ - mv sp, a0 + /* The next (or current) stack pointer is returned in a0 */ + mv sp, a0 - /* restore the rest of the registers */ - csrw mcause, s1 - csrw mstatus, s2 - restore_mepc - restore_general_regs + /* restore the rest of the registers */ + csrw mcause, s1 + csrw mstatus, s2 + restore_mepc + restore_general_regs - /* exit, this will also re-enable the interrupts */ - mret - .size _interrupt_handler, .-_interrupt_handler + /* exit, this will also re-enable the interrupts */ + mret + .size _interrupt_handler, .-_interrupt_handler