599 lines
16 KiB
C
599 lines
16 KiB
C
// Copyright 2020-2021 Beken
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <stdint.h>
|
|
#include "boot.h"
|
|
#include "sdkconfig.h"
|
|
#include "reset_reason.h"
|
|
#include <os/os.h>
|
|
#include "bk_arch.h"
|
|
#include "bk_rtos_debug.h"
|
|
#include <components/system.h>
|
|
#include <os/mem.h>
|
|
#include <components/log.h>
|
|
#include <common/bk_assert.h>
|
|
#include "arch_interrupt.h"
|
|
#include "stack_base.h"
|
|
#include <driver/wdt.h>
|
|
#include "wdt_driver.h"
|
|
#include <driver/wdt.h>
|
|
#include "bk_aon_wdt.h"
|
|
#include "armstar.h"
|
|
#if CONFIG_CM_BACKTRACE
|
|
#include "cm_backtrace.h"
|
|
#endif
|
|
|
|
#define MAX_DUMP_SYS_MEM_COUNT (8)
|
|
#define SOC_DTCM_DATA_SIZE (0x4000)
|
|
#define SOC_ITCM_DATA_SIZE (0x4000)
|
|
#define SOC_SRAM_TOTAL_SIZE (0xA0000)
|
|
#define SOC_SRAM_DATA_END (SOC_SRAM0_DATA_BASE + SOC_SRAM_TOTAL_SIZE)
|
|
|
|
#if (CONFIG_SOC_BK7236_SMP_TEMP || CONFIG_SOC_BK7239_SMP_TEMP || CONFIG_SOC_BK7286_SMP_TEMP)
|
|
extern unsigned char __itcm_cpu0_end__;
|
|
extern unsigned char __dtcm_cpu0_start__;
|
|
extern unsigned char _estack_cpu0;
|
|
extern unsigned char _sstack_cpu0;
|
|
|
|
#define __dtcm_end__ __itcm_cpu0_end__
|
|
#define __dtcm_start__ __dtcm_cpu0_start__
|
|
#define _estack _estack_cpu0
|
|
#define _sstack _sstack_cpu0
|
|
#endif
|
|
|
|
typedef struct sys_mem_info
|
|
{
|
|
uint32_t mem_base_addr;
|
|
uint32_t mem_size;
|
|
} sys_mem_info_t;
|
|
|
|
static unsigned int s_mem_count = 0;
|
|
static sys_mem_info_t s_dump_sys_mem_info[MAX_DUMP_SYS_MEM_COUNT] = {0};
|
|
|
|
static hook_func s_wifi_dump_func = NULL;
|
|
static hook_func s_ble_dump_func = NULL;
|
|
|
|
volatile unsigned int g_enter_exception = 0;
|
|
|
|
|
|
static void rtos_dump_plat_memory(void) {
|
|
// Dump DTCM
|
|
stack_mem_dump((uint32_t)SOC_DTCM_DATA_BASE, (uint32_t)(SOC_DTCM_DATA_BASE + SOC_DTCM_DATA_SIZE));
|
|
|
|
// Dump ITCM
|
|
stack_mem_dump((uint32_t)(SOC_ITCM_DATA_BASE + 0x20) , (uint32_t)(SOC_ITCM_DATA_BASE + SOC_ITCM_DATA_SIZE));
|
|
|
|
// Dump All SRAM
|
|
stack_mem_dump((uint32_t)SOC_SRAM3_DATA_BASE, (uint32_t)SOC_SRAM4_DATA_BASE);
|
|
stack_mem_dump((uint32_t)SOC_SRAM4_DATA_BASE, (uint32_t)SOC_SRAM_DATA_END);
|
|
|
|
stack_mem_dump((uint32_t)SOC_SRAM0_DATA_BASE, (uint32_t)SOC_SRAM1_DATA_BASE);
|
|
stack_mem_dump((uint32_t)SOC_SRAM1_DATA_BASE, (uint32_t)SOC_SRAM2_DATA_BASE);
|
|
stack_mem_dump((uint32_t)SOC_SRAM2_DATA_BASE, (uint32_t)SOC_SRAM3_DATA_BASE);
|
|
}
|
|
|
|
static void dump_peri_regs(void) {
|
|
#if CONFIG_SOC_BK7236XX
|
|
stack_mem_dump((uint32_t)SOC_SYS_REG_BASE, (uint32_t)SOC_SYS_REG_BASE + (0x5c*4));
|
|
stack_mem_dump((uint32_t)SOC_FLASH_REG_BASE, (uint32_t)SOC_FLASH_REG_BASE + (0x20*4));
|
|
stack_mem_dump((uint32_t)SOC_AON_PMU_REG_BASE, (uint32_t)SOC_AON_PMU_REG_BASE + (0x7f*4));
|
|
#if (GEN_SECURITY_DEV_UART1_IS_SECURE && !CONFIG_SPE) // if UART1 is used for TFM debug, NSPE cannot access gpio0/1 reg
|
|
stack_mem_dump((uint32_t)SOC_AON_GPIO_REG_BASE+ (0x2*4), (uint32_t)SOC_AON_GPIO_REG_BASE + (0x30*4));
|
|
#else
|
|
stack_mem_dump((uint32_t)SOC_AON_GPIO_REG_BASE, (uint32_t)SOC_AON_GPIO_REG_BASE + (0x30*4));
|
|
#endif
|
|
|
|
#if CONFIG_GENERAL_DMA
|
|
stack_mem_dump((uint32_t)SOC_GENER_DMA_REG_BASE, (uint32_t)SOC_GENER_DMA_REG_BASE + (0x44*4));
|
|
#if (SOC_DMA_UNIT_NUM > 1)
|
|
stack_mem_dump((uint32_t)SOC_GENER_DMA1_REG_BASE, (uint32_t)SOC_GENER_DMA1_REG_BASE + (0x44*4));
|
|
#endif
|
|
#endif
|
|
#if CONFIG_MAILBOX
|
|
stack_mem_dump((uint32_t)SOC_MBOX0_REG_BASE, (uint32_t)SOC_MBOX0_REG_BASE + (0x38*4));
|
|
stack_mem_dump((uint32_t)SOC_MBOX1_REG_BASE, (uint32_t)SOC_MBOX1_REG_BASE + (0x38*4));
|
|
#endif
|
|
#if CONFIG_AON_RTC
|
|
stack_mem_dump((uint32_t)SOC_AON_RTC_REG_BASE, (uint32_t)SOC_AON_RTC_REG_BASE + (0x0a*4));
|
|
#endif
|
|
#if CONFIG_PSRAM
|
|
stack_mem_dump((uint32_t)SOC_PSRAM_REG_BASE, (uint32_t)SOC_PSRAM_REG_BASE + (0x17*4));
|
|
#endif
|
|
#endif
|
|
/*dmup psram memory*/
|
|
stack_mem_dump((uint32_t)0x60000000, (uint32_t)(0x60000000+2048));
|
|
|
|
}
|
|
|
|
|
|
unsigned int arch_is_enter_exception(void) {
|
|
return g_enter_exception;
|
|
}
|
|
|
|
void arch_set_enter_exception(void) {
|
|
g_enter_exception = 1;
|
|
}
|
|
|
|
void rtos_regist_wifi_dump_hook(hook_func wifi_func)
|
|
{
|
|
s_wifi_dump_func = wifi_func;
|
|
}
|
|
|
|
void rtos_regist_ble_dump_hook(hook_func ble_func)
|
|
{
|
|
s_ble_dump_func = ble_func;
|
|
}
|
|
|
|
void rtos_regist_plat_dump_hook(uint32_t mem_base_addr, uint32_t mem_size)
|
|
{
|
|
if (mem_base_addr >= SOC_SRAM0_DATA_BASE
|
|
&& (mem_base_addr + mem_size) < SOC_SRAM_DATA_END) {
|
|
#if CONFIG_SPE
|
|
//BK_DUMP_OUT("rtos_regist_plat_dump_hook memory(0x%x) in sram, need not dump again.\r\n", mem_base_addr);
|
|
#else
|
|
//UART/Log is not ready yet!
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < s_mem_count; i++) {
|
|
if(mem_base_addr == s_dump_sys_mem_info[i].mem_base_addr
|
|
&& mem_size == s_dump_sys_mem_info[i].mem_size) {
|
|
BK_DUMP_OUT("rtos_regist_plat_dump_hook memory(0x%x) already register.\r\n", mem_base_addr);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (s_mem_count < MAX_DUMP_SYS_MEM_COUNT) {
|
|
s_dump_sys_mem_info[s_mem_count].mem_base_addr = mem_base_addr;
|
|
s_dump_sys_mem_info[s_mem_count].mem_size = mem_size;
|
|
s_mem_count++;
|
|
} else {
|
|
BK_DUMP_OUT("rtos_regist_plat_dump_hook failed:s_mem_count(%d).\r\n", s_mem_count);
|
|
}
|
|
}
|
|
|
|
void rtos_dump_plat_sys_mems(void) {
|
|
#if CONFIG_MEMDUMP_ALL
|
|
rtos_dump_plat_memory();
|
|
|
|
for (int i = 0; i < s_mem_count; i++) {
|
|
uint32_t begin = s_dump_sys_mem_info[i].mem_base_addr;
|
|
uint32_t end = begin + s_dump_sys_mem_info[i].mem_size;
|
|
stack_mem_dump(begin, end);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if CONFIG_FREERTOS_SMP
|
|
#define CPU_ID rtos_get_core_id()
|
|
#else
|
|
|
|
#if (CONFIG_MAILBOX) && (CONFIG_CPU_CNT > 1)
|
|
#include "mb_ipc_cmd.h"
|
|
#endif
|
|
|
|
#if (CONFIG_SYS_CPU0)
|
|
#define CPU_ID 0
|
|
#endif
|
|
|
|
#if (CONFIG_SYS_CPU1)
|
|
#define CPU_ID 1
|
|
#endif
|
|
|
|
#if (CONFIG_SYS_CPU2)
|
|
#define CPU_ID 2
|
|
#endif
|
|
|
|
#endif
|
|
|
|
static const char * const fault_type[] =
|
|
{
|
|
[0] = NULL,
|
|
[1] = NULL,
|
|
[2] = "Watchdog\r\n",
|
|
[3] = "HardFault\r\n",
|
|
[4] = "MemFault\r\n",
|
|
[5] = "BusFault\r\n",
|
|
[6] = "UsageFault\r\n",
|
|
[7] = "SecureFault\r\n",
|
|
[8] = NULL,
|
|
[9] = NULL,
|
|
[10] = NULL,
|
|
[11] = "SVC\r\n",
|
|
[12] = "DebugFault\r\n",
|
|
[13] = NULL,
|
|
[14] = "PendSV\r\n",
|
|
[15] = "SysTick\r\n",
|
|
};
|
|
|
|
#if (CONFIG_SHELL_ASYNCLOG)
|
|
extern void shell_set_log_cpu(u8 req_cpu);
|
|
#endif
|
|
|
|
static void dump_prologue(void)
|
|
{
|
|
#if CONFIG_FREERTOS_SMP
|
|
|
|
#if (CONFIG_SHELL_ASYNCLOG)
|
|
shell_set_log_cpu(CPU_ID);
|
|
#endif
|
|
|
|
#else
|
|
|
|
#if (CONFIG_SYS_CPU0)
|
|
#if (CONFIG_SHELL_ASYNCLOG)
|
|
shell_set_log_cpu(CONFIG_CPU_CNT);
|
|
shell_set_log_cpu(CPU_ID);
|
|
#endif
|
|
#elif (CONFIG_SYS_CPU1)
|
|
ipc_send_trap_handle_begin();
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
static void dump_epilogue(void)
|
|
{
|
|
#if CONFIG_FREERTOS_SMP
|
|
|
|
#if (CONFIG_SHELL_ASYNCLOG)
|
|
shell_set_log_cpu(CONFIG_CPU_CNT);
|
|
#endif
|
|
|
|
#else
|
|
|
|
#if (CONFIG_SYS_CPU0)
|
|
#if (CONFIG_SHELL_ASYNCLOG)
|
|
shell_set_log_cpu(CONFIG_CPU_CNT);
|
|
#endif
|
|
#elif (CONFIG_SYS_CPU1)
|
|
ipc_send_trap_handle_end();
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* this function will show registers of CPU
|
|
*
|
|
* @param mcause
|
|
* @param context
|
|
*/
|
|
static void arch_dump_cpu_registers(uint32_t mcause, SAVED_CONTEXT *context) {
|
|
|
|
BK_DUMP_OUT("CPU%d Current regs:\r\n", CPU_ID);
|
|
|
|
// context of task.
|
|
BK_DUMP_OUT("0 r0 x 0x%lx\r\n", context->r0);
|
|
BK_DUMP_OUT("1 r1 x 0x%lx\r\n", context->r1);
|
|
BK_DUMP_OUT("2 r2 x 0x%lx\r\n", context->r2);
|
|
BK_DUMP_OUT("3 r3 x 0x%lx\r\n", context->r3);
|
|
BK_DUMP_OUT("4 r4 x 0x%lx\r\n", context->r4);
|
|
BK_DUMP_OUT("5 r5 x 0x%lx\r\n", context->r5);
|
|
BK_DUMP_OUT("6 r6 x 0x%lx\r\n", context->r6);
|
|
BK_DUMP_OUT("7 r7 x 0x%lx\r\n", context->r7);
|
|
BK_DUMP_OUT("8 r8 x 0x%lx\r\n", context->r8);
|
|
BK_DUMP_OUT("9 r9 x 0x%lx\r\n", context->r9);
|
|
BK_DUMP_OUT("10 r10 x 0x%lx\r\n", context->r10);
|
|
BK_DUMP_OUT("11 r11 x 0x%lx\r\n", context->r11);
|
|
BK_DUMP_OUT("12 r12 x 0x%lx\r\n", context->r12);
|
|
BK_DUMP_OUT("14 sp x 0x%lx\r\n", context->sp);
|
|
BK_DUMP_OUT("15 lr x 0x%lx\r\n", context->lr);
|
|
BK_DUMP_OUT("16 pc x 0x%lx\r\n", context->pc);
|
|
BK_DUMP_OUT("17 xpsr x 0x%lx\r\n", context->xpsr);
|
|
BK_DUMP_OUT("18 msp x 0x%lx\r\n", context->msp);
|
|
BK_DUMP_OUT("19 psp x 0x%lx\r\n", context->psp);
|
|
BK_DUMP_OUT("20 primask x 0x%lx\r\n", context->primask);
|
|
BK_DUMP_OUT("21 basepri x 0x%lx\r\n", context->basepri);
|
|
BK_DUMP_OUT("22 faultmask x 0x%lx\r\n", context->faultmask);
|
|
BK_DUMP_OUT("23 fpscr x 0x%lx\r\n", context->fpscr);
|
|
|
|
// context of ISR.
|
|
mcause = __get_xPSR();
|
|
BK_DUMP_OUT("30 CPU%d xPSR x 0x%lx\r\n", CPU_ID, mcause);
|
|
BK_DUMP_OUT("31 LR x 0x%lx\r\n", context->control); // exception LR.
|
|
BK_DUMP_OUT("32 control x 0x%lx\r\n", __get_CONTROL());
|
|
|
|
BK_DUMP_OUT("40 MMFAR x 0x%lx\r\n", SCB->MMFAR);
|
|
BK_DUMP_OUT("41 BFAR x 0x%lx\r\n", SCB->BFAR);
|
|
BK_DUMP_OUT("42 CFSR x 0x%lx\r\n", SCB->CFSR);
|
|
BK_DUMP_OUT("43 HFSR x 0x%lx\r\n", SCB->HFSR);
|
|
|
|
mcause = mcause & 0x1FF;
|
|
|
|
if ( (mcause <= 0x0F) && (fault_type[mcause] != NULL) )
|
|
{
|
|
BK_DUMP_OUT((char *)fault_type[mcause]);
|
|
}
|
|
|
|
}
|
|
|
|
static void dump_context(uint32_t lr, uint32_t msp)
|
|
{
|
|
SAVED_CONTEXT regs;
|
|
|
|
regs.r4 = ((uint32_t *)msp)[-8];
|
|
regs.r5 = ((uint32_t *)msp)[-7];
|
|
regs.r6 = ((uint32_t *)msp)[-6];
|
|
regs.r7 = ((uint32_t *)msp)[-5];
|
|
regs.r8 = ((uint32_t *)msp)[-4];
|
|
regs.r9 = ((uint32_t *)msp)[-3];
|
|
regs.r10 = ((uint32_t *)msp)[-2];
|
|
regs.r11 = ((uint32_t *)msp)[-1];
|
|
regs.control = lr; // exception LR.
|
|
|
|
regs.msp = __get_MSP();
|
|
regs.psp = __get_PSP();
|
|
|
|
regs.primask = __get_PRIMASK();
|
|
regs.basepri = __get_BASEPRI();
|
|
regs.faultmask = __get_FAULTMASK();
|
|
|
|
regs.fpscr = __get_FPSCR();
|
|
|
|
uint32_t stack_pointer = msp;
|
|
uint32_t stack_adj = 8 * sizeof(uint32_t);
|
|
|
|
if(lr & (1UL << 2))
|
|
{
|
|
stack_pointer = __get_PSP();
|
|
}
|
|
|
|
if((lr & (1UL << 4)) == 0)
|
|
{
|
|
stack_adj += 18 * sizeof(uint32_t); // 18 FPU regs.
|
|
}
|
|
|
|
regs.r0 = ((uint32_t *)stack_pointer)[0];
|
|
regs.r1 = ((uint32_t *)stack_pointer)[1];
|
|
regs.r2 = ((uint32_t *)stack_pointer)[2];
|
|
regs.r3 = ((uint32_t *)stack_pointer)[3];
|
|
regs.r12 = ((uint32_t *)stack_pointer)[4];
|
|
regs.lr = ((uint32_t *)stack_pointer)[5];
|
|
regs.pc = ((uint32_t *)stack_pointer)[6];
|
|
regs.xpsr = ((uint32_t *)stack_pointer)[7];
|
|
|
|
if(regs.xpsr & (1UL << 9))
|
|
{
|
|
stack_adj += 1 * sizeof(uint32_t);
|
|
}
|
|
regs.sp = stack_pointer + stack_adj;
|
|
|
|
rtos_disable_int();
|
|
bk_wdt_feed();
|
|
#if (CONFIG_INT_AON_WDT)
|
|
bk_int_aon_wdt_feed();
|
|
#endif
|
|
bk_set_printf_sync(true);
|
|
dump_prologue();
|
|
arch_dump_cpu_registers(0, ®s);
|
|
}
|
|
|
|
static void rtos_dump_system(void)
|
|
{
|
|
#if CONFIG_DEBUG_FIRMWARE || CONFIG_DUMP_ENABLE
|
|
BK_LOG_FLUSH();
|
|
bk_set_printf_sync(true);
|
|
|
|
BK_DUMP_OUT("***********************************************************************************************\r\n");
|
|
BK_DUMP_OUT("***********************************user except handler begin***********************************\r\n");
|
|
BK_DUMP_OUT("***********************************************************************************************\r\n");
|
|
|
|
bk_wdt_feed();
|
|
#if (CONFIG_INT_AON_WDT)
|
|
bk_int_aon_wdt_feed();
|
|
#endif
|
|
|
|
if(NULL != s_wifi_dump_func) {
|
|
s_wifi_dump_func();
|
|
}
|
|
|
|
if(NULL != s_ble_dump_func) {
|
|
s_ble_dump_func();
|
|
}
|
|
|
|
rtos_dump_plat_sys_mems();
|
|
|
|
bk_psram_heap_dump_data();
|
|
|
|
#if CONFIG_FREERTOS && CONFIG_MEM_DEBUG
|
|
os_dump_memory_stats(0, 0, NULL);
|
|
#endif
|
|
|
|
rtos_dump_backtrace();
|
|
rtos_dump_task_list();
|
|
#if CONFIG_FREERTOS
|
|
rtos_dump_task_runtime_stats();
|
|
#endif
|
|
|
|
BK_DUMP_OUT("***********************************************************************************************\r\n");
|
|
BK_DUMP_OUT("************************************user except handler end************************************\r\n");
|
|
BK_DUMP_OUT("***********************************************************************************************\r\n");
|
|
|
|
dump_peri_regs();
|
|
#endif //CONFIG_DEBUG_FIRMWARE || CONFIG_DUMP_ENABLE
|
|
}
|
|
|
|
#define CHECK_TASK_WDT_INTERRUPT (0x13)
|
|
|
|
uint32_t g_wdt_handler_lr;
|
|
|
|
static void user_except_handler(uint32_t reset_reason, SAVED_CONTEXT *regs)
|
|
{
|
|
if (0 == g_enter_exception) {
|
|
// Make sure the interrupt is disable
|
|
uint32_t int_level = rtos_disable_int();
|
|
|
|
/* Handled Trap */
|
|
g_enter_exception = 1;
|
|
|
|
// if it is a task WDT assert!
|
|
if((regs->xpsr & 0x1FF) == CHECK_TASK_WDT_INTERRUPT) // it can be used for any interrupts if LR is saved at entrance of ISR.
|
|
{
|
|
if(g_wdt_handler_lr & (1UL << 2))
|
|
{
|
|
uint32_t stack_pointer = __get_PSP();
|
|
uint32_t stack_adj = 8 * sizeof(uint32_t);
|
|
|
|
if((g_wdt_handler_lr & (1UL << 4)) == 0)
|
|
{
|
|
stack_adj += 18 * sizeof(uint32_t); // 18 FPU regs.
|
|
}
|
|
|
|
regs->r0 = ((uint32_t *)stack_pointer)[0];
|
|
regs->r1 = ((uint32_t *)stack_pointer)[1];
|
|
regs->r2 = ((uint32_t *)stack_pointer)[2];
|
|
regs->r3 = ((uint32_t *)stack_pointer)[3];
|
|
regs->r12 = ((uint32_t *)stack_pointer)[4];
|
|
regs->lr = ((uint32_t *)stack_pointer)[5];
|
|
regs->pc = ((uint32_t *)stack_pointer)[6];
|
|
regs->xpsr = ((uint32_t *)stack_pointer)[7];
|
|
|
|
if(regs->xpsr & (1UL << 9))
|
|
{
|
|
stack_adj += 1 * sizeof(uint32_t);
|
|
}
|
|
regs->sp = stack_pointer + stack_adj;
|
|
}
|
|
}
|
|
|
|
bk_set_printf_sync(true);
|
|
dump_prologue();
|
|
arch_dump_cpu_registers(ECAUSE_ASSERT, regs);
|
|
|
|
rtos_dump_system();
|
|
dump_epilogue();
|
|
|
|
#if CONFIG_SYS_CPU0
|
|
bk_reboot_ex(reset_reason);
|
|
#endif
|
|
while(g_enter_exception);
|
|
|
|
rtos_enable_int(int_level);
|
|
} else {
|
|
dump_epilogue();
|
|
#if CONFIG_SYS_CPU0
|
|
bk_wdt_force_reboot();
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
///1. Save to stack is better
|
|
///2. Some regs already saved in stack
|
|
static void store_cpu_regs(uint32_t mcause, SAVED_CONTEXT *regs) {
|
|
regs->r0 = __get_R0();
|
|
regs->r1 = __get_R1();
|
|
regs->r2 = __get_R2();
|
|
regs->r3 = __get_R3();
|
|
regs->r4 = __get_R4();
|
|
regs->r5 = __get_R5();
|
|
regs->r6 = __get_R6();
|
|
regs->r7 = __get_R7();
|
|
regs->r8 = __get_R8();
|
|
regs->r9 = __get_R9();
|
|
regs->r10 = __get_R10();
|
|
regs->r11 = __get_R11();
|
|
regs->r12 = __get_R12();
|
|
regs->sp = __get_SP();
|
|
regs->lr = __get_LR();
|
|
regs->pc = __get_PC();
|
|
|
|
regs->xpsr = __get_xPSR();
|
|
regs->msp = __get_MSP();
|
|
regs->psp = __get_PSP();
|
|
|
|
regs->primask = __get_PRIMASK();
|
|
regs->basepri = __get_BASEPRI();
|
|
regs->faultmask = __get_FAULTMASK();
|
|
|
|
regs->control = __get_CONTROL();
|
|
regs->fpscr = __get_FPSCR();
|
|
}
|
|
|
|
extern void bk_set_jtag_mode(uint32_t cpu_id, uint32_t group_id);
|
|
extern volatile const uint8_t build_version[];
|
|
|
|
void bk_system_dump(void)
|
|
{
|
|
SAVED_CONTEXT regs = {0};
|
|
store_cpu_regs(ECAUSE_ASSERT, ®s);
|
|
uint32_t int_level = rtos_disable_int();
|
|
|
|
bk_wdt_feed();
|
|
#if (CONFIG_INT_AON_WDT)
|
|
bk_int_aon_wdt_feed();
|
|
#endif
|
|
|
|
BK_DUMP_OUT("build time => %s !\r\n", build_version);
|
|
|
|
user_except_handler(RESET_SOURCE_CRASH_ASSERT, ®s);
|
|
|
|
bk_set_jtag_mode(CPU_ID, 0);
|
|
rtos_enable_int(int_level);
|
|
}
|
|
|
|
/*when a cpu hangs,use this variable to judge whether the cpu has entered an exception*/
|
|
#if CONFIG_INTERRUPT_DEBUG_RECORDER
|
|
__attribute__((__used__)) static volatile uint32_t CPUx_crash_recorder = 0;
|
|
#endif
|
|
void user_except_handler_ex(uint32_t reset_reason, uint32_t lr, uint32_t sp)
|
|
{
|
|
|
|
if (0 == g_enter_exception) {
|
|
#if CONFIG_INTERRUPT_DEBUG_RECORDER
|
|
CPUx_crash_recorder = sp;
|
|
#endif
|
|
dump_context(lr, sp);
|
|
// Make sure the interrupt is disable
|
|
uint32_t int_level = rtos_disable_int();
|
|
|
|
/* Handled Trap */
|
|
g_enter_exception = 1;
|
|
|
|
BK_DUMP_OUT("build time => %s !\r\n", build_version);
|
|
|
|
rtos_dump_system();
|
|
|
|
#if CONFIG_CM_BACKTRACE
|
|
cm_backtrace_fault(lr, sp);
|
|
#endif
|
|
|
|
dump_epilogue();
|
|
|
|
#if CONFIG_SYS_CPU0
|
|
bk_reboot_ex(reset_reason);
|
|
#endif
|
|
while(g_enter_exception);
|
|
|
|
rtos_enable_int(int_level);
|
|
} else {
|
|
#if CONFIG_INTERRUPT_DEBUG_RECORDER
|
|
CPUx_crash_recorder = 0;
|
|
#endif
|
|
dump_epilogue();
|
|
#if CONFIG_SYS_CPU0
|
|
bk_misc_set_reset_reason(reset_reason);
|
|
bk_wdt_force_reboot();
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
__attribute__((used, section(".null_trap_handler"))) \
|
|
void bk_null_trap_handler(void) {
|
|
BK_ASSERT(0);
|
|
}
|