mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-08-20 21:29:42 +08:00
[libcpu][riscv]整合libcpu/riscv中的移植文件 提供一份公共代码于common (#6941)
整合libcpu/riscv中的移植文件 提供一份公共代码于common 在提交本pr时,除hpmicro的内核,rv32内核bsp已完成去除大部分的冗余,大部分代码采用common中的实现。本pr的作用是进一步统一common中的文件,从而提供一份公用代码,新移植的RV32内核的BSP可以全部使用common代码。 - 在common中提供一份公用文件:interrupt_gcc.S - 修改原有的文件,将原有的中断中上下文切换代码替换为interrupt_gcc.S - 基于上述修改,修改仓库中risc-v内核的BSP与移植相关的部分 (主要包含中断入口函数 中断栈等) - 在common中提供一份公用文件:trap_common.c;提供统一中断入口函数,中断入口函数初始化,中断入口注册等函数,并完善异常时的信息输出 - 在common中提供一份公用文件:rt_hw_stack_frame.h;将栈帧结构体剥离,供用户使用 - 在上述工作完成后,在上述工作的基础上测试仓库中risc-v内核的BSP - 完善函数中的命名,完善中断栈的获取 - 提供一份详细的基于现有common文件的移植指南 #### 在什么测试环境下测试通过 - 1.CH32V307V-R1-R0 - 2.CH32V208W-R0-1V4 - 3.HPM6750EVKMINI - 4.GD32VF103V-EVAL - 5.qemu(CORE-V-MCU ) > 与上述开发板使用同样芯片的BSP均测试通过 在CH32V307V-R1-R0与HPM6750EVKMINI上基于现有移植文件进行多线程复杂场景下的长时间测试,测试过程系统运行正常。
This commit is contained in:
@@ -10,14 +10,10 @@ group = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
# add common code files
|
||||
if rtconfig.CPU == "nuclei" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "virt64" :
|
||||
if rtconfig.CPU == "virt64" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "c906" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "hpmicro":
|
||||
group = group
|
||||
else :
|
||||
group = group + SConscript(os.path.join('common', 'SConscript'))
|
||||
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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,18 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
csrrw ra, 0x07ED, ra
|
||||
|
||||
li t0, 0x08
|
||||
csrc mstatus, t0
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
@@ -2,16 +2,11 @@
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ' -I ' + cwd
|
||||
|
||||
if rtconfig.PLATFORM == 'gcc':
|
||||
src += Glob('*_gcc.S')
|
||||
|
||||
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* 2021-09-09 WCH the first version
|
||||
* 2023-01-04 WangShun Remove redundant files
|
||||
*/
|
||||
#include "rtconfig.h"
|
||||
#if defined (SOC_RISCV_SERIES_CH32V1)
|
||||
#include "ch32v10x.h"
|
||||
#elif defined (SOC_RISCV_SERIES_CH32V2)
|
||||
@@ -17,11 +18,7 @@
|
||||
#else
|
||||
#error "CH32 architecture doesn't support!"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* trigger soft interrupt
|
||||
*/
|
||||
void sw_setpend(void)
|
||||
void rt_trigger_software_interrupt(void)
|
||||
{
|
||||
/*CH32V103 does not support systick software interrupt*/
|
||||
#if defined(SOC_RISCV_SERIES_CH32V1)
|
||||
@@ -31,39 +28,14 @@ void sw_setpend(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* clear soft interrupt
|
||||
*/
|
||||
void sw_clearpend(void)
|
||||
void rt_hw_do_after_save_above(void)
|
||||
{
|
||||
__asm volatile ("li t0,0x20" );
|
||||
__asm volatile ("csrs 0x804, t0");
|
||||
/*CH32V103 does not support systick software interrupt*/
|
||||
#if defined(SOC_RISCV_SERIES_CH32V1)
|
||||
NVIC_ClearPendingIRQ(Software_IRQn);
|
||||
#else
|
||||
SysTick->CTLR &= ~(1 << 31);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* disable interrupt and save mstatus
|
||||
*/
|
||||
rt_weak rt_base_t rt_hw_interrupt_disable(void)
|
||||
{
|
||||
rt_base_t value=0;
|
||||
#if defined(SOC_RISCV_SERIES_CH32V3)
|
||||
asm("csrrw %0, mstatus, %1":"=r"(value):"r"(0x7800));
|
||||
#else
|
||||
asm("csrrw %0, mstatus, %1":"=r"(value):"r"(0x1800));
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* enable interrupt and resume mstatus
|
||||
*/
|
||||
rt_weak void rt_hw_interrupt_enable(rt_base_t level)
|
||||
{
|
||||
asm("csrw mstatus, %0": :"r"(level));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -46,6 +46,9 @@ rt_hw_interrupt_enable:
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
la t0, __rt_rvstack
|
||||
csrw mscratch,t0
|
||||
|
||||
LOAD sp, (a0)
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
@@ -214,9 +217,9 @@ rt_hw_context_switch_exit:
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
li t0, 0x00007800
|
||||
li t0, 0x7800
|
||||
#else
|
||||
li t0, 0x00001800
|
||||
li t0, 0x1800
|
||||
#endif
|
||||
csrw mstatus, t0
|
||||
LOAD a0, 2 * REGBYTES(sp)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "rt_hw_stack_frame.h"
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
@@ -21,76 +22,6 @@ 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
|
||||
*
|
||||
@@ -127,14 +58,24 @@ rt_uint8_t *rt_hw_stack_init(void *tentry,
|
||||
|
||||
/* force to machine mode(MPP=11) and set MPIE to 1 */
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
frame->mstatus = 0x00007880;
|
||||
frame->mstatus = 0x7880;
|
||||
#else
|
||||
frame->mstatus = 0x00001880;
|
||||
frame->mstatus = 0x1880;
|
||||
#endif
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
rt_weak void rt_trigger_software_interrupt(void)
|
||||
{
|
||||
while (0);
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_do_after_save_above(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* #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);
|
||||
@@ -150,9 +91,9 @@ rt_weak void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_t
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
#if defined(SOC_RISCV_FAMILY_CH32)
|
||||
sw_setpend();
|
||||
#endif
|
||||
|
||||
rt_trigger_software_interrupt();
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif /* end of RT_USING_SMP */
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#if defined(SOC_RISCV_FAMILY_CH32)
|
||||
#include "interrupt.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef RT_USING_SMP
|
||||
@@ -32,6 +27,15 @@ typedef union {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Preprocessor Definition */
|
||||
#if __riscv_flen == 32
|
||||
#define ARCH_RISCV_FPU_S
|
||||
#endif
|
||||
|
||||
#if __riscv_flen == 64
|
||||
#define ARCH_RISCV_FPU_D
|
||||
#endif
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
#define STORE sd
|
||||
@@ -43,6 +47,7 @@ typedef union {
|
||||
#define REGBYTES 4
|
||||
#endif
|
||||
|
||||
/* Preprocessor Definition */
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
#ifdef ARCH_RISCV_FPU_D
|
||||
#define FSTORE fsd
|
||||
|
||||
@@ -5,17 +5,23 @@
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 WCH the first version
|
||||
* 2022-12-27 WangShun Merge WCH series mcu port files
|
||||
* 2023/01/17 WangShun The first version
|
||||
*/
|
||||
|
||||
#define __ASSEMBLY__
|
||||
#include "cpuport.h"
|
||||
|
||||
.global SW_handler
|
||||
.align 2
|
||||
.section .text.entry, "ax"
|
||||
#if defined(SOC_SERIES_GD32VF103V)
|
||||
.align 6
|
||||
#else
|
||||
.align 2
|
||||
#endif
|
||||
.global SW_handler
|
||||
|
||||
SW_handler:
|
||||
/* save all from thread context */
|
||||
li t0, 0x08
|
||||
csrc mstatus, t0
|
||||
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
@@ -51,21 +57,13 @@ SW_handler:
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
#endif
|
||||
|
||||
/* save all from thread context */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
|
||||
/* saved MPIE */
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
|
||||
/* Temporarily disable HPE */
|
||||
#if defined (SOC_RISCV_SERIES_CH32V3)
|
||||
li t0, 0x20
|
||||
csrs 0x804, t0
|
||||
#endif
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
/* Mandatory set the MPIE of mstatus */
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp)
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
@@ -95,20 +93,23 @@ SW_handler:
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* switch to interrupt stack */
|
||||
csrrw sp,mscratch,sp
|
||||
csrrw sp,mscratch,sp
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
/* clear interrupt */
|
||||
jal sw_clearpend
|
||||
/* Do the work after saving the above */
|
||||
jal rt_hw_do_after_save_above
|
||||
|
||||
call rt_interrupt_leave
|
||||
/* switch to from thread stack */
|
||||
csrrw sp,mscratch,sp
|
||||
csrrw sp,mscratch,sp
|
||||
|
||||
/* if rt_thread_switch_interrupt_flag=1,then clear it */
|
||||
/* Determine whether to trigger scheduling at the interrupt function */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, 1f
|
||||
/* clear the flag of rt_thread_switch_interrupt_flag */
|
||||
sw zero, 0(s0)
|
||||
#1:
|
||||
|
||||
csrr a0, mepc
|
||||
STORE a0, 0 * REGBYTES(sp)
|
||||
|
||||
@@ -123,16 +124,14 @@ SW_handler:
|
||||
LOAD a0, 0 * REGBYTES(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
1: LOAD x1, 1 * REGBYTES(sp)
|
||||
#if defined (SOC_RISCV_SERIES_CH32V3)
|
||||
li t0,0x7800
|
||||
csrs mstatus, t0
|
||||
#else
|
||||
li t0,0x1800
|
||||
csrs mstatus, t0
|
||||
#endif
|
||||
LOAD t0, 2*REGBYTES(sp)
|
||||
csrs mstatus, t0
|
||||
1:
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
/* Set the mode after MRET */
|
||||
li t0, 0x1800
|
||||
csrs mstatus, t0
|
||||
LOAD t0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, t0
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
@@ -162,9 +161,8 @@ SW_handler:
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
|
||||
/* load float reg */
|
||||
addi sp, sp, 32 * REGBYTES
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
FLOAD f0, 0 * FREGBYTES(sp)
|
||||
FLOAD f1, 1 * FREGBYTES(sp)
|
||||
@@ -198,6 +196,7 @@ SW_handler:
|
||||
FLOAD f29, 29 * FREGBYTES(sp)
|
||||
FLOAD f30, 30 * FREGBYTES(sp)
|
||||
FLOAD f31, 31 * FREGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32 * FREGBYTES
|
||||
#endif
|
||||
mret
|
||||
@@ -83,5 +83,4 @@ typedef struct rt_hw_stack_frame
|
||||
#endif
|
||||
}rt_hw_stack_frame_t;
|
||||
|
||||
|
||||
#endif /* RISCV_STACKFRAME_H */
|
||||
@@ -0,0 +1,105 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "riscv-ops.h"
|
||||
#include "rt_hw_stack_frame.h"
|
||||
|
||||
#define ISR_NUMBER 32
|
||||
static volatile rt_hw_stack_frame_t *s_stack_frame;
|
||||
static struct rt_irq_desc rv32irq_table[ISR_NUMBER];
|
||||
void rt_show_stack_frame(void);
|
||||
|
||||
/**
|
||||
* Temporary interrupt entry function
|
||||
*
|
||||
* @param mcause Machine Cause Register
|
||||
* @return RT_NULL
|
||||
*/
|
||||
rt_weak rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t mcause)
|
||||
{
|
||||
rt_kprintf("UN-handled interrupt %d occurred!!!\n", mcause);
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt entry function initialization
|
||||
*/
|
||||
rt_weak void rt_hw_interrupt_init(void)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
for (idx = 0; idx < ISR_NUMBER; idx++)
|
||||
{
|
||||
rv32irq_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
rv32irq_table[idx].param = RT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Break Entry Function Binding
|
||||
*
|
||||
* @param vector interrupt number
|
||||
* @param handler Break-in function requiring binding
|
||||
* @param param NULL
|
||||
* @param name NULL
|
||||
* @return NULL
|
||||
*/
|
||||
rt_weak rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
void *user_param = param;
|
||||
char *user_name = name;
|
||||
if(vector < ISR_NUMBER)
|
||||
{
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
rv32irq_table[vector].handler = (rt_isr_handler_t)handler;
|
||||
rv32irq_table[vector].param = param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query and Distribution Entry for Exception and Interrupt Sources
|
||||
*
|
||||
* @param mcause Machine Cause Register
|
||||
*/
|
||||
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
|
||||
{
|
||||
rt_uint32_t mscratch = read_csr(0x340);
|
||||
rt_uint32_t irq_id = (mcause & 0x1F);
|
||||
rt_uint32_t exception = !(mcause & 0x80000000);
|
||||
if(exception)
|
||||
{
|
||||
s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
|
||||
rt_show_stack_frame();
|
||||
}
|
||||
else
|
||||
{
|
||||
rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Print on Exception
|
||||
*/
|
||||
rt_weak void rt_show_stack_frame(void)
|
||||
{
|
||||
rt_kprintf("Stack frame:\r\n----------------------------------------\r\n");
|
||||
rt_kprintf("ra : 0x%08x\r\n", s_stack_frame->ra);
|
||||
rt_kprintf("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus
|
||||
rt_kprintf("t0 : 0x%08x\r\n", s_stack_frame->t0);
|
||||
rt_kprintf("t1 : 0x%08x\r\n", s_stack_frame->t1);
|
||||
rt_kprintf("t2 : 0x%08x\r\n", s_stack_frame->t2);
|
||||
rt_kprintf("a0 : 0x%08x\r\n", s_stack_frame->a0);
|
||||
rt_kprintf("a1 : 0x%08x\r\n", s_stack_frame->a1);
|
||||
rt_kprintf("a2 : 0x%08x\r\n", s_stack_frame->a2);
|
||||
rt_kprintf("a3 : 0x%08x\r\n", s_stack_frame->a3);
|
||||
rt_kprintf("a4 : 0x%08x\r\n", s_stack_frame->a4);
|
||||
rt_kprintf("a5 : 0x%08x\r\n", s_stack_frame->a5);
|
||||
rt_kprintf("a6 : 0x%08x\r\n", s_stack_frame->a6);
|
||||
rt_kprintf("a7 : 0x%08x\r\n", s_stack_frame->a7);
|
||||
rt_kprintf("t3 : 0x%08x\r\n", s_stack_frame->t3);
|
||||
rt_kprintf("t4 : 0x%08x\r\n", s_stack_frame->t4);
|
||||
rt_kprintf("t5 : 0x%08x\r\n", s_stack_frame->t5);
|
||||
rt_kprintf("t6 : 0x%08x\r\n", s_stack_frame->t6);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
typedef void (*irq_handler_t)(void);
|
||||
extern const irq_handler_t isr_table[];
|
||||
|
||||
extern void vSystemIrqHandler(uint32_t mcause);
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* 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, __freertos_irq_stack_top
|
||||
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call vSystemIrqHandler
|
||||
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,16 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call rt_rv32_system_irq_handler
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
@@ -11,7 +11,7 @@ if rtconfig.PLATFORM == 'gcc':
|
||||
src += Glob('*_gcc.S')
|
||||
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
ASFLAGS = ' -I ' + cwd
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
#include <rt-thread/libcpu/risc-v/hpmicro/cpuport.h>
|
||||
#include <rt-thread/libcpu/risc-v/hpmicro/riscv-stackframe.h>
|
||||
* 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 "riscv-stackframe.h"
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
*/
|
||||
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 ;
|
||||
}
|
||||
|
||||
/** 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);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
||||
#define STORE sw
|
||||
#define LOAD lw
|
||||
#define REGBYTES 4
|
||||
|
||||
#ifdef __riscv_flen
|
||||
#define ARCH_RISCV_FPU
|
||||
|
||||
#if __riscv_flen == 32
|
||||
#define ARCH_RISCV_FPU_S
|
||||
#endif
|
||||
|
||||
#if __riscv_flen == 64
|
||||
#define ARCH_RISCV_FPU_D
|
||||
#endif
|
||||
#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
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 - 2022 hpmicro
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022/01/16 HPMicro The first version
|
||||
* 2020/04/27 HPMicro Bugfix for interrupt management
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .isr_vector, "ax"
|
||||
.global irq_handler_trap
|
||||
.align 2
|
||||
irq_handler_trap:
|
||||
#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 all from thread context */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp) // ra
|
||||
li t0, 0x80
|
||||
STORE t0, 2 * REGBYTES(sp) // mstatus
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp) // tp - thread pointer
|
||||
STORE x5, 5 * REGBYTES(sp) // t0
|
||||
STORE x6, 6 * REGBYTES(sp) // t1
|
||||
STORE x7, 7 * REGBYTES(sp) // t2
|
||||
STORE x8, 8 * REGBYTES(sp) // s0/fp
|
||||
STORE x9, 9 * REGBYTES(sp) // s1
|
||||
STORE x10, 10 * REGBYTES(sp) // a0
|
||||
STORE x11, 11 * REGBYTES(sp) // a1
|
||||
STORE x12, 12 * REGBYTES(sp) // a2
|
||||
STORE x13, 13 * REGBYTES(sp) // a3
|
||||
STORE x14, 14 * REGBYTES(sp) // a4
|
||||
STORE x15, 15 * REGBYTES(sp) // a5
|
||||
STORE x16, 16 * REGBYTES(sp) // a6
|
||||
STORE x17, 17 * REGBYTES(sp) // a7
|
||||
STORE x18, 18 * REGBYTES(sp) // s2
|
||||
STORE x19, 19 * REGBYTES(sp) // s3
|
||||
STORE x20, 20 * REGBYTES(sp) // s4
|
||||
STORE x21, 21 * REGBYTES(sp) // s5
|
||||
STORE x22, 22 * REGBYTES(sp) // s6
|
||||
STORE x23, 23 * REGBYTES(sp) // s7
|
||||
STORE x24, 24 * REGBYTES(sp) // s8
|
||||
STORE x25, 25 * REGBYTES(sp) // s9
|
||||
STORE x26, 26 * REGBYTES(sp) // s10
|
||||
STORE x27, 27 * REGBYTES(sp) // s11
|
||||
STORE x28, 28 * REGBYTES(sp) // t3
|
||||
STORE x29, 29 * REGBYTES(sp) // t4
|
||||
STORE x30, 30 * REGBYTES(sp) // t5
|
||||
STORE x31, 31 * REGBYTES(sp) // t6
|
||||
|
||||
/* Save the thread stack frame base to mscratch */
|
||||
csrw mscratch, sp
|
||||
|
||||
/* switch to interrupt stack */
|
||||
la sp, _stack
|
||||
|
||||
/* interrupt handle */
|
||||
call rt_interrupt_enter
|
||||
/* Get the thread stack frame base from mscratch */
|
||||
csrr a0, mscratch
|
||||
call trap_entry
|
||||
call rt_interrupt_leave
|
||||
|
||||
/* switch to thread stack */
|
||||
csrr sp, mscratch
|
||||
|
||||
/* 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) // ra
|
||||
/* Remain in M-mode after mret */
|
||||
li t0, 0x00001800
|
||||
csrs mstatus, t0
|
||||
LOAD t0, 2 * REGBYTES(sp)
|
||||
csrs mstatus, t0 // mstatus.mpie
|
||||
|
||||
LOAD x4, 4 * REGBYTES(sp) // tp
|
||||
LOAD x5, 5 * REGBYTES(sp) // t0
|
||||
LOAD x6, 6 * REGBYTES(sp) // t1
|
||||
LOAD x7, 7 * REGBYTES(sp) // t2
|
||||
LOAD x8, 8 * REGBYTES(sp) // s0/fp
|
||||
LOAD x9, 9 * REGBYTES(sp) // s1
|
||||
LOAD x10, 10 * REGBYTES(sp) // a0
|
||||
LOAD x11, 11 * REGBYTES(sp) // a1
|
||||
LOAD x12, 12 * REGBYTES(sp) // a2
|
||||
LOAD x13, 13 * REGBYTES(sp) // a3
|
||||
LOAD x14, 14 * REGBYTES(sp) // a4
|
||||
LOAD x15, 15 * REGBYTES(sp) // a5
|
||||
LOAD x16, 16 * REGBYTES(sp) // a6
|
||||
LOAD x17, 17 * REGBYTES(sp) // a7
|
||||
LOAD x18, 18 * REGBYTES(sp) // s2
|
||||
LOAD x19, 19 * REGBYTES(sp) // s3
|
||||
LOAD x20, 20 * REGBYTES(sp) // s4
|
||||
LOAD x21, 21 * REGBYTES(sp) // s5
|
||||
LOAD x22, 22 * REGBYTES(sp) // s6
|
||||
LOAD x23, 23 * REGBYTES(sp) // s7
|
||||
LOAD x24, 24 * REGBYTES(sp) // s8
|
||||
LOAD x25, 25 * REGBYTES(sp) // s9
|
||||
LOAD x26, 26 * REGBYTES(sp) // s10
|
||||
LOAD x27, 27 * REGBYTES(sp) // s11
|
||||
LOAD x28, 28 * REGBYTES(sp) // t3
|
||||
LOAD x29, 29 * REGBYTES(sp) // t4
|
||||
LOAD x30, 30 * REGBYTES(sp) // t5
|
||||
LOAD x31, 31 * REGBYTES(sp) // t6
|
||||
|
||||
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,12 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
csrr a0, mscratch
|
||||
call trap_entry
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
@@ -7,7 +7,7 @@ Import('rtconfig')
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
ASFLAGS = ' -I ' + cwd
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* 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_base_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);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* 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,18 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
csrrw ra, 0x07ED, ra
|
||||
|
||||
li t0, 0x08
|
||||
csrc mstatus, t0
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
@@ -0,0 +1,212 @@
|
||||
### RV32移植指南
|
||||
|
||||
#### 1.概述
|
||||
|
||||
为了简化RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹
|
||||
|
||||
| 文件名 | 文件内容 |
|
||||
| :-----------------: | :----------------------------: |
|
||||
| context_gcc.S | 开关全局中断,线程上下文切换等 |
|
||||
| cpuport.c | 线程栈初始化,软件中断触发等 |
|
||||
| cpuport.h | 数据加载写入指令 |
|
||||
| interrupt_gcc.S | 线程间上下文切换 |
|
||||
| riscv-ops.h | 控制状态寄存器读写 |
|
||||
| rt_hw_stack_frame.h | 线程栈格式 |
|
||||
| trap_common.c | 中断注册,中断查询分发 |
|
||||
|
||||
#### 2.移植接口
|
||||
|
||||
(1)软件中断触发函数,通常向量管理中断需实现该函数,非向量中断管理方式一般不需要
|
||||
|
||||
```c
|
||||
void rt_trigger_software_interrupt(void)
|
||||
```
|
||||
|
||||
(2)保存上文后执行函数,该函数向量中断与非向量中断均需实现
|
||||
|
||||
```c
|
||||
void rt_hw_do_after_save_above(void)
|
||||
```
|
||||
|
||||
该函数需要实现的工作如下:
|
||||
|
||||
步骤1:将函数返回地址(ra)保存栈中
|
||||
|
||||
步骤2:加载中断处理函数的入口参数
|
||||
|
||||
步骤3:调用中断处理函数
|
||||
|
||||
步骤4:从栈中加载返回地址(ra),返回至SW_handler函数
|
||||
|
||||
#### 3.准备工作
|
||||
|
||||
- 准备一个基础的裸机工程,需具备以下条件:
|
||||
|
||||
- 明确中断管理方式(向量中断/非向量中断)
|
||||
|
||||
- 实现系统节拍定时器中断
|
||||
- 实现一个串口中断
|
||||
|
||||
#### 4.移植步骤
|
||||
|
||||
<font color=red>对于新移植的RISC-V 32位内核,若采用非向量中断管理方式,推荐使用common中的文件,除了下述步骤中必要的修改以及中断初始化与注册步骤外,用户仅需拷贝一份cv32e40p移植文件,重命名为具体内核名称即可 。</font>
|
||||
|
||||
- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler**
|
||||
|
||||
- 根据使用的中断管理方式,执行下述操作
|
||||
|
||||
- 向量中断管理方式
|
||||
|
||||
> 通常会使用一个软件中断(该中断的优先级被配置为最低)作为在中断中触发上下文切换的入口函数。SW_handler在此仅作为触发软件中断时的入口参数,其他类型中断触发时跳转至各自的中断入口函数。
|
||||
>
|
||||
|
||||
移植方法:修改原有的中断向量表中软件中断所在位置,将原有软件中断函数名修改为**SW_handler**
|
||||
|
||||
示例(ch32系列):
|
||||
|
||||
```assembly
|
||||
_vector_base:
|
||||
.option norvc;
|
||||
.word _start
|
||||
...
|
||||
.word SW_handler /* 将这里原来放置的软件中断函数名修改为SW_handler */
|
||||
```
|
||||
|
||||
- 非向量中断
|
||||
|
||||
> 当有中断触发时,会进入一个统一的中断入口函数进行中断查询分发。SW_handler在此处不仅作为作为在中断中触发上下文切换的入口函数,同时承担中断查询分发与执行。
|
||||
>
|
||||
|
||||
移植方法:将**SW_handler**的地址加载到保存统一中断入口地址的寄存器(通常为mtevc,具体名称需要根据具体的内核指定)
|
||||
|
||||
示例(hpm6750系列):
|
||||
|
||||
```assembly
|
||||
la t0, SW_handler
|
||||
csrw mtvec, t0
|
||||
```
|
||||
|
||||
- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码
|
||||
|
||||
- 将下述代码放置于链接脚本中中断栈顶名之后
|
||||
|
||||
```assembly
|
||||
PROVIDE( __rt_rvstack = . );
|
||||
```
|
||||
|
||||
- 示例(core-v-mcu链接脚本):
|
||||
|
||||
```assembly
|
||||
.stack : ALIGN(16)
|
||||
{
|
||||
stack_start = .;
|
||||
__stack_bottom = .;
|
||||
. += __stack_size;
|
||||
__stack_top = .;
|
||||
PROVIDE( __rt_rvstack = . );//移植时添加
|
||||
stack = .;
|
||||
} > L2
|
||||
```
|
||||
|
||||
> __stack_top为core-v-mcu工程的中断栈顶名 不同工程此处的名称可能不一致 按上述方法将给出的代码放到具体工程链接脚本中断栈顶名称之后即可。
|
||||
|
||||
- 步骤三:实现在中断上下文切换的函数接口
|
||||
|
||||
<font color=red>RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,为用户提供了统一的中断查询分发函数以及相关函数 ,该部分内容位于common文件夹的trap_common.c文件中,对于移植一个新的RV32内核推荐使用RT-Thread提供的统一函数接口。以下是两种实现方式的示例:</font>
|
||||
|
||||
(一)采用RT-Thread通用中断分发函数
|
||||
|
||||
采用RT-Thread提供的通用中断查询分发函数时,移植文件直接拷贝一份cv32e40p内核移植文件,重命名为具体内核名称即可,移植代码如下:
|
||||
|
||||
```assembly
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call rt_rv32_system_irq_handler
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
```
|
||||
|
||||
RT-Thread提供的通用中断分发函数如下:
|
||||
|
||||
```c
|
||||
rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause)
|
||||
{
|
||||
rt_uint32_t mscratch = read_csr(0x340);
|
||||
rt_uint32_t irq_id = (mcause & 0x1F);
|
||||
rt_uint32_t exception = !(mcause & 0x80000000);
|
||||
if(exception)
|
||||
{
|
||||
s_stack_frame = (rt_hw_stack_frame_t *)mscratch;
|
||||
rt_show_stack_frame();
|
||||
}
|
||||
else
|
||||
{
|
||||
rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
随后用户仅需调用rt_hw_interrupt_init进行初始化,然后将中断入口函数通过rt_hw_interrupt_install函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下:
|
||||
|
||||
```c
|
||||
rt_hw_interrupt_init();
|
||||
rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");
|
||||
rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");
|
||||
```
|
||||
|
||||
(二)采用原有裸机的中断入口处理函数
|
||||
|
||||
新建一个文件夹,并以移植的内核的名称命名:
|
||||
|
||||
- 向量中断(可参考ch32)
|
||||
|
||||
(1)在刚才新建的文件夹下,创建一个c文件,用于实现上文提供的两个函数接口
|
||||
|
||||
(2)实现上述两个函数接口
|
||||
- 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作
|
||||
- 在void rt_hw_do_after_save_above(void)中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作
|
||||
|
||||
- 非向量中断(可参考cv32e40p)
|
||||
|
||||
- 在刚才新建的文件夹下,创建一个汇编文件,实现上述提供的函数接口
|
||||
- 对于非向量中断的管理方式仅需实现rt_hw_do_after_save_above函数即可
|
||||
|
||||
示例代码:
|
||||
|
||||
```assembly
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4 // 移动栈指针
|
||||
STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中
|
||||
|
||||
csrr a0, mscratch // 加载函数入口参数
|
||||
call trap_entry // 调用中断处理函数
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值
|
||||
addi sp, sp, 4 // 移动栈指针
|
||||
ret // 返回SW_handler
|
||||
```
|
||||
|
||||
trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。
|
||||
|
||||
|
||||
|
||||
#### 5.验证
|
||||
|
||||
- 创建一个静态线程,在线程中调用RT-Thread提供的与系统时基相关函数接口,例如rt_thread_mdelay,调试观察系统是否可以正常运行
|
||||
- 移植RT-Thread的shell进一步验证系统是否移植成功
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* 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,16 @@
|
||||
#include "cpuport.h"
|
||||
|
||||
.globl rt_hw_do_after_save_above
|
||||
.type rt_hw_do_after_save_above,@function
|
||||
rt_hw_do_after_save_above:
|
||||
addi sp, sp, -4
|
||||
STORE ra, 0 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call SystemIrqHandler
|
||||
|
||||
LOAD ra, 0 * REGBYTES(sp)
|
||||
addi sp, sp, 4
|
||||
ret
|
||||
Reference in New Issue
Block a user