1.1 模拟复现条件
能够复现bug才能对问题进行定位、解决以及验证。找到bug存在的特定的条件,进行重现。对于依赖外部输入的条件,如果条件比较复杂难以模拟可以在程序里预设直接进入对应状态。
1.2 打印Log
根据问题的现象,在抱有疑问的代码处增加LOG输出,以此来追踪程序执行流程以及关键变量的值,观察是否与预期相符。
1.3 在线调试
在线调试可以起到和打印LOG类似的作用,另外此方法特别适合排查程序崩溃类的BUG,当程序陷入异常中断(HardFault,看门狗中断等)的时候可以直接STOP查看call stack以及内核寄存器的值,快速定位问题点。
1.4 版本回退
使用版本管理工具时可以通过不断回退版本并
测试验证来定位首次引入该问题的版本,之后可以围绕该版本增改的代码进行排查。
1.5 二分注释
二分注释即以类似二分查找法的方式注释掉部分代码,以此判断问题是否由注释掉的这部分代码引起。具体方法为将与问题不相干的部分代码注释掉一半,看问题是否解决,未解决则注释另一半,如果解决则继续将注释范围缩小一半,以此类推逐渐缩小问题的范围。
1.6 保存内核寄存器快照
Cortex M内核陷入异常中断时会将几个内核寄存器的值压入栈中。
可以在陷入异常中断时将栈上的内核寄存器值写入RAM的一段复位后保留默认值的区域内,执行复位操作后再从RAM将该信息读出并分析,通过PC、LR确认当时执行的函数,通过R0-R3分析当时处理的变量是否异常,通过SP分析是否可能出现栈溢出等。
车载Bug分析处理
结合问题现象以及定位的问题代码位置分析造成问题的原因。
2.1 停止运行
2.1.1 软件问题
1、HardFault 以下情况会造成HardFault:
· 在外设时钟门未使能的情况下操作该外设的寄存器;
· 跳转函数地址越界,通常发生在函数指针被篡改,排查方法同数值异常;
· 解引用指针时出现对齐问题:
以小端序为例,如果声明了一个强制对齐的结构体如下:
此时a.val1的地址为0x00000001,如果以uint16_t类型去解引用此地址则会因为对齐问题进入HardFault,如果一定要用指针方式操作该变量则应当使用memcpy()。
2、中断服务函数中未清除中断标志
中断服务函数退出前不正确清除中断标志,当程序执行从中断服务函数内退出后又会立刻进入中断服务函数,表现出程序的“假死”现象。
3、NMI中断
调试时曾遇到SPI的MISO引脚复用NMI功能,当通过SPI连接的外设损坏时MISO被拉高,导致单片机复位后在把NMI引脚配置成SPI功能之前就直接进入NMI中断,程序挂死在NMI中断中。这种情况可以在NMI的中断服务函数内禁用NMI功能来使其退出NMI中断。
2.1.2 硬件问题
· 晶振未起振
· 供电电压不足
· 复位引脚拉低
2.2 复位
2.2.1 软件问题
看门狗复位,除了喂狗超时导致的复位以外,还要注意看门狗配置的特殊要求,以Freescale KEA单片机为例,该单片机看门狗在配置时需要执行解锁序列(向其寄存器连续写入两个不同的值),该解锁序列必须在16个总线时钟内完成,超时则会引起看门狗复位。此类问题只能熟读单片机数据手册,注意类似的细节问题。
2.2.2 硬件问题
1、供电电压不稳
2、电源带载能力不足