rt-thread/bsp/hpmicro/libraries/hpm_sdk/soc/HPM6360/toolchains/trap.c

258 lines
7.7 KiB
C
Raw Normal View History

/*
* Copyright (c) 2021 hpmicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "hpm_common.h"
#include "hpm_soc.h"
/********************** MCAUSE exception types **************************************/
#define MCAUSE_INSTR_ADDR_MISALIGNED (0U) /* !< Instruction Address misaligned */
#define MCAUSE_INSTR_ACCESS_FAULT (1U) /* !< Instruction access fault */
#define MCAUSE_ILLEGAL_INSTR (2U) /* !< Illegal instruction */
#define MCAUSE_BREAKPOINT (3U) /* !< Breakpoint */
#define MCAUSE_LOAD_ADDR_MISALIGNED (4U) /* !< Load address misaligned */
#define MCAUSE_LOAD_ACCESS_FAULT (5U) /* !< Load access fault */
#define MCAUSE_STORE_AMO_ADDR_MISALIGNED (6U) /* !< Store/AMO address misaligned */
#define MCAUSE_STORE_AMO_ACCESS_FAULT (7U) /* !< Store/AMO access fault */
#define MCAUSE_ECALL_FROM_USER_MODE (8U) /* !< Environment call from User mode */
#define MCAUSE_ECALL_FROM_SUPERVISOR_MODE (9U) /* !< Environment call from Supervisor mode */
#define MCAUSE_ECALL_FROM_MACHINE_MODE (11U) /* !< Environment call from machine mode */
#define MCAUSE_INSTR_PAGE_FAULT (12U) /* !< Instruction page fault */
#define MCAUSE_LOAD_PAGE_FAULT (13) /* !< Load page fault */
#define MCAUSE_STORE_AMO_PAGE_FAULT (15U) /* !< Store/AMO page fault */
#define IRQ_S_SOFT 1
#define IRQ_H_SOFT 2
#define IRQ_M_SOFT 3
#define IRQ_S_TIMER 5
#define IRQ_H_TIMER 6
#define IRQ_M_TIMER 7
#define IRQ_S_EXT 9
#define IRQ_H_EXT 10
#define IRQ_M_EXT 11
#define IRQ_COP 12
#define IRQ_HOST 13
__attribute__((weak)) void mchtmr_isr(void)
{
}
__attribute__((weak)) void swi_isr(void)
{
}
__attribute__((weak)) void syscall_handler(long n, long a0, long a1, long a2, long a3)
{
}
__attribute__((weak)) long exception_handler(long cause, long epc)
{
switch (cause) {
case MCAUSE_INSTR_ADDR_MISALIGNED:
break;
case MCAUSE_INSTR_ACCESS_FAULT:
break;
case MCAUSE_ILLEGAL_INSTR:
break;
case MCAUSE_BREAKPOINT:
break;
case MCAUSE_LOAD_ADDR_MISALIGNED:
break;
case MCAUSE_LOAD_ACCESS_FAULT:
break;
case MCAUSE_STORE_AMO_ADDR_MISALIGNED:
break;
case MCAUSE_STORE_AMO_ACCESS_FAULT:
break;
case MCAUSE_ECALL_FROM_USER_MODE:
break;
case MCAUSE_ECALL_FROM_SUPERVISOR_MODE:
break;
case MCAUSE_ECALL_FROM_MACHINE_MODE:
break;
case MCAUSE_INSTR_PAGE_FAULT:
break;
case MCAUSE_LOAD_PAGE_FAULT:
break;
case MCAUSE_STORE_AMO_PAGE_FAULT:
break;
default:
break;
}
/* Unhandled Trap */
return epc;
}
__attribute__((weak)) long exception_s_handler(long cause, long epc)
{
return epc;
}
__attribute__((weak)) void swi_s_isr(void)
{
}
__attribute__((weak)) void mchtmr_s_isr(void)
{
}
#ifndef CONFIG_FREERTOS
[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上基于现有移植文件进行多线程复杂场景下的长时间测试,测试过程系统运行正常。
2023-03-01 14:32:43 +08:00
void SW_handler(void) __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4)));
#else
[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上基于现有移植文件进行多线程复杂场景下的长时间测试,测试过程系统运行正常。
2023-03-01 14:32:43 +08:00
void SW_handler(void) __attribute__ ((section(".isr_vector")));
#endif
[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上基于现有移植文件进行多线程复杂场景下的长时间测试,测试过程系统运行正常。
2023-03-01 14:32:43 +08:00
void SW_handler(void)
{
long mcause = read_csr(CSR_MCAUSE);
long mepc = read_csr(CSR_MEPC);
long mstatus = read_csr(CSR_MSTATUS);
#if SUPPORT_PFT_ARCH
long mxstatus = read_csr(CSR_MXSTATUS);
#endif
#ifdef __riscv_dsp
int ucode = read_csr(CSR_UCODE);
#endif
#ifdef __riscv_flen
int fcsr = read_fcsr();
#endif
/* clobbers list for ecall */
#ifdef __riscv_32e
__asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
#else
__asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
#endif
/* Do your trap handling */
if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_TIMER)) {
/* Machine timer interrupt */
mchtmr_isr();
}
#ifdef USE_NONVECTOR_MODE
else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_EXT)) {
typedef void(*isr_func_t)(void);
/* Machine-level interrupt from PLIC */
uint32_t irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE);
if (irq_index) {
/* Workaround: irq number returned by __plic_claim_irq might be 0, which is caused by plic. So skip invalid irq_index as a workaround */
#ifndef DISABLE_IRQ_PREEMPTIVE
enable_global_irq(CSR_MSTATUS_MIE_MASK);
#endif
((isr_func_t)__vector_table[irq_index])();
__plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_M_MODE, irq_index);
}
}
#endif
else if ((mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == IRQ_M_SOFT)) {
/* Machine SWI interrupt */
swi_isr();
intc_m_complete_swi();
} else if (!(mcause & CSR_MCAUSE_INTERRUPT_MASK) && ((mcause & CSR_MCAUSE_EXCEPTION_CODE_MASK) == MCAUSE_ECALL_FROM_MACHINE_MODE)) {
/* Machine Syscal call */
__asm volatile(
"mv a4, a3\n"
"mv a3, a2\n"
"mv a2, a1\n"
"mv a1, a0\n"
#ifdef __riscv_32e
"mv a0, t0\n"
#else
"mv a0, a7\n"
#endif
"jalr %0\n"
: :"r"(syscall_handler) : "a4"
);
mepc += 4;
} else {
mepc = exception_handler(mcause, mepc);
}
/* Restore CSR */
write_csr(CSR_MSTATUS, mstatus);
write_csr(CSR_MEPC, mepc);
#if SUPPORT_PFT_ARCH
write_csr(CSR_MXSTATUS, mxstatus);
#endif
#ifdef __riscv_dsp
write_csr(CSR_UCODE, ucode);
#endif
#ifdef __riscv_flen
write_fcsr(fcsr);
#endif
}
#ifndef CONFIG_FREERTOS
void irq_handler_s_trap(void) __attribute__ ((section(".isr_s_vector"), interrupt("supervisor"), aligned(4)));
#else
void irq_handler_s_trap(void) __attribute__ ((section(".isr_s_vector")));
#endif
void irq_handler_s_trap(void)
{
long scause = read_csr(CSR_SCAUSE);
long sepc = read_csr(CSR_SEPC);
long sstatus = read_csr(CSR_SSTATUS);
/* clobbers list for ecall */
#ifdef __riscv_32e
__asm volatile("" : : :"t0", "a0", "a1", "a2", "a3");
#else
__asm volatile("" : : :"a7", "a0", "a1", "a2", "a3");
#endif
/* Do your trap handling */
if ((scause & CSR_SCAUSE_INTERRUPT_MASK) && ((scause & CSR_SCAUSE_EXCEPTION_CODE_MASK) == IRQ_S_TIMER)) {
/* Machine timer interrupt */
mchtmr_s_isr();
}
#ifdef USE_NONVECTOR_MODE
else if ((scause & CSR_SCAUSE_INTERRUPT_MASK) && ((scause & CSR_SCAUSE_EXCEPTION_CODE_MASK) == IRQ_S_EXT)) {
typedef void(*isr_func_t)(void);
/* Machine-level interrupt from PLIC */
uint32_t irq_index = __plic_claim_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_S_MODE);
#ifndef DISABLE_IRQ_PREEMPTIVE
enable_s_global_irq(CSR_SSTATUS_SIE_MASK);
#endif
((isr_func_t)__vector_s_table[irq_index])();
__plic_complete_irq(HPM_PLIC_BASE, HPM_PLIC_TARGET_S_MODE, irq_index);
}
#endif
else if ((scause & CSR_SCAUSE_INTERRUPT_MASK) && ((scause & CSR_SCAUSE_EXCEPTION_CODE_MASK) == IRQ_S_SOFT)) {
/* Machine SWI interrupt */
intc_m_claim_swi();
swi_s_isr();
intc_s_complete_swi();
} else if (!(scause & CSR_SCAUSE_INTERRUPT_MASK) && ((scause & CSR_SCAUSE_EXCEPTION_CODE_MASK) == MCAUSE_ECALL_FROM_SUPERVISOR_MODE)) {
/* Machine Syscal call */
__asm volatile(
"mv a4, a3\n"
"mv a3, a2\n"
"mv a2, a1\n"
"mv a1, a0\n"
#ifdef __riscv_32e
"mv a0, t0\n"
#else
"mv a0, a7\n"
#endif
"jalr %0\n"
: :"r"(syscall_handler) : "a4"
);
sepc += 4;
} else {
sepc = exception_s_handler(scause, sepc);
}
/* Restore CSR */
write_csr(CSR_SSTATUS, sstatus);
write_csr(CSR_SEPC, sepc);
}