|
@@ -1,36 +1,29 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2006-2021, RT-Thread Development Team
|
|
|
+ * Copyright (c) 2006-2024, RT-Thread Development Team
|
|
|
*
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
*
|
|
|
* Change Logs:
|
|
|
* Date Author Notes
|
|
|
- * 2021/1/30 lizirui first version
|
|
|
- * 2021/10/20 JasonHu move to trap.c
|
|
|
+ * 2022-12-08 RT-Thread first version
|
|
|
*/
|
|
|
|
|
|
#include <rthw.h>
|
|
|
#include <rtthread.h>
|
|
|
#include <stdint.h>
|
|
|
|
|
|
-
|
|
|
-#include "board.h"
|
|
|
-#include "tick.h"
|
|
|
-
|
|
|
#include <mm_fault.h>
|
|
|
-#include "mmu.h"
|
|
|
-#include "encoding.h"
|
|
|
-#include "stack.h"
|
|
|
-#include "sbi.h"
|
|
|
-#include "riscv.h"
|
|
|
-#include "rt_interrupt.h"
|
|
|
-#include "plic.h"
|
|
|
+#include <mmu.h>
|
|
|
+#include <encoding.h>
|
|
|
+#include <stack.h>
|
|
|
+#include <sbi.h>
|
|
|
+#include <riscv.h>
|
|
|
+#include <interrupt.h>
|
|
|
+#include <plic.h>
|
|
|
+#include <tick.h>
|
|
|
|
|
|
#ifdef RT_USING_SMART
|
|
|
#include <lwp_arch.h>
|
|
|
-void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc);
|
|
|
-#else
|
|
|
-#define rt_hw_backtrace(...) (0)
|
|
|
#endif
|
|
|
|
|
|
#define DBG_TAG "libcpu.trap"
|
|
@@ -42,7 +35,8 @@ 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("\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);
|
|
@@ -62,15 +56,27 @@ void dump_regs(struct rt_hw_stack_frame *regs)
|
|
|
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("sstatus = 0x%p\n", regs->sstatus);
|
|
|
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
|
|
|
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
|
|
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
|
|
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
|
|
|
- rt_kprintf("\t%s\n", (regs->sstatus & (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("\t%s\n", (regs->sstatus & SSTATUS_SIE)
|
|
|
+ ? "Supervisor Interrupt Enabled"
|
|
|
+ : "Supervisor Interrupt Disabled");
|
|
|
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE)
|
|
|
+ ? "Last Time Supervisor Interrupt Enabled"
|
|
|
+ : "Last Time Supervisor Interrupt Disabled");
|
|
|
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP)
|
|
|
+ ? "Last Privilege is Supervisor Mode"
|
|
|
+ : "Last Privilege is User Mode");
|
|
|
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM)
|
|
|
+ ? "Permit to Access User Page"
|
|
|
+ : "Not Permit to Access User Page");
|
|
|
+ rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19))
|
|
|
+ ? "Permit to Read Executable-only Page"
|
|
|
+ : "Not Permit to Read Executable-only Page");
|
|
|
+ rt_ubase_t satp_v = read_csr(satp);
|
|
|
rt_kprintf("satp = 0x%p\n", satp_v);
|
|
|
- rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n", __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
|
|
|
- rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
|
|
|
+ rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n",
|
|
|
+ __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
|
|
|
+ rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16))
|
|
|
+ << PAGE_OFFSET_BIT);
|
|
|
const char *mode_str = "Unknown Address Translation/Protection Mode";
|
|
|
|
|
|
switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
|
|
@@ -92,50 +98,44 @@ void dump_regs(struct rt_hw_stack_frame *regs)
|
|
|
rt_kprintf("-----------------Dump OK---------------------\n");
|
|
|
}
|
|
|
|
|
|
-static const char *Exception_Name[] =
|
|
|
- {
|
|
|
- "Instruction Address Misaligned",
|
|
|
- "Instruction Access Fault",
|
|
|
- "Illegal Instruction",
|
|
|
- "Breakpoint",
|
|
|
- "Load Address Misaligned",
|
|
|
- "Load Access Fault",
|
|
|
- "Store/AMO Address Misaligned",
|
|
|
- "Store/AMO Access Fault",
|
|
|
- "Environment call from U-mode",
|
|
|
- "Environment call from S-mode",
|
|
|
- "Reserved-10",
|
|
|
- "Reserved-11",
|
|
|
- "Instruction Page Fault",
|
|
|
- "Load Page Fault",
|
|
|
- "Reserved-14",
|
|
|
- "Store/AMO Page Fault"};
|
|
|
-
|
|
|
-static const char *Interrupt_Name[] =
|
|
|
- {
|
|
|
- "User Software Interrupt",
|
|
|
- "Supervisor Software Interrupt",
|
|
|
- "Reversed-2",
|
|
|
- "Reversed-3",
|
|
|
- "User Timer Interrupt",
|
|
|
- "Supervisor Timer Interrupt",
|
|
|
- "Reversed-6",
|
|
|
- "Reversed-7",
|
|
|
- "User External Interrupt",
|
|
|
- "Supervisor External Interrupt",
|
|
|
- "Reserved-10",
|
|
|
- "Reserved-11",
|
|
|
+static const char *Exception_Name[] = {"Instruction Address Misaligned",
|
|
|
+ "Instruction Access Fault",
|
|
|
+ "Illegal Instruction",
|
|
|
+ "Breakpoint",
|
|
|
+ "Load Address Misaligned",
|
|
|
+ "Load Access Fault",
|
|
|
+ "Store/AMO Address Misaligned",
|
|
|
+ "Store/AMO Access Fault",
|
|
|
+ "Environment call from U-mode",
|
|
|
+ "Environment call from S-mode",
|
|
|
+ "Reserved-10",
|
|
|
+ "Reserved-11",
|
|
|
+ "Instruction Page Fault",
|
|
|
+ "Load Page Fault",
|
|
|
+ "Reserved-14",
|
|
|
+ "Store/AMO Page Fault"};
|
|
|
+
|
|
|
+static const char *Interrupt_Name[] = {
|
|
|
+ "User Software Interrupt",
|
|
|
+ "Supervisor Software Interrupt",
|
|
|
+ "Reversed-2",
|
|
|
+ "Reversed-3",
|
|
|
+ "User Timer Interrupt",
|
|
|
+ "Supervisor Timer Interrupt",
|
|
|
+ "Reversed-6",
|
|
|
+ "Reversed-7",
|
|
|
+ "User External Interrupt",
|
|
|
+ "Supervisor External Interrupt",
|
|
|
+ "Reserved-10",
|
|
|
+ "Reserved-11",
|
|
|
};
|
|
|
|
|
|
#ifndef RT_USING_SMP
|
|
|
static volatile int nested = 0;
|
|
|
-#define ENTER_TRAP \
|
|
|
- nested += 1
|
|
|
-#define EXIT_TRAP \
|
|
|
- nested -= 1
|
|
|
+#define ENTER_TRAP nested += 1
|
|
|
+#define EXIT_TRAP nested -= 1
|
|
|
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
|
|
- if (nested != 1) \
|
|
|
- handle_nested_trap_panic(cause, tval, epc, eframe)
|
|
|
+ if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe)
|
|
|
#endif /* RT_USING_SMP */
|
|
|
|
|
|
static const char *get_exception_msg(int id)
|
|
@@ -153,9 +153,11 @@ static const char *get_exception_msg(int id)
|
|
|
}
|
|
|
|
|
|
#ifdef RT_USING_SMART
|
|
|
-void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
|
|
|
+#include "lwp.h"
|
|
|
+void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
|
|
|
+ struct rt_hw_stack_frame *sp)
|
|
|
{
|
|
|
- rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
|
|
|
+ rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
|
|
struct rt_lwp *lwp;
|
|
|
|
|
|
/* user page fault */
|
|
@@ -165,11 +167,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
|
|
{
|
|
|
case EP_LOAD_PAGE_FAULT:
|
|
|
fault_op = MM_FAULT_OP_READ;
|
|
|
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
|
|
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
|
|
break;
|
|
|
case EP_LOAD_ACCESS_FAULT:
|
|
|
fault_op = MM_FAULT_OP_READ;
|
|
|
- fault_type = MM_FAULT_TYPE_GENERIC;
|
|
|
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
|
|
break;
|
|
|
case EP_LOAD_ADDRESS_MISALIGNED:
|
|
|
fault_op = MM_FAULT_OP_READ;
|
|
@@ -177,11 +179,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
|
|
break;
|
|
|
case EP_STORE_PAGE_FAULT:
|
|
|
fault_op = MM_FAULT_OP_WRITE;
|
|
|
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
|
|
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
|
|
break;
|
|
|
case EP_STORE_ACCESS_FAULT:
|
|
|
fault_op = MM_FAULT_OP_WRITE;
|
|
|
- fault_type = MM_FAULT_TYPE_GENERIC;
|
|
|
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
|
|
break;
|
|
|
case EP_STORE_ADDRESS_MISALIGNED:
|
|
|
fault_op = MM_FAULT_OP_WRITE;
|
|
@@ -189,11 +191,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
|
|
break;
|
|
|
case EP_INSTRUCTION_PAGE_FAULT:
|
|
|
fault_op = MM_FAULT_OP_EXECUTE;
|
|
|
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
|
|
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
|
|
break;
|
|
|
case EP_INSTRUCTION_ACCESS_FAULT:
|
|
|
fault_op = MM_FAULT_OP_EXECUTE;
|
|
|
- fault_type = MM_FAULT_TYPE_GENERIC;
|
|
|
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
|
|
break;
|
|
|
case EP_INSTRUCTION_ADDRESS_MISALIGNED:
|
|
|
fault_op = MM_FAULT_OP_EXECUTE;
|
|
@@ -213,28 +215,31 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
|
|
.fault_vaddr = (void *)stval,
|
|
|
};
|
|
|
|
|
|
- __asm__ volatile ("csrrsi %0, sstatus, 2":"=r"(saved_stat));
|
|
|
+ __asm__ volatile("csrrsi %0, sstatus, 2" : "=r"(saved_stat));
|
|
|
if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg))
|
|
|
{
|
|
|
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
|
|
|
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
|
|
|
return;
|
|
|
}
|
|
|
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
|
|
|
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
|
|
|
}
|
|
|
LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id));
|
|
|
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
|
|
dump_regs(sp);
|
|
|
|
|
|
- rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
|
|
|
+ rt_thread_t cur_thr = rt_thread_self();
|
|
|
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
|
|
|
+ rt_kprintf("fp = %p\n", frame.fp);
|
|
|
+ lwp_backtrace_frame(cur_thr, &frame);
|
|
|
|
|
|
- LOG_E("User Fault, killing thread: %s", rt_thread_self()->parent.name);
|
|
|
+ LOG_E("User Fault, killing thread: %s", cur_thr->parent.name);
|
|
|
|
|
|
EXIT_TRAP;
|
|
|
sys_exit_group(-1);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-#ifdef ENABLE_VECTOR
|
|
|
+#ifdef ARCH_RISCV_VECTOR
|
|
|
static void vector_enable(struct rt_hw_stack_frame *sp)
|
|
|
{
|
|
|
sp->sstatus |= SSTATUS_VS_INITIAL;
|
|
@@ -243,7 +248,8 @@ static void vector_enable(struct rt_hw_stack_frame *sp)
|
|
|
/**
|
|
|
* detect V/D support, and do not distinguish V/D instruction
|
|
|
*/
|
|
|
-static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *sp)
|
|
|
+static int illegal_inst_recoverable(rt_ubase_t stval,
|
|
|
+ struct rt_hw_stack_frame *sp)
|
|
|
{
|
|
|
// first 7 bits is opcode
|
|
|
int opcode = stval & 0x7f;
|
|
@@ -254,12 +260,12 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
|
|
|
|
|
switch (opcode)
|
|
|
{
|
|
|
- case 0x57: // V
|
|
|
- case 0x27: // scalar FLOAT
|
|
|
- case 0x07:
|
|
|
- case 0x73: // CSR
|
|
|
- flag = 1;
|
|
|
- break;
|
|
|
+ case 0x57: // V
|
|
|
+ case 0x27: // scalar FLOAT
|
|
|
+ case 0x07:
|
|
|
+ case 0x73: // CSR
|
|
|
+ flag = 1;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
if (flag)
|
|
@@ -271,11 +277,9 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static void handle_nested_trap_panic(
|
|
|
- rt_size_t cause,
|
|
|
- rt_size_t tval,
|
|
|
- rt_size_t epc,
|
|
|
- struct rt_hw_stack_frame *eframe)
|
|
|
+static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval,
|
|
|
+ rt_ubase_t epc,
|
|
|
+ struct rt_hw_stack_frame *eframe)
|
|
|
{
|
|
|
LOG_E("\n-------- [SEVER ERROR] --------");
|
|
|
LOG_E("Nested trap detected");
|
|
@@ -285,21 +289,23 @@ static void handle_nested_trap_panic(
|
|
|
}
|
|
|
|
|
|
#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP)
|
|
|
-#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
|
|
|
+#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
|
|
|
|
|
|
/* Trap entry */
|
|
|
-void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
|
|
|
+void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
|
|
|
+ struct rt_hw_stack_frame *sp)
|
|
|
{
|
|
|
- rt_size_t id = __MASKVALUE(scause,__MASK(63UL));
|
|
|
+ ENTER_TRAP;
|
|
|
+ rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
|
|
const char *msg;
|
|
|
|
|
|
/* supervisor external interrupt */
|
|
|
- if ((SCAUSE_INTERRUPT & scause) && SCAUSE_S_EXTERNAL_INTR == (scause & 0xff))
|
|
|
+ if ((SCAUSE_INTERRUPT & scause) &&
|
|
|
+ SCAUSE_S_EXTERNAL_INTR == (scause & 0xff))
|
|
|
{
|
|
|
rt_interrupt_enter();
|
|
|
plic_handle_irq();
|
|
|
rt_interrupt_leave();
|
|
|
- return;
|
|
|
}
|
|
|
else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause)
|
|
|
{
|
|
@@ -307,44 +313,74 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
|
|
|
rt_interrupt_enter();
|
|
|
tick_isr();
|
|
|
rt_interrupt_leave();
|
|
|
- return;
|
|
|
}
|
|
|
- else if (SCAUSE_INTERRUPT & scause)
|
|
|
+ else
|
|
|
{
|
|
|
- if(id < sizeof(Interrupt_Name) / sizeof(const char *))
|
|
|
+ if (SCAUSE_INTERRUPT & scause)
|
|
|
{
|
|
|
- msg = Interrupt_Name[id];
|
|
|
+ if (id < sizeof(Interrupt_Name) / sizeof(const char *))
|
|
|
+ {
|
|
|
+ msg = Interrupt_Name[id];
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ msg = "Unknown Interrupt";
|
|
|
+ }
|
|
|
+
|
|
|
+ LOG_E("Unhandled Interrupt %ld:%s\n", id, msg);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- msg = "Unknown Interrupt";
|
|
|
+#ifdef ARCH_RISCV_VECTOR
|
|
|
+ if (scause == 0x2)
|
|
|
+ {
|
|
|
+ if (!(sp->sstatus & SSTATUS_VS) &&
|
|
|
+ illegal_inst_recoverable(stval, sp))
|
|
|
+ goto _exit;
|
|
|
+ }
|
|
|
+#endif /* ARCH_RISCV_VECTOR */
|
|
|
+#ifdef RT_USING_SMART
|
|
|
+ if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
|
|
|
+ {
|
|
|
+ handle_user(scause, stval, sepc, sp);
|
|
|
+ // if handle_user() return here, jump to u mode then
|
|
|
+ goto _exit;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ // handle kernel exception:
|
|
|
+ rt_kprintf("Unhandled Exception %ld:%s\n", id,
|
|
|
+ get_exception_msg(id));
|
|
|
}
|
|
|
- LOG_E("Unhandled Interrupt %ld:%s\n",id,msg);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+
|
|
|
+ // trap cannot nested when handling another trap / interrupt
|
|
|
+ CHECK_NESTED_PANIC(scause, stval, sepc, sp);
|
|
|
+
|
|
|
+ rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
|
|
+ dump_regs(sp);
|
|
|
+
|
|
|
+ rt_thread_t cur_thr = rt_thread_self();
|
|
|
+ rt_kprintf("--------------Thread list--------------\n");
|
|
|
+ rt_kprintf("current thread: %s\n", cur_thr->parent.name);
|
|
|
+
|
|
|
+ rt_kprintf("--------------Backtrace--------------\n");
|
|
|
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
|
|
|
+
|
|
|
#ifdef RT_USING_SMART
|
|
|
- if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
|
|
|
+ if (!(sp->sstatus & 0x100))
|
|
|
{
|
|
|
- handle_user(scause, stval, sepc, sp);
|
|
|
- // if handle_user() return here, jump to u mode then
|
|
|
- return ;
|
|
|
+ lwp_backtrace_frame(cur_thr, &frame);
|
|
|
}
|
|
|
+ else
|
|
|
#endif
|
|
|
+ {
|
|
|
+ rt_backtrace_frame(cur_thr, &frame);
|
|
|
+ }
|
|
|
|
|
|
- // handle kernel exception:
|
|
|
- rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
|
|
|
+ while (1)
|
|
|
+ ;
|
|
|
}
|
|
|
-
|
|
|
- rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
|
|
- dump_regs(sp);
|
|
|
- rt_kprintf("--------------Thread list--------------\n");
|
|
|
- rt_kprintf("current thread: %s\n", rt_thread_self()->parent.name);
|
|
|
-
|
|
|
- extern struct rt_thread *rt_current_thread;
|
|
|
- rt_kprintf("--------------Backtrace--------------\n");
|
|
|
- rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
|
|
|
-
|
|
|
- while (1)
|
|
|
- ;
|
|
|
+_exit:
|
|
|
+ EXIT_TRAP;
|
|
|
+ return;
|
|
|
}
|