错误种类
对于Cortex-M内核,架构采用错误异常的机制来检测问题,当核心检测到一个错误时,异常中断会被触发,并且核心会跳转到相应的异常终端处理函数执行,错误异常的终端分为以下四种:
HardFault
MemManage
BusFault
UsageFault
其中hardfault为最常见的错误类型,并且,在没有开启其他异常处理的情况下,默认进入hardfault异常中断处理函数:
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
2) 可能的原因
从软件角度,产生hardfault的可能原因有:
(1)数组越界
(2)野指针
(3)未初始化硬件却开始操作,或无中断服务函数
(4)任务堆栈溢出
方法1.查看寄存器
- 查看fault种类
通过菜单栏Peripherals >Core Peripherals >Fault Reports打开fault reports
但是查看fault种类有时可能对解决问题并没有直接帮助,关键是如何定位在进入异常中断前执行的代码段
- 调试定位步骤
-
确定当前使用堆栈是MSP还是PSP
异常发生后会把进入异常前的 R0-R3,R12, LR, PC,PSR 寄存器值栈入 Main Stack 或Process Stack(取决于异常发生时使用的哪个栈)。 进入异常后链接寄存器 LR 中存放异常返回值 EXC_RETURN, 如果其 bit 2=0 那么用的就是 Main Stack,如果 bit 2=1,那么用的就是 Process Stack。
由上图和下图可以看出,当前使用的堆栈为MSP
-
找到异常发生代码地址
在memory中,定位到堆栈地址:0x200014D8,依据:R0~R3、R12、LR、PC、XPRS 顺序,找到LR的值,即第6个寄存器值
LR = 0x08002879
PC = 0x0800288C
-
Disassembly反汇编中,查找定位代码
在反汇编窗口中点击右键,选中show disassembly at address 。
输入LR地址:为发生异常后调用的下一条指令的地址
输入PC地址:可以定位到发生异常的调用语句
方法2: Call Stack
在仿真状态下,调出Call Stack Window,可直接跳转到调用代码
方法3: .map文件
.map文件在keil工程里面随着程序的编译会自动生成,需要正确设置以下选项:
双击Target位置即可打开.map文件
在.map文件里我们查找LR = 0x08002879,找到了0x08002865指示是buzzer_device_ops_callback函数,到此我们找到了异常代码所在的位置。