STM32F103项目中使用了uCOS-II,出现一个致命问题:当只跑uCOS-II时,程序运行正常,一旦开启USB功能(或任何其它带高优先级中断的程序),程序运行一段时间后就会死掉,时间是随机的。
通过keil启动程序,死机时停下来,看到死在HardFault_Handler中:
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
提示出现了硬件错误。
看下这时的寄存器:
注意其中的LR,它是一个奇怪的值0xFFFFFFF5,后面再介绍它。
既然出现了硬件错误,可以看下异常寄存器(菜单Peripherals->Core Peripherals->Fault Reports):
(这样查看比较快,后文有通过寄存器查看的方法)
可以看到硬件错误(Hard Faults)是上访造成的(FORCED位),而真实的错误原因是由用法错误(Usage Faults)引起的,具体引起用法错误的原因是INVPC错误。
如果用的不是Keil,也可以通过直接查看异常寄存器值来得到错误原因。
查看《ARM Cortex-M3 Processor Technical Reference Manual》和《Cortex-M3 Devices Generic User Guide》这两个手册(可以从ARM官网直接下载),SCB寄存器(System control block (SCB))的地址是0xE000E000开始的,HardFault Status Register的地址是0xE000ED2C(HFSR,百度上也有),查看相应地址的值:
可以看到HFSR(0xE000ED2C)的值是0x40000000,而UFSR(0xE000ED2A)的值是0x0004,查看《Cortex-M3 Devices Generic User Guide》手册,相应比特位的意思是:
HFSR的FORCED位为1,表示硬件错误的原因是上访造成的,此位置1表示产生了其他类型的异常,但由于优先级问题或者使能问题导致无法处理异常,于是这些异常就升级成硬件错误异常。
UFSR的INVPC位为1,表示在异常中断返回时尝试向PC载入非法的EXC_RETURN值,从而引起用法错误。
这里用法错误升级为硬件错误的原因是没有使能用法错误位,SHCRS(0xE000ED24, System Handler Control and State Register)的USGFAULTENA位为0。
使用keil重新加载程序,在运行程序之前先将0xE000ED24的值改为0x00070000(临时使能USGFAULTENA位),然后再次运行,程序死机时可以看到死机的位置变成UsageFault_Handler了(这一步没必要,只是为了验证对异常机制的理解)。
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
这个时候异常寄存器的值也变成了:
可以看到HFSR的值没有了,只剩UFSR的值指示发生了INVPC错误。
现在要检查为什么会发生INVPC错误。