mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
riscv: Adds support for returning from exception handler
This commit is contained in:
@@ -23,37 +23,41 @@
|
|||||||
.equ panic_from_exception, xt_unhandled_exception
|
.equ panic_from_exception, xt_unhandled_exception
|
||||||
.equ panic_from_isr, panicHandler
|
.equ panic_from_isr, panicHandler
|
||||||
|
|
||||||
.macro save_regs
|
/* Macro which first allocates space on the stack to save general
|
||||||
addi sp, sp, -CONTEXT_SIZE
|
* purpose registers, and then save them. GP register is excluded.
|
||||||
sw ra, RV_STK_RA(sp)
|
* The default size allocated on the stack is CONTEXT_SIZE, but it
|
||||||
sw tp, RV_STK_TP(sp)
|
* can be overridden. */
|
||||||
sw t0, RV_STK_T0(sp)
|
.macro save_general_regs cxt_size=CONTEXT_SIZE
|
||||||
sw t1, RV_STK_T1(sp)
|
addi sp, sp, -\cxt_size
|
||||||
sw t2, RV_STK_T2(sp)
|
sw ra, RV_STK_RA(sp)
|
||||||
sw s0, RV_STK_S0(sp)
|
sw tp, RV_STK_TP(sp)
|
||||||
sw s1, RV_STK_S1(sp)
|
sw t0, RV_STK_T0(sp)
|
||||||
sw a0, RV_STK_A0(sp)
|
sw t1, RV_STK_T1(sp)
|
||||||
sw a1, RV_STK_A1(sp)
|
sw t2, RV_STK_T2(sp)
|
||||||
sw a2, RV_STK_A2(sp)
|
sw s0, RV_STK_S0(sp)
|
||||||
sw a3, RV_STK_A3(sp)
|
sw s1, RV_STK_S1(sp)
|
||||||
sw a4, RV_STK_A4(sp)
|
sw a0, RV_STK_A0(sp)
|
||||||
sw a5, RV_STK_A5(sp)
|
sw a1, RV_STK_A1(sp)
|
||||||
sw a6, RV_STK_A6(sp)
|
sw a2, RV_STK_A2(sp)
|
||||||
sw a7, RV_STK_A7(sp)
|
sw a3, RV_STK_A3(sp)
|
||||||
sw s2, RV_STK_S2(sp)
|
sw a4, RV_STK_A4(sp)
|
||||||
sw s3, RV_STK_S3(sp)
|
sw a5, RV_STK_A5(sp)
|
||||||
sw s4, RV_STK_S4(sp)
|
sw a6, RV_STK_A6(sp)
|
||||||
sw s5, RV_STK_S5(sp)
|
sw a7, RV_STK_A7(sp)
|
||||||
sw s6, RV_STK_S6(sp)
|
sw s2, RV_STK_S2(sp)
|
||||||
sw s7, RV_STK_S7(sp)
|
sw s3, RV_STK_S3(sp)
|
||||||
sw s8, RV_STK_S8(sp)
|
sw s4, RV_STK_S4(sp)
|
||||||
sw s9, RV_STK_S9(sp)
|
sw s5, RV_STK_S5(sp)
|
||||||
sw s10, RV_STK_S10(sp)
|
sw s6, RV_STK_S6(sp)
|
||||||
sw s11, RV_STK_S11(sp)
|
sw s7, RV_STK_S7(sp)
|
||||||
sw t3, RV_STK_T3(sp)
|
sw s8, RV_STK_S8(sp)
|
||||||
sw t4, RV_STK_T4(sp)
|
sw s9, RV_STK_S9(sp)
|
||||||
sw t5, RV_STK_T5(sp)
|
sw s10, RV_STK_S10(sp)
|
||||||
sw t6, RV_STK_T6(sp)
|
sw s11, RV_STK_S11(sp)
|
||||||
|
sw t3, RV_STK_T3(sp)
|
||||||
|
sw t4, RV_STK_T4(sp)
|
||||||
|
sw t5, RV_STK_T5(sp)
|
||||||
|
sw t6, RV_STK_T6(sp)
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro save_mepc
|
.macro save_mepc
|
||||||
@@ -61,37 +65,40 @@
|
|||||||
sw t0, RV_STK_MEPC(sp)
|
sw t0, RV_STK_MEPC(sp)
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro restore_regs
|
/* Restore the general purpose registers (excluding gp) from the context on
|
||||||
lw ra, RV_STK_RA(sp)
|
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
|
||||||
lw tp, RV_STK_TP(sp)
|
* but it can be overriden. */
|
||||||
lw t0, RV_STK_T0(sp)
|
.macro restore_general_regs cxt_size=CONTEXT_SIZE
|
||||||
lw t1, RV_STK_T1(sp)
|
lw ra, RV_STK_RA(sp)
|
||||||
lw t2, RV_STK_T2(sp)
|
lw tp, RV_STK_TP(sp)
|
||||||
lw s0, RV_STK_S0(sp)
|
lw t0, RV_STK_T0(sp)
|
||||||
lw s1, RV_STK_S1(sp)
|
lw t1, RV_STK_T1(sp)
|
||||||
lw a0, RV_STK_A0(sp)
|
lw t2, RV_STK_T2(sp)
|
||||||
lw a1, RV_STK_A1(sp)
|
lw s0, RV_STK_S0(sp)
|
||||||
lw a2, RV_STK_A2(sp)
|
lw s1, RV_STK_S1(sp)
|
||||||
lw a3, RV_STK_A3(sp)
|
lw a0, RV_STK_A0(sp)
|
||||||
lw a4, RV_STK_A4(sp)
|
lw a1, RV_STK_A1(sp)
|
||||||
lw a5, RV_STK_A5(sp)
|
lw a2, RV_STK_A2(sp)
|
||||||
lw a6, RV_STK_A6(sp)
|
lw a3, RV_STK_A3(sp)
|
||||||
lw a7, RV_STK_A7(sp)
|
lw a4, RV_STK_A4(sp)
|
||||||
lw s2, RV_STK_S2(sp)
|
lw a5, RV_STK_A5(sp)
|
||||||
lw s3, RV_STK_S3(sp)
|
lw a6, RV_STK_A6(sp)
|
||||||
lw s4, RV_STK_S4(sp)
|
lw a7, RV_STK_A7(sp)
|
||||||
lw s5, RV_STK_S5(sp)
|
lw s2, RV_STK_S2(sp)
|
||||||
lw s6, RV_STK_S6(sp)
|
lw s3, RV_STK_S3(sp)
|
||||||
lw s7, RV_STK_S7(sp)
|
lw s4, RV_STK_S4(sp)
|
||||||
lw s8, RV_STK_S8(sp)
|
lw s5, RV_STK_S5(sp)
|
||||||
lw s9, RV_STK_S9(sp)
|
lw s6, RV_STK_S6(sp)
|
||||||
lw s10, RV_STK_S10(sp)
|
lw s7, RV_STK_S7(sp)
|
||||||
lw s11, RV_STK_S11(sp)
|
lw s8, RV_STK_S8(sp)
|
||||||
lw t3, RV_STK_T3(sp)
|
lw s9, RV_STK_S9(sp)
|
||||||
lw t4, RV_STK_T4(sp)
|
lw s10, RV_STK_S10(sp)
|
||||||
lw t5, RV_STK_T5(sp)
|
lw s11, RV_STK_S11(sp)
|
||||||
lw t6, RV_STK_T6(sp)
|
lw t3, RV_STK_T3(sp)
|
||||||
addi sp, sp, CONTEXT_SIZE
|
lw t4, RV_STK_T4(sp)
|
||||||
|
lw t5, RV_STK_T5(sp)
|
||||||
|
lw t6, RV_STK_T6(sp)
|
||||||
|
addi sp,sp, \cxt_size
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro restore_mepc
|
.macro restore_mepc
|
||||||
@@ -141,40 +148,17 @@ _vector_table:
|
|||||||
/* Exception handler.*/
|
/* Exception handler.*/
|
||||||
.type _panic_handler, @function
|
.type _panic_handler, @function
|
||||||
_panic_handler:
|
_panic_handler:
|
||||||
addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */
|
/* Allocate space on the stack and store general purpose registers */
|
||||||
/* save general registers */
|
save_general_regs RV_STK_FRMSZ
|
||||||
sw ra, RV_STK_RA(sp)
|
|
||||||
sw gp, RV_STK_GP(sp)
|
/* As gp register is not saved by the macro, save it here */
|
||||||
sw tp, RV_STK_TP(sp)
|
sw gp, RV_STK_GP(sp)
|
||||||
sw t0, RV_STK_T0(sp)
|
|
||||||
sw t1, RV_STK_T1(sp)
|
/* Same goes for the SP value before trapping */
|
||||||
sw t2, RV_STK_T2(sp)
|
|
||||||
sw s0, RV_STK_S0(sp)
|
|
||||||
sw s1, RV_STK_S1(sp)
|
|
||||||
sw a0, RV_STK_A0(sp)
|
|
||||||
sw a1, RV_STK_A1(sp)
|
|
||||||
sw a2, RV_STK_A2(sp)
|
|
||||||
sw a3, RV_STK_A3(sp)
|
|
||||||
sw a4, RV_STK_A4(sp)
|
|
||||||
sw a5, RV_STK_A5(sp)
|
|
||||||
sw a6, RV_STK_A6(sp)
|
|
||||||
sw a7, RV_STK_A7(sp)
|
|
||||||
sw s2, RV_STK_S2(sp)
|
|
||||||
sw s3, RV_STK_S3(sp)
|
|
||||||
sw s4, RV_STK_S4(sp)
|
|
||||||
sw s5, RV_STK_S5(sp)
|
|
||||||
sw s6, RV_STK_S6(sp)
|
|
||||||
sw s7, RV_STK_S7(sp)
|
|
||||||
sw s8, RV_STK_S8(sp)
|
|
||||||
sw s9, RV_STK_S9(sp)
|
|
||||||
sw s10, RV_STK_S10(sp)
|
|
||||||
sw s11, RV_STK_S11(sp)
|
|
||||||
sw t3, RV_STK_T3(sp)
|
|
||||||
sw t4, RV_STK_T4(sp)
|
|
||||||
sw t5, RV_STK_T5(sp)
|
|
||||||
sw t6, RV_STK_T6(sp)
|
|
||||||
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
|
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
|
||||||
sw t0, RV_STK_SP(sp)
|
sw t0, RV_STK_SP(sp)
|
||||||
|
|
||||||
|
/* Save CSRs */
|
||||||
csrr t0, mepc
|
csrr t0, mepc
|
||||||
sw t0, RV_STK_MEPC(sp)
|
sw t0, RV_STK_MEPC(sp)
|
||||||
csrr t0, mstatus
|
csrr t0, mstatus
|
||||||
@@ -198,17 +182,31 @@ _panic_handler:
|
|||||||
li t0, 0x80000000
|
li t0, 0x80000000
|
||||||
bgeu a1, t0, _call_panic_handler
|
bgeu a1, t0, _call_panic_handler
|
||||||
sw a1, RV_STK_MCAUSE(sp)
|
sw a1, RV_STK_MCAUSE(sp)
|
||||||
/* exception_from_panic never returns */
|
jal panic_from_exception
|
||||||
j panic_from_exception
|
/* We arrive here if the exception handler has returned. */
|
||||||
|
j _return_from_exception
|
||||||
|
|
||||||
_call_panic_handler:
|
_call_panic_handler:
|
||||||
/* Remove highest bit from mcause (a1) register and save it in the
|
/* Remove highest bit from mcause (a1) register and save it in the
|
||||||
* structure */
|
* structure */
|
||||||
not t0, t0
|
not t0, t0
|
||||||
and a1, a1, t0
|
and a1, a1, t0
|
||||||
sw a1, RV_STK_MCAUSE(sp)
|
sw a1, RV_STK_MCAUSE(sp)
|
||||||
/* exception_from_isr never returns */
|
jal panic_from_isr
|
||||||
j panic_from_isr
|
|
||||||
.size panic_from_isr, .-panic_from_isr
|
/* We arrive here if the exception handler has returned. This means that
|
||||||
|
* the exception was handled, and the execution flow should resume.
|
||||||
|
* Restore the registers and return from the exception.
|
||||||
|
*/
|
||||||
|
_return_from_exception:
|
||||||
|
restore_mepc
|
||||||
|
/* MTVEC and SP are assumed to be unmodified.
|
||||||
|
* MSTATUS, MHARTID, MTVAL are read-only and not restored.
|
||||||
|
*/
|
||||||
|
lw gp, RV_STK_GP(sp)
|
||||||
|
restore_general_regs RV_STK_FRMSZ
|
||||||
|
mret
|
||||||
|
.size _panic_handler, .-_panic_handler
|
||||||
|
|
||||||
/* This is the interrupt handler.
|
/* This is the interrupt handler.
|
||||||
* It saves the registers on the stack,
|
* It saves the registers on the stack,
|
||||||
@@ -220,7 +218,7 @@ _call_panic_handler:
|
|||||||
.type _interrupt_handler, @function
|
.type _interrupt_handler, @function
|
||||||
_interrupt_handler:
|
_interrupt_handler:
|
||||||
/* entry */
|
/* entry */
|
||||||
save_regs
|
save_general_regs
|
||||||
save_mepc
|
save_mepc
|
||||||
|
|
||||||
/* Though it is not necessary we save GP and SP here.
|
/* Though it is not necessary we save GP and SP here.
|
||||||
@@ -306,7 +304,7 @@ _interrupt_handler:
|
|||||||
csrw mcause, s1
|
csrw mcause, s1
|
||||||
csrw mstatus, s2
|
csrw mstatus, s2
|
||||||
restore_mepc
|
restore_mepc
|
||||||
restore_regs
|
restore_general_regs
|
||||||
|
|
||||||
/* exit, this will also re-enable the interrupts */
|
/* exit, this will also re-enable the interrupts */
|
||||||
mret
|
mret
|
||||||
|
Reference in New Issue
Block a user