实战--根据hard fault打印的寄存器信息分析代码异常地址

1、前言

     阅读本文请需要先了解一下技术原理,请阅读一下这篇文章:https://blog.csdn.net/fhqlongteng/article/details/112756689

2、故障时的寄存器信息

      程序在运行中串口打印出如下信息,程序进入hard fault中断并打印出异常点的寄存器数据。

[E/NET_SW] Invalid low power sensor data on the uart2 channel
psr: 0x21000200
r00: 0x000000f6
r01: 0x000000f5
r02: 0x0000006a
r03: 0x20030000
r04: 0x000000a3
r05: 0x00000085
r06: 0x00000085
r07: 0x00000250
r08: 0x00000250
r09: 0x00000018
r10: 0x200200f7
r11: 0x00000000
r12: 0x0000e8bc
lr: 0x0800df1b
pc: 0x0800dbcc
hard fault on thread: mlp_cln
 
thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
mlp_cln    7  suspend 0x000000a0 0x00000600    56%   0x00000012 000
mlp_cln    7  suspend 0x000000a4 0x00000600    24%   0x0000000e 000
mlp_cln    7  suspend 0x000000a0 0x00000600    22%   0x00000013 000
mlp_cln    7  ready   0x000000a4 0x00000600    27%   0x00000004 000
Dw_send    9  suspend 0x000000ac 0x00000800    08%   0x0000000a 000
Up_send    8  suspend 0x000000ac 0x00000800    14%   0x00000007 000
tshell    20  suspend 0x0000013c 0x00000800    20%   0x00000003 000
ntp_sync  26  suspend 0x00000078 0x00000600    41%   0x00000002 000
sys_work  23  suspend 0x00000070 0x00000800    05%   0x0000000a 000
tcpip      6  suspend 0x000000c0 0x00000400    50%   0x00000014 000
etx        7  suspend 0x00000094 0x00000400    14%   0x0000000f 000
erx        7  suspend 0x0000009c 0x00000400    51%   0x00000010 000
tidle     31  ready   0x00000050 0x00000400    09%   0x00000005 000
timer      8  suspend 0x00000084 0x00000400    42%   0x00000006 000
main      10  suspend 0x000000a8 0x00000800    33%   0x00000013 000
bus fault:
SCB_CFSR_BFSR:0x82 PRECISERR SCB->BFAR:20030000

    通过打印信息可以看出,程序发生异常的点是PC=0x0800dbcc, 返回寄存器LR= 0x0800DF1B,打开程序的源码,查看汇编程序的位置来确认一下出现源代码的位置。总线异常0x0800dbcc发生在函数 sensor_crc16 中iIndex = ucCRCLo ^ *( pucFrame++ )语句中。

      根据返回寄存器LR= 0x0800DF1B,程序在执行完成当前函数 sensor_crc16会返回到0x0800DF1B的位置,就是 函数sensor_data_is_valid中,如下图,通过分析sensor_data_is_valid的代码,可以看到当给这个函数你传入len=1时, 调用sensor_crc16函数传入的第二个参数就是0xFFFFFFFF,这会导致sensor_crc16程序访问到非法的内存,导致出现总线错误引发硬件错误。这种故障通过程序执行这个函数时,人为修改len=1,即可复现这样子的寄存器打印信息。

 3、解决办法

        找到异常代码的问题,解决起来就很简单了,在sensor_data_is_valid入口增加对输入长度len的判断,即当len < 3时返回,代码更改如下:

int  sensor_data_is_valid(rt_uint8_t *data, rt_uint32_t len)
{ 
    rt_uint16_t    crc = 0;

    RT_ASSERT(data);

    /*if len == 1, the programe will enter the hardfault interrupt by bus fault  20210120*/
    if(len < 3)
    {
        return RT_FALSE;    
    }

    crc = (data[len - 2] << 8) | data[len - 1];

    if(crc != sensor_crc16(data, len - 2))
    {
        return RT_FALSE;
    }
    else
    {
        return RT_TRUE;
    }
} 

      

 

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值