1. ARM ETM调试架构:从硬件探针到精准事件捕获
在嵌入式系统开发,尤其是涉及复杂实时任务、多核交互或难以复现的偶发性故障时,传统的断点调试和日志打印往往力不从心。它们要么侵入性太强,改变了程序的时间特性;要么信息量不足,无法还原故障瞬间完整的执行上下文。这时,硬件辅助的指令跟踪技术就成了我们手中的“显微镜”。ARM CoreSight架构下的嵌入式跟踪宏单元,正是这样一套强大而精密的片上调试系统。它不像软件调试器那样需要暂停CPU,而是通过专用的硬件电路,在处理器全速运行的同时,非侵入式地捕获每一条执行指令的地址流,甚至包括数据访问、周期计数等丰富信息。
但问题来了:处理器每秒钟执行数十亿条指令,产生的原始跟踪数据是海量的,直接记录和传输既不现实,也无必要。我们真正关心的,可能只是某个特定函数内部的执行情况,或者某次异常的数据访问。这就引出了ETM设计的精髓:事件触发与过滤。ETM内部集成了多种可编程的“哨兵”,比如地址比较器、计数器、状态机(序列器),我们可以将它们组合起来,定义复杂的触发条件。只有当预设的条件被满足时,ETM才开始或停止记录跟踪数据,或者标记数据流中的特定点。而配置这些“哨兵”如何工作、如何组合的关键,就在于一系列的控制寄存器。
今天,我们就以德州仪器AM62L Sitara处理器中的ARM CoreSight ETMv4.x实现为例,深入剖析其中两个核心的配置寄存器:资源选择控制寄存器和单次触发控制寄存器。理解它们,你就能从“会打开跟踪”进阶到“能精准捕获想要的事件”。这对于进行性能热点分析、死锁排查、中断响应延迟测量等高级调试任务至关重要。无论你是嵌入式软件工程师、系统架构师,还是驱动开发者,掌握这些寄存器的配置逻辑,都能让你在解决深层次系统问题时,拥有外科手术般精准的工具。
2. 核心概念解析:资源、选择器与单次触发
在深入寄存器位域之前,我们必须先建立几个核心概念模型。ETM的触发逻辑可以被看作一个可编程的逻辑电路,其输入是各种内部“资源”的状态,输出是控制跟踪行为(如启停、触发标记)的信号。
2.1 什么是“资源”?
在ETM的语境下,资源指的是能够产生布尔(真/假)状态信号的内部硬件单元。它们是构成触发条件的基本元素。AM62L ETM提供的典型资源包括:
- 地址比较器:包括单地址比较器和地址范围比较器。当CPU的程序计数器或数据访问地址与预设值匹配(或在预设范围内)时,该资源输出为“真”。
- 计数器:ETM内置了几个计数器,可以统计诸如指令执行数、周期数或其他事件的发生次数。当计数值达到预设阈值(例如减到零)时,产生“真”信号。
- 序列器:一个简单的有限状态机,可以根据资源输入在几个状态间跳转。特定状态(如状态1)可以作为资源输出。
- 外部输入:来自芯片其他部分或外部引脚的事件信号,可以作为触发输入。
- 上下文ID比较器:当进程的上下文ID(如ASID)与预设值匹配时触发。
- 虚拟机ID比较器:在虚拟化环境中,当VMID匹配时触发。
- 处理器事件:来自CPU内核的特定微架构事件,如异常入口、分支误预测等。
2.2 资源选择控制寄存器的作用
单个资源的状态可能不足以描述一个复杂的触发场景。例如,我们想捕获“当CPU进入函数X(),并且此时计数器C已经溢出”这一事件。这就需要将多个资源的输出进行逻辑组合。
资源选择控制寄存器就是用来完成“选择”和“初步逻辑处理”的配置单元。一个ETM通常有多个这样的寄存器(例如TRCRSCTLR0到TRCRSCTLR15),每个寄存器可以配置一个“资源选择器”。它的核心工作流程是:
- 选择资源组:通过
GROUP字段,决定从上述哪一大类资源中进行选择(例如,选择“单地址比较器”这个组)。 - 选择组内具体资源:通过
SELECT字段(一个位图),从选定的组中挑选一个或多个具体的资源(例如,选择组内的比较器0和比较器3)。 - 逻辑运算:对选中的一个或多个资源输出进行逻辑“或”操作。如果
SELECT中设置了多个位,则这些被选中的资源中,任何一个输出为真,该选择器的输出即为真。 - 逻辑取反:通过
INV位,可以将上述“或”运算的结果取反。这对于实现“当不在某地址时触发”这类条件非常有用。 - 配对与取反:对于某些成对使用的资源(如地址范围比较器通常是两个一组,分别表示上下界),
PAIRINV位(仅在偶数编号的选择器中有效)用于控制配对资源组合后的输出是否取反。
一个资源选择器的最终输出,就是一个布尔信号,我们称之为一个“选择器事件”。这个事件可以作为其他更高级逻辑(如序列器、计数器使能、最终触发)的输入。
2.3 单次触发控制寄存器的意义
有些调试场景需要“一次性”的触发。例如,我们只想在系统启动后,第一次调用某个关键函数时进行跟踪,后续的调用则忽略。或者,我们想用一次触发事件来复位一个计数器,开始新的计数周期。这就是单次触发功能的应用场景。
单次触发控制寄存器管理着一组特殊的资源——单次触发比较器。它的核心思想是“触发即锁存”。一旦配置好的条件被满足,单次触发比较器就会“点火”,并产生一个持续的触发状态。这个状态会一直保持,直到被软件显式清除。在此期间,即使原始条件再次满足,也不会产生新的触发事件。
这个寄存器主要配置两件事:
- 关联哪些比较器:通过
SAC和ARC字段,将特定的单地址比较器或地址范围比较器“绑定”到某个单次触发控制资源上。当这些被绑定的比较器匹配时,会触发单次触发事件。 - 触发后行为:通过
RST位控制,当单次触发事件发生后,是否自动复位关联的比较器。如果设置为自动复位,那么该单次触发资源可以再次被触发,否则它将保持“已触发”状态,直到软件干预。
单次触发状态寄存器则用于查询单次触发资源当前的状态(是否已触发),并查看硬件支持的比较器类型(指令地址、数据地址、数据值)。
2.4 寄存器访问基础:OS Lock与电源管理
在配置这些功能强大的调试寄存器之前,必须确保我们能安全地访问它们。ETM提供了两重保护机制:
OS锁:这是一个软件锁,用于防止非调试状态下的意外修改。寄存器
TRCOSLAR是锁访问寄存器,向其最低位写入0xC5ACCE55这个“密钥”值可以解锁,写入其他值则上锁。TRCOSLSR是锁状态寄存器,可以查询当前锁定状态。在尝试配置任何ETM功能寄存器前,必须先解锁OS锁。电源域控制:为了节能,ETM可能位于一个独立的、可关断的电源域中。
TRCPDCR是功耗控制寄存器,向其PU位写1可以请求给ETM上电。TRCPDSR是功耗状态寄存器,其中的POWER位指示当前是否已上电,STICKYPD位则指示寄存器状态是否因掉电而失效。如果POWER位为0或STICKYPD位为1,必须先通过TRCPDCR上电,并可能需要重新初始化寄存器。
注意:在实际操作中,调试器(如Lauterbach Trace32, DS-5/DS, OpenOCD)通常会帮你处理这些底层解锁和上电序列。但理解其原理,对于编写底层初始化代码或排查“为什么寄存器写不进去”的问题至关重要。
3. 寄存器详解与配置实战
理解了核心概念后,我们结合AM62L TRM中的寄存器定义,进行逐位解析,并给出具体的配置示例和代码片段。
3.1 资源选择控制寄存器详解
以COMPUTE_CLUSTER_ARM_COREPACK_0_APBADDR_ETM_CPU0_TRCRSCTLR15为例,其偏移地址为0x23C。
寄存器位域布局:
| 位域 | 名称 | 类型 | 复位值 | 描述 |
|---|---|---|---|---|
| 31:22 | RES0 | R/W | 0x0 | 保留,必须写0。 |
| 21 | PAIRINV | R/W | 0x0 | 配对取反控制。仅当本寄存器编号n为偶数时有效。0:不取反;1:将配对资源的组合结果取反。 |
| 20 | INV | R/W | 0x0 | 取反控制。0:不取反;1:将GROUP和SELECT选中的资源输出取反。 |
| 19:16 | GROUP | R/W | 0x0 | 资源组选择。选择一大类资源。 |
| 15:0 | SELECT | R/W | 0x0 | 资源选择位图。在GROUP选定的组内,选择具体的一个或多个资源。位[n]对应组内的资源n。 |
GROUP字段编码详解:这是配置的核心,它定义了SELECT位图所选择的资源池。
0000:选择外部输入选择器0-3。SELECT[3:0]分别对应外部输入0-3,高位保留。0001:选择处理器比较器输入0-7。SELECT[7:0]分别对应来自CPU核心的8个事件输入,高位保留。0010:选择计数器归零事件0-3和序列器状态0-3。SELECT[3:0]对应计数器0-3归零事件;SELECT[7:4]对应序列器状态0-3,高位保留。0011:选择单次触发比较器控制0-7。SELECT[7:0]对应单次触发资源0-7,高位保留。0100:选择单地址比较器0-15。SELECT[15:0]对应全部16个单地址比较器。0101:选择地址范围比较器0-7。SELECT[7:0]对应全部8个地址范围比较器,高位保留。0110:选择上下文ID比较器0-7。SELECT[7:0]对应全部8个上下文ID比较器,高位保留。0111:选择虚拟机ID比较器0-7。SELECT[7:0]对应全部8个VMID比较器,高位保留。- 其他值:保留。
配置示例1:选择“函数A入口或函数B入口”作为事件假设函数func_a的地址为0x80001000,配置在单地址比较器0;函数func_b地址为0x80002000,配置在单地址比较器1。我们想在任何一处入口都触发一个事件。
- 首先,需要正确配置单地址比较器0和1的数值寄存器(
TRCACVR0/1)和控制寄存器(TRCACTRLR0/1,设置使能和匹配类型,例如精确匹配)。 - 然后,配置一个资源选择器(例如
TRCRSCTLR0):GROUP = 0x4(选择单地址比较器组)SELECT = 0x0003(位0和位1置1,选择比较器0和1)INV = 0(不取反)PAIRINV忽略(因为n=0是偶数,但这里不涉及配对资源)。
- 此时,
TRCRSCTLR0选择器的输出,在CPU执行到0x80001000或0x80002000时,会变为真。
配置示例2:选择“当计数器1非零时”作为事件ETM的计数器在未达到零时,其“计数器归零”资源输出为假。我们想要“计数器非零”这个条件,就需要取反。
- 假设计数器1被配置为递减某个事件。
- 配置资源选择器(例如
TRCRSCTLR1):GROUP = 0x2(选择计数器归零/序列器状态组)SELECT = 0x0002(位1置1,选择计数器1的归零事件)INV = 1(取反!这样当计数器1未归零时,输出为真)
- 这个选择器的输出,就可以用来作为“当计数器1正在计数时”的条件。
3.2 单次触发控制与状态寄存器详解
单次触发涉及三个寄存器:控制寄存器TRCSSCCR0、状态寄存器TRCSSCSR0,以及之前提到的、在资源选择器中引用单次触发资源的GROUP=0x3。
3.2.1 单次触发控制寄存器以TRCSSCCR0(偏移0x280)为例:
| 位域 | 名称 | 类型 | 复位值 | 描述 |
|---|---|---|---|---|
| 31:25 | RES0 | R/W | 0x0 | 保留。 |
| 24 | RST | R/W | 0x0 | 复位控制。0:单次触发资源触发后不自动复位;1:触发后自动复位,允许再次触发。 |
| 23:16 | ARC | R/W | 0x0 | 地址范围比较器选择。位[n]对应地址范围比较器对n。1表示选择该对用于单次触发控制。实际位数由TRCIDR4.NUMACPAIRS决定。 |
| 15:0 | SAC | R/W | 0x0 | 单地址比较器选择。位[n]对应单地址比较器n。1表示选择该比较器用于单次触发控制。实际位数由2 * TRCIDR4.NUMACPAIRS决定。 |
关键点:
ARC和SAC是位图,可以同时选择多个比较器。只要其中任何一个被选中的比较器发生匹配,就会触发该单次触发资源(例如资源0)。RST位决定了触发行为是“一次性”还是“可重复”。设为0时,触发后状态锁存,直到软件清除TRCSSCSR0.STATUS位;设为1时,触发后硬件自动清除状态,可以立即响应下一次匹配。
3.2.2 单次触发状态寄存器TRCSSCSR0(偏移0x2A0):
| 位域 | 名称 | 类型 | 复位值 | 描述 |
|---|---|---|---|---|
| 31 | STATUS | R/W | 0x0 | 单次触发状态位。0:无匹配发生;1:已发生匹配。如果RST=0,此位需软件写0清除才能再次触发。 |
| 30:3 | RES0 | R/W | 0x0 | 保留。 |
| 2 | DV | RO | 0x0 | 支持数据值比较。1表示支持。 |
| 1 | DA | RO | 0x0 | 支持数据地址比较。1表示支持。 |
| 0 | INST | RO | 0x1 | 支持指令地址比较。AM62L ETM复位后此位为1,表示支持。 |
STATUS位的特殊性:它是一个可写的状态位。在初始化配置单次触发功能时,必须先将其写为0,以确保从一个已知的未触发状态开始。即使你希望它立即触发,也需要先写0,再使能比较器。
配置示例:捕获函数首次调用目标:只在系统启动后,第一次进入函数critical_init()时触发跟踪。
- 配置地址比较器:假设使用单地址比较器0,将其值设置为
critical_init的入口地址,并使其能。 - 配置单次触发控制:
- 向
TRCSSCCR0写入:SAC = (1 << 0)(选择比较器0),RST = 0(不自动复位)。 - 向
TRCSSCSR0写入:STATUS = 0(清除状态,确保初始未触发)。
- 向
- 在触发逻辑中使用单次触发事件:
- 配置一个资源选择器(例如
TRCRSCTLR2):GROUP = 0x3(单次触发组),SELECT = (1 << 0)(选择单次触发资源0)。 - 将这个选择器(
TRCRSCTLR2的输出)连接到ETM的全局“触发启动跟踪”输入(这通常通过另一个寄存器TRCEVENTCTL或TRCVICTL来配置)。
- 配置一个资源选择器(例如
- 运行结果:当CPU第一次执行到
critical_init时,单地址比较器0匹配,触发单次触发资源0。TRCSSCSR0.STATUS变为1。TRCRSCTLR2输出为真,启动跟踪。此后,即使函数被再次调用,因为单次触发状态已锁存且未复位,TRCRSCTLR2输出保持为真(或取决于具体逻辑),但不会产生新的“启动跟踪”边沿事件(除非逻辑配置为电平触发),或者由于单次触发资源输出已为高,无法再次���生上升沿触发。这就实现了“首次调用捕获”。
3.3 地址比较器值寄存器
这是配置触发条件的基础。TRCACVR0_31_0和TRCACVR0_63_32共同组成一个64位的地址比较器0的值寄存器。AM62L作为64位ARM处理器,地址比较器支持64位宽。当处理器运行在AArch32(32位)状态时,硬件会自动忽略高32位,因此软件通常只需要配置低32位即可。
配置注意事项:
- 对齐:指令地址比较通常需要考虑指令对齐(ARM/Thumb状态)。
- 范围比较:地址范围比较需要一对地址比较器(如
ACVR0和ACVR1)来分别设置下界和上界,并在对应的地址比较器控制寄存器(TRCACATLRn)中配置为范围模式。 - 虚拟地址与物理地址:ETM比较的是处理器发出的虚拟地址。在使能MMU的系统中,这通常是虚拟地址(Virtual Address, VA)。如果需要基于物理地址触发,需要确保MMU映射关系明确,或者使用某些处理器提供的物理地址比较功能(如果支持)。
4. 完整配置流程与实战技巧
理论最终要服务于实践。下面我们勾勒一个完整的配置流程,并分享一些从调试中总结出的“坑点”。
4.1 一个典型的ETM触发配置流程
假设我们要在AM62L上设置一个复杂触发条件:当进程A(上下文ID=0x100)第一次调用函数process_data(),并且此时ETM内置计数器0的计数值大于5时,开始跟踪,并在跟踪满1000条指令后停止。
这个条件涉及:上下文ID、单次触发、计数器、地址匹配。
步骤1:前期准备与解锁
// 伪代码,假设已定义寄存器基址 ETM_BASE volatile uint32_t *etm_reg = (uint32_t*)ETM_BASE; // 1. 检查并请求ETM电源域上电 if ((etm_reg[TRCPDSR/4] & POWER_MASK) == 0) { etm_reg[TRCPDCR/4] |= PU_MASK; // 请求上电 while ((etm_reg[TRCPDSR/4] & POWER_MASK) == 0); // 等待上电完成 } // 2. 解锁OS Lock etm_reg[TRCOSLAR/4] = 0xC5ACCE55; // 写入解锁密钥 while (etm_reg[TRCOSLSR/4] & LOCKED_MASK); // 确认已解锁步骤2:配置基础资源
- 配置上下文ID比较器0:将
TRCCIDCVR0设置为0x100,并在TRCCIDCTLR0中使能匹配。 - 配置单地址比较器0:将
TRCACVR0设置为process_data的函数地址,并在TRCACTRLR0中配置为指令地址精确匹配、使能。 - 配置计数器0:在
TRCCNTRLDVR0中设置重载值(例如6,因为计数器减到0触发,>5即计数从6减到0),在TRCCNTCTLR0中配置事件源(如每指令递减)和使能。
步骤3:构建中间事件(使用资源选择器)
- 选择器A(上下文ID匹配):配置
TRCRSCTLR0:GROUP=0x6(CID),SELECT=0x01。 - 选择器B(函数地址匹配):配置
TRCRSCTLR1:GROUP=0x4(单地址),SELECT=0x01。 - 选择器C(计数器0未归零):配置
TRCRSCTLR2:GROUP=0x2(计数器),SELECT=0x01,INV=1。
步骤4:配置单次触发
- 配置单次触发控制:我们希望“第一次调用”时触发。将单地址比较器0关联到单次触发资源0。
etm_reg[TRCSSCCR0/4] = (0 << 24) | (0x0001); // RST=0, SAC[0]=1 etm_reg[TRCSSCSR0/4] &= ~(1<<31); // 清除STATUS位 - 选择器D(单次触发事件):配置
TRCRSCTLR3:GROUP=0x3,SELECT=0x01。
步骤5:构建最终触发条件(使用序列器)ETM的序列器是一个两状态(或更多)机,可以用来描述“与”、“或”、“顺序”逻辑。假设我们使用序列器0。
- 初始状态(STATE0):等待“上下文ID匹配”且“函数地址匹配”且“计数器>5”。这可以通过将选择器A、B、C的输出进行逻辑“与”来实现。ETM通常有专门的“资源组合”寄存器(如
TRCRSCTLR的复杂模式或TRCEVENTCTL)来定义“与”逻辑。假设我们配置了一个“与”事件E1 = (A & B & C)。 - 配置序列器:当在STATE0且事件E1发生时,跳转到STATE1。在STATE1,我们让序列器输出为真(作为资源)。
- 将单次触发与序列器输出“与”:最终的触发条件是“单次触发有效”且“序列器处于STATE1”。再配置一个“与”事件E2 = (D & SeqState1)。
- 将E2连接到跟踪启动:通过
TRCTRACEENCTLR或TRCPRGCTLR等寄存器,将事件E2映射为“跟踪使能”信号。
步骤6:配置跟踪停止条件
- 配置另一个计数器(如计数器1)为指令计数,重载值1000,模式为“跟踪使能时计数”。
- 配置计数器1归零事件连接到跟踪停止事件。
步骤7:启动跟踪
- 使能ETM跟踪生成 (
TRCPRGCTLR)。 - 使能Trace Port(如果使用TPIU输出)。
4.2 调试心得与避坑指南
顺序很重要:配置ETM时,建议遵循“先基础,后逻辑”的顺序。先配置好所有比较器、计数器的值,再配置资源选择器,最后配置序列器和全局控制。在使能任何功能前,确保单次触发状态寄存器等状态位已被正确初始化(通常写0)。
理解“触发”与“使能”:ETM的“触发”是一个事件,通常是一个信号的边沿(如从0到1)。而“跟踪使能”是一个状态。你需要将触发事件连接到控制“跟踪使能状态”的开关上。单次触发资源的输出是一个电平,从0跳变到1的瞬间是触发事件,之后维持高电平。如果你用这个电平直接去控制“跟踪使能”,那么触发后跟踪会一直进行。通常我们需要的是触发事件的边沿。
善用序列器实现复杂逻辑:资源选择器主要实现“或”和“取反”。对于“与”逻辑和简单的状态顺序,必须依赖序列器。把序列器理解为一个双状态触发器,能极大地扩展触发条件的表达能力。
地址对齐与指令集状态:ARM处理器有ARM、Thumb、ThumbEE等多种指令集状态,指令地址的最低位可能有特殊含义。在设置指令地址比较器时,要确保地址值与当前处理器状态匹配(例如,Thumb指令地址通常是2字节对齐,最低位可能被硬件忽略或用于状态指示)。最稳妥的方式是使用调试器反汇编获取准确的指令地址。
性能计数器作为资源:ETM内部的计数器功能有限。对于更复杂的性能事件触发(如缓存未命中次数),需要利用处理器核心的性能监视单元产生的事件,通过“处理器比较器输入”(
GROUP=0x1)连接到ETM。这需要查阅具体的CPU核心手册(如Cortex-A系列PMU事件列表)。验证配置:在复杂配置后,不要急于运行全系统。可以先用一个简单的、已知的条件(如某个绝对地址)测试触发是否工作,再逐步增加复杂度。利用ETM的触发输出引脚(如果芯片引出)连接逻辑分析仪,可以直观地观察触发信号,是验证硬件配置的最直接手段。
AM62L特定提示:AM62L文档中
TRCIDR4.NUMACPAIRS指明了实现的地址比较器对数。在配置TRCSSCCR0.ARC/SAC位宽时,需要参考这个值。未实现的位是RAZ/WI(读为0,写忽略),所以按最大位宽写全1也是安全的,但最好根据实际数量配置,提高代码可移植性。
5. 高级应用场景与问题排查
掌握了基本配置后,我们可以探索一些更高级的应用场景,并看看当触发不工作时该如何排查。
5.1 高级应用场景
场景一:时间窗跟踪目标:只跟踪某个函数调用后的最初N个时钟周期内的执行流。实现:
- 配置一个计数器为时钟周期递减模式。
- 用函数地址匹配事件作为“启动计数器”和“启动跟踪”的触发条件。
- 将计数器归零事件作为“停止跟踪”的条件。
- 通过序列器确保逻辑顺序:触发→启动跟踪并启动计数器→计��器归零→停止跟踪。
场景二:数据访问断点目标:当某个特定变量(位于已知地址)被写入特定值时,触发跟踪。实现:
- 这需要ETM支持数据地址和数据值比较(查看
TRCSSCSR0.DA和.DV位)。 - 配置一个数据地址比较器指向变量地址。
- 配置一个数据值比较器指向期望的值。
- 配置一个资源选择器,将上述两个比较器的输出进行逻辑“与”(可能需要通过序列器实现)。
- 将此“与”事件作为触发条件。
场景三:多核交互跟踪目标:跟踪CPU0在向一个共享缓冲区写入数据后,CPU1从该缓冲区读取数据的过程。实现:
- 在每个核心的ETM上独立配置。
- CPU0 ETM:配置数据地址比较器(写操作)作为触发,触发后记录一段跟踪。
- CPU1 ETM:配置数据地址比较器(读操作)作为触发。
- 使用CoreSight的交叉触发接口:将CPU0的触发事件通过CTI(交叉触发接口)发送给CPU1的ETM,作为其启动跟踪的条件之一。这样就能将两个核的事件关联起来。
5.2 常见问题排查清单
当你的ETM触发配置没有按预期工作时,可以按照以下清单逐步排查:
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 完全无跟踪数据输出 | 1. ETM未上电或未解锁。 2. Trace Port或Funnel未配置。 3. 全局跟踪未使能。 | 1. 检查TRCPDSR.POWER和TRCOSLSR.LOCKED。2. 检查TPIU/ETF的配置寄存器,确认时钟和模式正确。 3. 检查 TRCPRGCTLR或TRCTRACEENCTLR,确认跟踪生成已使能。 |
| 有跟踪数据,但从未触发 | 1. 触发条件太复杂,从未满足。 2. 资源选择器 GROUP或SELECT配置错误。3. 地址比较器值或控制寄存器配置错误(如未使能)。 4. 单次触发 STATUS位未初始化。 | 1. 简化触发条件,例如先用一个确定的地址测试。 2. 仔细核对 GROUP编码和SELECT位图。用调试器读取寄存器确认写入值。3. 确认 TRCACTRLR中的EN位已设置,匹配类型正确。4. 确认在使能前已向 TRCSSCSR.STATUS写0。 |
| 触发过于频繁或一直触发 | 1. 触发条件配置成了电平有效而非边沿有效。 2. 资源选择器 INV位配置反了。3. 单次触发 RST=1导致重复触发。 | 1. 检查触发事件是如何连接到跟踪使能的。确保使用的是边沿(从0到1的变化)。 2. 检查 INV和PAIRINV设置。3. 检查 TRCSSCCR.RST位,如果希望单次触发,应设为0。 |
| 触发点偏移几条指令 | 1. ETM的流水线深度导致触发延迟。 2. 指令预取导致地址比较在指令提交前发生。 | 1. 这是硬件特性,ETM触发到实际记录指令之间存在几个周期的延迟。需要在分析跟踪数据时考虑这个偏移量。查阅芯片勘误表或ETM技术参考手册了解具体延迟。 2. 确保地址比较器配置为指令地址比较,并了解处理器在该模式下比较的是取指地址还是提交地址。 |
| 多核触发不同步 | 1. 各核ETM时钟或电源域不同步。 2. 交叉触发配置错误。 | 1. 确认所有涉及的ETM核心都已上电并解锁。 2. 仔细检查CTI的触发输入输出映射寄存器,确保事件正确路由。使用CTI的触发状态寄存器进行调试。 |
调试ETM触发是一个需要耐心和细致的过程。最有效的方法是分解问题:先确保最简单的触发(如一个绝对地址)能工作,然后逐步添加条件(上下文ID、计数器等),每步都进行验证。充分利用调试器的ETM配置视图和状态读取功能,对比你写入的值和实际读回的值,可以快速发现配置错误。记住,硬件调试工具本身也是软件,也可能有bug,在极度复杂的情况下,回归最简单的测试用例是厘清问题的黄金法则。