This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] 如何追踪导致TI-RTOS应用程序异常的代码?

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 = 0xffffffff SP(R13) = 0x20002390

R6 = 0xffffffff LR(R14) = 0x00010cf1

R7 = 0xffffffff PC(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和调试器向后追溯到导致异常的代码点。