Ozone可以帮助用户快速分析和查找导致CPU故障的软件bug。本文解释如何使用Ozone的调试功能,深入了解Cortex-M架构上的这些错误。
故障分析流程
我们首先基于一个示例应用程序演示Ozone的故障分析工作流。示例应用程序可以生成不同类型的Cortex-M故障,工程下载链接https://wiki.segger.com/File:CortexM_FaultTest.zip(请复制链接到浏览器下载)。在下图中,示例应用程序被下载到SEGGER Cortex-M trace参考板,调试工具使用J-Trace PRO。程序执行到函数_NoThumbFunc中,PC位于跳转到地址0的指令处,由于在地址0处是一条Thumb指令,继续执行程序将导致Cortex-M CPU故障。恢复程序执行,看看Ozone是如何处理故障。
目标异常对话框
点击GO后,程序执行中断,Ozone弹出目标异常对话框:
目标异常对话框描述了CPU故障及其系统寄存器上下文。本例中,SHCSR寄存器的USGFAULTACT位表示发生了一个Cortex-M UsageFault异常。寄存器UFSR提供了发生的UsageFault异常的具体类型。示例中,INVSTATE位被置位,表示指令在无效的CPU状态下执行。USGFAULTENA字段表示启用了UsageFault处理程序,否则异常将升级为HardFault。异常寄存器上下文的解释与特定体系结构相关,Ozone旨在通过异常描述显示尽可能多的处理信息,当程序执行停止并且目标处于异常状态时,会显示目标异常对话框。
向量捕获
当调试会话开始时,Ozone设置捕获所有Cortex-M故障向量,在程序进入错误处理程序时立即中断执行,也使Ozone能够在故障进入时立即弹出目标异常对话框。可以通过Ozone的Break&Tracepoints窗口设置或清除某个向量捕获。Ozone也提供命令Break.SetVectorCatch以编程方式设置目标的向量捕获状态。例如,该命令可以用来修改Ozone在调试会话开始时的默认vector catch 的行为,该命令在项目脚本函数OnProjectLoad中使用。
调试窗口
使用Ozone的调试窗口来进一步了解故障。
Call Stack窗口表示目标处于UsageFault异常状态。该窗口还指出故障源自函数_NoThumbFunc。在Call Stack窗口中选择_NoThumbFunc调用帧,Ozone的调用帧感知调试窗口将输出切换到所选帧的执行上下文。Local Data窗口表明在_NoThumbFunc函数中执行了一个到地址0的跳转,导致CPU在ARM状态下执行Thumb指令。查看Ozone的寄存器窗口,寄存器UFSR确认CPU已经发出INVSTATE UsageFault。这是Ozone基本故障分析工作流程。
嵌套的异常
Ozone可以提供关于Cortex-M上嵌套异常和嵌套故障的准确信息。为了演示这一点,让我们继续调试前一节的示例应用程序。我们现在用一条未定义的指令覆盖UsageFault处理程序的单个分支指令:
在跳过0x8000384地址的未定义指令后,Ozone的目标异常对话框再次弹出:
对话框通知抢占了UsageFault异常的为HardFault异常。除了寄存器字段INVSTATE之外,还设置了字段UNDEFINSTR。这表明在调用路径中发生了两种类型的UsageFault异常。HFSR寄存器字段FORCED进一步表明UNDEFINSTR异常已经升级为HardFault。
由于Cortex-M CPU现在正在处理嵌套异常,Ozone的Call Stack窗口相应更新:
在多个堆栈上嵌套异常
关于嵌套异常的信息可以占用两个堆栈,如下一个示例所示,在这种情况下,Ozone能够提供准确的调用堆栈和本地数据信息。本例中,程序执行已停止在调用堆栈5级的SVC指令上:
在执行SVC调用之后,在处理程序模式下执行了一个附加的函数调用路径。应用程序现在停止在load加载指令上,该指令即将从无效地址0x100000加载:
此时,Ozone的Call Stack窗口表明堆栈交换已经发生。从表列stack Used中堆栈使用值0的位置,用户可以看到:
上面的调用帧,包括SVC_Handler都在主栈上。
下面的调用帧,包括SVCall Exception)位于进程堆栈上。
当前使用了40字节的主堆栈和88字节的进程堆栈。
注意,Ozone用尖括号括起了特定于目标的调用帧。继续执行程序,看看Ozone是如何处理即将发生的故障。程序恢复执行后,立即弹出目标异常对话框,指示HardFault异常:
由于没有启用BusFault异常处理程序,Cortex-M将BusFault异常升级为HardFault。寄存器字段PRECISERR表示发生了精确的BusFault异常。字段BFARVALID表示错误的load/store指令的内存访问地址可用。Ozone将所有这些信息集成到目标异常对话框顶部区域中的异常描述中。字段SVCALLACT进一步表明,一个SVC处理程序已被当前异常抢占。
关闭目标异常对话框,使用Ozone的调试窗口进一步调查故障。
如上图所示,Ozone的调用帧感知调试窗口提供了故障的清晰图像:Local data窗口显示了解引用数据指针的无效值。Call Stack窗口显示完整的程序执行路径,跟踪多个嵌套异常和CPU堆栈。用户可以在register窗口中查询到相同信息。
使用Trace分析故障
在不精确的故障场景中,当Cortex-M内核无法提供故障指令的精确PC时,可以使用Ozone的trace窗口来快速识别故障指令,确定更复杂故障的原因,特别是不精确的故障。
如上图所示,使用Ozone的回溯特性,可以很容易地将不精确的BusFault异常追溯到出错的存储指令。
Ozone是一块面向嵌入式应用程序的调试器。使用Ozone,可以在C/ C++ /Rust源代码和汇编级别调试嵌入式应用。Ozone与J-Link和J-Trace紧密集成,提供丰富的调试分析功能。
全部0条评论
快来发表一下你的评论吧 !