/* * Copyright (c) @CompanyNameMagicTag 2018-2019. All rights reserved. * Description: LOG OML EXCEPTION MODULE */ #ifdef SUPPORT_DFX_EXCEPTION #include "exception.h" #endif #include "debug_print.h" #include "securec.h" #include "log_def.h" #include "log_common.h" #include "log_reg_dump.h" #include "tcxo.h" #include "non_os.h" #include "log_oml_exception.h" #ifdef USE_CMSIS_OS #ifdef __LITEOS__ #include "los_task_pri.h" #endif #endif #include "watchdog.h" #include "watchdog_porting.h" #if SLAVE_BY_WS53_ONLY #include "preserve.h" #include "nonos_trace.h" #endif #if CORE != CORE_LOGGING #include "log_buffer.h" #endif #if CORE == CORE_LOGGING #include "log_uart.h" #endif #ifdef SDT_LOG_BY_UART #include "sdt_by_uart_external.h" #endif #if MCU_ONLY #include "non_os_reboot.h" #include "preserve.h" #endif #if CORE == CORE_LOGGING #ifdef HSO_SUPPORT #include "last_dump.h" #include "last_dump_adapt.h" #endif #endif #include "chip_io.h" #define STACK_SIZE 3 #if (ARCH == RISCV31) || (ARCH == RISCV70) #define GENERAL_REG_NUM 32 #elif((ARCH == CM3) || (ARCH == CM7)) #define GENERAL_REG_NUM 13 #endif #define DUMP_DELAY 6000ULL #define LOG_DELAY 2000ULL #if defined(__GNUC__) extern uint32_t g_stack_system; #endif #if (ARCH == RISCV31) || (ARCH == RISCV70) static void log_oml_get_reg_value(uint32_t *general_reg, const exc_context_t *exc_buf_addr) { general_reg[REG_NUM_0] = 0x0; general_reg[REG_NUM_1] = exc_buf_addr->task_context.ra; general_reg[REG_NUM_2] = exc_buf_addr->task_context.sp; general_reg[REG_NUM_3] = exc_buf_addr->gp; general_reg[REG_NUM_4] = exc_buf_addr->task_context.tp; general_reg[REG_NUM_5] = exc_buf_addr->task_context.t0; general_reg[REG_NUM_6] = exc_buf_addr->task_context.t1; general_reg[REG_NUM_7] = exc_buf_addr->task_context.t2; general_reg[REG_NUM_8] = exc_buf_addr->task_context.s0; general_reg[REG_NUM_9] = exc_buf_addr->task_context.s1; general_reg[REG_NUM_10] = exc_buf_addr->task_context.a0; general_reg[REG_NUM_11] = exc_buf_addr->task_context.a1; general_reg[REG_NUM_12] = exc_buf_addr->task_context.a2; general_reg[REG_NUM_13] = exc_buf_addr->task_context.a3; general_reg[REG_NUM_14] = exc_buf_addr->task_context.a4; general_reg[REG_NUM_15] = exc_buf_addr->task_context.a5; general_reg[REG_NUM_16] = exc_buf_addr->task_context.a6; general_reg[REG_NUM_17] = exc_buf_addr->task_context.a7; general_reg[REG_NUM_18] = exc_buf_addr->task_context.s2; general_reg[REG_NUM_19] = exc_buf_addr->task_context.s3; general_reg[REG_NUM_20] = exc_buf_addr->task_context.s4; general_reg[REG_NUM_21] = exc_buf_addr->task_context.s5; general_reg[REG_NUM_22] = exc_buf_addr->task_context.s6; general_reg[REG_NUM_23] = exc_buf_addr->task_context.s7; general_reg[REG_NUM_24] = exc_buf_addr->task_context.s8; general_reg[REG_NUM_25] = exc_buf_addr->task_context.s9; general_reg[REG_NUM_26] = exc_buf_addr->task_context.s10; general_reg[REG_NUM_27] = exc_buf_addr->task_context.s11; general_reg[REG_NUM_28] = exc_buf_addr->task_context.t3; general_reg[REG_NUM_29] = exc_buf_addr->task_context.t4; general_reg[REG_NUM_30] = exc_buf_addr->task_context.t5; general_reg[REG_NUM_31] = exc_buf_addr->task_context.t6; } #endif static void log_oml_hard_fault(uint32_t reason) { #if (ARCH == CM3) || (ARCH == CM7) if (reason & SCB_HFSR_DEBUGEVT_Msk) { PRINT("[Hard Fault]: Caused by Debug Event" NEWLINE); } if (reason & SCB_HFSR_FORCED_Msk) { PRINT("[Hard Fault]: Caused by Other Faults" NEWLINE); } if (reason & SCB_HFSR_VECTTBL_Msk) { PRINT("[Hard Fault]: Caused by Fetching vector" NEWLINE); } #else UNUSED(reason); #endif } static void log_oml_mem_fault(uint32_t reason) { #if (ARCH == CM3) || (ARCH == CM7) if (reason & SCB_CFSR_MSTKERR_Msk) { PRINT("[Mem Fault] Enter Stack Fault" NEWLINE); } else if (reason & SCB_CFSR_MUNSTKERR_Msk) { PRINT("[Mem Fault] Quit Stack Fault" NEWLINE); } else if (reason & SCB_CFSR_DACCVIOL_Msk) { PRINT("[Mem Fault] Data Access Fault" NEWLINE); } else if (reason & SCB_CFSR_IACCVIOL_Msk) { PRINT("[Mem Fault] Instruction Access Fault" NEWLINE); } #else UNUSED(reason); #endif } static void log_oml_bus_fault(uint32_t reason) { #if (ARCH == CM3) || (ARCH == CM7) if (reason & SCB_CFSR_STKERR_Msk) { PRINT("[Bus Fault] Enter Stack Fault" NEWLINE); } if (reason & SCB_CFSR_UNSTKERR_Msk) { PRINT("[Bus Fault] Quit Stack Fault" NEWLINE); } if (reason & SCB_CFSR_IMPRECISERR_Msk) { PRINT("[Bus Fault] Non Exact Data Access Fault" NEWLINE); } if (reason & SCB_CFSR_PRECISERR_Msk) { PRINT("[Bus Fault] Data Access Fault" NEWLINE); } if (reason & SCB_CFSR_IBUSERR_Msk) { PRINT("[Bus Fault] Instruction Access Fault" NEWLINE); } #else UNUSED(reason); #endif } static void log_oml_usage_fault(uint32_t reason) { #if (ARCH == CM3) || (ARCH == CM7) if (reason & SCB_CFSR_DIVBYZERO_Msk) { PRINT("[Usage Fault] DIV Zero Fault" NEWLINE); } if (reason & SCB_CFSR_UNALIGNED_Msk) { PRINT("[Usage Fault] unaligned access Fault" NEWLINE); } if (reason & SCB_CFSR_NOCP_Msk) { PRINT("[Usage Fault] Try to execute co-processor instr Fault" NEWLINE); } if (reason & SCB_CFSR_INVPC_Msk) { PRINT("[Usage Fault] Invalid EXC_RETURN to PC Fault" NEWLINE); } if (reason & SCB_CFSR_INVSTATE_Msk) { PRINT("[Usage Fault] Try to Enter ARM State Fault" NEWLINE); } if (reason & SCB_CFSR_UNDEFINSTR_Msk) { PRINT("[Usage Fault] Undefined instruction Fault" NEWLINE); } #else UNUSED(reason); #endif } #if SLAVE_BY_WS53_ONLY static void log_exception_print_para(const exc_context_t *e_contex) { task_context_t contex = e_contex->task_context; PRINT("mcause:0x%x\n""ccause:0x%x\n""mstatus:0x%x\n""ra:0x%x\n""sp:0x%x\n""gp:0x%x\n", e_contex->mcause, e_contex->ccause, contex.mstatus, contex.ra, contex.sp, e_contex->gp); PRINT("a0:0x%x\n""a1:0x%x\n""a2:0x%x\n""a3:0x%x\n""a4:0x%x\n""a5:0x%x\n""a6:0x%x\n""a7:0x%x\n" "tp:0x%x\n""t0:0x%x\n""t1:0x%x\n""t2:0x%x\n""t3:0x%x\n""t4:0x%x\n""t5:0x%x\n""t6:0x%x\n", contex.a0, contex.a1, contex.a2, contex.a3, contex.a4, contex.a5, contex.a6, contex.a7, contex.tp, contex.t0, contex.t1, contex.t2, contex.t3, contex.t4, contex.t5, contex.t6); PRINT("s0/fp:0x%x\n""s1:0x%x\n""s2:0x%x\n""s3:0x%x\n""s4:0x%x\n""s5:0x%x\n" "s6:0x%x\n""s7:0x%x\n""s8:0x%x\n""s9:0x%x\n""s10:0x%x\n""s11:0x%x\n", contex.s0, contex.s1, contex.s2, contex.s3, contex.s4, contex.s5, contex.s6, contex.s7, contex.s8, contex.s9, contex.s10, contex.s11); } #endif #if (ARCH == RISCV31) || (ARCH == RISCV70) static uint32_t log_get_fault_type(uint32_t irq_id) { switch (irq_id) { case IRQ_ID_INSTRUCTION_ADDRESS_MISALIGNED: return OM_INSTRUCTION_ADDRESS_MISALIGNED; case IRQ_ID_INSTRUCTION_ACCESS_FAULT: return OM_INSTRUCTION_ACCESS_FAULT; case IRQ_ID_ILLEGAL_INSTRUCTION: return OM_ILLEGAL_INSTRUCTION; case IRQ_ID_BREAKPOINT: return OM_BREAKPOINT; case IRQ_ID_LOAD_ADDERSS_MISALIGNED: return OM_LOAD_ADDERSS_MISALIGNED; case IRQ_ID_LOAD_ACCESS_FAULT: return OM_LOAD_ACCESS_FAULT; case IRQ_ID_STORE_OR_AMO_ADDRESS_MISALIGNED: return OM_STORE_OR_AMO_ADDRESS_MISALIGNED; case IRQ_ID_STORE_OR_AMO_ACCESS_FALUT: return OM_STORE_OR_AMO_ACCESS_FALUT; case IRQ_ID_ENVIRONMENT_CALL_FROM_UMODE: return OM_ENVIRONMENT_CALL_FROM_UMODE; case IRQ_ID_ENVIRONMENT_CALL_FROM_SMODE: return OM_ENVIRONMENT_CALL_FROM_SMODE; case IRQ_ID_ENVIRONMENT_CALL_FROM_MMODE: return OM_ENVIRONMENT_CALL_FROM_MMODE; case IRQ_ID_INSTRUCTION_PAGE_FAULT: return OM_INSTRUCTION_PAGE_FAULT; case IRQ_ID_LOAD_PAGE_FAULT: return OM_LOAD_PAGE_FAULT; case IRQ_ID_STORE_OR_AMO_PAGE_FAULT: return OM_STORE_OR_AMO_PAGE_FAULT; case IRQ_ID_NMI_INTERRUPT: return OM_NMI_INTERRUPT; #if (ARCH == RISCV31) case IRQ_ID_HARD_FAULT: return OM_RISCV_HARD_FAULT; case IRQ_ID_LOCK_UP: return OM_LOCK_UP; #else case IRQ_ID_ASYNCHRONOUS_EXCEPTION: return OM_ASYNCHRONOUS_EXCEPTION; #endif default: PRINT("Unknown Fault[%x]" NEWLINE, irq_id); return 0; } } void log_exception_dump(uint32_t irq_id, exc_context_t *exc_buf_addr) { UNUSED(log_oml_usage_fault); UNUSED(log_oml_bus_fault); UNUSED(log_oml_mem_fault); UNUSED(log_oml_hard_fault); uint32_t fault_type = 0; #if defined(HSO_SUPPORT) fault_type = log_get_fault_type(irq_id); #if MCU_ONLY reboot_cause_t reset_cause = get_cpu_utils_reset_cause(); switch (reset_cause) { case REBOOT_CAUSE_BT_WATCHDOG: case REBOOT_CAUSE_APPLICATION_CHIP_WDT: fault_type = OM_WDT_TIMEOUT_INTERRUPT; break; case REBOOT_CAUSE_APPLICATION_XIP_CTRL: fault_type = OM_APPLICATION_XIP_CTRL_INTERRUPT; break; case REBOOT_CAUSE_APPLICATION_XIP_CACHE: fault_type = OM_APPLICATION_XIP_CACHE_INTERRUPT; break; case REBOOT_CAUSE_APPLICATION_MDMA: fault_type = OM_APPLICATION_MDMA_INTERRUPT; break; case REBOOT_CAUSE_APPLICATION_SMDMA: fault_type = OM_APPLICATION_SMDMA_INTERRUPT; break; default: break; } #endif #else UNUSED(irq_id); UNUSED(log_get_fault_type); fault_type = OM_WDT_TIMEOUT; #endif #if SLAVE_BY_WS53_ONLY log_exception_print_para(exc_buf_addr); syserr_backtrace_print(exc_buf_addr); show_reboot_info(); fault_type = log_get_fault_type(irq_id); #endif log_oml_exception_info_send(fault_type, exc_buf_addr); /* Send ram */ log_oml_memory_dump(); } #else void log_exception_dump(uint32_t int_id, uint32_t reason, uint32_t addr, exc_info_t *exc_info) { uint32_t fault_type = 0; switch (int_id) { case INT_ID_HARD_FAULT: fault_type = OM_HARD_FAULT; log_oml_hard_fault(reason); break; case INT_ID_MEM_FAULT: fault_type = OM_MEM_FAULT; log_oml_mem_fault(reason); break; case INT_ID_BUS_FAULT: fault_type = OM_BUS_FAULT; log_oml_bus_fault(reason); break; case INT_ID_USAGE_FAULT: fault_type = OM_USAGE_FAULT; log_oml_usage_fault(reason); break; #if CORE == MASTER_BY_ALL case INT_ID_CHIP_WATCHDOG_FAULT: #endif case INT_ID_WATCHDOG_FAULT: fault_type = OM_WDT_TIMEOUT; break; default: PRINT("Unknown Fault[%d]" NEWLINE, int_id); break; } #if MCU_ONLY if ((get_cpu_utils_reset_cause() == REBOOT_CAUSE_BT_WATCHDOG) || (get_cpu_utils_reset_cause() == REBOOT_CAUSE_APPLICATION_CHIP_WDT)) { fault_type = OM_WDT_TIMEOUT; } #endif log_oml_exception_info_send(addr, fault_type, reason, exc_info); /* Send ram */ log_oml_memory_dump(); } #endif void log_exception_send_data(const uint8_t *data, uint16_t length) { #if CORE == CORE_LOGGING log_uart_send_buffer(data, length); #elif defined(SDT_LOG_BY_UART) oml_write_uart_fifo((uint8*)data, length, LOGUART_BASE); #else /* APP core need to wait enough share memory to write next block of data */ uint32_t available = 0; while (available <= length) { (void)log_buffer_get_available_for_next_message(&available); } log_event(data, length); #endif } static void log_exception_dump_memory(uint32_t addr, uint32_t length) { #if (USE_COMPRESS_LOG_INSTEAD_OF_SDT_LOG == NO) uint32_t ram_addr = addr; uint32_t ram_size = length; uint32_t length_tmp = length; uint8_t msg_tail = OM_FRAME_DELIMITER; om_msg_header_stru_t msg_header = { 0 }; om_msg_dump_header_stru_t dump_header = { 0 }; msg_header.frame_start = OM_FRAME_DELIMITER; msg_header.func_type = OM_MSG_TYPE_LAST; msg_header.prime_id = OM_LOG_SAVE_STACK; dump_header.end_flag = 0; dump_header.count = 0; non_os_enter_critical(); while (ram_size > 0) { length_tmp = MIN(ram_size, DUMP_MAX_LENGTH_PER_TRANS); if (length_tmp == ram_size) { dump_header.end_flag = OM_FRAME_DUMP_DELIMITER; } msg_header.frame_len = (uint16_t)(sizeof(om_msg_header_stru_t) + length_tmp + sizeof(msg_tail) + sizeof(om_msg_dump_header_stru_t)); /* Send exception stack */ log_exception_send_data((uint8_t *)(&msg_header), sizeof(om_msg_header_stru_t)); log_exception_send_data((uint8_t *)(&dump_header), sizeof(om_msg_dump_header_stru_t)); log_exception_send_data((uint8_t *)(uintptr_t)ram_addr, (uint16_t)length_tmp); log_exception_send_data((uint8_t *)(&msg_tail), sizeof(msg_tail)); dump_header.count++; ram_addr += length_tmp; ram_size -= length_tmp; } non_os_exit_critical(); #else UNUSED(addr); UNUSED(length); #endif } void log_oml_dump_stack(void) { #if (ARCH == CM3) || (ARCH == CM7) #ifdef USE_CMSIS_OS #ifdef __LITEOS__ LosTaskCB *los_task_cb = NULL; uint32_t loops; uint32_t stack_addr = 0; uint32_t stack_size = 0; uint32_t sp = __get_PSP(); for (loops = 0; loops < g_taskMaxNum; loops++) { los_task_cb = (((LosTaskCB *)g_osTaskCBArray) + loops); if (los_task_cb->taskStatus & OS_TASK_STATUS_UNUSED) { continue; } if (sp > los_task_cb->topOfStack && sp < los_task_cb->topOfStack + los_task_cb->stackSize) { stack_addr = los_task_cb->topOfStack; stack_size = los_task_cb->stackSize; PRINT("current task stack_point: 0x%x\r\n", sp); PRINT("stack addr:0x%x,stack size:0x%x\r\n", stack_addr, stack_size); pf_write_fifo_log_alter(LOG_PFMODULE, LOG_NUM_LIB_LOG, LOG_LEVEL_ERROR, "[PF][DUMP INFO] stack point: 0x%x, stack address: 0x%x, stack size: 0x%x", STACK_SIZE, sp, stack_addr, stack_size); break; } } log_exception_dump_memory(stack_addr, stack_size); #endif #endif #else UNUSED(log_exception_dump_memory); #endif } static void log_watch_dog_reconfigure(void) { watchdog_turnon_clk(); uapi_watchdog_disable(); /* DUMP流程耗时过大,需要重新配置狗超时时间 */ uapi_watchdog_set_time(CHIP_WDT_TIMEOUT_256S); uapi_watchdog_enable(WDT_MODE_INTERRUPT); } void log_bt_req_dump(void) { #if (USE_COMPRESS_LOG_INSTEAD_OF_SDT_LOG == NO) log_watch_dog_reconfigure(); #endif #ifdef HSO_SUPPORT dfx_last_dump(); #endif return; } void log_oml_memory_dump(void) { #if (USE_COMPRESS_LOG_INSTEAD_OF_SDT_LOG == NO) log_watch_dog_reconfigure(); #if CORE == BT /* BT core has just one block of ram */ uapi_tcxo_delay_ms(DUMP_DELAY); #elif CORE == APPS && !defined(BUILD_RECOVERY_IMAGE) #ifdef HSO_SUPPORT dfx_last_dump(); #else log_exception_dump_memory(APP_ITCM_ORIGIN, APP_ITCM_LENGTH); log_exception_dump_memory(APP_DTCM_ORIGIN, APP_DTCM_LENGTH); log_exception_dump_memory(SHARED_MEM_START, SHARED_MEM_LENGTH); log_exception_dump_memory(MCPU_TRACE_MEM_REGION_START, CPU_TRACE_MEM_REGION_LENGTH); log_exception_dump_memory(BT_RAM_ORIGIN_APP_MAPPING, BT_RAM_ORIGIN_APP_MAPPING_LENGTH); log_exception_dump_memory(BCPU_TRACE_MEM_REGION_START, CPU_TRACE_MEM_REGION_LENGTH); log_exception_dump_reg(); #endif /* mem dump save in flash */ #if (FLASH_DUMP_START != 0) dfx_last_dump2flash(FLASH_DUMP_START, FLASH_DUMP_SIZE); #endif #ifdef NO_TCXO_SUPPORT volatile int time_cnt = 0xFFFF; while (time_cnt--) { __asm__ __volatile__("nop"); __asm__ __volatile__("nop"); } #else uapi_tcxo_delay_ms(LOG_DELAY); #endif #elif CORE == WIFI log_exception_dump_memory(WL_BOOT_ROM_START, WL_BOOT_ROM_LEN); log_exception_dump_memory(WL_ITCM_IROM_START, WL_ITCM_IROM_LEN); log_exception_dump_memory(WL_TCM_RAM_START, WL_TCM_RAM_LEN); log_exception_dump_memory(WL_DTCM_PKTMEM_START, WL_DTCM_PKTMEM_LEN); log_exception_dump_memory(WCPU_TRACE_MEM_REGION_START, CPU_TRACE_MEM_REGION_LENGTH); tcxo_delay_ms(DUMP_DELAY); return; #elif CORE == CONTROL_CORE log_exception_dump_memory(CT_SRAM_ORIGIN, CT_SRAM_LENGTH); log_exception_dump_memory(CT_ROM_ORIGIN, CT_ROM_LENGTH); log_exception_dump_memory(CCORE_FLASH_PROGRAM_ORIGIN, CCORE_FLASH_PROGRAM_LENGTH); uapi_tcxo_delay_ms(DUMP_DELAY); return; #endif #else /* USE_COMPRESS_LOG_INSTEAD_OF_SDT_LOG == YES */ #endif /* USE_COMPRESS_LOG_INSTEAD_OF_SDT_LOG */ } #if defined(__ICCARM__) #pragma segment = "CSTACK" #endif #if (ARCH == RISCV31) || (ARCH == RISCV70) static void log_oml_build_last_run_info(om_exception_info_stru_t *last_run_info, uint32_t irq_id, const exc_context_t *exc_buf_addr) { uint32_t stack_limit; #if defined(__GNUC__) stack_limit = (uint32_t)((uintptr_t)&(g_stack_system)); #else stack_limit = 0; #endif last_run_info->msg_header.frame_start = OM_FRAME_DELIMITER; last_run_info->msg_header.func_type = OM_MSG_TYPE_LAST; last_run_info->msg_header.prime_id = OM_LOG_RPT_IND; last_run_info->msg_header.sn = get_log_sn_number(); last_run_info->stack_limit = stack_limit; last_run_info->fault_type = irq_id; last_run_info->fault_reason = 0; last_run_info->address = 0; last_run_info->psp_value = exc_buf_addr->task_context.sp; last_run_info->lr_value = exc_buf_addr->task_context.ra; last_run_info->pc_value = exc_buf_addr->task_context.mepc; last_run_info->psps_value = exc_buf_addr->gp; last_run_info->primask_value = exc_buf_addr->task_context.mstatus; last_run_info->fault_mask_value = exc_buf_addr->mtval; last_run_info->bserpri_value = exc_buf_addr->ccause; last_run_info->control_value = exc_buf_addr->mtval; last_run_info->msg_header.frame_len = (uint16_t)sizeof(om_exception_info_stru_t); last_run_info->msg_tail = OM_FRAME_DELIMITER; } void log_oml_exception_info_send(uint32_t irq_id, const exc_context_t *exc_buf_addr) { om_exception_info_stru_t last_run_info = { 0 }; memset_s((void *)&last_run_info, sizeof(last_run_info), 0, sizeof(last_run_info)); log_oml_build_last_run_info(&last_run_info, irq_id, exc_buf_addr); log_oml_get_reg_value(last_run_info.reg_value, exc_buf_addr); /* * Waiting for the entire log to be sent * Because it is possible that the uart transmission is not completed, * the structure assignment is placed in front to ensure that there is information in the stack. */ #if CORE == CORE_LOGGING #ifdef HSO_SUPPORT dfx_last_word_send((uint8_t *)&last_run_info + sizeof(om_msg_header_stru_t), sizeof(last_run_info) - sizeof(om_msg_header_stru_t) - OM_FRAME_DELIMITER_LEN); #else log_uart_send_buffer((uint8_t *)&last_run_info, sizeof(last_run_info)); #endif #elif defined(SDT_LOG_BY_UART) oml_write_uart_fifo((uint8_t *)&last_run_info, sizeof(last_run_info), LOGUART_BASE); #else log_event((uint8_t *)&last_run_info, sizeof(last_run_info)); log_trigger(); #endif #ifdef NO_TCXO_SUPPORT volatile int time_cnt = 0xFFFF; while (time_cnt--) { __asm__ __volatile__("nop"); __asm__ __volatile__("nop"); } #else uapi_tcxo_delay_ms(LOG_DELAY); #endif } #else void log_oml_exception_info_send(uint32_t address, uint32_t fault_type, uint32_t fault_reason, const exc_info_t *exc_info) { if (exc_info == NULL) { return; } om_exception_info_stru_t last_run_info = { 0 }; uint8_t loop; uint32_t stack_limit; memset_s((void *)&last_run_info, sizeof(last_run_info), 0, sizeof(last_run_info)); #if defined(__GNUC__) stack_limit = (uint32_t)((uintptr_t)&(g_stack_system)); #elif defined(__ICCARM__) stack_limit = (uint32_t)__sfe("CSTACK") - 4; // 4 byte #else stack_limit = 0; #endif last_run_info.msg_header.frame_start = OM_FRAME_DELIMITER; last_run_info.msg_header.func_type = OM_MSG_TYPE_LAST; last_run_info.msg_header.prime_id = OM_LOG_RPT_IND; last_run_info.msg_header.sn = get_log_sn_number(); last_run_info.stack_limit = stack_limit; last_run_info.fault_type = fault_type; last_run_info.fault_reason = fault_reason; last_run_info.address = address; memcpy_s((void *)&last_run_info.reg_value[0], AULREG_VALUE_INDEX, &(exc_info->context->r4), AULREG_VALUE_INDEX); #if (ARCH == CM3) || (ARCH == CM7) last_run_info.psp_value = __get_PSP(); last_run_info.lr_value = exc_info->context->lr; last_run_info.pc_value = exc_info->context->pc; last_run_info.psps_value = exc_info->context->xpsr; last_run_info.primask_value = __get_PRIMASK(); last_run_info.fault_mask_value = (uint32_t)__get_FAULTMASK(); last_run_info.bserpri_value = (uint32_t)__get_BASEPRI(); last_run_info.control_value = __get_CONTROL(); last_run_info.msg_header.frame_len = sizeof(om_exception_info_stru_t); last_run_info.msg_tail = OM_FRAME_DELIMITER; #endif /* * Waiting for the entire log to be sent * Because it is possible that the uart transmission is not completed, * the structure assignment is placed in front to ensure that there is information in the stack. */ #if CORE == CORE_LOGGING #ifdef HSO_SUPPORT dfx_last_word_send((uint8_t *)&last_run_info + sizeof(om_msg_header_stru_t), sizeof(last_run_info) - sizeof(om_msg_header_stru_t) - OM_FRAME_DELIMITER_LEN); #else log_uart_send_buffer((uint8_t *)&last_run_info, sizeof(last_run_info)); #endif #else log_event((uint8_t *)&last_run_info, sizeof(last_run_info)); log_trigger(); #endif uapi_tcxo_delay_ms(LOG_DELAY); } #endif void default_register_hal_exception_dump_callback(void) { #ifdef SUPPORT_DFX_EXCEPTION hal_register_exception_dump_callback(log_exception_dump); #endif }