当前位置: 首页 > news >正文

Cortex-M7进入异常中断分析

使用cmbacktrace库,其支持M3,4,7。

1、串口输出异常信息

#define cmb_println(...)    Debug_Printf(__VA_ARGS__)

//cmb_println处理可变参数和格式化字符串
int Debug_Printf(const char *fmt, ...) {
    char buffer[DEBUG_TxBUFLEN];
	INT16U n;
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(buffer, sizeof(buffer), fmt, args);
    va_end(args);
	for ( n = 0; n < len; n++ )  WriteDebugTxBuffer( buffer[n] );
    return len;
}

//串口查询方式发送,被cm_backtrace_fault调用
void UartDbg_CheckSend(void)
{
#if 1
	INT32U status;

	if ( DebugBuf.PtrTxHead == DebugBuf.PtrTxTail ) return;

	status = LPUART_GetStatusFlags( DEBUG_SIO_BASE );

	if ( status & kLPUART_TxDataRegEmptyFlag )
	{
		LPUART_WriteByte( DEBUG_SIO_BASE, DebugBuf.TxBuffer[ DebugBuf.PtrTxTail ] );
		++DebugBuf.PtrTxTail;
		if ( DebugBuf.PtrTxTail >= DEBUG_TxBUFLEN ) DebugBuf.PtrTxTail = 0;
	}
#endif
}


/**
 * backtrace for fault
 * @note only call once
 *
 * @param fault_handler_lr the LR register value on fault handler
 * @param fault_handler_sp the stack pointer on fault handler
 */
void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) {
    uint32_t stack_pointer = fault_handler_sp, saved_regs_addr = stack_pointer, tcb_stack_pointer = 0;
    const char *regs_name[] = { "R0 ", "R1 ", "R2 ", "R3 ", "R12", "LR ", "PC ", "PSR" };

#ifdef CMB_USING_DUMP_STACK_INFO
    uint32_t stack_start_addr = main_stack_start_addr;
    size_t stack_size = main_stack_size;
#endif

    CMB_ASSERT(init_ok);
    /* only call once */
    CMB_ASSERT(!on_fault);

    on_fault = true;

    cmb_println(" ");
    cm_backtrace_firmware_info();

#ifdef CMB_USING_OS_PLATFORM
    on_thread_before_fault = fault_handler_lr & (1UL << 2);
    /* check which stack was used before (MSP or PSP) */
    if (on_thread_before_fault) {
        cmb_println(print_info[PRINT_FAULT_ON_THREAD], get_cur_thread_name() != NULL ? get_cur_thread_name() : "NO_NAME");
        saved_regs_addr = stack_pointer = cmb_get_psp();

#ifdef CMB_USING_DUMP_STACK_INFO
        get_cur_thread_stack_info(&tcb_stack_pointer, &stack_start_addr, &stack_size);
#endif /* CMB_USING_DUMP_STACK_INFO */

    } else {
        cmb_println(print_info[PRINT_FAULT_ON_HANDLER]);
    }
#else
    /* bare metal(no OS) environment */
    cmb_println(print_info[PRINT_FAULT_ON_HANDLER]);
#endif /* CMB_USING_OS_PLATFORM */

    /* delete saved R0~R3, R12, LR,PC,xPSR registers space */
    stack_pointer += sizeof(size_t) * 8;

#if (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M4) || (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M7) || \
    (CMB_CPU_PLATFORM_TYPE == CMB_CPU_ARM_CORTEX_M33)
    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) */

#ifdef CMB_USING_DUMP_STACK_INFO
    /* check stack overflow */
    if (stack_pointer < stack_start_addr || stack_pointer > stack_start_addr + stack_size) {
        cmb_println("stack_pointer: 0x%08x, stack_start_addr: 0x%08x, stack_end_addr: 0x%08x", stack_pointer, stack_start_addr,
            stack_start_addr + stack_size);
        stack_is_overflow = true;
#if (CMB_OS_PLATFORM_TYPE == CMB_OS_PLATFORM_RTT)
        if (on_thread_before_fault) {
             /* change the stack start adder to TCB->sp when stack is overflow  */
            stack_pointer = tcb_stack_pointer;
        }
#endif
    }
    /* dump stack information */
    dump_stack(stack_start_addr, stack_size, (uint32_t *) stack_pointer);
#endif /* CMB_USING_DUMP_STACK_INFO */

    {
        /* dump register */
        cmb_println(print_info[PRINT_REGS_TITLE]);

        regs.saved.r0        = ((uint32_t *)saved_regs_addr)[0];  // Register R0
        regs.saved.r1        = ((uint32_t *)saved_regs_addr)[1];  // Register R1
        regs.saved.r2        = ((uint32_t *)saved_regs_addr)[2];  // Register R2
        regs.saved.r3        = ((uint32_t *)saved_regs_addr)[3];  // Register R3
        regs.saved.r12       = ((uint32_t *)saved_regs_addr)[4];  // Register R12
        regs.saved.lr        = ((uint32_t *)saved_regs_addr)[5];  // Link register LR
        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,
                                                                regs_name[3], regs.saved.r3);
        cmb_println("  %s: %08x  %s: %08x  %s: %08x  %s: %08x", regs_name[4], regs.saved.r12,
                                                                regs_name[5], regs.saved.lr,
                                                                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)
    regs.syshndctrl.value = CMB_SYSHND_CTRL;  // System Handler Control and State Register
    regs.mfsr.value       = CMB_NVIC_MFSR;    // Memory Fault Status Register
    regs.mmar             = CMB_NVIC_MMAR;    // Memory Management Fault Address Register
    regs.bfsr.value       = CMB_NVIC_BFSR;    // Bus Fault Status Register
    regs.bfar             = CMB_NVIC_BFAR;    // Bus Fault Manage Address Register
    regs.ufsr.value       = CMB_NVIC_UFSR;    // Usage Fault Status Register
    regs.hfsr.value       = CMB_NVIC_HFSR;    // Hard Fault Status Register
    regs.dfsr.value       = CMB_NVIC_DFSR;    // Debug Fault Status Register
    regs.afsr             = CMB_NVIC_AFSR;    // Auxiliary Fault Status Register

    fault_diagnosis();
#endif

    print_call_stack(stack_pointer);
    //在末尾处执行串口发送
	while (1)
		{
		UartDbg_CheckSend();
		}
}

 Firmware name: CmBacktrace, hardware version: V1.00, software version: V1.00Fault on interrupt or bare metal(no OS) environment=================== Registers information ====================  R0 : 20015ca0  R1 : 00000064  R2 : 00000000  R3 : 00000001  R12: 00000001  LR : 7008fe8b  PC : 7008fdee  PSR: 01000000==============================================================Usage fault is caused by Indicates a divide by zero has taken place (can be set only if DIV_0_TRP is set)Show more call stack info by run: addr2line -e CmBacktrace.out -afpiC 7008fdee 7008fe8a 7009b45a 

2、ddr2line解析地址,解析出来函数名和行数,准确解析了trigger_hardfault_by_div0函数115行出错

0x7008fe8b
MainFunction
E:\tfs\12.5\Equipment\firmware\Smartsafe\MC\Source\User_5200N\UserIAR\MiddleControl/Main_Mid.c:171
0x7008fdee
trigger_hardfault_by_div0
E:\tfs\12.5\Equipment\firmware\Smartsafe\MC\Source\User_5200N\UserIAR\MiddleControl/Main_Mid.c:115
PS F:\CmBacktrace\tools\addr2line\win64> 

 

相关文章:

  • 写一个输入框校验类,链式实现表单校验
  • sql2022 复制 事务级别发布后无法删除
  • 在IDEA中使用TortoiseSVN
  • 自然语言处理(NLP)技术的应用面有哪些
  • 往期项目shader着色器实践效果应用合集
  • 【网络通信安全】基于华为 eNSP 的链路聚合、手工负载分担模式与 LACP 扩展配置 全解析
  • 【时时三省】(C语言基础)if语句一般形式
  • 上下文离群值深度解析:定义、应用场景与检测方法实战
  • 第 12 章(番外)| Solidity 安全前沿趋势 × 审计生态 × 职业路径规划
  • 一周掌握Flutter开发--8. 调试与性能优化(上)
  • 高效事件驱动设计模式——Reactor 模式
  • 【点盾云】加密技术如何防止视频内容随意传播?
  • Angular的理解
  • HTTP 1.0和2.0 有什么区别?
  • 超详细docker部署搭建私有仓库harbor
  • 【django】2-1 (django配置) 应用配置、中间件配置、模板配置
  • 食品计算—Augmented/mixed reality technologies for food: A review
  • Linux 常见漏洞修复方法和防御措施整理
  • 【git】基本操作
  • fork系统调用
  • 高龄老人骨折后,生死可能就在家属一念之间
  • 白宫启动“返乡计划” ,鼓励非法移民自愿离开美国
  • 早期投资人蜂巧资本清仓泡泡玛特套现超22亿港元,称基金即将到期
  • 8大类1000多支,中国红十字会已建成10万人规模救援队伍
  • 自然资源部印发地理信息数据分类分级指南
  • 长三角多地重启游轮跨市游,“恢复苏杭夜航船”呼声又起