sdio+fatfs创建
This commit is contained in:
commit
f762d5d7f8
2473 files changed
+1192014
No files matched your search
@@ -0,0 +1,28 @@
|
||||
# RT-Thread building script for bridge
|
||||
|
||||
import os
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
group = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
# add common code files
|
||||
if rtconfig.CPU == "e9xx" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "nuclei" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "virt64" :
|
||||
group = group
|
||||
else :
|
||||
group = group + SConscript(os.path.join('common', 'SConscript'))
|
||||
|
||||
# cpu porting code files
|
||||
if rtconfig.CPU == "e9xx" :
|
||||
group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript'))
|
||||
else :
|
||||
group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 6 /* In ECLIC mode, the trap entry must be 64bytes aligned */
|
||||
.global irq_entry
|
||||
irq_entry:
|
||||
|
||||
/* save all from thread context */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
move s0, sp
|
||||
|
||||
/* switch to interrupt stack */
|
||||
la sp, _sp
|
||||
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
csrrw ra, 0x07ED, ra
|
||||
call rt_interrupt_leave
|
||||
|
||||
/* switch to from thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
/* clear switch interrupt flag */
|
||||
sw zero, 0(s0)
|
||||
|
||||
csrr a0, mepc
|
||||
STORE a0, 0 * REGBYTES(sp)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
spurious_interrupt:
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* Remain in M-mode after mret */
|
||||
li t0, 0x00001800
|
||||
csrs mstatus, t0
|
||||
LOAD t0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, t0
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
mret
|
||||
@@ -0,0 +1,12 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting implementation
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable(void);
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
csrrci a0, mstatus, 8
|
||||
ret
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
csrw mstatus, a0
|
||||
ret
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* #endif
|
||||
* a0 --> to
|
||||
* a1 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
LOAD sp, (a0)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a1
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrw mstatus, a0
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*
|
||||
* a0 --> from
|
||||
* a1 --> to
|
||||
* a2 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
/* saved from thread context
|
||||
* x1/ra -> sp(0)
|
||||
* x1/ra -> sp(1)
|
||||
* mstatus.mie -> sp(2)
|
||||
* x(i) -> sp(i-4)
|
||||
*/
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
STORE sp, (a0)
|
||||
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mstatus
|
||||
andi a0, a0, 8
|
||||
beqz a0, save_mpie
|
||||
li a0, 0x80
|
||||
save_mpie:
|
||||
STORE a0, 2 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* restore to thread context
|
||||
* sp(0) -> epc;
|
||||
* sp(1) -> ra;
|
||||
* sp(i) -> x(i+2)
|
||||
*/
|
||||
LOAD sp, (a1)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a2
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
*
|
||||
* a0 --> context
|
||||
* a1 --> from
|
||||
* a2 --> to
|
||||
* a3 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
|
||||
STORE a0, 0(a1)
|
||||
|
||||
LOAD sp, 0(a2)
|
||||
move a0, a3
|
||||
call rt_cpus_lock_status_restore
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#endif
|
||||
|
||||
.global rt_hw_context_switch_exit
|
||||
rt_hw_context_switch_exit:
|
||||
#ifdef RT_USING_SMP
|
||||
#ifdef RT_USING_SIGNALS
|
||||
mv a0, sp
|
||||
|
||||
csrr t0, mhartid
|
||||
/* switch interrupt stack of current cpu */
|
||||
la sp, __stack_start__
|
||||
addi t1, t0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
call rt_signal_check
|
||||
mv sp, a0
|
||||
#endif
|
||||
#endif
|
||||
/* resw ra to mepc */
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
li t0, 0x00007800
|
||||
csrw mstatus, t0
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, a0
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
FLOAD f2, 2 * FREGBYTES(sp)
|
||||
FLOAD f3, 3 * FREGBYTES(sp)
|
||||
FLOAD f4, 4 * FREGBYTES(sp)
|
||||
FLOAD f5, 5 * FREGBYTES(sp)
|
||||
FLOAD f6, 6 * FREGBYTES(sp)
|
||||
FLOAD f7, 7 * FREGBYTES(sp)
|
||||
FLOAD f8, 8 * FREGBYTES(sp)
|
||||
FLOAD f9, 9 * FREGBYTES(sp)
|
||||
FLOAD f10, 10 * FREGBYTES(sp)
|
||||
FLOAD f11, 11 * FREGBYTES(sp)
|
||||
FLOAD f12, 12 * FREGBYTES(sp)
|
||||
FLOAD f13, 13 * FREGBYTES(sp)
|
||||
FLOAD f14, 14 * FREGBYTES(sp)
|
||||
FLOAD f15, 15 * FREGBYTES(sp)
|
||||
FLOAD f16, 16 * FREGBYTES(sp)
|
||||
FLOAD f17, 17 * FREGBYTES(sp)
|
||||
FLOAD f18, 18 * FREGBYTES(sp)
|
||||
FLOAD f19, 19 * FREGBYTES(sp)
|
||||
FLOAD f20, 20 * FREGBYTES(sp)
|
||||
FLOAD f21, 21 * FREGBYTES(sp)
|
||||
FLOAD f22, 22 * FREGBYTES(sp)
|
||||
FLOAD f23, 23 * FREGBYTES(sp)
|
||||
FLOAD f24, 24 * FREGBYTES(sp)
|
||||
FLOAD f25, 25 * FREGBYTES(sp)
|
||||
FLOAD f26, 26 * FREGBYTES(sp)
|
||||
FLOAD f27, 27 * FREGBYTES(sp)
|
||||
FLOAD f28, 28 * FREGBYTES(sp)
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
|
||||
mret
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /* epc - epc - program counter */
|
||||
rt_ubase_t ra; /* x1 - ra - return address for jumps */
|
||||
rt_ubase_t mstatus; /* - machine status register */
|
||||
rt_ubase_t gp; /* x3 - gp - global pointer */
|
||||
rt_ubase_t tp; /* x4 - tp - thread pointer */
|
||||
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
|
||||
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /* x17 - s7 - function argument 7 */
|
||||
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
rv_floatreg_t f0; /* f0 */
|
||||
rv_floatreg_t f1; /* f1 */
|
||||
rv_floatreg_t f2; /* f2 */
|
||||
rv_floatreg_t f3; /* f3 */
|
||||
rv_floatreg_t f4; /* f4 */
|
||||
rv_floatreg_t f5; /* f5 */
|
||||
rv_floatreg_t f6; /* f6 */
|
||||
rv_floatreg_t f7; /* f7 */
|
||||
rv_floatreg_t f8; /* f8 */
|
||||
rv_floatreg_t f9; /* f9 */
|
||||
rv_floatreg_t f10; /* f10 */
|
||||
rv_floatreg_t f11; /* f11 */
|
||||
rv_floatreg_t f12; /* f12 */
|
||||
rv_floatreg_t f13; /* f13 */
|
||||
rv_floatreg_t f14; /* f14 */
|
||||
rv_floatreg_t f15; /* f15 */
|
||||
rv_floatreg_t f16; /* f16 */
|
||||
rv_floatreg_t f17; /* f17 */
|
||||
rv_floatreg_t f18; /* f18 */
|
||||
rv_floatreg_t f19; /* f19 */
|
||||
rv_floatreg_t f20; /* f20 */
|
||||
rv_floatreg_t f21; /* f21 */
|
||||
rv_floatreg_t f22; /* f22 */
|
||||
rv_floatreg_t f23; /* f23 */
|
||||
rv_floatreg_t f24; /* f24 */
|
||||
rv_floatreg_t f25; /* f25 */
|
||||
rv_floatreg_t f26; /* f26 */
|
||||
rv_floatreg_t f27; /* f27 */
|
||||
rv_floatreg_t f28; /* f28 */
|
||||
rv_floatreg_t f29; /* f29 */
|
||||
rv_floatreg_t f30; /* f30 */
|
||||
rv_floatreg_t f31; /* f31 */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
void *parameter,
|
||||
rt_uint8_t *stack_addr,
|
||||
void *texit)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
int i;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
|
||||
/* force to machine mode(MPP=11) and set MPIE to 1 */
|
||||
frame->mstatus = 0x00007880;
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*/
|
||||
#ifndef RT_USING_SMP
|
||||
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
|
||||
{
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif /* end of RT_USING_SMP */
|
||||
|
||||
/** shutdown CPU */
|
||||
RT_WEAK void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
* 2020/11/20 BalanceTWK Add FPU support
|
||||
*/
|
||||
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define REGBYTES 8
|
||||
#else
|
||||
#define STORE sw
|
||||
#define LOAD lw
|
||||
#define REGBYTES 4
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
#ifdef ARCH_RISCV_FPU_D
|
||||
#define FSTORE fsd
|
||||
#define FLOAD fld
|
||||
#define FREGBYTES 8
|
||||
#define rv_floatreg_t rt_int64_t
|
||||
#endif
|
||||
#ifdef ARCH_RISCV_FPU_S
|
||||
#define FSTORE fsw
|
||||
#define FLOAD flw
|
||||
#define FREGBYTES 4
|
||||
#define rv_floatreg_t rt_int32_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef RISCV_OPS_H__
|
||||
#define RISCV_OPS_H__
|
||||
|
||||
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
|
||||
|
||||
#define read_csr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
|
||||
#define write_csr(reg, val) ({ \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||
|
||||
#define set_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
|
||||
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
#endif /* end of __GNUC__ */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef RISCV_PLIC_H__
|
||||
#define RISCV_PLIC_H__
|
||||
|
||||
#ifndef PLIC_BASE_ADDR
|
||||
#define PLIC_BASE_ADDR 0x0
|
||||
#endif
|
||||
|
||||
/* Priority Register - 32 bits per source */
|
||||
#define PLIC_PRIORITY_OFFSET (0x00000000UL)
|
||||
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
|
||||
|
||||
/* Pending Register - 1 bit per soirce */
|
||||
#define PLIC_PENDING_OFFSET (0x00001000UL)
|
||||
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
|
||||
|
||||
/* Enable Register - 0x80 per target */
|
||||
#define PLIC_ENABLE_OFFSET (0x00002000UL)
|
||||
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
|
||||
|
||||
/* Priority Threshold Register - 0x1000 per target */
|
||||
#define PLIC_THRESHOLD_OFFSET (0x00200000UL)
|
||||
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
|
||||
|
||||
/* Claim Register - 0x1000 per target */
|
||||
#define PLIC_CLAIM_OFFSET (0x00200004UL)
|
||||
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
|
||||
|
||||
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
|
||||
__attribute__((always_inline)) static inline void __plic_set_feature(unsigned int feature)
|
||||
{
|
||||
volatile unsigned int *feature_ptr = (volatile unsigned int *)PLIC_BASE_ADDR;
|
||||
*feature_ptr = feature;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_threshold(unsigned int threshold)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *threshold_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_THRESHOLD_OFFSET +
|
||||
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
||||
*threshold_ptr = threshold;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_priority(unsigned int source, unsigned int priority)
|
||||
{
|
||||
volatile unsigned int *priority_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_PRIORITY_OFFSET +
|
||||
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
|
||||
*priority_ptr = priority;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_set_pending(unsigned int source)
|
||||
{
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_PENDING_OFFSET +
|
||||
((source >> 5) << 2));
|
||||
*current_ptr = (1 << (source & 0x1F));
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_enable(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_ENABLE_OFFSET +
|
||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
||||
((source >> 5) << 2));
|
||||
unsigned int current = *current_ptr;
|
||||
current = current | (1 << (source & 0x1F));
|
||||
*current_ptr = current;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_disable(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_ENABLE_OFFSET +
|
||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
||||
((source >> 5) << 2));
|
||||
unsigned int current = *current_ptr;
|
||||
current = current & ~((1 << (source & 0x1F)));
|
||||
*current_ptr = current;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline unsigned int __plic_irq_claim(void)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_CLAIM_OFFSET +
|
||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
||||
return *claim_addr;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __plic_irq_complete(unsigned int source)
|
||||
{
|
||||
unsigned int hart_id = read_csr(mhartid);
|
||||
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
|
||||
PLIC_CLAIM_OFFSET +
|
||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
||||
*claim_addr = source;
|
||||
}
|
||||
#endif /* end of __GNUC__ */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/02 Bernard The first version
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
|
||||
/* save all from thread context */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* save break thread stack to s0 */
|
||||
move s0, sp
|
||||
/* switch to interrupt stack */
|
||||
la sp, _sp
|
||||
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
/* switch to from_thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
sw zero, 0(s0)
|
||||
|
||||
csrr a0, mepc
|
||||
STORE a0, 0 * REGBYTES(sp)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
spurious_interrupt:
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* Remain in M-mode after mret */
|
||||
li t0, 0x00001800
|
||||
csrs mstatus, t0
|
||||
LOAD t0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, t0
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
mret
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021/04/24 Juice The first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
typedef void (*irq_handler_t)(void);
|
||||
extern const irq_handler_t isrTable[];
|
||||
|
||||
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc, uintptr_t *sp)
|
||||
{
|
||||
uint32_t intNum;
|
||||
if (mcause & 0x80000000) /* For external interrupt. */
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
intNum = mcause & 0x1FUL;
|
||||
/* Now call the real irq handler for intNum */
|
||||
if (intNum <= 24)
|
||||
{
|
||||
if (isrTable[intNum])isrTable[intNum]();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021/04/24 Juice The first version
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
|
||||
/* save thread context to thread stack */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mstatus
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mepc
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* switch to interrupt stack */
|
||||
move s0, sp
|
||||
|
||||
/* handle interrupt */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, s0
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
|
||||
/* switch to from_thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
sw zero, 0(s0)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
spurious_interrupt:
|
||||
tail rt_hw_context_switch_exit
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021/04/24 Juice The first version
|
||||
*/
|
||||
|
||||
|
||||
.global _start
|
||||
.section ".start", "ax"
|
||||
_start:
|
||||
.align 3
|
||||
csrw mideleg, 0
|
||||
csrw medeleg, 0
|
||||
csrw mie, 0
|
||||
csrw mip, 0
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x3, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10, 0
|
||||
li x11, 0
|
||||
li x12, 0
|
||||
li x13, 0
|
||||
li x14, 0
|
||||
li x15, 0
|
||||
li x16, 0
|
||||
li x17, 0
|
||||
li x18, 0
|
||||
li x19, 0
|
||||
li x20, 0
|
||||
li x21, 0
|
||||
li x22, 0
|
||||
li x23, 0
|
||||
li x24, 0
|
||||
li x25, 0
|
||||
li x26, 0
|
||||
li x27, 0
|
||||
li x28, 0
|
||||
li x29, 0
|
||||
li x30, 0
|
||||
li x31, 0
|
||||
|
||||
/* set to initial state of FPU and disable interrupt */
|
||||
li t0, 0
|
||||
csrs mstatus, t0
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
la sp, __stack
|
||||
call entry
|
||||
call exit
|
||||
.option pop
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/12/23 Bernard The first version
|
||||
* 2018/12/27 Jesven Add secondary cpu boot
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
#include <encoding.h>
|
||||
#include <clint.h>
|
||||
#include <atomic.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
int rt_hw_cpu_id(void)
|
||||
{
|
||||
return read_csr(mhartid);
|
||||
}
|
||||
|
||||
void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
((spinlock_t *)lock)->lock = 0;
|
||||
}
|
||||
|
||||
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
spinlock_lock((spinlock_t *)lock);
|
||||
}
|
||||
|
||||
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
spinlock_unlock((spinlock_t *)lock);
|
||||
}
|
||||
|
||||
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < RT_CPUS_NR; idx ++)
|
||||
{
|
||||
if (cpu_mask & (1 << idx))
|
||||
{
|
||||
clint_ipi_send(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern rt_base_t secondary_boot_flag;
|
||||
void rt_hw_secondary_cpu_up(void)
|
||||
{
|
||||
mb();
|
||||
secondary_boot_flag = 0xa55a;
|
||||
}
|
||||
|
||||
extern void rt_hw_scondary_interrupt_init(void);
|
||||
extern int rt_hw_tick_init(void);
|
||||
extern int rt_hw_clint_ipi_enable(void);
|
||||
|
||||
void secondary_cpu_c_start(void)
|
||||
{
|
||||
rt_hw_spin_lock(&_cpus_lock);
|
||||
|
||||
/* initialize interrupt controller */
|
||||
rt_hw_scondary_interrupt_init();
|
||||
|
||||
rt_hw_tick_init();
|
||||
|
||||
rt_hw_clint_ipi_enable();
|
||||
|
||||
rt_system_scheduler_start();
|
||||
}
|
||||
|
||||
void rt_hw_secondary_cpu_idle_exec(void)
|
||||
{
|
||||
asm volatile ("wfi");
|
||||
}
|
||||
#endif /*RT_USING_SMP*/
|
||||
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Change irq enable/disable to cpu0
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
#include <plic.h>
|
||||
#include <clint.h>
|
||||
#include <interrupt.h>
|
||||
|
||||
#define CPU_NUM 2
|
||||
#define MAX_HANDLERS IRQN_MAX
|
||||
|
||||
static struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
int rt_hw_clint_ipi_enable(void)
|
||||
{
|
||||
/* Set the Machine-Software bit in MIE */
|
||||
set_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_clint_ipi_disable(void)
|
||||
{
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_enable(plic_irq_t irq_number)
|
||||
{
|
||||
unsigned long core_id = 0;
|
||||
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Set enable bit in enable bit array */
|
||||
current |= (uint32_t)1 << (irq_number % 32);
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_disable(plic_irq_t irq_number)
|
||||
{
|
||||
unsigned long core_id = 0;
|
||||
|
||||
/* Check parameters */
|
||||
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
|
||||
return -1;
|
||||
/* Get current enable bit array by IRQ number */
|
||||
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
|
||||
/* Clear enable bit in enable bit array */
|
||||
current &= ~((uint32_t)1 << (irq_number % 32));
|
||||
/* Write back the enable bit array */
|
||||
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
int idx;
|
||||
int cpuid;
|
||||
|
||||
cpuid = current_coreid();
|
||||
|
||||
/* Disable all interrupts for the current core. */
|
||||
for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
|
||||
plic->target_enables.target[cpuid].enable[idx] = 0;
|
||||
|
||||
/* Set priorities to zero. */
|
||||
for (idx = 0; idx < PLIC_NUM_SOURCES; idx++)
|
||||
plic->source_priorities.priority[idx] = 0;
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
plic->targets.target[cpuid].priority_threshold = 0;
|
||||
|
||||
/* init exceptions table */
|
||||
for (idx = 0; idx < MAX_HANDLERS; idx++)
|
||||
{
|
||||
rt_hw_interrupt_mask(idx);
|
||||
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
irq_desc[idx].param = RT_NULL;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
|
||||
irq_desc[idx].counter = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(mie, MIP_MEIP);
|
||||
}
|
||||
|
||||
void rt_hw_scondary_interrupt_init(void)
|
||||
{
|
||||
int idx;
|
||||
int cpuid;
|
||||
|
||||
cpuid = current_coreid();
|
||||
|
||||
/* Disable all interrupts for the current core. */
|
||||
for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
|
||||
plic->target_enables.target[cpuid].enable[idx] = 0;
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
plic->targets.target[cpuid].priority_threshold = 0;
|
||||
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(mie, MIP_MEIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
rt_hw_plic_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
plic_set_priority(vector, 1);
|
||||
rt_hw_plic_irq_enable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param new_handler the interrupt service routine to be installed
|
||||
* @param old_handler the old interrupt service routine
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if(vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = irq_desc[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
irq_desc[vector].handler = (rt_isr_handler_t)handler;
|
||||
irq_desc[vector].param = param;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
|
||||
irq_desc[vector].counter = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
RT_WEAK
|
||||
void plic_irq_handle(plic_irq_t irq)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
|
||||
return ;
|
||||
}
|
||||
|
||||
uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
|
||||
{
|
||||
/*
|
||||
* After the highest-priority pending interrupt is claimed by a target
|
||||
* and the corresponding IP bit is cleared, other lower-priority
|
||||
* pending interrupts might then become visible to the target, and so
|
||||
* the PLIC EIP bit might not be cleared after a claim. The interrupt
|
||||
* handler can check the local meip/heip/seip/ueip bits before exiting
|
||||
* the handler, to allow more efficient service of other interrupts
|
||||
* without first restoring the interrupted context and taking another
|
||||
* interrupt trap.
|
||||
*/
|
||||
if (read_csr(mip) & MIP_MEIP)
|
||||
{
|
||||
/* Get current core id */
|
||||
uint64_t core_id = current_coreid();
|
||||
/* Get primitive interrupt enable flag */
|
||||
uint64_t ie_flag = read_csr(mie);
|
||||
/* Get current IRQ num */
|
||||
uint32_t int_num = plic->targets.target[core_id].claim_complete;
|
||||
/* Get primitive IRQ threshold */
|
||||
uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
|
||||
/* Set new IRQ threshold = current IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
|
||||
|
||||
/* Disable software interrupt and timer interrupt */
|
||||
clear_csr(mie, MIP_MTIP | MIP_MSIP);
|
||||
|
||||
if (irq_desc[int_num].handler == (rt_isr_handler_t)rt_hw_interrupt_handle)
|
||||
{
|
||||
/* default handler, route to kendryte bsp plic driver */
|
||||
plic_irq_handle(int_num);
|
||||
}
|
||||
else if (irq_desc[int_num].handler)
|
||||
{
|
||||
irq_desc[int_num].handler(int_num, irq_desc[int_num].param);
|
||||
}
|
||||
|
||||
/* Perform IRQ complete */
|
||||
plic->targets.target[core_id].claim_complete = int_num;
|
||||
/* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
|
||||
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
|
||||
/* Restore primitive interrupt enable flag */
|
||||
write_csr(mie, ie_flag);
|
||||
/* Restore primitive IRQ threshold */
|
||||
plic->targets.target[core_id].priority_threshold = int_threshold;
|
||||
}
|
||||
|
||||
return epc;
|
||||
}
|
||||
struct exception_stack_frame
|
||||
{
|
||||
uint64_t x1;
|
||||
uint64_t x2;
|
||||
uint64_t x3;
|
||||
uint64_t x4;
|
||||
uint64_t x5;
|
||||
uint64_t x6;
|
||||
uint64_t x7;
|
||||
uint64_t x8;
|
||||
uint64_t x9;
|
||||
uint64_t x10;
|
||||
uint64_t x11;
|
||||
uint64_t x12;
|
||||
uint64_t x13;
|
||||
uint64_t x14;
|
||||
uint64_t x15;
|
||||
uint64_t x16;
|
||||
uint64_t x17;
|
||||
uint64_t x18;
|
||||
uint64_t x19;
|
||||
uint64_t x20;
|
||||
uint64_t x21;
|
||||
uint64_t x22;
|
||||
uint64_t x23;
|
||||
uint64_t x24;
|
||||
uint64_t x25;
|
||||
uint64_t x26;
|
||||
uint64_t x27;
|
||||
uint64_t x28;
|
||||
uint64_t x29;
|
||||
uint64_t x30;
|
||||
uint64_t x31;
|
||||
};
|
||||
|
||||
void print_stack_frame(uintptr_t * sp)
|
||||
{
|
||||
struct exception_stack_frame * esf = (struct exception_stack_frame *)(sp+1);
|
||||
|
||||
rt_kprintf("\n=================================================================\n");
|
||||
rt_kprintf("x1 (ra : Return address ) ==> 0x%08x%08x\n", esf->x1 >> 32 , esf->x1 & UINT32_MAX);
|
||||
rt_kprintf("x2 (sp : Stack pointer ) ==> 0x%08x%08x\n", esf->x2 >> 32 , esf->x2 & UINT32_MAX);
|
||||
rt_kprintf("x3 (gp : Global pointer ) ==> 0x%08x%08x\n", esf->x3 >> 32 , esf->x3 & UINT32_MAX);
|
||||
rt_kprintf("x4 (tp : Thread pointer ) ==> 0x%08x%08x\n", esf->x4 >> 32 , esf->x4 & UINT32_MAX);
|
||||
rt_kprintf("x5 (t0 : Temporary ) ==> 0x%08x%08x\n", esf->x5 >> 32 , esf->x5 & UINT32_MAX);
|
||||
rt_kprintf("x6 (t1 : Temporary ) ==> 0x%08x%08x\n", esf->x6 >> 32 , esf->x6 & UINT32_MAX);
|
||||
rt_kprintf("x7 (t2 : Temporary ) ==> 0x%08x%08x\n", esf->x7 >> 32 , esf->x7 & UINT32_MAX);
|
||||
rt_kprintf("x8 (s0/fp: Save register,frame pointer ) ==> 0x%08x%08x\n", esf->x8 >> 32 , esf->x8 & UINT32_MAX);
|
||||
rt_kprintf("x9 (s1 : Save register ) ==> 0x%08x%08x\n", esf->x9 >> 32 , esf->x9 & UINT32_MAX);
|
||||
rt_kprintf("x10(a0 : Function argument,return value) ==> 0x%08x%08x\n", esf->x10 >> 32 , esf->x10 & UINT32_MAX);
|
||||
rt_kprintf("x11(a1 : Function argument,return value) ==> 0x%08x%08x\n", esf->x11 >> 32 , esf->x11 & UINT32_MAX);
|
||||
rt_kprintf("x12(a2 : Function argument ) ==> 0x%08x%08x\n", esf->x12 >> 32 , esf->x12 & UINT32_MAX);
|
||||
rt_kprintf("x13(a3 : Function argument ) ==> 0x%08x%08x\n", esf->x13 >> 32 , esf->x13 & UINT32_MAX);
|
||||
rt_kprintf("x14(a4 : Function argument ) ==> 0x%08x%08x\n", esf->x14 >> 32 , esf->x14 & UINT32_MAX);
|
||||
rt_kprintf("x15(a5 : Function argument ) ==> 0x%08x%08x\n", esf->x15 >> 32 , esf->x15 & UINT32_MAX);
|
||||
rt_kprintf("x16(a6 : Function argument ) ==> 0x%08x%08x\n", esf->x16 >> 32 , esf->x16 & UINT32_MAX);
|
||||
rt_kprintf("x17(a7 : Function argument ) ==> 0x%08x%08x\n", esf->x17 >> 32 , esf->x17 & UINT32_MAX);
|
||||
rt_kprintf("x18(s2 : Save register ) ==> 0x%08x%08x\n", esf->x18 >> 32 , esf->x18 & UINT32_MAX);
|
||||
rt_kprintf("x19(s3 : Save register ) ==> 0x%08x%08x\n", esf->x19 >> 32 , esf->x19 & UINT32_MAX);
|
||||
rt_kprintf("x20(s4 : Save register ) ==> 0x%08x%08x\n", esf->x20 >> 32 , esf->x20 & UINT32_MAX);
|
||||
rt_kprintf("x21(s5 : Save register ) ==> 0x%08x%08x\n", esf->x21 >> 32 , esf->x21 & UINT32_MAX);
|
||||
rt_kprintf("x22(s6 : Save register ) ==> 0x%08x%08x\n", esf->x22 >> 32 , esf->x22 & UINT32_MAX);
|
||||
rt_kprintf("x23(s7 : Save register ) ==> 0x%08x%08x\n", esf->x23 >> 32 , esf->x23 & UINT32_MAX);
|
||||
rt_kprintf("x24(s8 : Save register ) ==> 0x%08x%08x\n", esf->x24 >> 32 , esf->x24 & UINT32_MAX);
|
||||
rt_kprintf("x25(s9 : Save register ) ==> 0x%08x%08x\n", esf->x25 >> 32 , esf->x25 & UINT32_MAX);
|
||||
rt_kprintf("x26(s10 : Save register ) ==> 0x%08x%08x\n", esf->x26 >> 32 , esf->x26 & UINT32_MAX);
|
||||
rt_kprintf("x27(s11 : Save register ) ==> 0x%08x%08x\n", esf->x27 >> 32 , esf->x27 & UINT32_MAX);
|
||||
rt_kprintf("x28(t3 : Temporary ) ==> 0x%08x%08x\n", esf->x28 >> 32 , esf->x28 & UINT32_MAX);
|
||||
rt_kprintf("x29(t4 : Temporary ) ==> 0x%08x%08x\n", esf->x29 >> 32 , esf->x29 & UINT32_MAX);
|
||||
rt_kprintf("x30(t5 : Temporary ) ==> 0x%08x%08x\n", esf->x30 >> 32 , esf->x30 & UINT32_MAX);
|
||||
rt_kprintf("x31(t6 : Temporary ) ==> 0x%08x%08x\n", esf->x31 >> 32 , esf->x31 & UINT32_MAX);
|
||||
rt_kprintf("=================================================================\n");
|
||||
}
|
||||
|
||||
|
||||
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc, uintptr_t * sp)
|
||||
{
|
||||
int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK;
|
||||
|
||||
if (mcause & (1UL << 63))
|
||||
{
|
||||
switch (cause)
|
||||
{
|
||||
case IRQ_M_SOFT:
|
||||
{
|
||||
uint64_t core_id = current_coreid();
|
||||
|
||||
clint_ipi_clear(core_id);
|
||||
rt_schedule();
|
||||
}
|
||||
break;
|
||||
case IRQ_M_EXT:
|
||||
handle_irq_m_ext(mcause, epc);
|
||||
break;
|
||||
case IRQ_M_TIMER:
|
||||
tick_isr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_thread_t tid;
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
extern long list_thread();
|
||||
#endif
|
||||
|
||||
rt_hw_interrupt_disable();
|
||||
|
||||
tid = rt_thread_self();
|
||||
rt_kprintf("\nException:\n");
|
||||
switch (cause)
|
||||
{
|
||||
case CAUSE_MISALIGNED_FETCH:
|
||||
rt_kprintf("Instruction address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_FETCH:
|
||||
rt_kprintf("Instruction access fault");
|
||||
break;
|
||||
case CAUSE_ILLEGAL_INSTRUCTION:
|
||||
rt_kprintf("Illegal instruction");
|
||||
break;
|
||||
case CAUSE_BREAKPOINT:
|
||||
rt_kprintf("Breakpoint");
|
||||
break;
|
||||
case CAUSE_MISALIGNED_LOAD:
|
||||
rt_kprintf("Load address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_LOAD:
|
||||
rt_kprintf("Load access fault");
|
||||
break;
|
||||
case CAUSE_MISALIGNED_STORE:
|
||||
rt_kprintf("Store address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_STORE:
|
||||
rt_kprintf("Store access fault");
|
||||
break;
|
||||
case CAUSE_USER_ECALL:
|
||||
rt_kprintf("Environment call from U-mode");
|
||||
break;
|
||||
case CAUSE_SUPERVISOR_ECALL:
|
||||
rt_kprintf("Environment call from S-mode");
|
||||
break;
|
||||
case CAUSE_HYPERVISOR_ECALL:
|
||||
rt_kprintf("Environment call from H-mode");
|
||||
break;
|
||||
case CAUSE_MACHINE_ECALL:
|
||||
rt_kprintf("Environment call from M-mode");
|
||||
break;
|
||||
default:
|
||||
rt_kprintf("Uknown exception : %08lX", cause);
|
||||
break;
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
print_stack_frame(sp);
|
||||
rt_kprintf("exception pc => 0x%08x\n", epc);
|
||||
rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
while(1);
|
||||
}
|
||||
|
||||
return epc;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/02 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP schedule
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
|
||||
/* save thread context to thread stack */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mstatus
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, mepc
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* switch to interrupt stack */
|
||||
move s0, sp
|
||||
|
||||
/* get cpu id */
|
||||
csrr t0, mhartid
|
||||
|
||||
/* switch interrupt stack of current cpu */
|
||||
la sp, __stack_start__
|
||||
addi t1, t0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
/* handle interrupt */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, s0
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* s0 --> sp */
|
||||
mv sp, s0
|
||||
mv a0, s0
|
||||
call rt_scheduler_do_irq_switch
|
||||
tail rt_hw_context_switch_exit
|
||||
|
||||
#else
|
||||
|
||||
/* switch to from_thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
sw zero, 0(s0)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
#endif
|
||||
|
||||
spurious_interrupt:
|
||||
tail rt_hw_context_switch_exit
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
*/
|
||||
|
||||
#define MSTATUS_FS 0x00006000U /* initial state of FPU */
|
||||
#include <cpuport.h>
|
||||
|
||||
.global _start
|
||||
.section ".start", "ax"
|
||||
_start:
|
||||
j 1f
|
||||
.word 0xdeadbeef
|
||||
.align 3
|
||||
.global g_wake_up
|
||||
g_wake_up:
|
||||
.dword 1
|
||||
.dword 0
|
||||
1:
|
||||
csrw mideleg, 0
|
||||
csrw medeleg, 0
|
||||
csrw mie, 0
|
||||
csrw mip, 0
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
|
||||
li x1, 0
|
||||
li x2, 0
|
||||
li x3, 0
|
||||
li x4, 0
|
||||
li x5, 0
|
||||
li x6, 0
|
||||
li x7, 0
|
||||
li x8, 0
|
||||
li x9, 0
|
||||
li x10,0
|
||||
li x11,0
|
||||
li x12,0
|
||||
li x13,0
|
||||
li x14,0
|
||||
li x15,0
|
||||
li x16,0
|
||||
li x17,0
|
||||
li x18,0
|
||||
li x19,0
|
||||
li x20,0
|
||||
li x21,0
|
||||
li x22,0
|
||||
li x23,0
|
||||
li x24,0
|
||||
li x25,0
|
||||
li x26,0
|
||||
li x27,0
|
||||
li x28,0
|
||||
li x29,0
|
||||
li x30,0
|
||||
li x31,0
|
||||
|
||||
/* set to initial state of FPU and disable interrupt */
|
||||
li t0, MSTATUS_FS
|
||||
csrs mstatus, t0
|
||||
|
||||
fssr x0
|
||||
fmv.w.x f0, x0
|
||||
fmv.w.x f1, x0
|
||||
fmv.w.x f2, x0
|
||||
fmv.w.x f3, x0
|
||||
fmv.w.x f4, x0
|
||||
fmv.w.x f5, x0
|
||||
fmv.w.x f6, x0
|
||||
fmv.w.x f7, x0
|
||||
fmv.w.x f8, x0
|
||||
fmv.w.x f9, x0
|
||||
fmv.w.x f10,x0
|
||||
fmv.w.x f11,x0
|
||||
fmv.w.x f12,x0
|
||||
fmv.w.x f13,x0
|
||||
fmv.w.x f14,x0
|
||||
fmv.w.x f15,x0
|
||||
fmv.w.x f16,x0
|
||||
fmv.w.x f17,x0
|
||||
fmv.w.x f18,x0
|
||||
fmv.w.x f19,x0
|
||||
fmv.w.x f20,x0
|
||||
fmv.w.x f21,x0
|
||||
fmv.w.x f22,x0
|
||||
fmv.w.x f23,x0
|
||||
fmv.w.x f24,x0
|
||||
fmv.w.x f25,x0
|
||||
fmv.w.x f26,x0
|
||||
fmv.w.x f27,x0
|
||||
fmv.w.x f28,x0
|
||||
fmv.w.x f29,x0
|
||||
fmv.w.x f30,x0
|
||||
fmv.w.x f31,x0
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
/* get cpu id */
|
||||
csrr a0, mhartid
|
||||
|
||||
la sp, __stack_start__
|
||||
addi t1, a0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
/* other cpu core, jump to cpu entry directly */
|
||||
bnez a0, secondary_cpu_entry
|
||||
tail primary_cpu_entry
|
||||
|
||||
secondary_cpu_entry:
|
||||
#ifdef RT_USING_SMP
|
||||
la a0, secondary_boot_flag
|
||||
ld a0, 0(a0)
|
||||
li a1, 0xa55a
|
||||
beq a0, a1, 1f
|
||||
#endif
|
||||
j secondary_cpu_entry
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
1:
|
||||
tail secondary_cpu_c_start
|
||||
|
||||
.data
|
||||
.global secondary_boot_flag
|
||||
.align 3
|
||||
secondary_boot_flag:
|
||||
.dword 0
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <encoding.h>
|
||||
#include <clint.h>
|
||||
#include <sysctl.h>
|
||||
|
||||
static volatile unsigned long tick_cycles = 0;
|
||||
int tick_isr(void)
|
||||
{
|
||||
uint64_t core_id = current_coreid();
|
||||
|
||||
clint->mtimecmp[core_id] += tick_cycles;
|
||||
rt_tick_increase();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets and enable the timer interrupt */
|
||||
int rt_hw_tick_init(void)
|
||||
{
|
||||
/* Read core id */
|
||||
unsigned long core_id = current_coreid();
|
||||
unsigned long interval = 1000/RT_TICK_PER_SECOND;
|
||||
|
||||
/* Clear the Machine-Timer bit in MIE */
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
|
||||
/* calculate the tick cycles */
|
||||
tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
|
||||
/* Set mtimecmp by core id */
|
||||
clint->mtimecmp[core_id] = clint->mtime + tick_cycles;
|
||||
|
||||
/* Enable the Machine-Timer bit in MIE */
|
||||
set_csr(mie, MIP_MTIP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#ifndef TICK_H__
|
||||
#define TICK_H__
|
||||
|
||||
int tick_isr(void);
|
||||
int rt_hw_tick_init(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/03/26 Huaqi First Nuclei RISC-V porting implementation
|
||||
*/
|
||||
|
||||
#include "riscv_encoding.h"
|
||||
|
||||
#ifndef __riscv_32e
|
||||
#define RT_SAVED_REGNUM 30
|
||||
#else
|
||||
#define RT_SAVED_REGNUM 14
|
||||
#endif
|
||||
|
||||
#define RT_CONTEXT_SIZE (RT_SAVED_REGNUM * REGBYTES)
|
||||
|
||||
.extern rt_interrupt_from_thread
|
||||
.extern rt_interrupt_to_thread
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* a0 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
|
||||
/* Start the first task. This also clears the bit that indicates the FPU is
|
||||
in use in case the FPU was used before the scheduler was started - which
|
||||
would otherwise result in the unnecessary leaving of space in the stack
|
||||
for lazy saving of FPU registers. */
|
||||
.align 3
|
||||
rt_hw_context_switch_to:
|
||||
/* Setup Interrupt Stack using
|
||||
The stack that was used by main()
|
||||
before the scheduler is started is
|
||||
no longer required after the scheduler is started.
|
||||
Interrupt stack pointer is stored in CSR_MSCRATCH */
|
||||
la t0, _sp
|
||||
csrw CSR_MSCRATCH, t0
|
||||
LOAD sp, 0x0(a0) /* Read sp from first TCB member(a0) */
|
||||
|
||||
/* Pop PC from stack and set MEPC */
|
||||
LOAD t0, 0 * REGBYTES(sp)
|
||||
csrw CSR_MEPC, t0
|
||||
/* Pop mstatus from stack and set it */
|
||||
LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
|
||||
csrw CSR_MSTATUS, t0
|
||||
/* Interrupt still disable here */
|
||||
/* Restore Registers from Stack */
|
||||
LOAD x1, 1 * REGBYTES(sp) /* RA */
|
||||
LOAD x5, 2 * REGBYTES(sp)
|
||||
LOAD x6, 3 * REGBYTES(sp)
|
||||
LOAD x7, 4 * REGBYTES(sp)
|
||||
LOAD x8, 5 * REGBYTES(sp)
|
||||
LOAD x9, 6 * REGBYTES(sp)
|
||||
LOAD x10, 7 * REGBYTES(sp)
|
||||
LOAD x11, 8 * REGBYTES(sp)
|
||||
LOAD x12, 9 * REGBYTES(sp)
|
||||
LOAD x13, 10 * REGBYTES(sp)
|
||||
LOAD x14, 11 * REGBYTES(sp)
|
||||
LOAD x15, 12 * REGBYTES(sp)
|
||||
#ifndef __riscv_32e
|
||||
LOAD x16, 13 * REGBYTES(sp)
|
||||
LOAD x17, 14 * REGBYTES(sp)
|
||||
LOAD x18, 15 * REGBYTES(sp)
|
||||
LOAD x19, 16 * REGBYTES(sp)
|
||||
LOAD x20, 17 * REGBYTES(sp)
|
||||
LOAD x21, 18 * REGBYTES(sp)
|
||||
LOAD x22, 19 * REGBYTES(sp)
|
||||
LOAD x23, 20 * REGBYTES(sp)
|
||||
LOAD x24, 21 * REGBYTES(sp)
|
||||
LOAD x25, 22 * REGBYTES(sp)
|
||||
LOAD x26, 23 * REGBYTES(sp)
|
||||
LOAD x27, 24 * REGBYTES(sp)
|
||||
LOAD x28, 25 * REGBYTES(sp)
|
||||
LOAD x29, 26 * REGBYTES(sp)
|
||||
LOAD x30, 27 * REGBYTES(sp)
|
||||
LOAD x31, 28 * REGBYTES(sp)
|
||||
#endif
|
||||
|
||||
addi sp, sp, RT_CONTEXT_SIZE
|
||||
|
||||
mret
|
||||
|
||||
.align 2
|
||||
.global eclic_msip_handler
|
||||
eclic_msip_handler:
|
||||
addi sp, sp, -RT_CONTEXT_SIZE
|
||||
STORE x1, 1 * REGBYTES(sp) /* RA */
|
||||
STORE x5, 2 * REGBYTES(sp)
|
||||
STORE x6, 3 * REGBYTES(sp)
|
||||
STORE x7, 4 * REGBYTES(sp)
|
||||
STORE x8, 5 * REGBYTES(sp)
|
||||
STORE x9, 6 * REGBYTES(sp)
|
||||
STORE x10, 7 * REGBYTES(sp)
|
||||
STORE x11, 8 * REGBYTES(sp)
|
||||
STORE x12, 9 * REGBYTES(sp)
|
||||
STORE x13, 10 * REGBYTES(sp)
|
||||
STORE x14, 11 * REGBYTES(sp)
|
||||
STORE x15, 12 * REGBYTES(sp)
|
||||
#ifndef __riscv_32e
|
||||
STORE x16, 13 * REGBYTES(sp)
|
||||
STORE x17, 14 * REGBYTES(sp)
|
||||
STORE x18, 15 * REGBYTES(sp)
|
||||
STORE x19, 16 * REGBYTES(sp)
|
||||
STORE x20, 17 * REGBYTES(sp)
|
||||
STORE x21, 18 * REGBYTES(sp)
|
||||
STORE x22, 19 * REGBYTES(sp)
|
||||
STORE x23, 20 * REGBYTES(sp)
|
||||
STORE x24, 21 * REGBYTES(sp)
|
||||
STORE x25, 22 * REGBYTES(sp)
|
||||
STORE x26, 23 * REGBYTES(sp)
|
||||
STORE x27, 24 * REGBYTES(sp)
|
||||
STORE x28, 25 * REGBYTES(sp)
|
||||
STORE x29, 26 * REGBYTES(sp)
|
||||
STORE x30, 27 * REGBYTES(sp)
|
||||
STORE x31, 28 * REGBYTES(sp)
|
||||
#endif
|
||||
/* Push mstatus to stack */
|
||||
csrr t0, CSR_MSTATUS
|
||||
STORE t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
|
||||
|
||||
/* Push additional registers */
|
||||
|
||||
/* Store sp to task stack */
|
||||
LOAD t0, rt_interrupt_from_thread
|
||||
STORE sp, 0(t0)
|
||||
|
||||
csrr t0, CSR_MEPC
|
||||
STORE t0, 0(sp)
|
||||
|
||||
jal rt_hw_taskswitch
|
||||
|
||||
/* Switch task context */
|
||||
LOAD t0, rt_interrupt_to_thread
|
||||
LOAD sp, 0x0(t0)
|
||||
|
||||
/* Pop PC from stack and set MEPC */
|
||||
LOAD t0, 0 * REGBYTES(sp)
|
||||
csrw CSR_MEPC, t0
|
||||
|
||||
/* Pop additional registers */
|
||||
|
||||
/* Pop mstatus from stack and set it */
|
||||
LOAD t0, (RT_SAVED_REGNUM - 1) * REGBYTES(sp)
|
||||
csrw CSR_MSTATUS, t0
|
||||
/* Interrupt still disable here */
|
||||
/* Restore Registers from Stack */
|
||||
LOAD x1, 1 * REGBYTES(sp) /* RA */
|
||||
LOAD x5, 2 * REGBYTES(sp)
|
||||
LOAD x6, 3 * REGBYTES(sp)
|
||||
LOAD x7, 4 * REGBYTES(sp)
|
||||
LOAD x8, 5 * REGBYTES(sp)
|
||||
LOAD x9, 6 * REGBYTES(sp)
|
||||
LOAD x10, 7 * REGBYTES(sp)
|
||||
LOAD x11, 8 * REGBYTES(sp)
|
||||
LOAD x12, 9 * REGBYTES(sp)
|
||||
LOAD x13, 10 * REGBYTES(sp)
|
||||
LOAD x14, 11 * REGBYTES(sp)
|
||||
LOAD x15, 12 * REGBYTES(sp)
|
||||
#ifndef __riscv_32e
|
||||
LOAD x16, 13 * REGBYTES(sp)
|
||||
LOAD x17, 14 * REGBYTES(sp)
|
||||
LOAD x18, 15 * REGBYTES(sp)
|
||||
LOAD x19, 16 * REGBYTES(sp)
|
||||
LOAD x20, 17 * REGBYTES(sp)
|
||||
LOAD x21, 18 * REGBYTES(sp)
|
||||
LOAD x22, 19 * REGBYTES(sp)
|
||||
LOAD x23, 20 * REGBYTES(sp)
|
||||
LOAD x24, 21 * REGBYTES(sp)
|
||||
LOAD x25, 22 * REGBYTES(sp)
|
||||
LOAD x26, 23 * REGBYTES(sp)
|
||||
LOAD x27, 24 * REGBYTES(sp)
|
||||
LOAD x28, 25 * REGBYTES(sp)
|
||||
LOAD x29, 26 * REGBYTES(sp)
|
||||
LOAD x30, 27 * REGBYTES(sp)
|
||||
LOAD x31, 28 * REGBYTES(sp)
|
||||
#endif
|
||||
|
||||
addi sp, sp, RT_CONTEXT_SIZE
|
||||
mret
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/03/26 Huaqi Nuclei RISC-V Core porting code.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
#define SYSTICK_TICK_CONST (SOC_TIMER_FREQ / RT_TICK_PER_SECOND)
|
||||
|
||||
/* Interrupt level for kernel systimer interrupt and software timer interrupt */
|
||||
#define RT_KERNEL_INTERRUPT_LEVEL 0
|
||||
|
||||
/* Initial CSR MSTATUS value when thread created */
|
||||
#define RT_INITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
|
||||
|
||||
/**
|
||||
* @brief from thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
/**
|
||||
* @brief to thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
/**
|
||||
* @brief flag to indicate context switch in interrupt or not
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
/**
|
||||
* @brief thread stack frame of saved context
|
||||
*
|
||||
*/
|
||||
struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /*!< epc - epc - program counter */
|
||||
rt_ubase_t ra; /*!< x1 - ra - return address for jumps */
|
||||
rt_ubase_t t0; /*!< x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /*!< x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /*!< x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /*!< x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /*!< x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /*!< x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /*!< x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /*!< x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /*!< x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /*!< x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /*!< x15 - a5 - function argument 5 */
|
||||
#ifndef __riscv_32e
|
||||
rt_ubase_t a6; /*!< x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /*!< x17 - s7 - function argument 7 */
|
||||
rt_ubase_t s2; /*!< x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /*!< x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /*!< x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /*!< x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /*!< x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /*!< x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /*!< x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /*!< x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /*!< x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /*!< x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /*!< x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /*!< x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /*!< x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /*!< x31 - t6 - temporary register 6 */
|
||||
#endif
|
||||
rt_ubase_t mstatus; /*!< - machine status register */
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
void *parameter,
|
||||
rt_uint8_t *stack_addr,
|
||||
void *texit)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
int i;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
|
||||
frame->mstatus = RT_INITIAL_MSTATUS;
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do rt-thread context switch in interrupt context
|
||||
*
|
||||
* @param from thread sp of from thread
|
||||
* @param to thread sp of to thread
|
||||
*/
|
||||
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
|
||||
{
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
RT_YIELD();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do rt-thread context switch in task context
|
||||
*
|
||||
* @param from thread sp of from thread
|
||||
* @param to thread sp of to thread
|
||||
*/
|
||||
void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)
|
||||
{
|
||||
rt_hw_context_switch_interrupt(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief shutdown CPU
|
||||
*
|
||||
*/
|
||||
RT_WEAK void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do extra task switch code
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* - Clear software timer interrupt request flag
|
||||
* - clear rt_thread_switch_interrupt_flag to 0
|
||||
*/
|
||||
void rt_hw_taskswitch(void)
|
||||
{
|
||||
/* Clear Software IRQ, A MUST */
|
||||
SysTimer_ClearSWIRQ();
|
||||
rt_thread_switch_interrupt_flag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup systimer and software timer interrupt
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* - Set Systimer interrupt as NON-VECTOR interrupt with lowest interrupt level
|
||||
* - Set software timer interrupt as VECTOR interrupt with lowest interrupt level
|
||||
* - Enable these two interrupts
|
||||
*/
|
||||
void rt_hw_ticksetup(void)
|
||||
{
|
||||
uint64_t ticks = SYSTICK_TICK_CONST;
|
||||
|
||||
/* Make SWI and SysTick the lowest priority interrupts. */
|
||||
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
|
||||
SysTick_Config(ticks);
|
||||
ECLIC_DisableIRQ(SysTimer_IRQn);
|
||||
ECLIC_SetLevelIRQ(SysTimer_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
|
||||
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
|
||||
ECLIC_EnableIRQ(SysTimer_IRQn);
|
||||
|
||||
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
|
||||
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
|
||||
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, RT_KERNEL_INTERRUPT_LEVEL);
|
||||
ECLIC_EnableIRQ(SysTimerSW_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* systimer interrupt handler eclic_mtip_handler
|
||||
* is hard coded in startup_<Device>.S
|
||||
* We define SysTick_Handler as eclic_mtip_handler
|
||||
* for easy understanding
|
||||
*/
|
||||
#define SysTick_Handler eclic_mtip_handler
|
||||
|
||||
/**
|
||||
* @brief This is the timer interrupt service routine.
|
||||
*
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
/* Reload systimer */
|
||||
SysTick_Reload(SYSTICK_TICK_CONST);
|
||||
|
||||
/* enter interrupt */
|
||||
rt_interrupt_enter();
|
||||
|
||||
/* tick increase */
|
||||
rt_tick_increase();
|
||||
|
||||
/* leave interrupt */
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable cpu interrupt
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* - Disable cpu interrupt by clear MIE bit in MSTATUS
|
||||
* - Return the previous value in MSTATUS before clear MIE bit
|
||||
*
|
||||
* @return the previous value in MSTATUS before clear MIE bit
|
||||
*/
|
||||
rt_base_t rt_hw_interrupt_disable(void)
|
||||
{
|
||||
return __RV_CSR_READ_CLEAR(CSR_MSTATUS, MSTATUS_MIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore previous saved interrupt status
|
||||
*
|
||||
* @param level previous saved MSTATUS value
|
||||
*/
|
||||
void rt_hw_interrupt_enable(rt_base_t level)
|
||||
{
|
||||
__RV_CSR_WRITE(CSR_MSTATUS, level);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/03/26 hqfang Nuclei RISC-V Core porting code.
|
||||
*/
|
||||
|
||||
#ifndef __CPUPORT_H__
|
||||
#define __CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
#include <nuclei_sdk_soc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define RT_YIELD() \
|
||||
{ \
|
||||
/* Set a software interrupt(SWI) request to request a context switch. */ \
|
||||
SysTimer_SetSWIRQ(); \
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__RWMB(); \
|
||||
__FENCE_I(); \
|
||||
}
|
||||
|
||||
extern void rt_hw_ticksetup(void);
|
||||
extern void rt_hw_taskswitch(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/03/26 hqfang First Nuclei RISC-V porting implementation
|
||||
*/
|
||||
|
||||
#include "riscv_encoding.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 8
|
||||
|
||||
/**
|
||||
* \brief Global interrupt disabled
|
||||
* \details
|
||||
* This function disable global interrupt.
|
||||
* \remarks
|
||||
* - All the interrupt requests will be ignored by CPU.
|
||||
*/
|
||||
.macro DISABLE_MIE
|
||||
csrc CSR_MSTATUS, MSTATUS_MIE
|
||||
.endm
|
||||
|
||||
/**
|
||||
* \brief Macro for context save
|
||||
* \details
|
||||
* This macro save ABI defined caller saved registers in the stack.
|
||||
* \remarks
|
||||
* - This Macro could use to save context when you enter to interrupt
|
||||
* or exception
|
||||
*/
|
||||
/* Save caller registers */
|
||||
.macro SAVE_CONTEXT
|
||||
csrrw sp, CSR_MSCRATCHCSWL, sp
|
||||
/* Allocate stack space for context saving */
|
||||
#ifndef __riscv_32e
|
||||
addi sp, sp, -20*REGBYTES
|
||||
#else
|
||||
addi sp, sp, -14*REGBYTES
|
||||
#endif /* __riscv_32e */
|
||||
|
||||
STORE x1, 0*REGBYTES(sp)
|
||||
STORE x4, 1*REGBYTES(sp)
|
||||
STORE x5, 2*REGBYTES(sp)
|
||||
STORE x6, 3*REGBYTES(sp)
|
||||
STORE x7, 4*REGBYTES(sp)
|
||||
STORE x10, 5*REGBYTES(sp)
|
||||
STORE x11, 6*REGBYTES(sp)
|
||||
STORE x12, 7*REGBYTES(sp)
|
||||
STORE x13, 8*REGBYTES(sp)
|
||||
STORE x14, 9*REGBYTES(sp)
|
||||
STORE x15, 10*REGBYTES(sp)
|
||||
#ifndef __riscv_32e
|
||||
STORE x16, 14*REGBYTES(sp)
|
||||
STORE x17, 15*REGBYTES(sp)
|
||||
STORE x28, 16*REGBYTES(sp)
|
||||
STORE x29, 17*REGBYTES(sp)
|
||||
STORE x30, 18*REGBYTES(sp)
|
||||
STORE x31, 19*REGBYTES(sp)
|
||||
#endif /* __riscv_32e */
|
||||
.endm
|
||||
|
||||
/**
|
||||
* \brief Macro for restore caller registers
|
||||
* \details
|
||||
* This macro restore ABI defined caller saved registers from stack.
|
||||
* \remarks
|
||||
* - You could use this macro to restore context before you want return
|
||||
* from interrupt or exeception
|
||||
*/
|
||||
/* Restore caller registers */
|
||||
.macro RESTORE_CONTEXT
|
||||
LOAD x1, 0*REGBYTES(sp)
|
||||
LOAD x4, 1*REGBYTES(sp)
|
||||
LOAD x5, 2*REGBYTES(sp)
|
||||
LOAD x6, 3*REGBYTES(sp)
|
||||
LOAD x7, 4*REGBYTES(sp)
|
||||
LOAD x10, 5*REGBYTES(sp)
|
||||
LOAD x11, 6*REGBYTES(sp)
|
||||
LOAD x12, 7*REGBYTES(sp)
|
||||
LOAD x13, 8*REGBYTES(sp)
|
||||
LOAD x14, 9*REGBYTES(sp)
|
||||
LOAD x15, 10*REGBYTES(sp)
|
||||
#ifndef __riscv_32e
|
||||
LOAD x16, 14*REGBYTES(sp)
|
||||
LOAD x17, 15*REGBYTES(sp)
|
||||
LOAD x28, 16*REGBYTES(sp)
|
||||
LOAD x29, 17*REGBYTES(sp)
|
||||
LOAD x30, 18*REGBYTES(sp)
|
||||
LOAD x31, 19*REGBYTES(sp)
|
||||
|
||||
/* De-allocate the stack space */
|
||||
addi sp, sp, 20*REGBYTES
|
||||
#else
|
||||
/* De-allocate the stack space */
|
||||
addi sp, sp, 14*REGBYTES
|
||||
#endif /* __riscv_32e */
|
||||
csrrw sp, CSR_MSCRATCHCSWL, sp
|
||||
.endm
|
||||
|
||||
/**
|
||||
* \brief Macro for save necessary CSRs to stack
|
||||
* \details
|
||||
* This macro store MCAUSE, MEPC, MSUBM to stack.
|
||||
*/
|
||||
.macro SAVE_CSR_CONTEXT
|
||||
/* Store CSR mcause to stack using pushmcause */
|
||||
csrrwi x0, CSR_PUSHMCAUSE, 11
|
||||
/* Store CSR mepc to stack using pushmepc */
|
||||
csrrwi x0, CSR_PUSHMEPC, 12
|
||||
/* Store CSR msub to stack using pushmsub */
|
||||
csrrwi x0, CSR_PUSHMSUBM, 13
|
||||
.endm
|
||||
|
||||
/**
|
||||
* \brief Macro for restore necessary CSRs from stack
|
||||
* \details
|
||||
* This macro restore MSUBM, MEPC, MCAUSE from stack.
|
||||
*/
|
||||
.macro RESTORE_CSR_CONTEXT
|
||||
LOAD x5, 13*REGBYTES(sp)
|
||||
csrw CSR_MSUBM, x5
|
||||
LOAD x5, 12*REGBYTES(sp)
|
||||
csrw CSR_MEPC, x5
|
||||
LOAD x5, 11*REGBYTES(sp)
|
||||
csrw CSR_MCAUSE, x5
|
||||
.endm
|
||||
|
||||
/**
|
||||
* \brief Exception/NMI Entry
|
||||
* \details
|
||||
* This function provide common entry functions for exception/nmi.
|
||||
* \remarks
|
||||
* This function provide a default exception/nmi entry.
|
||||
* ABI defined caller save register and some CSR registers
|
||||
* to be saved before enter interrupt handler and be restored before return.
|
||||
*/
|
||||
.section .text.trap
|
||||
/* In CLIC mode, the exeception entry must be 64bytes aligned */
|
||||
.align 6
|
||||
.global exc_entry
|
||||
exc_entry:
|
||||
/* Save the caller saving registers (context) */
|
||||
SAVE_CONTEXT
|
||||
/* Save the necessary CSR registers */
|
||||
SAVE_CSR_CONTEXT
|
||||
|
||||
/*
|
||||
* Set the exception handler function arguments
|
||||
* argument 1: mcause value
|
||||
* argument 2: current stack point(SP) value
|
||||
*/
|
||||
csrr a0, mcause
|
||||
mv a1, sp
|
||||
/*
|
||||
* TODO: Call the exception handler function
|
||||
* By default, the function template is provided in
|
||||
* system_Device.c, you can adjust it as you want
|
||||
*/
|
||||
call core_exception_handler
|
||||
|
||||
/* Restore the necessary CSR registers */
|
||||
RESTORE_CSR_CONTEXT
|
||||
/* Restore the caller saving registers (context) */
|
||||
RESTORE_CONTEXT
|
||||
|
||||
/* Return to regular code */
|
||||
mret
|
||||
|
||||
/**
|
||||
* \brief Non-Vector Interrupt Entry
|
||||
* \details
|
||||
* This function provide common entry functions for handling
|
||||
* non-vector interrupts
|
||||
* \remarks
|
||||
* This function provide a default non-vector interrupt entry.
|
||||
* ABI defined caller save register and some CSR registers need
|
||||
* to be saved before enter interrupt handler and be restored before return.
|
||||
*/
|
||||
.section .text.irq
|
||||
/* In CLIC mode, the interrupt entry must be 4bytes aligned */
|
||||
.align 2
|
||||
.global irq_entry
|
||||
/* This label will be set to MTVT2 register */
|
||||
irq_entry:
|
||||
/* Save the caller saving registers (context) */
|
||||
SAVE_CONTEXT
|
||||
/* Save the necessary CSR registers */
|
||||
SAVE_CSR_CONTEXT
|
||||
|
||||
/* This special CSR read/write operation, which is actually
|
||||
* claim the CLIC to find its pending highest ID, if the ID
|
||||
* is not 0, then automatically enable the mstatus.MIE, and
|
||||
* jump to its vector-entry-label, and update the link register
|
||||
*/
|
||||
csrrw ra, CSR_JALMNXTI, ra
|
||||
|
||||
/* Critical section with interrupts disabled */
|
||||
DISABLE_MIE
|
||||
|
||||
/* Restore the necessary CSR registers */
|
||||
RESTORE_CSR_CONTEXT
|
||||
/* Restore the caller saving registers (context) */
|
||||
RESTORE_CONTEXT
|
||||
|
||||
/* Return to regular code */
|
||||
mret
|
||||
|
||||
/* Default Handler for Exceptions / Interrupts */
|
||||
.global default_intexc_handler
|
||||
Undef_Handler:
|
||||
default_intexc_handler:
|
||||
1:
|
||||
j 1b
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <RV32M1_ri5cy.h>
|
||||
|
||||
typedef void (*irq_handler_t)(void);
|
||||
extern const irq_handler_t isrTable[];
|
||||
|
||||
void SystemIrqHandler(uint32_t mcause)
|
||||
{
|
||||
uint32_t intNum;
|
||||
|
||||
if (mcause & 0x80000000) /* For external interrupt. */
|
||||
{
|
||||
intNum = mcause & 0x1FUL;
|
||||
|
||||
/* Clear pending flag in EVENT unit .*/
|
||||
EVENT_UNIT->INTPTPENDCLEAR = (1U << intNum);
|
||||
|
||||
/* Now call the real irq handler for intNum */
|
||||
isrTable[intNum]();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/02 Bernard The first version
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global IRQ_Handler
|
||||
IRQ_Handler:
|
||||
|
||||
/* save all from thread context */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
move s0, sp
|
||||
|
||||
/* switch to interrupt stack */
|
||||
la sp, __stack
|
||||
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call SystemIrqHandler
|
||||
call rt_interrupt_leave
|
||||
|
||||
/* switch to from thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
/* clear switch interrupt flag */
|
||||
sw zero, 0(s0)
|
||||
|
||||
csrr a0, mepc
|
||||
STORE a0, 0 * REGBYTES(sp)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
spurious_interrupt:
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* Remain in M-mode after mret */
|
||||
li t0, 0x00001800
|
||||
csrs mstatus, t0
|
||||
LOAD t0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, t0
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
mret
|
||||
@@ -0,0 +1,12 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
* Copyright (c) 2021, Alibaba Group Holding Limited
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/08/20 zx.chen The T-HEAD RISC-V CPU E906 porting implementation
|
||||
* 2021/08/13 zx.chen update T-HEAD E9xx-series(E906/7/F/D/P) CPU porting code.
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions: vPortYield
|
||||
*/
|
||||
.global vPortYield
|
||||
.type vPortYield, %function
|
||||
vPortYield:
|
||||
li t0, 0xE080100C
|
||||
lb t1, (t0)
|
||||
li t2, 0x01
|
||||
or t1, t1, t2
|
||||
sb t1, (t0)
|
||||
|
||||
ret
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* #endif
|
||||
* a0 --> to
|
||||
* a1 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
/* save a0 to to_thread */
|
||||
la t0, rt_interrupt_to_thread
|
||||
STORE a0, (t0)
|
||||
|
||||
/* save 0 to from_thread */
|
||||
la t0, rt_interrupt_from_thread
|
||||
li t1, 0
|
||||
STORE t1, (t0)
|
||||
|
||||
/* set rt_thread_switch_interrupt_flag=1 */
|
||||
la t0, rt_thread_switch_interrupt_flag
|
||||
li t1, 1
|
||||
STORE t1, (t0)
|
||||
|
||||
/* enable mexstatus SPUSHEN */
|
||||
#ifdef CONFIG_THEAD_EXT_SPUSHEN
|
||||
li t0, 0x10000
|
||||
csrs mexstatus, t0
|
||||
#endif
|
||||
|
||||
csrw mscratch, sp
|
||||
/* set software interrupt */
|
||||
li t0, 0xE080100C
|
||||
lb t1, (t0)
|
||||
li t2, 0x01
|
||||
or t1, t1, t2
|
||||
sb t1, (t0)
|
||||
|
||||
/* enable global interrup */
|
||||
csrsi mstatus, 8
|
||||
|
||||
ret
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*
|
||||
* a0 --> from
|
||||
* a1 --> to
|
||||
* a2 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
/* check rt_thread_switch_interrupt_flag */
|
||||
la t0, rt_thread_switch_interrupt_flag
|
||||
lw t1, (t0)
|
||||
li t2, 1
|
||||
beq t1, t2, .reswitch
|
||||
/* set rt_thread_switch_interrupt_flag=1 */
|
||||
STORE t2, (t0)
|
||||
|
||||
/* update from_thread */
|
||||
la t0, rt_interrupt_from_thread
|
||||
STORE a0, (t0)
|
||||
|
||||
.reswitch:
|
||||
/* update to_thread */
|
||||
la t0, rt_interrupt_to_thread
|
||||
STORE a1, (t0)
|
||||
/* set software interrupt */
|
||||
li t0, 0xE080100C
|
||||
lb t1, (t0)
|
||||
li t2, 0x01
|
||||
or t1, t1, t2
|
||||
sb t1, (t0)
|
||||
|
||||
ret
|
||||
|
||||
/*
|
||||
* PendSV_Handler
|
||||
*/
|
||||
.global PendSV_Handler
|
||||
.type PendSV_Handler, %function
|
||||
PendSV_Handler:
|
||||
|
||||
/* check rt_thread_switch_interrupt_flag */
|
||||
sw t0, (-4)(sp)
|
||||
sw t1, (-8)(sp)
|
||||
la t0, rt_thread_switch_interrupt_flag
|
||||
lw t1, (t0)
|
||||
beqz t1, .pendsv_exit
|
||||
|
||||
/* clear rt_thread_switch_interrupt_flag */
|
||||
li t1, 0x0
|
||||
sw t1, (t0)
|
||||
|
||||
/* check rt_interrupt_from_thread */
|
||||
la t0, rt_interrupt_from_thread
|
||||
lw t1, (t0)
|
||||
beqz t1, .switch_to_thead
|
||||
|
||||
/* restore from thread context t0,t1 */
|
||||
lw t0, (-4)(sp)
|
||||
lw t1, (-8)(sp)
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_DSP
|
||||
addi sp, sp, -33 * REGBYTES
|
||||
#else
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
#endif
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
csrr x1, mepc
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
csrr x1, mstatus
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
/* x3 don't need save */
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
#ifdef ARCH_RISCV_DSP
|
||||
csrr t0, vxsat
|
||||
STORE t0, 32 * REGBYTES(sp)
|
||||
#endif
|
||||
|
||||
/* store from_thread sp */
|
||||
la t0, rt_interrupt_from_thread
|
||||
lw t0, (t0)
|
||||
sw sp, (t0)
|
||||
|
||||
.switch_to_thead:
|
||||
/* restore to thread context
|
||||
* sp(0) -> epc;
|
||||
* sp(1) -> ra;
|
||||
* sp(i) -> x(i+2)
|
||||
*/
|
||||
la t0, rt_interrupt_to_thread
|
||||
lw t0, (t0)
|
||||
LOAD sp, (t0)
|
||||
|
||||
|
||||
#ifdef ARCH_RISCV_DSP
|
||||
LOAD a1, 32 * REGBYTES(sp)
|
||||
csrw vxsat, a1
|
||||
#endif
|
||||
|
||||
/* restore ra to mepc */
|
||||
LOAD a1, 0 * REGBYTES(sp)
|
||||
csrw mepc, a1
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* force to machine mode(MPP=11) */
|
||||
LOAD a1, 2 * REGBYTES(sp)
|
||||
csrw mstatus, a1
|
||||
/* x3 don't need restore */
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
#ifdef ARCH_RISCV_DSP
|
||||
addi sp, sp, 33 * REGBYTES
|
||||
#else
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
FLOAD f2, 2 * FREGBYTES(sp)
|
||||
FLOAD f3, 3 * FREGBYTES(sp)
|
||||
FLOAD f4, 4 * FREGBYTES(sp)
|
||||
FLOAD f5, 5 * FREGBYTES(sp)
|
||||
FLOAD f6, 6 * FREGBYTES(sp)
|
||||
FLOAD f7, 7 * FREGBYTES(sp)
|
||||
FLOAD f8, 8 * FREGBYTES(sp)
|
||||
FLOAD f9, 9 * FREGBYTES(sp)
|
||||
FLOAD f10, 10 * FREGBYTES(sp)
|
||||
FLOAD f11, 11 * FREGBYTES(sp)
|
||||
FLOAD f12, 12 * FREGBYTES(sp)
|
||||
FLOAD f13, 13 * FREGBYTES(sp)
|
||||
FLOAD f14, 14 * FREGBYTES(sp)
|
||||
FLOAD f15, 15 * FREGBYTES(sp)
|
||||
FLOAD f16, 16 * FREGBYTES(sp)
|
||||
FLOAD f17, 17 * FREGBYTES(sp)
|
||||
FLOAD f18, 18 * FREGBYTES(sp)
|
||||
FLOAD f19, 19 * FREGBYTES(sp)
|
||||
FLOAD f20, 20 * FREGBYTES(sp)
|
||||
FLOAD f21, 21 * FREGBYTES(sp)
|
||||
FLOAD f22, 22 * FREGBYTES(sp)
|
||||
FLOAD f23, 23 * FREGBYTES(sp)
|
||||
FLOAD f24, 24 * FREGBYTES(sp)
|
||||
FLOAD f25, 25 * FREGBYTES(sp)
|
||||
FLOAD f26, 26 * FREGBYTES(sp)
|
||||
FLOAD f27, 27 * FREGBYTES(sp)
|
||||
FLOAD f28, 28 * FREGBYTES(sp)
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
|
||||
.pendsv_exit:
|
||||
mret
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable(void);
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
.type rt_hw_interrupt_disable, %function
|
||||
rt_hw_interrupt_disable:
|
||||
csrrci a0, mstatus, 8
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
.type rt_hw_interrupt_enable, %function
|
||||
rt_hw_interrupt_enable:
|
||||
csrw mstatus, a0
|
||||
ret
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
* Copyright (c) 2021, Alibaba Group Holding Limited
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020/08/20 zx.chen The T-HEAD RISC-V CPU E906 porting code.
|
||||
* 2021/08/13 zx.chen update T-HEAD E9xx-series(E906/7/F/D/P) CPU porting code.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /* epc - epc - program counter */
|
||||
rt_ubase_t ra; /* x1 - ra - return address for jumps */
|
||||
rt_ubase_t mstatus; /* - machine status register */
|
||||
rt_ubase_t gp; /* x3 - gp - global pointer */
|
||||
rt_ubase_t tp; /* x4 - tp - thread pointer */
|
||||
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
|
||||
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /* x17 - s7 - function argument 7 */
|
||||
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
|
||||
#ifdef ARCH_RISCV_DSP
|
||||
rt_ubase_t vxsat; /* P-ext vxsat reg */
|
||||
#endif
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
rv_floatreg_t f0; /* f0 */
|
||||
rv_floatreg_t f1; /* f1 */
|
||||
rv_floatreg_t f2; /* f2 */
|
||||
rv_floatreg_t f3; /* f3 */
|
||||
rv_floatreg_t f4; /* f4 */
|
||||
rv_floatreg_t f5; /* f5 */
|
||||
rv_floatreg_t f6; /* f6 */
|
||||
rv_floatreg_t f7; /* f7 */
|
||||
rv_floatreg_t f8; /* f8 */
|
||||
rv_floatreg_t f9; /* f9 */
|
||||
rv_floatreg_t f10; /* f10 */
|
||||
rv_floatreg_t f11; /* f11 */
|
||||
rv_floatreg_t f12; /* f12 */
|
||||
rv_floatreg_t f13; /* f13 */
|
||||
rv_floatreg_t f14; /* f14 */
|
||||
rv_floatreg_t f15; /* f15 */
|
||||
rv_floatreg_t f16; /* f16 */
|
||||
rv_floatreg_t f17; /* f17 */
|
||||
rv_floatreg_t f18; /* f18 */
|
||||
rv_floatreg_t f19; /* f19 */
|
||||
rv_floatreg_t f20; /* f20 */
|
||||
rv_floatreg_t f21; /* f21 */
|
||||
rv_floatreg_t f22; /* f22 */
|
||||
rv_floatreg_t f23; /* f23 */
|
||||
rv_floatreg_t f24; /* f24 */
|
||||
rv_floatreg_t f25; /* f25 */
|
||||
rv_floatreg_t f26; /* f26 */
|
||||
rv_floatreg_t f27; /* f27 */
|
||||
rv_floatreg_t f28; /* f28 */
|
||||
rv_floatreg_t f29; /* f29 */
|
||||
rv_floatreg_t f30; /* f30 */
|
||||
rv_floatreg_t f31; /* f31 */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
void *parameter,
|
||||
rt_uint8_t *stack_addr,
|
||||
void *texit)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
int i;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
|
||||
/* force to machine mode(MPP=11) and set MPIE to 1 */
|
||||
frame->mstatus = 0x00007880;
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
/** shutdown CPU */
|
||||
RT_WEAK void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-08-20 zx.chen The first version
|
||||
*/
|
||||
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
#include <theadconfig.h>
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_RISCV_64
|
||||
#define DFSTORE fsd
|
||||
#define DFLOAD fld
|
||||
#define SFSTORE fsw
|
||||
#define SFLOAD flw
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define REGBYTES 8
|
||||
#define SFREGBYTES 4
|
||||
#define DFREGBYTES 8
|
||||
#else
|
||||
#define DFSTORE fsd
|
||||
#define DFLOAD fld
|
||||
#define SFSTORE fsw
|
||||
#define SFLOAD flw
|
||||
#define STORE sw
|
||||
#define LOAD lw
|
||||
|
||||
#define REGBYTES 4
|
||||
#define SFREGBYTES 4
|
||||
#define DFREGBYTES 8
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
#ifdef ARCH_RISCV_FPU_D
|
||||
#define FSTORE fsd
|
||||
#define FLOAD fld
|
||||
#define FREGBYTES 8
|
||||
#define rv_floatreg_t rt_int64_t
|
||||
#endif
|
||||
#ifdef ARCH_RISCV_FPU_S
|
||||
#define FSTORE fsw
|
||||
#define FLOAD flw
|
||||
#define FREGBYTES 4
|
||||
#define rv_floatreg_t rt_int32_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting implementation
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
* 2021/02/02 lizhirui Add userspace support
|
||||
*/
|
||||
#include "cpuport.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable(void);
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
#ifdef RISCV_S_MODE
|
||||
csrrci a0, sstatus, 2
|
||||
#else
|
||||
csrrci a0, mstatus, 8
|
||||
#endif
|
||||
ret
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
csrw SRC_XSTATUS, a0
|
||||
ret
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* #endif
|
||||
* a0 --> to
|
||||
* a1 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
LOAD sp, (a0)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a1
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrw SRC_XSTATUS, a0
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*
|
||||
* a0 --> from
|
||||
* a1 --> to
|
||||
* a2 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
/* saved from thread context
|
||||
* x1/ra -> sp(0)
|
||||
* x1/ra -> sp(1)
|
||||
* mstatus.mie -> sp(2)
|
||||
* x(i) -> sp(i-4)
|
||||
*/
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
STORE sp, (a0)
|
||||
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
|
||||
csrr a0, SRC_XSTATUS
|
||||
#ifdef RISCV_S_MODE
|
||||
andi a0, a0, 2
|
||||
beqz a0, save_spie
|
||||
li a0, 0x20
|
||||
save_spie:
|
||||
STORE a0, 2 * REGBYTES(sp)
|
||||
#else
|
||||
andi a0, a0, 8
|
||||
beqz a0, save_mpie
|
||||
li a0, 0x80
|
||||
save_mpie:
|
||||
STORE a0, 2 * REGBYTES(sp)
|
||||
#endif
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* restore to thread context
|
||||
* sp(0) -> epc;
|
||||
* sp(1) -> ra;
|
||||
* sp(i) -> x(i+2)
|
||||
*/
|
||||
LOAD sp, (a1)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mv a0, a2
|
||||
call rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
*
|
||||
* a0 --> context
|
||||
* a1 --> from
|
||||
* a2 --> to
|
||||
* a3 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
|
||||
STORE a0, 0(a1)
|
||||
|
||||
LOAD sp, 0(a2)
|
||||
move a0, a3
|
||||
call rt_cpus_lock_status_restore
|
||||
|
||||
j rt_hw_context_switch_exit
|
||||
|
||||
#endif
|
||||
|
||||
.global rt_hw_context_switch_exit
|
||||
rt_hw_context_switch_exit:
|
||||
#ifdef RT_USING_SMP
|
||||
#ifdef RT_USING_SIGNALS
|
||||
mv a0, sp
|
||||
|
||||
csrr t0, mhartid
|
||||
/* switch interrupt stack of current cpu */
|
||||
la sp, __stack_start__
|
||||
addi t1, t0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
call rt_signal_check
|
||||
mv sp, a0
|
||||
#endif
|
||||
#endif
|
||||
/* resw ra to mepc */
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw SRC_XEPC, a0
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
li t0, 0x00000120
|
||||
csrw sstatus, t0
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrs sstatus, a0
|
||||
#else
|
||||
li t0, 0x00007800
|
||||
csrw mstatus, t0
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, a0
|
||||
#endif
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
FLOAD f2, 2 * FREGBYTES(sp)
|
||||
FLOAD f3, 3 * FREGBYTES(sp)
|
||||
FLOAD f4, 4 * FREGBYTES(sp)
|
||||
FLOAD f5, 5 * FREGBYTES(sp)
|
||||
FLOAD f6, 6 * FREGBYTES(sp)
|
||||
FLOAD f7, 7 * FREGBYTES(sp)
|
||||
FLOAD f8, 8 * FREGBYTES(sp)
|
||||
FLOAD f9, 9 * FREGBYTES(sp)
|
||||
FLOAD f10, 10 * FREGBYTES(sp)
|
||||
FLOAD f11, 11 * FREGBYTES(sp)
|
||||
FLOAD f12, 12 * FREGBYTES(sp)
|
||||
FLOAD f13, 13 * FREGBYTES(sp)
|
||||
FLOAD f14, 14 * FREGBYTES(sp)
|
||||
FLOAD f15, 15 * FREGBYTES(sp)
|
||||
FLOAD f16, 16 * FREGBYTES(sp)
|
||||
FLOAD f17, 17 * FREGBYTES(sp)
|
||||
FLOAD f18, 18 * FREGBYTES(sp)
|
||||
FLOAD f19, 19 * FREGBYTES(sp)
|
||||
FLOAD f20, 20 * FREGBYTES(sp)
|
||||
FLOAD f21, 21 * FREGBYTES(sp)
|
||||
FLOAD f22, 22 * FREGBYTES(sp)
|
||||
FLOAD f23, 23 * FREGBYTES(sp)
|
||||
FLOAD f24, 24 * FREGBYTES(sp)
|
||||
FLOAD f25, 25 * FREGBYTES(sp)
|
||||
FLOAD f26, 26 * FREGBYTES(sp)
|
||||
FLOAD f27, 27 * FREGBYTES(sp)
|
||||
FLOAD f28, 28 * FREGBYTES(sp)
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
|
||||
XRET
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
* 2021-02-11 lizhirui add gp support
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "stack.h"
|
||||
|
||||
/**
|
||||
* @brief from thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
/**
|
||||
* @brief to thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
/**
|
||||
* @brief flag to indicate context switch in interrupt or not
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
void *parameter,
|
||||
rt_uint8_t *stack_addr,
|
||||
void *texit)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
int i;
|
||||
extern int __global_pointer$;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->gp = (rt_ubase_t)&__global_pointer$;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame));
|
||||
|
||||
#ifndef RISCV_S_MODE
|
||||
frame->xstatus = 0x00007880;
|
||||
#else
|
||||
frame->xstatus = 0x00040120;
|
||||
#endif
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*/
|
||||
#ifndef RT_USING_SMP
|
||||
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
|
||||
{
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif /* end of RT_USING_SMP */
|
||||
|
||||
/** shutdown CPU */
|
||||
void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
rt_thread_t rt_thread_sp_to_thread(void *spmember_addr)
|
||||
{
|
||||
return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread,sp)));
|
||||
}
|
||||
|
||||
void *get_thread_kernel_stack_top(rt_thread_t thread)
|
||||
{
|
||||
return (void *)(((rt_size_t)thread -> stack_addr) + ((rt_size_t)thread -> stack_size));
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define REGBYTES 8
|
||||
#else
|
||||
// error here, not portable
|
||||
#endif
|
||||
|
||||
#ifdef RISCV_U_MODE
|
||||
#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL
|
||||
#endif
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
//csr in s-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE sie
|
||||
#define SRC_XIP sip
|
||||
#define SRC_XTVEC stvec
|
||||
#define SRC_XSTATUS sstatus
|
||||
#define SRC_XSCRATCH sscratch
|
||||
#define SRC_XEPC sepc
|
||||
#define SRC_XCAUSE scause
|
||||
#define SRC_XTVAL stval
|
||||
#define XRET sret
|
||||
#else
|
||||
//csr in m-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE mie
|
||||
#define SRC_XIP mip
|
||||
#define SRC_XTVEC mtvec
|
||||
#define SRC_XSTATUS mstatus
|
||||
#define SRC_XSCRATCH mscratch
|
||||
#define SRC_XEPC mepc
|
||||
#define SRC_XCAUSE mcause
|
||||
#define SRC_XTVAL mtval
|
||||
#define XRET mret
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Change irq enable/disable to cpu0
|
||||
*/
|
||||
#include "tick.h"
|
||||
#include <plic.h>
|
||||
#include "encoding.h"
|
||||
#include "riscv.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
#define MAX_HANDLERS 128
|
||||
|
||||
static struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
int rt_hw_clint_ipi_enable(void)
|
||||
{
|
||||
/* Set the Machine-Software bit in MIE */
|
||||
set_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_clint_ipi_disable(void)
|
||||
{
|
||||
/* Clear the Machine-Software bit in MIE */
|
||||
clear_csr(mie, MIP_MSIP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_enable(int irq_number)
|
||||
{
|
||||
plic_irq_enable(irq_number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_hw_plic_irq_disable(int irq_number)
|
||||
{
|
||||
plic_irq_disable(irq_number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
int idx = 0;
|
||||
/* init exceptions table */
|
||||
for (idx = 0; idx < MAX_HANDLERS; idx++)
|
||||
{
|
||||
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
irq_desc[idx].param = RT_NULL;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
|
||||
irq_desc[idx].counter = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
plic_set_threshold(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
rt_hw_plic_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
plic_set_priority(vector, 1);
|
||||
|
||||
rt_hw_plic_irq_enable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param new_handler the interrupt service routine to be installed
|
||||
* @param old_handler the old interrupt service routine
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if(vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = irq_desc[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
irq_desc[vector].handler = (rt_isr_handler_t)handler;
|
||||
irq_desc[vector].param = param;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
|
||||
irq_desc[vector].counter = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
RT_WEAK
|
||||
void plic_irq_handle(int irq)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", irq);
|
||||
return ;
|
||||
}
|
||||
|
||||
void dump_regs(struct rt_hw_stack_frame *regs)
|
||||
{
|
||||
rt_kprintf("--------------Dump Registers-----------------\n");
|
||||
|
||||
rt_kprintf("Function Registers:\n");
|
||||
rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n",regs -> ra,regs -> user_sp_exc_stack);
|
||||
rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n",regs -> gp,regs -> tp);
|
||||
rt_kprintf("Temporary Registers:\n");
|
||||
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n",regs -> t0,regs -> t1);
|
||||
rt_kprintf("\tt2(x7) = 0x%p\n",regs -> t2);
|
||||
rt_kprintf("\tt3(x28) = 0x%p\tt4(x29) = 0x%p\n",regs -> t3,regs -> t4);
|
||||
rt_kprintf("\tt5(x30) = 0x%p\tt6(x31) = 0x%p\n",regs -> t5,regs -> t6);
|
||||
rt_kprintf("Saved Registers:\n");
|
||||
rt_kprintf("\ts0/fp(x8) = 0x%p\ts1(x9) = 0x%p\n",regs -> s0_fp,regs -> s1);
|
||||
rt_kprintf("\ts2(x18) = 0x%p\ts3(x19) = 0x%p\n",regs -> s2,regs -> s3);
|
||||
rt_kprintf("\ts4(x20) = 0x%p\ts5(x21) = 0x%p\n",regs -> s4,regs -> s5);
|
||||
rt_kprintf("\ts6(x22) = 0x%p\ts7(x23) = 0x%p\n",regs -> s6,regs -> s7);
|
||||
rt_kprintf("\ts8(x24) = 0x%p\ts9(x25) = 0x%p\n",regs -> s8,regs -> s9);
|
||||
rt_kprintf("\ts10(x26) = 0x%p\ts11(x27) = 0x%p\n",regs -> s10,regs -> s11);
|
||||
rt_kprintf("Function Arguments Registers:\n");
|
||||
rt_kprintf("\ta0(x10) = 0x%p\ta1(x11) = 0x%p\n",regs -> a0,regs -> a1);
|
||||
rt_kprintf("\ta2(x12) = 0x%p\ta3(x13) = 0x%p\n",regs -> a2,regs -> a3);
|
||||
rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n",regs -> a4,regs -> a5);
|
||||
rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n",regs -> a6,regs -> a7);
|
||||
rt_kprintf("xstatus = 0x%p\n",regs -> xstatus);
|
||||
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
||||
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
||||
rt_kprintf("\t%s\n",(regs -> xstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
|
||||
rt_kprintf("\t%s\n",(regs -> xstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
|
||||
rt_size_t satp_v = read_csr(satp);
|
||||
rt_kprintf("satp = 0x%p\n",satp_v);
|
||||
const char *mode_str = "Unknown Address Translation/Protection Mode";
|
||||
|
||||
switch(__MASKVALUE(satp_v >> 60,__MASK(4)))
|
||||
{
|
||||
case 0:
|
||||
mode_str = "No Address Translation/Protection Mode";
|
||||
break;
|
||||
|
||||
case 8:
|
||||
mode_str = "Page-based 39-bit Virtual Addressing Mode";
|
||||
break;
|
||||
|
||||
case 9:
|
||||
mode_str = "Page-based 48-bit Virtual Addressing Mode";
|
||||
break;
|
||||
}
|
||||
|
||||
rt_kprintf("\tMode = %s\n",mode_str);
|
||||
rt_kprintf("-----------------Dump OK---------------------\n");
|
||||
}
|
||||
|
||||
void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp)
|
||||
{
|
||||
int cause = (xcause & 0xFFFFFFFF);
|
||||
int plic_irq = 0;
|
||||
|
||||
if (xcause & (1UL << 63))
|
||||
{
|
||||
switch (cause)
|
||||
{
|
||||
case IRQ_M_SOFT:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
case IRQ_M_TIMER:
|
||||
tick_isr();
|
||||
break;
|
||||
case IRQ_S_TIMER:
|
||||
tick_isr();
|
||||
break;
|
||||
|
||||
case IRQ_S_EXT:
|
||||
plic_irq = plic_claim();
|
||||
plic_complete(plic_irq);
|
||||
irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
|
||||
break;
|
||||
|
||||
case IRQ_M_EXT:
|
||||
plic_irq = plic_claim();
|
||||
plic_complete(plic_irq);
|
||||
irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_thread_t tid;
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
extern long list_thread();
|
||||
#endif
|
||||
rt_hw_interrupt_disable();
|
||||
|
||||
rt_kprintf("xcause = %08x,xtval = %08x,xepc = %08x\n", xcause, xtval, xepc);
|
||||
tid = rt_thread_self();
|
||||
rt_kprintf("\nException:\n");
|
||||
switch (cause)
|
||||
{
|
||||
case CAUSE_MISALIGNED_FETCH:
|
||||
rt_kprintf("Instruction address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_FETCH:
|
||||
rt_kprintf("Instruction access fault");
|
||||
break;
|
||||
case CAUSE_ILLEGAL_INSTRUCTION:
|
||||
rt_kprintf("Illegal instruction");
|
||||
break;
|
||||
case CAUSE_BREAKPOINT:
|
||||
rt_kprintf("Breakpoint");
|
||||
break;
|
||||
case CAUSE_MISALIGNED_LOAD:
|
||||
rt_kprintf("Load address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_LOAD:
|
||||
rt_kprintf("Load access fault");
|
||||
break;
|
||||
case CAUSE_MISALIGNED_STORE:
|
||||
rt_kprintf("Store address misaligned");
|
||||
break;
|
||||
case CAUSE_FAULT_STORE:
|
||||
rt_kprintf("Store access fault");
|
||||
break;
|
||||
case CAUSE_USER_ECALL:
|
||||
rt_kprintf("Environment call from U-mode");
|
||||
break;
|
||||
case CAUSE_SUPERVISOR_ECALL:
|
||||
rt_kprintf("Environment call from S-mode");
|
||||
break;
|
||||
case CAUSE_HYPERVISOR_ECALL:
|
||||
rt_kprintf("Environment call from H-mode");
|
||||
break;
|
||||
case CAUSE_MACHINE_ECALL:
|
||||
rt_kprintf("Environment call from M-mode");
|
||||
break;
|
||||
default:
|
||||
rt_kprintf("Uknown exception : %08lX", cause);
|
||||
break;
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
dump_regs(sp);
|
||||
rt_kprintf("exception pc => 0x%08x\n", xepc);
|
||||
rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
while(1);
|
||||
}
|
||||
rt_hw_interrupt_enable(0);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic The first version
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPT_H__
|
||||
#define INTERRUPT_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include "stack.h"
|
||||
|
||||
int rt_hw_clint_ipi_enable(void);
|
||||
int rt_hw_clint_ipi_disable(void);
|
||||
int rt_hw_plic_irq_enable(int irq_number);
|
||||
int rt_hw_plic_irq_disable(int irq_number);
|
||||
void rt_hw_interrupt_init(void);
|
||||
void rt_hw_interrupt_mask(int vector);
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name);
|
||||
void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/02 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP schedule
|
||||
* 2021/02/02 lizhirui Add userspace support
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
|
||||
/* save thread context to thread stack */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XSTATUS
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XEPC
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* switch to interrupt stack */
|
||||
move s0, sp
|
||||
|
||||
#ifndef RISCV_S_MODE
|
||||
/* get cpu id */
|
||||
csrr t0, mhartid
|
||||
#else
|
||||
li t0, 0
|
||||
#endif
|
||||
|
||||
/* switch interrupt stack of current cpu */
|
||||
la sp, __stack_start__
|
||||
addi t1, t0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
/* handle interrupt */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, SRC_XCAUSE
|
||||
csrr a1, SRC_XEPC
|
||||
mv a2, s0
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* s0 --> sp */
|
||||
mv sp, s0
|
||||
mv a0, s0
|
||||
call rt_scheduler_do_irq_switch
|
||||
tail rt_hw_context_switch_exit
|
||||
|
||||
#else
|
||||
|
||||
/* switch to from_thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
sw zero, 0(s0)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
#endif
|
||||
|
||||
spurious_interrupt:
|
||||
tail rt_hw_context_switch_exit
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-30 lizhirui first version
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_H__
|
||||
#define __RISCV_H__
|
||||
|
||||
#include <encoding.h>
|
||||
|
||||
#define __SIZE(bit) (1UL << (bit))
|
||||
#define __MASK(bit) (__SIZE(bit) - 1UL)
|
||||
#define __UMASK(bit) (~(__MASK(bit)))
|
||||
#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
|
||||
#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
|
||||
#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count))))
|
||||
#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit))))
|
||||
|
||||
#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
|
||||
|
||||
#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
|
||||
#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_IO_H__
|
||||
#define __RISCV_IO_H__
|
||||
|
||||
static inline uint32_t __raw_hartid(void)
|
||||
{
|
||||
#ifdef RISCV_S_MODE
|
||||
extern int boot_hartid;
|
||||
return boot_hartid;
|
||||
#else
|
||||
uint32_t x;
|
||||
asm volatile("csrr %0, mhartid" : "=r" (x) );
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sb %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sh %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sw %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sd %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline rt_uint8_t __raw_readb(const volatile void *addr)
|
||||
{
|
||||
rt_uint8_t val;
|
||||
|
||||
asm volatile("lb %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline rt_uint16_t __raw_readw(const volatile void *addr)
|
||||
{
|
||||
rt_uint16_t val;
|
||||
|
||||
asm volatile("lh %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline rt_uint32_t __raw_readl(const volatile void *addr)
|
||||
{
|
||||
rt_uint32_t val;
|
||||
|
||||
asm volatile("lw %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
static inline rt_uint64_t __raw_readq(const volatile void *addr)
|
||||
{
|
||||
rt_uint64_t val;
|
||||
|
||||
asm volatile("ld %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: These are now the same as asm-generic */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define __io_rbr() do {} while (0)
|
||||
#define __io_rar() do {} while (0)
|
||||
#define __io_rbw() do {} while (0)
|
||||
#define __io_raw() do {} while (0)
|
||||
|
||||
#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
|
||||
#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
|
||||
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
|
||||
|
||||
#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
|
||||
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
|
||||
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
|
||||
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
|
||||
#endif
|
||||
|
||||
#define __io_br() do {} while (0)
|
||||
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
|
||||
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
|
||||
#define __io_aw() do {} while (0)
|
||||
|
||||
#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
|
||||
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
|
||||
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
|
||||
|
||||
#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
|
||||
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
|
||||
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
|
||||
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-30 lizhirui first version
|
||||
*/
|
||||
|
||||
#ifndef __STACK_H__
|
||||
#define __STACK_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /* epc - epc - program counter */
|
||||
rt_ubase_t ra; /* x1 - ra - return address for jumps */
|
||||
rt_ubase_t xstatus; /* - supervisor/machine/user status register */
|
||||
rt_ubase_t gp; /* x3 - gp - global pointer */
|
||||
rt_ubase_t tp; /* x4 - tp - thread pointer */
|
||||
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
|
||||
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /* x17 - s7 - function argument 7 */
|
||||
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
|
||||
rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-02-02 lizhirui first version
|
||||
* 2021-02-11 lizhirui fixed gp save/store bug
|
||||
*/
|
||||
|
||||
#ifndef __STACKFRAME_H__
|
||||
#define __STACKFRAME_H__
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.macro SAVE_ALL
|
||||
addi sp, sp, -33 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XSTATUS
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XEPC
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x3, 3 * REGBYTES(sp)
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
csrr t0, SRC_XSCRATCH
|
||||
STORE t0, 32 * REGBYTES(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL_ONLY
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
LOAD x3, 3 * REGBYTES(sp)
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 33 * REGBYTES
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
LOAD x3, 3 * REGBYTES(sp)
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
//restore user sp
|
||||
LOAD sp, 32 * REGBYTES(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_SYS_GP
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
.endm
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
* 2020/6/12 Xim Port to QEMU and remove SMP support
|
||||
*/
|
||||
|
||||
#define XSTATUS_FS (3 << 13) /* initial state of FPU, clear to disable */
|
||||
#define XSTATUS_PUM (1 << 18)
|
||||
#include <cpuport.h>
|
||||
|
||||
boot_hartid: .int
|
||||
.global boot_hartid
|
||||
|
||||
.global _start
|
||||
.section ".start", "ax"
|
||||
_start:
|
||||
#ifdef RISCV_S_MODE
|
||||
# save hartid
|
||||
la t0, boot_hartid # global varible rt_boot_hartid
|
||||
mv t1, a0 # get hartid in S-mode frome a0 register
|
||||
sw t1, (t0) # store t1 register low 4 bits in memory address which is stored in t0
|
||||
#else
|
||||
# setup stacks per hart
|
||||
csrr t0, mhartid # read current hart id
|
||||
slli t0, t0, 10 # shift left the hart id by 1024
|
||||
|
||||
# park harts with id != 0
|
||||
csrr a0, mhartid # read current hart id
|
||||
bnez a0, park # if we're not on the hart 0
|
||||
#endif
|
||||
|
||||
csrw SRC_XIE, 0 # clear Interrupt Registers
|
||||
csrw SRC_XIP, 0
|
||||
|
||||
la t0, trap_entry
|
||||
csrw SRC_XTVEC, t0 # set Trap Vector Base Address Register
|
||||
|
||||
/* set to disable FPU */
|
||||
li t0, XSTATUS_FS # close fpu
|
||||
csrc SRC_XSTATUS, t0
|
||||
#ifdef RISCV_S_MODE
|
||||
li t0, XSTATUS_PUM # PUM has no effect
|
||||
csrs SRC_XSTATUS, t0
|
||||
#endif
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
la sp, __stack_start__
|
||||
li t0, __STACKSIZE__
|
||||
add sp, sp, t0
|
||||
csrw SRC_XSCRATCH, sp
|
||||
j primary_cpu_entry
|
||||
|
||||
park:
|
||||
wfi
|
||||
j park
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "sbi.h"
|
||||
#include "tick.h"
|
||||
#include <riscv_io.h>
|
||||
#include <encoding.h>
|
||||
|
||||
#define VIRT_CLINT_TIMEBASE_FREQ (10000000)
|
||||
|
||||
static volatile uint64_t time_elapsed = 0;
|
||||
static volatile unsigned long tick_cycles = 0;
|
||||
|
||||
static uint64_t get_ticks()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"rdtime %0"
|
||||
: "=r"(time_elapsed));
|
||||
return time_elapsed;
|
||||
}
|
||||
|
||||
int tick_isr(void)
|
||||
{
|
||||
int tick_cycles = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
rt_tick_increase();
|
||||
#ifdef RISCV_S_MODE
|
||||
sbi_set_timer(get_ticks() + tick_cycles);
|
||||
#else
|
||||
*(uint64_t*)CLINT_MTIMECMP(__raw_hartid()) = *(uint64_t*)CLINT_MTIME + tick_cycles;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets and enable the timer interrupt */
|
||||
int rt_hw_tick_init(void)
|
||||
{
|
||||
unsigned long interval = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
/* Clear the Supervisor-Timer bit in SIE */
|
||||
clear_csr(sie, SIP_STIP);
|
||||
|
||||
/* calculate the tick cycles */
|
||||
// tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
|
||||
tick_cycles = 40000;
|
||||
/* Set timer */
|
||||
sbi_set_timer(get_ticks() + tick_cycles);
|
||||
|
||||
/* Enable the Supervisor-Timer bit in SIE */
|
||||
set_csr(sie, SIP_STIP);
|
||||
#else
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
clear_csr(mip, MIP_MTIP);
|
||||
*(uint64_t*)CLINT_MTIMECMP(__raw_hartid()) = *(uint64_t*)CLINT_MTIME + interval;
|
||||
set_csr(mie, MIP_MTIP);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#ifndef TICK_H__
|
||||
#define TICK_H__
|
||||
|
||||
//ask the CLINT for a timer interrupt.
|
||||
#define CLINT (0x2000000L)
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 4*(hartid))
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
||||
|
||||
int tick_isr(void);
|
||||
int rt_hw_tick_init(void);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user