mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
1d6e37a7f7
Cleanup of FE310 interrupt handler code Optimization of intr context frame Reduce size of intr stack Added unhandled trap output Fix PR #12237
115 lines
2.7 KiB
ArmAsm
115 lines
2.7 KiB
ArmAsm
/*
|
|
* Copyright (C) 2017, 2019 JP Bonn, Ken Rabold
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
#include "vendor/encoding.h"
|
|
#include "context_frame.h"
|
|
|
|
.section .text.entry
|
|
.align 2
|
|
.global trap_entry
|
|
|
|
trap_entry:
|
|
/* Save registers to stack */
|
|
addi sp, sp, -CONTEXT_FRAME_SIZE
|
|
|
|
sw s0, s0_OFFSET(sp)
|
|
sw s1, s1_OFFSET(sp)
|
|
sw s2, s2_OFFSET(sp)
|
|
sw s3, s3_OFFSET(sp)
|
|
sw s4, s4_OFFSET(sp)
|
|
sw s5, s5_OFFSET(sp)
|
|
sw s6, s6_OFFSET(sp)
|
|
sw s7, s7_OFFSET(sp)
|
|
sw s8, s8_OFFSET(sp)
|
|
sw s9, s9_OFFSET(sp)
|
|
sw s10, s10_OFFSET(sp)
|
|
sw s11, s11_OFFSET(sp)
|
|
sw ra, ra_OFFSET(sp)
|
|
sw t0, t0_OFFSET(sp)
|
|
sw t1, t1_OFFSET(sp)
|
|
sw t2, t2_OFFSET(sp)
|
|
sw t3, t3_OFFSET(sp)
|
|
sw t4, t4_OFFSET(sp)
|
|
sw t5, t5_OFFSET(sp)
|
|
sw t6, t6_OFFSET(sp)
|
|
sw a0, a0_OFFSET(sp)
|
|
sw a1, a1_OFFSET(sp)
|
|
sw a2, a2_OFFSET(sp)
|
|
sw a3, a3_OFFSET(sp)
|
|
sw a4, a4_OFFSET(sp)
|
|
sw a5, a5_OFFSET(sp)
|
|
sw a6, a6_OFFSET(sp)
|
|
sw a7, a7_OFFSET(sp)
|
|
|
|
|
|
/* Get the interrupt cause, PC, and address */
|
|
csrr a0, mcause
|
|
csrr a1, mepc
|
|
csrr a2, mtval
|
|
|
|
/* Save return PC in stack frame */
|
|
sw a1, pc_OFFSET(sp)
|
|
|
|
/* Get the active thread (could be NULL) */
|
|
lw tp, sched_active_thread
|
|
beqz tp, null_thread
|
|
|
|
/* Save stack pointer of current thread */
|
|
sw sp, SP_OFFSET_IN_THREAD(tp)
|
|
|
|
null_thread:
|
|
/* Switch to ISR stack. Interrupts are not nested so use fixed
|
|
* starting address and just abandon stack when finished. */
|
|
la sp, _sp
|
|
|
|
/* Call handle_trap with MCAUSE and MEPC register value as args */
|
|
call handle_trap
|
|
|
|
/* Get the active thread (guaranteed to be non NULL) */
|
|
lw tp, sched_active_thread
|
|
|
|
/* Load the thread SP of scheduled thread */
|
|
lw sp, SP_OFFSET_IN_THREAD(tp)
|
|
|
|
/* Set return PC */
|
|
lw a1, pc_OFFSET(sp)
|
|
csrw mepc, a1
|
|
|
|
/* Restore registers from stack */
|
|
lw s0, s0_OFFSET(sp)
|
|
lw s1, s1_OFFSET(sp)
|
|
lw s2, s2_OFFSET(sp)
|
|
lw s3, s3_OFFSET(sp)
|
|
lw s4, s4_OFFSET(sp)
|
|
lw s5, s5_OFFSET(sp)
|
|
lw s6, s6_OFFSET(sp)
|
|
lw s7, s7_OFFSET(sp)
|
|
lw s8, s8_OFFSET(sp)
|
|
lw s9, s9_OFFSET(sp)
|
|
lw s10, s10_OFFSET(sp)
|
|
lw s11, s11_OFFSET(sp)
|
|
lw ra, ra_OFFSET(sp)
|
|
lw t0, t0_OFFSET(sp)
|
|
lw t1, t1_OFFSET(sp)
|
|
lw t2, t2_OFFSET(sp)
|
|
lw t3, t3_OFFSET(sp)
|
|
lw t4, t4_OFFSET(sp)
|
|
lw t5, t5_OFFSET(sp)
|
|
lw t6, t6_OFFSET(sp)
|
|
lw a0, a0_OFFSET(sp)
|
|
lw a1, a1_OFFSET(sp)
|
|
lw a2, a2_OFFSET(sp)
|
|
lw a3, a3_OFFSET(sp)
|
|
lw a4, a4_OFFSET(sp)
|
|
lw a5, a5_OFFSET(sp)
|
|
lw a6, a6_OFFSET(sp)
|
|
lw a7, a7_OFFSET(sp)
|
|
|
|
addi sp, sp, CONTEXT_FRAME_SIZE
|
|
mret
|