mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
7d1d5e77d8
New CPU FE310 from SiFive based on RISC-V architecture build: add makefile for RISC-V builds Makefile for builds using RISC-V tools
152 lines
3.8 KiB
ArmAsm
152 lines
3.8 KiB
ArmAsm
/*
|
|
* Copyright (C) 2017 JP Bonn
|
|
*
|
|
* 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"
|
|
|
|
/* from platform.h TODO:fix this hard code.... */
|
|
CLINT_CTRL_ADDR = 0x02000000
|
|
|
|
.section .text.entry
|
|
.align 2
|
|
.global trap_entry
|
|
|
|
trap_entry:
|
|
/*
|
|
* Save all regs on the currently active stack.
|
|
* This coule be the active thread's stack,
|
|
* or if no thread is active, it is saved on ISR stack
|
|
* (if initial startup) or on the deactivated threads
|
|
* stack (in the case of thread exit). In the latter
|
|
* two cases the stack is just abandoned.
|
|
*/
|
|
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 tp, tp_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 */
|
|
csrr a0, mcause
|
|
|
|
/* Save active thread stack pointer in a callee save register */
|
|
mv s1, sp
|
|
|
|
/* Switch to ISR stack. Interrupts are not nested so use fixed
|
|
* starting address and just abandon stack when finished. */
|
|
la sp, _sp
|
|
addi sp, sp, -4
|
|
|
|
/* Is it a software interrupt? */
|
|
li t0, 0x80000003
|
|
beq a0, t0, context_switch
|
|
|
|
/* Call handle_trap with MCAUSE register value as arg */
|
|
jal handle_trap
|
|
|
|
/* See if a context switch was requested by the ISR */
|
|
lw a0, sched_context_switch_request
|
|
bnez a0, context_switch
|
|
|
|
/* Restore active thread stack pointer */
|
|
mv sp, s1
|
|
|
|
/* Restore remaining registers */
|
|
trap_exit:
|
|
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 tp, tp_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
|
|
|
|
|
|
context_switch:
|
|
/* clear the software interrupt */
|
|
li t0, CLINT_CTRL_ADDR
|
|
sw zero, (t0)
|
|
|
|
/* save the active thread's PC prior to interrupt on the stack */
|
|
csrr a0, mepc
|
|
sw a0, pc_OFFSET(s1)
|
|
|
|
/* get the active thread - it may be 0 if none currently active */
|
|
lw t0, sched_active_thread
|
|
/* was there a previously running thread? */
|
|
beqz t0, no_sp_save
|
|
/* if so, save the thread's SP in the _thread structure */
|
|
sw s1,SP_OFFSET_IN_THREAD(t0)
|
|
|
|
no_sp_save:
|
|
/* all current thread state is saved - schedule a new thread */
|
|
call sched_run
|
|
lw tp, sched_active_thread
|
|
|
|
/* set the threads SP from the newly scheduled thread
|
|
* and abandon ISR stack. */
|
|
lw sp, SP_OFFSET_IN_THREAD(tp)
|
|
|
|
/* restore the PC */
|
|
lw a0, pc_OFFSET(sp)
|
|
csrw mepc, a0
|
|
|
|
j trap_exit
|