Other Parts Discussed in Thread:SYSBIOS
Q: 我运行了程序,但它似乎处于“hang”状态。在CCS中暂停该程序时,我发现该程序在以下函数内陷入无限循环:
ti_sysbios_family_arm_m3_Hwi_excHandlerAsm__I()
如何找到原因?
A:
概述
这通常会在发生异常时看到。
SYS/BIOS(TI-RTOS)提供了多个目标唯一异常处理程序,它们将存储或打印出有关已检测到的异常的信息:
ti.sysbios.family.arm.exc.Exception – used by all Arm9 and A8 targets
ti.sysbios.family.arm.m3.Hwi – used by all cortex-M3 targets
ti.sysbios.family.c64p.Exception – used by all C6x targets
解码异常的方法取决于您使用的SYS/BIOS版本:
- 对于SYS/BIOS 6.35.02.45和兼容的较新版本,请参考使用Runtime Object View(ROV)解码CCS中异常的步骤。
- 对于6.32.00.28至6.35.01.29的SYS/BIOS版本,请参考使用Register View解码CCS中的异常转储的步骤。
使用Runtime Object View(ROV)解码CCS中异常
从SYS/BIOS版本6.35.02.45开始,异常模块提供了一个CallStack ROV异常视图。该视图可用于查看异常类型以及查找导致该异常的代码的信息。
先决条件
在使用ROV之前,至少必须安装CCS、XDCtools和SYS/BIOS。有关正确的版本信息,请参阅SYS/BIOS发布说明(release note)的“Compatibility Information”一节和/或SDK的文档。
有关使用ROV的更多信息,请参见https://training.ti.com/how-use-runtime-object-view。
使用ROV查看异常
1. 暂停应用程序并看到该程序遇到异常后,请使用“Tools”菜单打开ROV:
2. 点击“Connect” 将ROV连接到目标上。ROV随后将在左侧显示模块列表。
3. 点击“Hwi”模块以调出Hwi模块视图。
4. 从Hwi模块视图的下拉菜单中选择“Exception”。您应该看到以下内容:
5. 点击“Decoded exception”旁边的+号。这将显示发生的异常类型:
6. 解码的异常信息可提供有关导致异常的代码的线索。
7. 单击–符号以缩小“Decoded exception”视图
8. 单击“Exception call stack”旁边的+号。这将显示异常发生时调用堆栈的状态:
9. 调用堆栈信息或多或少会让您知道发生异常的代码点。通过分析所示行(及其上下文)的代码,您可能会找到问题源。
10. 尽管“Exception call stack”视图提供了发生异常时代码的位置以及相关代码的行号,但CCS调试器仍不会向您显示此相同信息。值得庆幸的是,ROV异常视图提供了更多信息,可用于将CCS调试器与所示的调用堆栈同步。
11. 点击“exception context”旁边的+号。这将显示有关发生异常时程序状态的一些信息,包括CPU寄存器的值。SP、LR和PC寄存器将用于帮助追溯到异常:
12. 用从“Exception context”视图中捕获到的SP、LR和PC寄存器的值,通过更新这些寄存器的值可使CCS调试器与ROV Exception context视图同步。。具体请参考下面的步骤。
13. 单击符号“–”以缩小“Exception context”视图
使用寄存器视图解码CCS中的异常转储
在SYS/BIOS 6.32.00.28至6.35.01.2版本中检测到异常时,异常处理程序会将完整的寄存器上下文转储输出到CCS控制台。输出将类似于以下内容:
ti.sysbios.family.arm.m3.Hwi: line 1095: E_hardFault: FORCED
ti.sysbios.family.arm.m3.Hwi: line 1172: E_busFault: PRECISERR: Immediate Bus Fault, exact addr known, address: ffffffff
Exception occurred in background thread at PC = 0x0001d750.
Core 0: Exception occurred in ThreadType_Task.
Task name: {unknown-instance-name}, handle: 0x20001d00.
Task stack base: 0x20001d60.
Task stack size: 0x800.
R0 = 0xffffffff R8 = 0xffffffff
R1 = 0xffffffff R9 = 0xffffffff
R2 = 0xffffffff R10 = 0xffffffff
R3 = 0xffffffff R11 = 0xffffffff
R4 = 0xffffffff R12 = 0x00000001
R5 = 0xffffffffSP(R13) = 0x20002390
R6 = 0xffffffffLR(R14) = 0x00010cf1
R7 = 0xffffffffPC(R15) = 0x0001d750
PSR = 0xffffffff
ICSR = 0xffffffff
MMFSR = 0x00
BFSR = 0x00
UFSR = 0x0000
HFSR = 0x00000000
DFSR = 0x0000000b
MMAR = 0xffffffff
BFAR = 0xffffffff
AFSR = 0x00000000
Terminating execution…
如果将PC、SP(和ARM的LR,C6X的B3)的异常转储值复制到CCS寄存器视图中的相应寄存器中,CCS通常将在调试窗口中提供非常有用的调用堆栈回溯追踪。
注意:一旦按照以下步骤更改了寄存器的值,就无法再运行应用程序。
1. 首先记录异常转储中显示的PC、SP(ARM的LR,C6X的B3)的寄存器值。
2. 从CCS的“View ”菜单中打开“Registers”窗口:
3. 一旦“Registers”窗口打开,请点击“Core Registers”旁边的+号以展开视图。您将看到CPU寄存器的列表,包括PC、SP和LR寄存器。
4. 使用ROV Exception context视图中显示的值更新“Registers”窗口的PC、SP和LR寄存器的值。(提示:从“ROV Exception context”视图复制寄存器值,并将其粘贴到“Registers”窗口中的相应字段中。)以下屏幕截图显示了更新后的Registers的值:
5. 更新PC、SP和LR寄存器后,将在CCS调试器中看到与ROV Exception相同的调用堆栈:
6. 花费一些时间来分析一下代码。请注意:在该常见问题解答的示例中,PC处于函数SlNetSock_init(),似乎没有任何明显迹象可能导致应用程序崩溃。毕竟,程序还没有进入函数!
7. 这种情况下,由于CPU已恢复到发生崩溃时的状态,因此有必要进行更深入的研究,这在CCS调试器中更容易实现。现在,您可通过单击堆栈中显示的函数名称向后移动。
8. 在此示例中,堆栈中的上一个位置是netIPAddrHook()。点击它后,调试器将跳回到调用SlNetSock_init()的位置:
9. 注意:在上述屏幕截图中,代码视图已更改为另一个文件,PC位于第81行(对SlNetSock_init()的调用)。现在让我们在此位置再检查一下代码…
10. 检查代码后,我们可看到在调用SlNetSock_init()之前,有一个NULL指针解引用。现在,我们使用了ROV和调试器向后追溯到导致异常的代码点。
Annie Liu:
我们建议您在发布新问题之前先搜索 E2E支持论坛,E2E支持论坛已经拥有数十万个已得到解答的话题。 这通常是解决问题的最快方法。