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

如何根据HardFault中断抛出的寄存器值排查数组越界

Gitee仓库

git clone https://gitee.com/banana-peel-x/freedom-learn.git

项目场景:

实习的时候遇到了函数不可重入问题,场景是上位机与MCU通过udp协议通信,控制MCU测试不同的功能项,频率为1s/次。其中测试CAN老化功能时,需要每秒让CAN控制器进入LoopBack模式,自发自收后上传。测试时偶发跑死,串口抛出异常。

根因:是由于在其他的task里会控制can的模式,在udp的钩子函数里(我的task)里也需要切换can的模式,自测没有问题是两者偶尔各自控制一下硬件没有影响,压测会出现同时控制can,出现HardFault。


问题描述

从本科做项目开始,排查Bug主要靠直觉,小代码量绰绰有余。对于代码量很大的程序却很低效。最后靠部门大佬帮忙解决,大佬一通操作直接看起了汇编,近来吃不好睡不香,故捡起来琢磨一下大佬的排查方法。

首先改进启动文件,startup_stm32f103xb.s:通常出现HardFault异常后会进入HardFault_Handler中断,这里弃用HardFault_Handler函数,改用hard_fault_handler_c函数。
常规

HardFault_Handler\PROCEXPORT  HardFault_Handler          [WEAK]B       .ENDP

改进

HardFault_Handler\PROCMOVS    r0, #4MOV     r1, lrTST     r0, r1BEQ     stacking_used_MSPMRS     r0, pspB       get_LR_and_branch
stacking_used_MSPMRS     r0, msp
get_LR_and_branchMOV     r1, lrIMPORT  hard_fault_handler_cBL       hard_fault_handler_c  ENDP

在hard_fault_handler_c函数中通过Uart抛出寄存器的值

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
{unsigned int stacked_r0;unsigned int stacked_r1;unsigned int stacked_r2;unsigned int stacked_r3;unsigned int stacked_r12;unsigned int stacked_lr;unsigned int stacked_pc;unsigned int stacked_psr;stacked_r0 = ((unsigned long) hardfault_args[0]);stacked_r1 = ((unsigned long) hardfault_args[1]);stacked_r2 = ((unsigned long) hardfault_args[2]);stacked_r3 = ((unsigned long) hardfault_args[3]);stacked_r12 = ((unsigned long) hardfault_args[4]);stacked_lr = ((unsigned long) hardfault_args[5]);stacked_pc = ((unsigned long) hardfault_args[6]);stacked_psr = ((unsigned long) hardfault_args[7]);printf ("[Hard fault handler]\r\n");printf ("R0 = %x\r\n", stacked_r0);printf ("R1 = %x\r\n", stacked_r1);printf ("R2 = %x\r\n", stacked_r2);printf ("R3 = %x\r\n", stacked_r3);printf ("R12 = %x\r\n", stacked_r12);printf ("Stacked LR = %x\r\n", stacked_lr);printf ("Stacked PC = %x\r\n", stacked_pc);printf ("Stacked PSR = %x\r\n", stacked_psr);printf ("Current LR = %x\r\n", lr_value);while(1); // endless loop
}

发生异常后,可以通过串口抛出的值快速定位问题,KEIL在不破坏现场的情况下进入Debug模式。
当中断或者异常发生时,内核会将xPSR、PC、LR、R12、R3、R2、R1、R0这些寄存器按照顺序依次存入堆栈,这些寄存器中的值是中断/异常发生前一刻的值。故抛出的PC寄存器存的就是被中断打断的指令的下一条指令地址,所以我们同个定位PC寄存器中地址所指向的代码,就可以精准定位或定位在问题代码附近。

原因分析:

根据Stacked PC = 8002e8c,在汇编中查找抛出异常前代码运行位置,可以看出StackFlow_50ms函数中数组越界。

在这里插入图片描述
在这里插入图片描述


http://www.xdnf.cn/news/320203.html

相关文章:

  • 【EasyPan】loadDataList方法及checkRootFilePid方法解析
  • 阿里云服务器-宝塔面板安装【保姆级教程】
  • 如何将B站(哔哩哔哩)的视频下载到电脑
  • 二叉查找树,平衡二叉树(AVL),b树,b+树,红黑树
  • 实验一:Linux静态路由
  • 如何利用 Elastic Load Balancing 提升应用性能与可用性?
  • VScode一直处于循环“正在重新激活终端“问题的解决方法
  • 软件设计师2025
  • 隐私计算技术及其在数据安全中的应用:守护数据隐私的新范式
  • Word如何制作三线表格
  • ABB机器人基础课件及培训视频教程
  • RabbitMQ中Exchange交换器的类型
  • 国产Word处理控件Spire.Doc教程:在Java中为Word文本和段落设置边框
  • 【Pandas】pandas DataFrame rolling
  • ✨WordToCard使用分享✨
  • 2-C#控件
  • [数据库之九] 数据库索引之顺序索引
  • Cloudera CDP 7.1.3 主机异常关机导致元数据丢失,node不能与CM通信
  • 007 Linux 开发工具(上)—— vim、解放sudo、gc+
  • Java学习手册:ORM 框架性能优化
  • 嵌入式软件学习指南:从入门到进阶
  • 澳鹏亮相2025中国生成式AI大会,以数据赋能大模型垂类应用新纪元
  • 42. PCB防静电环设计
  • QT人工智能篇-opencv
  • Kafka是什么?典型应用场景有哪些? (消息队列、流处理平台;日志收集、实时分析、事件驱动架构等)
  • CentOS 系统升级失败的原因与排查
  • LED实验
  • Web前端入门及基础代码
  • webRtc之指定摄像头设备绿屏问题
  • Java程序题案例分析