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] TMS570LC4357: Hercules 器件上的中止异常疑难解答

Part Number: TMS570LC4357

Hercules(TMS570 和 RM4x/RM5x)器件上发生的中止调试指南

  • 1 什么是异常?

    “异常”是一个事件,它使处理器暂时停止正常的程序执行流程,例如为来自外设的中断提供服务。在尝试处理异常之前,处理器会保留当前处理器状态的关键部分,以便在处理程序例程完成时原始程序能够恢复。

    在实际情况中,异常主要可以分为以下几类:

    • 中断(正常中断 IRQ 和快速中断 FIQ/NMI)
    • 中止(数据中止、预取中止)
    • 未定义指令 (UNDEF) 异常

    2 什么是异常优先级顺序?

    当多个异常同时发生时,系统会按照固定的优先级顺序来处理这些异常。系统依次处理每个异常,然后再继续执行用户程序。并非所有异常都会同时发生。例如,未定义指令和 SVC 异常是互斥的,因为它们都是通过执行指令触发的。

    由于数据中止异常的优先级高于 FIQ 异常,因此在处理 FIQ 之前实际上会注册数据中止。然后会进入数据中止处理程序,但随后会立即将控制权传递给 FIQ 处理程序。处理 FIQ 后,将控制权返回给数据中止处理程序。这意味着数据传输错误不会像在首先处理 FIQ 时那样无法被检测到。

    异常

    优先级

    复位

    1 (最高)

    数据中止

    2

    FIQ

    3

    IRQ

    4

    预取中止

    5

    SVC

    6

    未定义中止

    6(最低)

    在进入所有异常时禁用 IRQ。在进入 FIQ 和复位时禁用 FIQ。

    3 处理器对异常有何响应?

    发生异常时,ARM CPU:

    • 将 CPSR 复制到 SPSR_<模式> 中
    • 设置相应的 CPSR 位
      • 如果内核当前处于 Thumb 状态,则进入 ARM 状态
      • 模式字段位
      • 中断禁用位(如果适用)
    • 将返回地址存储在 LR_<模式> 中
    • 将 PC 设置为矢量地址

    4 中止(DABTPABT UNDEF)之间的差异

    如果从受保护或有故障的存储位置读取数据或向其中写入数据,则处理器会接收到数据中止异常。数据中止可以是同步的,也可以是异步的。

    导致数据中止的指令位于 R14_ABT – 8,这意味着指针指向导致中止的指令之后的两条指令。

    如果处理器尝试执行来自受保护或有故障的存储器位置的指令,则会接收到预取中止异常。所有预取中止都是同步的。

    导致数据中止的指令位于 R14_ABT – 4。lr_ABT 指向导致异常的指令的下一条指令。处理程序必须返回到 lr_ABT – 4

    当处理器遇到相应版本的 ARM 指令集中未定义的指令或者在 VFP 被禁用时用于 VFP 的指令时,处理器会接收到未定义指令异常。未定义指令异常可用于模拟未定义的指令,或仅用于处理故障情况。

    导致 UNDEF 中止的指令位于 R14_und – 4。

    5 预取中止和数据中止的返回地址为何不同?

    对于预取,返回地址为:R14_abt = 已中止指令的地址 + 4;对于数据中止,返回地址为:R14_abt = 已中止指令的地址 + 8。

    CPU 程序计数器 (PC) 会在执行期间的特定点更新。在提取/解码/执行的不同阶段都可能会发生异常。

    对于预取中止,只有当处理器实际尝试执行指令时才会发生此异常。在发出预取中止命令时不会更新程序计数器,lr_ABT 指向导致异常的指令的下一条指令。

    对于数据中止,指令正在执行并且指令的执行才导致出现此异常。当加载或存储指令尝试访问存储器时,程序计数器已更新。lr_ABT 中存储的值 (pc – 4) 指向生成异常的地址后的第二条指令。

    请参阅 ARM TRM 中的表 3-4。该表总结了进入异常时相关的 R14 中保存的 PC 值以及 ARM 建议的用于退出异常处理程序的指令。

    6 我如何知道存在中止?

    发生中止时,程序会在异常向量表处停止。如果在异常向量地址处设置了断点,程序计数器会在地址 0x0C (PABT)、0x10 (DABT) 或 0x04 (UNDEF) 处停止。

    有三个重要的 ARM Cortex-R4/R5 寄存器可用于确认处理器的当前状态:

    CPSRCPSR 可用于验证处理器的当前模式。CPSR 寄存器的模式位可用于检查当前模式是否为中止。

    M[4:0]

    模式

    10000

    用户

    10001

    FIQ

    10010

    IRQ

    10011

    管理

    10111

    中止

    11011

    未定义

    11111

    系统

    SPSRSPSR 可用于检查进入异常之前的模式。例如,如果处理器从系统模式转换至中止模式,则 SPSR 将模式显示为“系统”,而 CPSR 将模式显示为“中止”。SPSR 寄存器的位定义与 CPSR 寄存器的位定义相同。

    R14 寄存器:R14 寄存器用于查找导致同步中止的实际指令或函数调用。触发异常的指令的实际地址为 R14 - x,其中“x”取决于异常的类型。

    有关详细信息、请参阅 Cortex-R4/R5 TRM 中的表 3.4“异常进入和退出”:https://developer.arm.com/documentation/ddi0363/e/

    7 未定义指令异常 (UNDEF)

    如果 CPU 不理解提取的指令,则可能会发生未定义指令异常。

    该异常没有关联的故障状态和故障地址寄存器;只有连接寄存器 (R14_UND) 会提供相关信息。导致 UNDEF 中止的指令位于 R14_UND – 4。

    7.1 执行错误指令的可能原因

    • 分支到已损坏或尚未使用所需函数进行初始化的 RAM 代码
    • 堆栈上的返回地址已损坏(例如堆栈溢出或出栈/入栈计数不匹配)
    • 函数指针未初始化或损坏。

    7.2 处理未定义指令异常

    • 可以通过检查停止地址来确认 CPU 控制权是否滞留在未定义指令异常中。如果地址为 0x04,则未定义指令异常中的控制权已结束。
    • 检查 R14_UND 寄存器的值。R14_UND X 提供导致未定义指令异常的指令的地址。“X”取决于模式(对于 ARM 模式,X = 4;对于 Thumb 模式,X = 2)。
    • 检查从 R14_UND - X 读取的地址处的指令。

    a 如果该指令有效,则检查用于执行的模式(ARM THUMB)是否正确(有效指令的模式不匹配可能会导致未定义指令异常)。

    b 如果指令无效,则检查地址或 RAM 是否损坏。

    7.3 示例:

    如果 VFP 未启用,则在执行浮点运算时处理器会接收到未定义指令异常。CPSR[4:0] = b11011

    导致 UNDEF 异常的指令是位于 0x00007430 vldr s0, [r13, 0xc]

    r14_UND = 0x00007434。进入 UNDEF 中止前的模式为 SPSR_UND[4:0] = b11111(系统模式)。

    8 数据中止异常 (DABT)

    数据中止异常是对无效数据访问的响应。如果异常被确认为数据中止,则第一步应检查 Cortex-R CPU 的数据故障状态寄存器 (DFSR) 的值。

    DFSR 寄存器下图显示了 DFSR 寄存器位分配:

    通过“S”位 [10] 和“状态位”[0:3] 来了解数据中止的本质。有关状态说明,请参阅下表:

    SD

    SD 位用于区分发生外部中止时的 AXI 解码和从器件错误。该位仅对外部中止有效。对于所有其他类型的中止,该位被设置为零:

    0 = AXI 解码错误 (DECERR) AHB 错误导致了中止

    1 = AXI 从器件错误 (SLVERR) 或不支持的独占访问导致了中止。示例:使用 AHB 外设端口的独占访问

    RW

    RW 位指示是读取访问还是写入访问导致了中止。

    0 = 读取访问导致了中止

    1 = 写入访问导致了中止

    9 常见的数据中止类型

    9.1 后台:  对于 CPU 要访问的任何区域,存储器保护单元 (MPU) 设置必须正确。如果 CPU 发出的地址不处于定义的任何区域之内并且 MPU 被启用,则 MPU 被硬接线以中止访问。也就是说,对未映射到 MPU 中某个区域的地址的所有访问都会产生一个后台故障。

    如果后台区域被启用并且访问权限为特权,则不会发生后台故障。MPU

    后台故障可能表明堆栈溢出,可以通过分配更多堆栈进行纠正。

    9.2 权限:当 MPU 设置阻止区域访问时,可能会发生这种情况。例如,如果模式为用户的应用尝试访问仅限特权模式访问的区域,则会发生权限错误。

    示例:

    下面显示的写入操作触发了中止。0x08028008 处的存储器位置的 MPU 设置为只读。

    如下图所示,DFAR 寄存器显示触发数据中止的地址,因为它是 BTCM(使用 ADFSR 进行验证)处的权限错误(使用 DFSR 进行验证)。R14_abt 8 (0x000070E0) 指向导致该访问的指令。它显示了一个 STR 操作。

    无法从具有器件或严格排序存储器类型属性的区域执行指令。

    9.3 同步/异步外部中止:当访问已从 CPU 转移到 AXI/AHB 总线并遇到错误时,会发生此类数据中止。这是出现数据中止时的常见故障类型。如果中止是同步的,则可以使用数据故障地址寄存器 (DFAR) 检查访问时导致数据中止的实际存储器地址,DFAR 保存发生同步中止时的故障地址。

    9.4 同步/异步 ECC:如果在 TCM 接口处或高速缓存中检测到 ECC 错误,则会发生此类数据中止。

    10 数据中止异常示例

    10.1 同步中止异常

    一般而言,导致错误的从区域进行“加载”的指令或向存储器进行“存储”的指令是同步的。DFAR 显示了访问的目标地址。此外,如上一节所述,R14_abt 8 指向导致该访问的指令。

    示例 1:从具有 2 ECC 错误的存储器位置加载数据

    下面显示的读取操作触发了中止。0x08000010 处的数据具有 2 ECC 错误。

    如上图所示,DFAR 寄存器显示触发数据中止的地址,因为它是 BTCM(使用 ADFSR 进行验证)处的同步 ECC 错误(使用 DFSR 进行验证)。R14_abt 8 (0x00001F7C) 指向导致该访问的指令。它显示了一个 LDM 操作。

    示例 2:将数据写入未实现的存储器位置

    下面显示的写入操作触发了中止。地址 0x08100018 超出了有效存储器范围。

    如上图所示,DFAR 寄存器显示触发数据中止的地址,因为它是同步中止(使用 DFSR 进行验证)。R14_abt 8 (0x000070CC) 指向导致该访问的指令。它显示了一个 STR 操作。

    图:数据中止发生之前

    图:数据中止发生之后

    10.2 异步故障

    异步故障很难分析,因为我们无法跟踪导致中止的确切位置。我们无法使用同步故障中使用的 DFAR 寄存器。一般而言,向具有“正常”或“器件”存储器属性的区域进行“存储”(从而导致错误)的指令是同步的。

    通过 DFSR 寄存器,我们可以检查状态位、SD 位和 RW 位。SD:内部 AXI 解码错误或外部 AXI 从器件错误 RW:指示是读取访问还是写入访问导致了中止。有关详细信息,请阅读上面的第 8 节。

    10.3 如何跟踪导致异步数据中止的指令

    • R14_abt 8 是导致异常的指令附近的位置。
    • 找到 R14_abt 8 附近的一个“存储”指令,该指令可能会导致异常。

    11 由于 MPU 问题而导致的数据中止

    您应该为应用中访问的区域定义有效的 MPU 设置,以便 CPU 能够相应地访问该区域。如果您未定义所用区域的 MPU,该 MPU 可能会导致后台故障数据中止异常,具体取决于使用的是特权访问还是非特权访问:

    11.1 对于特权访问:

    如果 BR 位(SCTLR Arm 寄存器的第 17 位)被置位,则默认存储器映射将用作任何未命中指定区域的访问的后台区域;如果 BR 位为 0,则对于指定区域之外的任何访问都将发生后台故障异常。

    11.2 对于非特权访问:

    对于指定 MPU 区域之外的任何访问,都会发生后台故障异常。为了防止针对此类访问发生后台故障异常,请将区域 0 定义为涵盖整个存储器映射的后台区域,然后将其用作定义的 MPU 以外区域的后台区域。

    12 预取中止异常

    在指令提取导致错误时会发生预取中止 (PABT) 异常。当发生预取中止时,处理器将预取指令标记为无效,但在要执行指令之前不会接收到异常。如果未执行指令,例如因为指令在流水线中时产生分支,则不会发生中止。所有预取中止都是同步的。

    未定义指令中止异常和预取中止异常的区别在于:对于预取,CPU 无法从地址中提取指令;对于未定义指令异常,CPU 不知道指令的功能是什么。

    可以通过读取指令故障状态寄存器 (IFSR)、指令故障地址寄存器 (IFAR) 和辅助指令故障状态寄存器 (AIFSR) 来分析预取中止的原因。

    IFAR 包含 CPU 尝试从中提取指令的地址。IFAR 的内容对于预取中止始终有效,因为所有预取中止都是同步的。

    AIFSR 记录有关故障性质和位置的附加信息,例如 ATCM(闪存)或 BTCM (SRAM)

    12.1 预取中止的可能原因

    • MPU 设置不正确:如果基于 IFSR 状态发生了权限故障,则可能发生了以下情况之一:
      1. 正在从设置了“禁止执行”属性的位置提取指令。
      2. IFAR 读取的目标地址具有“器件”或“严格排序”存储器属性。这意味着这些区域没有可执行代码。
    • 读取指令时出现 ECC 错误:

    读取指令时检测到 ECC 错误。IFAR 寄存器提供导致检测到错误的地址。辅助 IFSR 指示 ECC 错误的来源。

    • 返回地址或分支地址错误 - 返回地址损坏 - 分支地址损坏

    12.2 处理预取中止异常

    • 可以通过检查停止地址来确认 CPU 控制权是否滞留在预取中止异常中。如果偏移量为 0x0C,则表示预取中止中的控制权已结束。
    • 检查 IFSR IFAR 中的状态,以确定故障类型和导致中止的地址。

    对于“权限”故障,请找到从 IFAR 寄存器读取的地址所在的区域。可以检查该区域中是否存在针对代码区域的 MPU 违规情况。(禁止执行设置、器件、严格排序存储器)

    12.3 预取中止异常示例

    示例 1

    以下示例演示了调试预取中止的步骤。在这里,CPU 执行滞留在预取中止处理程序中。相关的寄存器值如下所示:

    SPSR_Abt0x8000011F模式 (11111) 系统模式。这意味着当中止被触发时,CPU 处于系统模式。

    IFSR0x0000000D该状态指示权限中止。在 IFAR 中捕获的地址是有效的,是导致中止的实际地址。

    IFAR0x0013F800该地址位于具有严格排序属性的 MPU 区域下。

    示例 2

    示例 2 的相关寄存器值如下所示:

    SPSR_Abt0x600001D1模式 (10001) FIQ 模式。这意味着当中止被触发时,CPU 处于 FIQ 模式。

    IFSR0x00000409该状态指示同步外部中止或 ECC 中止。在 IFAR 中捕获的地址是有效的,是导致中止的实际地址。

    IFAR0x00009000该地址不包含有效指令,并且具有错误的 ECC 值。

    AIFSR0x00400000该状态表示错误源来自 ATCM(闪存)。