ARM Cortex-M33调试实战:深入解析CC35xx HOST_MCU与TPIU寄存器配置

1. 项目概述与核心价值

在嵌入式开发,尤其是基于ARM Cortex-M内核的无线MCU开发中,我们常常需要与芯片最底层的硬件模块打交道。这些模块,比如调试子系统、追踪接口、中断控制器,它们不像GPIO或UART那样有现成的HAL库函数可以轻松调用,而是通过一组组精密的内存映射寄存器来控制和交互。最近在折腾德州仪器CC35xx这款集成了Wi-Fi 6和蓝牙低功耗的无线MCU时,我就被其手册中关于HOST_MCU和TPIU(Trace Port Interface Unit)的寄存器章节给“吸引”住了。这些寄存器文档通常写得非常精炼,甚至有些晦涩,但对于实现高级调试功能、优化系统实时性、乃至解决一些棘手的软硬件协同问题,却是不可或缺的钥匙。

很多人拿到芯片参考手册,看到动辄几十页的寄存器描述,可能就直接跳过了,或者只在出问题时才去翻查。但我的经验是,提前吃透这些核心寄存器的设计逻辑,能在项目初期就规避很多潜在的坑。比如,你想用JTAG或SWD接口进行实时指令追踪,却发现数据流时断时续,这很可能就是TPIU的时钟分频或输出协议没配对;又或者,在多核或安全上下文(Secure/Non-Secure)交互的场景下,软件中断无法正确触发,问题根源或许就在HOST_MCU那组中断控制寄存器的配置细节里。

这篇文章,我就结合CC35xx的实际手册内容,把HOST_MCU和TPIU这两组关键寄存器的来龙去脉、每个比特位的实际含义,以及配置时的实操要点和避坑指南,给你掰开揉碎了讲清楚。我的目标不是照本宣科地翻译手册,而是以一个实际调试者的视角,告诉你这些寄存器“为什么”要这么设计,以及“怎么用”才能发挥最大效用。无论你是正在评估CC35xx,还是已经在用它开发产品,亦或是想深入了解Cortex-M33调试体系,这些内容都能给你提供直接的参考。

2. 内存映射寄存器基础与ARM CoreSight架构

在深入具体寄存器之前,我们有必要统一一下认知基础。所谓“内存映射寄存器”,其本质是CPU设计师为硬件控制逻辑开的一扇“后门”。他们给每一个需要软件干预的硬件状态或配置开关,都分配了一个唯一的、像内存地址一样的标识。当你对这个地址进行读写操作时,CPU的访存指令实际上并没有去访问真正的RAM,而是通过内部总线,将数据送到了对应的硬件电路里。读操作就是采样硬件状态,写操作就是下发控制命令。

在ARM Cortex-M世界,尤其是从M3、M4到M33这类带调试功能的处理器,这套硬件控制体系有一个统一的顶层架构——ARM CoreSight。你可以把它理解为一套标准化的“调试与追踪组件插座”。芯片厂商(比如TI)按照CoreSight的规范,把处理器内核、数据观察点单元(DWT)、指令追踪宏单元(ETM)、追踪端口接口单元(TPIU)等模块,像积木一样插在这个架构上。而CPU_ROM_TABLE寄存器组,就是这个架构的“组件目录”或“地址映射表”。

2.1 CoreSight ROM表:调试组件的“导航图”

手册中3.9.1节描述的CPU_ROM_TABLE寄存器组,就是这个导航图。它位于一个固定的、芯片设计时已知的地址区域。软件(通常是调试器)通过读取这个表,就能自动发现芯片内部集成了哪些调试组件,以及它们各自的基地址在哪里。这是一种非常巧妙的设计,使得调试工具无需预先知道芯片的具体型号,就能动态适配。

我们来看几个关键条目:

  • SCS_ENTRY(偏移 0h):指向系统控制空间(System Control Space),这是Cortex-M内核的系统寄存器区域,包含SysTick、NVIC等。
  • DWT_ENTRY(偏移 4h)FPB_ENTRY(偏移 8h):分别指向数据观察点与触发单元、闪存修补与断点单元。这是实现硬件断点、数据监视和指令流修补的基础。
  • TPIU_ENTRY(偏移 10h):这是我们今天的主角之一,指向追踪端口接口单元。它的ENTRY_PRESENT位复位值为0,这意味着TPIU组件在ROM表中的存在性是可选的,需要根据具体芯片型号确认。手册中给出的基地址0x000FFF41是一个相对偏移,需要加上ROM表基址才能得到TPIU模块的绝对地址。
  • ETM_ENTRY(偏移 14h):指向嵌入式追踪宏单元。如果芯片支持指令追踪(ETM),这个条目会存在。它的ENTRY_PRESENT位也是0,同样表示可选。

注意PIDR0PIDR7以及CIDR0CIDR3这些寄存器,是CoreSight组件的身份标识符。调试器通过读取这些ID,可以精确识别组件类型、设计厂商(如ARM)、部件号和版本。这在多核异构系统或使用第三方调试IP时尤为重要,是确保调试工具链兼容性的第一步。

2.2 HOST_MCU寄存器组:系统级调试与控制的“总闸”

如果说CoreSight ROM表是“地图”,那么HOST_MCU寄存器组(3.8.2节)就是这片领地上几个关键设施的“控制室”。它不属于标准的CoreSight组件,更像是TI为CC35xx这类集成无线子系统的复杂MCU定制的“系统管理”寄存器。它的功能更偏向于芯片整体的调试使能、子系统间通信(如中断)和资源仲裁。

  • 地址映射:这些寄存器位于芯片内存映射的特定区域,通过固定的偏移地址(如TRACECFG基址+0h)进行访问。
  • 核心功能:主要包括三大类:
    1. 追踪与调试控制(如TRACECFG,DBGSS,DBGSSLCK):管理追踪时钟、调试子系统的使能与访问锁。
    2. 跨上下文/跨核中断(如SWIRQ,NSSWIRQ,SWIRQCM3,SSWIRQ2NS):实现Cortex-M33安全世界与非安全世界之间,以及M33与可能存在的其他协处理器(如CM3)之间的软件触发中断。
    3. 总线仲裁策略ARBPOL):配置访问共享内存资源(MEMSS)时的仲裁器工作模式(固定优先级或轮询)。

理解HOST_MCU和标准TPIU寄存器的分工与联系,是进行有效配置的前提。简单来说,HOST_MCU负责“是否允许以及如何接入调试系统”,而TPIU负责“调试数据出来后,如何格式化并发送到物理引脚”。

3. HOST_MCU关键寄存器深度解析与配置实战

手册中列出了9个HOST_MCU寄存器,我们挑出最核心、最容易出问题的几个来详细拆解。

3.1 TRACECFG:追踪时钟的“节拍器”

这个寄存器是连接HOST_MCU配置与TPIU工作的桥梁。

// TRACECFG 寄存器 (偏移 0h) typedef struct { uint32_t RESERVED_31_9 : 23; // 保留位,必须写0 uint32_t CLKDIVEN : 1; // 位8: 时钟分频使能位。写1加载CLKDIVVAL值。 uint32_t RESERVED_7_2 : 6; // 保留位 uint32_t CLKDIVVAL : 2; // 位[1:0]: 追踪时钟分频值 } TRACECFG_Type;
  • CLKDIVVAL (位[1:0]):这是预分频系数选择位。它定义了TPIU模块的输入时钟(tpiu_trace_clk_in)的分频比。

    • 00(值0): 分频比2。假设源时钟80MHz,则TPIU时钟为40MHz。
    • 01(值1): 分频比4。假设源时钟80MHz,则TPIU时钟为20MHz。这是复位默认值。
    • 10(值2) 和11(值3):不支持,禁止使用。
    • 为什么需要分频?TPIU输出的追踪数据速率受限于物理引脚的速度和调试探头的捕获能力。过高的时钟会导致数据丢失。通常需要根据实际使用的SWO引脚最大波特率和调试器性能来调整此值。
  • CLKDIVEN (位8):这是分频值加载使能位。这是一个关键的操作顺序陷阱!

    1. 你必须先配置好CLKDIVVAL位。
    2. 然后,���CLKDIVEN位写1,新的分频值才会真正生效。
    3. 操作完成后,最好将CLKDIVEN位回写为0(根据手册描述,写1加载,但通常写0无影响,为安全起见可写回0)。

实操心得:很多人在配置追踪时钟后发现没输出,第一步就应该检查这里。正确的代码顺序应该是:

// 假设我们要设置分频为4 (20MHz) TRACECFG->CLKDIVVAL = 0x1; // 先写分频值 __DSB(); // 插入数据同步屏障,确保写入完成 TRACECFG->CLKDIVEN = 0x1; // 再使能加载 __DSB(); TRACECFG->CLKDIVEN = 0x0; // 可选:清除使能位

缺少__DSB()或顺序错误,都可能导致配置不生效。

3.2 软件中断寄存器族:跨越“世界”的通信

CC35xx的Cortex-M33支持TrustZone安全扩展,这就产生了安全(Secure)和非安全(Non-Secure)两个执行环境。SWIRQ,NSSWIRQ,SWIRQCM3,SSWIRQ2NS这几个寄存器,就是为这两个“世界”以及可能的其他处理器核心(如CM3)之间,提供一种由软件触发的即时中断机制。

  • SWIRQ(偏移 18h):这是一个通用的软件时间戳中断寄存器。其低16位TIMESTAMP字段可以写入一个时间戳值,当该寄存器被写入时,会触发一个事件到ETM总线,常用于为追踪数据打上精确的时间标记。
  • NSSWIRQ(偏移 1Ch)非安全世界触发安全世界中断。当运行在非安全环境的代码向该寄存器的EN字段写特定值时,可以触发一个到安全世界的中断。这是实现非安全态应用调用安全态服务(如密码学操作)的关键底层机制之一。
  • SSWIRQ2NS(偏移 0h,位于HOST_MCU_SEC区域)安全世界触发非安全世界中断。与NSSWIRQ相反,安全环境的代码通过写此寄存器,可以中断非安全环境的执行。常用于安全服务完成后的异步通知。
  • SWIRQCM3(偏移 20h) 与SWIRQ2CM3(偏移 4h,位于HOST_MCU_SEC区域):如果芯片内除了Cortex-M33还有一个Cortex-M3协处理器(例如用于管理射频),那么这两个寄存器分别允许非安全世界和安全世界的代码去中断那个CM3核心。

配置要点

  1. 明确权限:访问HOST_MCU_SEC区域的寄存器(SSWIRQ2NS,SWIRQ2CM3,LCKUP必须在安全世界(Secure State)下进行,否则会产生总线错误。
  2. 中断服务例程(ISR):触发这些中断前,必须在目标执行环境(安全或非安全)的NVIC中,正确配置对应的中断向量和优先级。仅仅写寄存器是不会执行任何代码的,它只是触发了一个中断请求。
  3. 使用场景:这类中断通常用于极低延迟的、事件驱动的跨域通信,比基于邮箱(Mailbox)的轮询方式更高效。

3.3 DBGSS、DBGSSLCK、DBGSSLM、DBGSSLS:调试子系统的“门禁”

这组寄存器管理着对调试子系统(DEBUGSS)的访问权限,在多核调试或安全场景下尤为重要。

  • DBGSS(偏移 28h):最简单的使能控制。位0的EN置1,使能调试子系统主机接口。
  • DBGSSLCK(偏移 2Ch)调试接口锁。这是一个典型的“读-修改-回写”锁机制。
    • 读操作:读LOCK位。如果返回1,表示成功获得锁(当前无调试请求);如果返回0,表示获取失败(有调试请求正在进行),需要重试。
    • 写操作:写1强制获取锁(无视调试请求状态);写0释放锁。
    • 类型:Write/Read-Clear。这意味着对该位的读操作可能会清除某些状态(具体行为依实现而定),操作时需严格遵循手册流程。
  • DBGSSLM(偏移 30h)锁条件掩码。位1的MASK位如果置1,会在检查锁条件时屏蔽(忽略)调试主机的强制活动请求。这给了软件更精细的控制能力,可以在某些关键代码段禁止调试器介入。
  • DBGSSLS(偏移 34h)锁条件状态。这是一个只读寄存器,用于查询调试子系统的当前状态。
    • FRCACT(位1): 为1表示调试主机正处于强制活动状态。
    • CSYSPWRREQ(位0): 为1表示调试主机正在请求C系统电源。

避坑指南: 在需要对芯片进行低功耗操作(如进入深度睡眠)前,务必通过DBGSSLCK机制尝试获取并持有调试锁,或者通过DBGSSLM屏蔽调试请求。否则,一个活跃的调试器连接可能会阻止电源管理单元关闭相关时钟和电源域,导致功耗降不下去,或者唤醒后系统状态异常。获取锁的典型代码模式如下:

bool acquire_debug_lock(void) { uint32_t retries = 1000; // 设置重试次数,避免死循环 while (retries--) { if (DBGSSLCK->LOCK != 0) { // 尝试读锁 // 读到了1,表示成功获取 return true; } // 读到了0,等待一小段时间再试 __NOP(); __NOP(); __NOP(); __NOP(); } // 重试多次后失败,可以考虑强制获取或报错 DBGSSLCK->LOCK = 0x1; // 强制获取锁(慎用,可能打断调试会话) return false; // 或根据情况返回true }

3.4 ARBPOL:内存访问的“交通规则”

ARBPOL寄存器控制着访问MEMSS(内存子系统)两个部分(Portion A和B)之前的仲裁器策略。这对于优化多主设备(如CPU, uDMA, 其他总线主机)并发访问内存时的带宽和延迟至关重要。

  • RNDRBNS0(位0) 和RNDRBNS1(位1):分别选择仲裁器0(Portion A前)和仲裁器1(Portion B前)的策略。
    • 0: 固定优先级(Fixed Priority)
    • 1: 轮询优先级(Round Robin)——复位默认值
  • S0PRIM0(位[3:2]) 和S0PRIM1(位[5:4]):当仲裁器0工作在固定优先级模式时,这两个字段用于配置udma/sahbocp两个主设备的优先级。数值越高,优先级通常越高(具体优先级映射需查更详细的总线手册)。
  • S1PRIM0(位[7:6]) 和S1PRIM1(位[9:8]):功能同上,对应仲裁器1。

配置建议

  • 默认情况:轮询模式通常能提供最公平的带宽分配,避免低优先级主设备被“饿死”,适合通用场景。
  • 低延迟需求:如果某个主设备(如负责音频传输的uDMA)对访问延迟极其敏感,可以将其对应的仲裁器切换到固定优先级模式,并将该主设备的优先级设为最高。但要注意,这可能会增加其他主设备的访问延迟。
  • 性能分析:在优化系统性能时,可以尝试不同的仲裁策略和优先级组合,结合性能分析工具(如CCS中的System Analyzer)观察总线利用率和任务执行时间,找到最佳配置。

4. TPIU寄存器全解析与追踪端口配置

TPIU是CoreSight追踪架构的“出口”。它接收来自DWT(数据追踪)和ETM(指令追踪)的并行追踪数据,将其序列化,并通过有限的引脚(SWO或TracePort)发送给外部的调试探头。其寄存器配置直接决定了追踪数据的输出格式、速率和可靠性。

4.1 端口大小与协议选择:匹配你的调试器

  • SSPSR(Supported Sync Port Sizes, 偏移 0h)只读寄存器。告诉你这个TPIU硬件支持哪些同步端口宽度。从手册看,CC35xx的TPIU支持1-bit、2-bit和4-bit模式(ONE,TWO,FOUR位为1),但不支持3-bit模式(THREE位为0)。这是硬件能力,无法更改。
  • CSPSR(Current Sync Port Size, 偏移 4h)可读写寄存器。用于设置当前使用的端口宽度。重要限制
    1. 只能设置SSPSR中声明为支持的位(即1、2、4-bit)。
    2. 一次只能设置其中一位为1。如果你同时把ONETWO都置1,行为是未定义的(Unpredictable)。
    3. 复位后默认为1-bit模式(ONE=1),这是最省引脚的模式(仅需一根SWO线)。
  • SPPR(Selected Pin Protocol, 偏移 F0h):选择物理引脚上的输出协议。
    • 00: TracePort模式。需要多根数据线(数量由CSPSR决定),时钟线独立。带宽最高,但占用引脚多。
    • 01:串行线输出(Manchester编码)。这是复位默认值。仅需一根SWO数据线,时钟信息嵌入在曼彻斯特编码中,对探头要求较高。
    • 10: 串行线输出(NRZ编码)。也只需一根SWO线,但需要独立的追踪时钟(TRACECLK)输入给调试探头。
    • 警告:手册明确提示,在追踪数据正在输出时更改此寄存器会导致数据损坏。因此,配置必须在开始追踪前完成。

如何选择?

  1. 引脚受限,追求简便:选择SPPR=0x01(Manchester SWO),CSPSR=0x1(1-bit)。这是最常见的SWD+SWO调试接口配置。
  2. 需要更高追踪带宽:如果芯片引脚和调试器(如TI的XDS560v2)支持,可以选择SPPR=0x00(TracePort),并配合CSPSR=0x4(4-bit),这样可以获得数倍于SWO的数据吞吐率,适合捕获密集的指令流。
  3. 使用NRZ编码:某些调试探头可能对曼彻斯特解码支持不好,NRZ模式可能更稳定,但务必确保TRACECLK引脚连接正确。

4.2 时钟与波特率计算:让数据流“匀速”

追踪数据最终是以串行比特流的形式发出的,因此波特率配置至关重要。

  • ACPR(Async Clock Prescaler, 偏移 10h)异步时钟预分频器。当SPPR选择串行线输出模式(Manchester或NRZ)时,此寄存器用于设置输出波特率。
    • 公式输出波特率 = tpiu_trace_clk_in / (PRESCALER + 1)
    • PRESCALER是寄存器的[12:0]位,13位宽,最大可设置8191。
    • 举例:假设tpiu_trace_clk_in为20MHz(由TRACECFG.CLKDIVVAL分频得到),希望SWO波特率为2Mbps。则PRESCALER = 20,000,000 / 2,000,000 - 1 = 10 - 1 = 9。应写入ACPR = 9
    • 常见问题:波特率设置过高,超过SWO引脚物理极限或调试器接收能力,会导致数据错误。通常,1-2Mbps是比较稳妥的范围。务必参考芯片数据手册中SWO引脚的最大速率。

4.3 格式化器与同步控制:保证数据“可读”

TPIU内部有一个格式化器(Formatter),负责给原始追踪数据包添加帧头、帧尾和同步信息。

  • FFSR(Formatter and Flush Status, 偏移 300h)只读状态寄存器。我们主要关注位3FTNONSTOP
    • 0: 格式化器可以停止。这意味着你可以安全地禁用TPIU或更改配置。
    • 1: 格式化器无法停止(正在处理数据流)。此时不要进行可能中断数据流的操作。
  • FFCR(Formatter and Flush Control, 偏移 304h):控制寄存器。
    • ENFCONT(位1): 使能连续格式化。通常保持为1(默认)。如果置0,格式化器会在每个数据包后停止,适用于某些特殊的、需要精确控制数据流的调试场景。
    • TRIGIN(位8): 指示当外部触发引脚被断言时,是否在数据流中插入触发标记。这对于在长长的追踪记录中定位特定事件非常有用,保持默认值1即可。
    • 重要提示:当SPPR选择TracePort模式时,此寄存器值固定为0x102,因为格式化器被强制使能。
  • PSCR(Periodic Synchronization Counter, 偏移 308h)周期性同步计数器
    • PSCOUNT字段决定了格式化器每隔多少字节的数据,就插入一个同步数据包。
    • 同步包对于调试器从数据流中正确恢复帧结构至关重要,尤其是在数据流开始或中断后。
    • 手册给出了示例值:0b00000禁用同步;0b00111对应128字节;0b01000对应256字节。这是一个重载值(Reload Value)。
    • 建议:除非有特殊需求,否则不要禁用同步。使用默认值或设置为一个合理的间隔(如128或256字节)。间隔太小会增加协议开销,间隔太大则在数据出错时调试器需要更长时间重新同步。

4.4 CLAIM TAG寄存器组:多调试器访问的“令牌”

CLAIMMASK,CLAIMSET,CLAIMTAG,CLAIMCLR这四个寄存器共享两个偏移地址(FA0hFA4h),通过读写操作来区分功能。它们实现了CoreSight的“声明标签”机制,主要用于防止多个调试代理(例如两个独立的调试器)同时访问和配置同一个TPIU组件,造成配置冲突。

其工作原理类似于一个简单的软件锁:

  1. 查看可用锁:读CLAIMMASK(地址FA0h),返回一个位掩码,例如0xF(二进制...00001111),表示低4位可用作声明标签。
  2. 尝试上锁:向CLAIMSET(地址FA0h写入一个值,例如0x1。这个操作会尝试将声明标签的对应位置1。如果成功,该位就被当前调试代理“声明”。
  3. 查看当前锁:读CLAIMTAG(地址FA4h),返回当前的声明标签值。如果看到你写的位是1,说明声明成功。
  4. 释放锁:向CLAIMCLR(地址FA4h写入一个值,例如0x1,将对应位清零,释放声明。

在单调试器场景下,这个机制通常是透明的,调试软件会自动处理。但在复杂的多核调试或脚本化调试环境中,理解它有助于避免“无法访问TPIU”的问题。

4.5 DEVID寄存器:快速识别追踪能力

DEVID寄存器(偏移FC8h)是一个简单的只读寄存器,用于快速识别TPIU是否连接了ETM(指令追踪单元)。

  • 如果读回0xCA1,表示有ETM存在,可以进行指令流追踪。
  • 如果读回0xCA0(手册中CC35xx的复位值),表示没有ETM或ETM未连接。此时,TPIU只能输出来自DWT的数据追踪信息(如变量值变化、计数器事件等),无法进行指令追踪。

在选购开发板或调试复杂的代码执行流问题时,先读一下这个寄存器,可以立刻明确芯片的指令追踪能力。

5. 完整配置流程与实战案例

假设我们要在CC35xx上配置SWO输出,用于在IDE(如Code Composer Studio)中实时查看printf重定向(通过ITM)或变量值变化(通过DWT)。

5.1 配置步骤

  1. 硬件连接:确保调试器(如XDS110)不仅连接了SWD的SWCLK和SWDIO,还连接了SWO引脚(通常是JTAG接口的TDO或一个专用的TRACESWO引脚)。参考你的开发板原理图。
  2. 初始化系统时钟:确保内核时钟和tpiu_trace_clk_in的时钟源已正确配置并运行。tpiu_trace_clk_in通常来源于系统主频或某个外设时钟。
  3. 配置HOST_MCU中的追踪时钟
    // 1. 设置TPIU输入时钟分频 (例如,系统时钟80MHz,想要20MHz给TPIU) HOST_MCU_REGS->TRACECFG.CLKDIVVAL = 0x1; // 分频比4 __DSB(); HOST_MCU_REGS->TRACECFG.CLKDIVEN = 0x1; // 使能分频 __DSB(); // 可选:HOST_MCU_REGS->TRACECFG.CLKDIVEN = 0x0;
  4. 配置TPIU
    // 2. 选择SWO引脚协议为Manchester编码 (默认) TPIU->SPPR = 0x1; // PROTOCOL = 0x01 __DSB(); // 3. 设置SWO波特率 (例如,tpiu_trace_clk_in=20MHz, 目标波特率1Mbps) // PRESCALER = 20,000,000 / 1,000,000 - 1 = 19 TPIU->ACPR = 19; __DSB(); // 4. 确保格式化器使能并设置同步 (使用默认值或显式设置) // FFCR复位后TRIGIN=1, ENFCONT=1,通常无需更改 // 设置每256字节插入一个同步包 TPIU->PSCR = 0x08; // PSCOUNT = 0b01000 __DSB(); // 5. 端口大小保持默认1-bit (CSPSR.ONE=1) // 如果需要,可改为2-bit: TPIU->CSPSR = 0x2; 但需硬件支持。
  5. 使能DWT/ITM追踪源:TPIU只是一个出口,还需要告诉内核哪些数据需要追踪。
    • 配置DWT单元,设置比较器来监视变量地址。
    • 配置ITM单元,使能刺激端口(Stimulus Port)用于printf输出。
    • 这部分属于Cortex-M内核标准调试寄存器配置,通常由调试器或库函数完成。
  6. 使能TPIU并解锁调试接口(如果需要):
    // 使能调试子系统主机接口 HOST_MCU_REGS->DBGSS.EN = 0x1; __DSB(); // 如果之前有锁定,确保获取调试锁 // acquire_debug_lock(); // 调用前面定义的函数
  7. 在IDE中配置:在Code Composer Studio的调试配置中,找到“Target Configuration”或“Debugger”选项,确保使能了“Trace”功能,并将协议设置为“SWO”,波特率与你代码中设置的(1Mbps)匹配。

5.2 常见问题排查表

现象可能原因排查步骤
IDE中无法看到SWO数据1. 硬件连接错误(SWO线未接或接错)
2. TPIU时钟未配置或配置错误
3. SWO波特率不匹配
4. 追踪源(ITM/DWT)未使能
1. 检查硬件连接和原理图。
2. 检查TRACECFG寄存器配置,确认CLKDIVEN已置位。
3. 检查ACPR寄存器计算值,并在IDE中确认波特率设置一致。
4. 检查CoreSight的DWT/ITM控制寄存器是否已正确配置。
SWO数据断断续续,大量错误1. 波特率过高,超过硬件极限。
2. 系统时钟不稳定。
3. 电源噪声干扰。
1. 降低ACPR值以降低波特率(如降至500kbps)。
2. 检查系统时钟配置,确保时钟源稳定。
3. 检查板级电源和接地,SWO线附近避免高速信号。
无法访问TPIU或HOST_MCU寄存器1. 调试子系统被锁定(DBGSSLCK)。
2. 芯片处于低功耗模式,调试接口被禁用。
3. 安全世界下试图访问非安全寄存器,或反之。
1. 尝试读取DBGSSLCK.LOCK,或强制写1获取锁。
2. 确保芯片处于运行模式,或已配置调试接口在低功耗下保持活动。
3. 确认当前CPU执行状态,并检查寄存器所属的安全域。
指令追踪(ETM)无法工作1. 芯片不支持ETM(DEVID寄存器值为0xCA0)。
2. ETM单元未使能或未配置。
3. TPIU未配置为TracePort模式(如果ETM需要并行输出)。
1. 读取DEVID寄存器确认。
2. 检查ETM相关的控制寄存器(如果存在)。
3. 对于高速指令追踪,可能需要将SPPR设为TracePort模式,并增加CSPSR的端口宽度。
跨安全世界中断不触发1. 目标世界的NVIC未使能对应中断。
2. 中断优先级配置错误。
3. 安全状态切换后,中断配置被复位。
1. 确认在安全/非安全世界的NVIC中正确配置了中断向量和使能位。
2. 检查中断优先级,确保它高于当前屏蔽阈值(如BASEPRI)。
3. 在安全世界初始化代码中,确保相关中断配置在切换至非安全世界后依然有效。

5.3 一个具体的调试案例:定位非安全世界调用安全服务的延迟

场景:在CC35xx上开发,非安全世界的应用通过NSSWIRQ寄存器触发安全世界的服务。发现有时调用延迟异常高。

排查过程

  1. 检查中断配置:确认安全世界NVIC中对应的中断已使能,优先级合理。
  2. 检查仲裁策略:怀疑是总线访问冲突。查看ARBPOL寄存器,发现仲裁器0(MEMSS Portion A)处于轮询模式。而安全世界服务函数需要频繁访问位于Portion A的某个安全外设。
  3. 分析与调整:非安全世界触发中断是瞬间的,但安全世界ISR执行时,如果总线上有其他主设备(如uDMA)也在争抢,在轮询策略下可能会引入不确定的延迟。
  4. 优化:将仲裁器0的策略改为固定优先级(RNDRBNS0=0),并将安全世界访问的总线主设备优先级(通过S0PRIM0S0PRIM1)设为最高。同时,确保这个改动不会对系统中其他实时任务(如无线通信)造成负面影响。
  5. 验证:修改后,再次测试,延迟的高抖动现象消失,变得稳定可控。

这个案例说明,理解并合理配置像ARBPOL这样的底层寄存器,对于满足系统的实时性要求至关重要。它不再是手册里一个生僻的表格,而是解决实际性能问题的有力工具。