|
|
|
|
@ -63,6 +63,8 @@ enum {
|
|
|
|
|
PRINT_ASSERT_ON_HANDLER,
|
|
|
|
|
PRINT_THREAD_STACK_INFO,
|
|
|
|
|
PRINT_MAIN_STACK_INFO,
|
|
|
|
|
PRINT_THREAD_STACK_OVERFLOW,
|
|
|
|
|
PRINT_MAIN_STACK_OVERFLOW,
|
|
|
|
|
PRINT_CALL_STACK_INFO,
|
|
|
|
|
PRINT_CALL_STACK_ERR,
|
|
|
|
|
PRINT_FAULT_ON_THREAD,
|
|
|
|
|
@ -102,6 +104,8 @@ static const char *print_info[] = {
|
|
|
|
|
[PRINT_ASSERT_ON_HANDLER] = "Assert on interrupt or bare metal(no OS) environment",
|
|
|
|
|
[PRINT_THREAD_STACK_INFO] = "===== Thread stack information =====",
|
|
|
|
|
[PRINT_MAIN_STACK_INFO] = "====== Main stack information ======",
|
|
|
|
|
[PRINT_THREAD_STACK_OVERFLOW] = "Error: Thread stack(%08x) was overflow",
|
|
|
|
|
[PRINT_MAIN_STACK_OVERFLOW] = "Error: Main stack(%08x) was overflow",
|
|
|
|
|
[PRINT_CALL_STACK_INFO] = "Show more call stack info by run: addr2line -e %s%s -a -f %.*s",
|
|
|
|
|
[PRINT_CALL_STACK_ERR] = "Dump call stack has an error",
|
|
|
|
|
[PRINT_FAULT_ON_THREAD] = "Fault on thread %s",
|
|
|
|
|
@ -138,6 +142,8 @@ static const char *print_info[] = {
|
|
|
|
|
[PRINT_ASSERT_ON_HANDLER] = "在中断或裸机环境下发生断言",
|
|
|
|
|
[PRINT_THREAD_STACK_INFO] = "=========== 线程堆栈信息 ===========",
|
|
|
|
|
[PRINT_MAIN_STACK_INFO] = "============ 主堆栈信息 ============",
|
|
|
|
|
[PRINT_THREAD_STACK_OVERFLOW] = "错误:线程栈(%08x)发生溢出",
|
|
|
|
|
[PRINT_MAIN_STACK_OVERFLOW] = "错误:主栈(%08x)发生溢出",
|
|
|
|
|
[PRINT_CALL_STACK_INFO] = "查看更多函数调用栈信息,请运行:addr2line -e %s%s -a -f %.*s",
|
|
|
|
|
[PRINT_CALL_STACK_ERR] = "获取函数调用栈失败",
|
|
|
|
|
[PRINT_FAULT_ON_THREAD] = "在线程(%s)中发生错误异常",
|
|
|
|
|
@ -183,6 +189,7 @@ static size_t code_size = 0;
|
|
|
|
|
static bool init_ok = false;
|
|
|
|
|
static char call_stack_info[CMB_CALL_STACK_MAX_DEPTH * (8 + 1)] = { 0 };
|
|
|
|
|
static bool on_fault = false;
|
|
|
|
|
static bool stack_is_overflow = false;
|
|
|
|
|
static struct cmb_hard_fault_regs regs;
|
|
|
|
|
|
|
|
|
|
#if (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M4) || (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M7)
|
|
|
|
|
@ -282,26 +289,26 @@ static const char *get_cur_thread_name(void) {
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef CMB_USING_DUMP_STACK_INFO
|
|
|
|
|
/**
|
|
|
|
|
* dump current thread stack information
|
|
|
|
|
*/
|
|
|
|
|
static void dump_cur_thread_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *stack_pointer) {
|
|
|
|
|
cmb_println(print_info[PRINT_THREAD_STACK_INFO]);
|
|
|
|
|
for (; (uint32_t) stack_pointer < stack_start_addr + stack_size; stack_pointer++) {
|
|
|
|
|
cmb_println(" addr: %08x data: %08x", stack_pointer, *stack_pointer);
|
|
|
|
|
}
|
|
|
|
|
cmb_println("====================================");
|
|
|
|
|
}
|
|
|
|
|
#endif /* CMB_USING_DUMP_STACK_INFO */
|
|
|
|
|
#endif /* CMB_USING_OS_PLATFORM */
|
|
|
|
|
|
|
|
|
|
#ifdef CMB_USING_DUMP_STACK_INFO
|
|
|
|
|
/**
|
|
|
|
|
* dump current main stack information
|
|
|
|
|
* dump current stack information
|
|
|
|
|
*/
|
|
|
|
|
static void dump_main_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *stack_pointer) {
|
|
|
|
|
cmb_println(print_info[PRINT_MAIN_STACK_INFO]);
|
|
|
|
|
static void dump_stack(uint32_t stack_start_addr, size_t stack_size, uint32_t *stack_pointer) {
|
|
|
|
|
if (stack_is_overflow) {
|
|
|
|
|
if (on_thread_before_fault) {
|
|
|
|
|
cmb_println(print_info[PRINT_THREAD_STACK_OVERFLOW], stack_pointer);
|
|
|
|
|
} else {
|
|
|
|
|
cmb_println(print_info[PRINT_MAIN_STACK_OVERFLOW], stack_pointer);
|
|
|
|
|
}
|
|
|
|
|
if ((uint32_t) stack_pointer < stack_start_addr) {
|
|
|
|
|
stack_pointer = (uint32_t *) stack_start_addr;
|
|
|
|
|
} else if ((uint32_t) stack_pointer > stack_start_addr + stack_size) {
|
|
|
|
|
stack_pointer = (uint32_t *) (stack_start_addr + stack_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cmb_println(print_info[PRINT_THREAD_STACK_INFO]);
|
|
|
|
|
for (; (uint32_t) stack_pointer < stack_start_addr + stack_size; stack_pointer++) {
|
|
|
|
|
cmb_println(" addr: %08x data: %08x", stack_pointer, *stack_pointer);
|
|
|
|
|
}
|
|
|
|
|
@ -324,6 +331,7 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) {
|
|
|
|
|
bool regs_saved_lr_is_valid = false;
|
|
|
|
|
|
|
|
|
|
if (on_fault) {
|
|
|
|
|
if (!stack_is_overflow) {
|
|
|
|
|
/* first depth is PC */
|
|
|
|
|
buffer[depth++] = regs.saved.pc;
|
|
|
|
|
/* second depth is from LR, so need decrease a word to PC */
|
|
|
|
|
@ -333,6 +341,7 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) {
|
|
|
|
|
buffer[depth++] = pc;
|
|
|
|
|
regs_saved_lr_is_valid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef CMB_USING_OS_PLATFORM
|
|
|
|
|
/* program is running on thread before fault */
|
|
|
|
|
@ -348,6 +357,14 @@ size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stack_is_overflow) {
|
|
|
|
|
if (sp < stack_start_addr) {
|
|
|
|
|
sp = stack_start_addr;
|
|
|
|
|
} else if (sp > stack_start_addr + stack_size) {
|
|
|
|
|
sp = stack_start_addr + stack_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* copy called function address */
|
|
|
|
|
for (; sp < stack_start_addr + stack_size; sp += sizeof(size_t)) {
|
|
|
|
|
/* the *sp value may be LR, so need decrease a word to PC */
|
|
|
|
|
@ -410,7 +427,7 @@ void cm_backtrace_assert(uint32_t sp) {
|
|
|
|
|
cmb_println(print_info[PRINT_ASSERT_ON_HANDLER]);
|
|
|
|
|
|
|
|
|
|
#ifdef CMB_USING_DUMP_STACK_INFO
|
|
|
|
|
dump_main_stack(main_stack_start_addr, main_stack_size, (uint32_t *) sp);
|
|
|
|
|
dump_stack(main_stack_start_addr, main_stack_size, (uint32_t *) sp);
|
|
|
|
|
#endif /* CMB_USING_DUMP_STACK_INFO */
|
|
|
|
|
|
|
|
|
|
} else if (cur_stack_pointer == cmb_get_psp()) {
|
|
|
|
|
@ -420,7 +437,7 @@ void cm_backtrace_assert(uint32_t sp) {
|
|
|
|
|
uint32_t stack_start_addr;
|
|
|
|
|
size_t stack_size;
|
|
|
|
|
get_cur_thread_stack_info(sp, &stack_start_addr, &stack_size);
|
|
|
|
|
dump_cur_thread_stack(stack_start_addr, stack_size, (uint32_t *) sp);
|
|
|
|
|
dump_stack(stack_start_addr, stack_size, (uint32_t *) sp);
|
|
|
|
|
#endif /* CMB_USING_DUMP_STACK_INFO */
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@ -429,7 +446,7 @@ void cm_backtrace_assert(uint32_t sp) {
|
|
|
|
|
|
|
|
|
|
/* bare metal(no OS) environment */
|
|
|
|
|
#ifdef CMB_USING_DUMP_STACK_INFO
|
|
|
|
|
dump_main_stack(main_stack_start_addr, main_stack_size, (uint32_t *) sp);
|
|
|
|
|
dump_stack(main_stack_start_addr, main_stack_size, (uint32_t *) sp);
|
|
|
|
|
#endif /* CMB_USING_DUMP_STACK_INFO */
|
|
|
|
|
|
|
|
|
|
#endif /* CMB_USING_OS_PLATFORM */
|
|
|
|
|
@ -609,20 +626,18 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) {
|
|
|
|
|
stack_pointer = statck_del_fpu_regs(fault_handler_lr, stack_pointer);
|
|
|
|
|
#endif /* (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M4) || (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M7) */
|
|
|
|
|
|
|
|
|
|
/* check stack overflow */
|
|
|
|
|
if (stack_pointer < stack_start_addr || stack_pointer > stack_start_addr + stack_size) {
|
|
|
|
|
stack_is_overflow = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dump stack information */
|
|
|
|
|
#ifdef CMB_USING_DUMP_STACK_INFO
|
|
|
|
|
#ifdef CMB_USING_OS_PLATFORM
|
|
|
|
|
if (on_thread_before_fault) {
|
|
|
|
|
dump_cur_thread_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer);
|
|
|
|
|
} else {
|
|
|
|
|
dump_main_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* bare metal(no OS) environment */
|
|
|
|
|
dump_main_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer);
|
|
|
|
|
#endif /* CMB_USING_OS_PLATFORM */
|
|
|
|
|
dump_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer);
|
|
|
|
|
#endif /* CMB_USING_DUMP_STACK_INFO */
|
|
|
|
|
|
|
|
|
|
/* the stack frame may be get failed when it is overflow */
|
|
|
|
|
if (!stack_is_overflow) {
|
|
|
|
|
/* dump register */
|
|
|
|
|
cmb_println(print_info[PRINT_REGS_TITLE]);
|
|
|
|
|
|
|
|
|
|
@ -635,7 +650,6 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) {
|
|
|
|
|
regs.saved.pc = ((uint32_t *)saved_regs_addr)[6]; // Program counter PC
|
|
|
|
|
regs.saved.psr.value = ((uint32_t *)saved_regs_addr)[7]; // Program status word PSR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmb_println(" %s: %08x %s: %08x %s: %08x %s: %08x", regs_name[0], regs.saved.r0,
|
|
|
|
|
regs_name[1], regs.saved.r1,
|
|
|
|
|
regs_name[2], regs.saved.r2,
|
|
|
|
|
@ -645,6 +659,7 @@ void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) {
|
|
|
|
|
regs_name[6], regs.saved.pc,
|
|
|
|
|
regs_name[7], regs.saved.psr.value);
|
|
|
|
|
cmb_println("==============================================================");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* the Cortex-M0 is not support fault diagnosis */
|
|
|
|
|
#if (CMB_CPU_PLATFORM_TYPE != CMB_CPU_ARM_CORTEX_M0)
|
|
|
|
|
|