63、Cortex-M处理器调试跟踪组件详解

Cortex-M处理器调试跟踪组件详解

1. Instrumentation Trace Macrocell (ITM)概述

ITM仅在Cortex - M33处理器中可用,Cortex - M23处理器中没有该组件。它具备多种功能:
- 软件生成跟踪 :软件可直接向ITM刺激端口寄存器写入消息以生成跟踪数据。之后,ITM会将数据封装在跟踪数据包中,并通过跟踪接口输出。
- 时间戳数据包生成 :可对ITM进行编程,使其生成时间戳数据包,并插入到跟踪流中,帮助调试器重建事件的时间顺序。
- 跟踪数据包合并 :在处理器内部,ITM作为跟踪数据包合并设备,将来自DWT的跟踪数据包、软件生成的刺激端口寄存器中的跟踪数据包以及时间戳生成器的时间戳数据包进行合并。
- FIFO :ITM内部有一个小型的先进先出(FIFO)缓冲区,可降低跟踪溢出的可能性。

要使用ITM进行调试,微控制器或SoC设备必须具备跟踪端口接口。若设备没有跟踪接口,或者调试适配器不支持跟踪捕获,仍可通过其他外设接口(如UART或LCD模块)输出控制台文本消息,但像DWT分析等其他功能将无法使用。部分调试器还支持使用核心调试寄存器(如CoreDebug->DCRDR)作为通信通道来实现printf(以及其他半主机功能)。

在访问任何ITM寄存器或使用其功能之前,必须将CoreDebug->DEMCR中的TRCENA位(跟踪启用)设置为1。在CoreSight跟踪系统中,每个跟踪源都必须分配一个跟踪源ID值,该值是可编程的,也是ITM跟踪控制寄存器中的一个位域(TraceBusID)。通常,此跟踪ID值由调试器自动设置,且必须与其他跟踪源的ID完全不同,以便调试主机能将ITM的跟踪数据包与其他跟踪数据包区分开来。

2. ITM的程序员模型

ITM包含以下关键寄存器:
| 地址 (NS别名) | 名称 | 类型 |
| — | — | — |
| 0xE0000000 + n * 4 (0xE0020000 + n * 4) | ITM刺激端口寄存器n (ITM_STIM[n]) | R/W |
| 0xE0000E00 + n * 4 (0xE0020E00 + n * 4) | ITM跟踪启用寄存器n (ITM_TER[n]) | R/W |
| 0xE0000E40 (0xE0020E40) | ITM跟踪特权寄存器 (ITM_TPR) | R/W |
| 0xE0000E80 (0xE0000E80) | ITM跟踪控制寄存器 (ITM_TCR) | R/W |
| 0xE0000FBC (0xE0020FBC) | ITM设备架构寄存器 (FP_DEVARCH) | RO |
| 0xE0000FCC (0xE0020FCC) | ITM设备类型寄存器 (FP_DEVTYPE) | RO |
| 0xE0000FD0 — 0xE0000FFC (0xE0020FD0 — 0xE0020FFC) | ITM外设和组件ID寄存器 | RO |

在使用ITM功能之前,首先需要向ITM跟踪控制寄存器(ITM_TCR)写入数据,以设置主启用位。ITM_TCR的位域如下表所示:
| 位 | 名称 | 类型 | 复位值 | 描述 |
| — | — | — | — | — |
| 31:24 | Reserved | – | – | 保留 |
| 23 | BUSY | RO | – | 为1时,表示ITM当前正在生成跟踪数据包(由软件、ITM自身或处理来自DWT的数据包) |
| 22:16 | TraceBusID | R/W | – | ATB(高级跟踪总线)上的总线ID,正常使用时设置为0x01到0x6F |
| 15:12 | Reserved | – | – | 保留 |
| 11:10 | GTSFREQ | R/W | 00 | 全局时间戳频率,00表示全局时间戳禁用;01表示大约每128个周期生成一个全局时间戳;10表示大约每8192个周期生成一个全局时间戳;11表示当跟踪输出阶段的FIFO为空时,每个数据包后生成一个全局时间戳 |
| 9:8 | TSPrescale | R/W | 00 | 本地时间戳预分频器,控制时间戳生成器的预分频器,适用于通过ITM传输的跟踪数据包的时间戳。00表示无预分频;01表示除以4;10表示除以16;11表示除以64 |
| 7:6 | Reserved | – | – | 保留 |
| 5 | STALLENA | R/W | – | 暂停启用,设置为1时,当ITM FIFO满时,处理器暂停,以便跟踪系统能跟上并传递数据跟踪数据包;设置为0时,当FIFO满时,DWT数据跟踪数据包将被丢弃,并使用溢出数据包表示数据包丢失。此功能在Cortex - M33的r0p1版本中可用 |
| 4 | SWOENA | R/W | – | SWO启用,启用本地时间戳计数器的异步时钟 |
| 3 | TXENA | R/W | 0 | 传输启用,设置为1时,启用DWT数据包的转发 |
| 2 | SYNCENA | R/W | 0 | 同步启用,启用同步数据包生成 |
| 1 | TSENA | R/W | 0 | 本地时间戳启用,启用本地时间戳数据包生成 |
| 0 | ITMENA | R/W | 0 | ITM的主启用位 |

ITM刺激端口寄存器用于软件为调试主机生成消息。通过使用多个刺激端口寄存器,可提供多个消息通道。当数据写入其中一个刺激端口寄存器时,刺激端口号会被封装在跟踪数据包中,以便调试主机能识别数据所属的消息通道。在Cortex - M33和现有的Armv7 - M处理器中,ITM支持32个刺激端口。最常用的刺激端口(通常是刺激端口#0)用于处理“printf”消息,使消息能在调试主机上运行的控制台程序中显示。在Keil MDK中使用RTX RTOS时,刺激端口#31用于支持操作系统感知调试,操作系统会输出其状态信息,以便调试器判断上下文切换的时间以及处理器正在运行的任务。

在使用ITM刺激端口之前,需要完成以下操作:
1. 启用ITM(必须设置DEMCR.TRCENA,然后设置ITM_TCR.ITMENA)。
2. 配置ITM跟踪启用寄存器(ITM_TER)以启用要使用的刺激端口。
3. 配置ITM_TCR中的TraceBusID。

对于读取操作,ITM_STIM[n]具有以下返回值:
| 位 | 名称 | 类型 | 复位值 | 描述 |
| — | — | — | — | — |
| 31:2 | Reserved | – | – | 保留 |
| 1 | DISABLED | R | – | 值为1时,表示刺激端口被禁用 |
| 0 | FIFOREADY | R | – | 值为1时,表示刺激端口准备好接受一个数据 |

写入ITM刺激端口寄存器时,可进行字节、半字或字大小的写入,写入传输大小定义了要输出到跟踪的数据大小。ITM会将数据大小封装在跟踪数据包协议中,以便调试主机能正确显示“printf”的字符写入序列。例如,Keil MDK开发工具中的μVision IDE可在ITM查看器中收集并显示printf文本输出。

与基于UART的文本输出不同,使用ITM输出不会过多延迟应用程序。尽管ITM内部使用了FIFO缓冲区,写入的输出消息会被缓冲,但在写入之前仍需检查FIFO是否已满。输出消息可在跟踪端口接口或TPIU上的串行线输出接口(SWO)收集。由于在没有连接调试器时,跟踪系统会被禁用(TRCENA控制位为低),写入ITM的操作会被忽略,因此无需从最终代码中移除生成调试消息的代码。如果最终代码中具备文本消息生成功能,可根据需要在“实时”系统中开启输出消息。在这种情况下,可通过控制跟踪启用寄存器选择性地启用ITM刺激端口,仅输出特定刺激端口中的部分消息。

为辅助软件开发,CMSIS - CORE提供了一个函数用于处理使用ITM刺激端口的文本消息:

unit32_t ITM_SendChar (uint32_t ch)

该函数使用刺激端口#0,并返回“ch”输入的值。通常,调试器会为你设置跟踪端口和ITM,你只需调用此函数即可输出要显示的每个字符。要使用此函数,必须设置调试器以启用跟踪捕获。例如,若使用SWO信号,调试器必须使用正确的传输速度捕获跟踪,通常可通过调试器的图形用户界面(GUI)配置TPIU频率和串行线输出的速度(通过调整TPIU的SWO部分中的时钟分频比来实现)。此外,若SWO输出与TDO引脚共享,必须选择串行线调试通信协议。

虽然ITM仅允许数据输出,但CMSIS - CORE头文件中还包含一个函数,允许调试器向运行在微控制器上的应用程序输出字符:

int32_t ITM_ReceiveChar (void)

尽管此函数名称带有“ITM_”前缀,但从调试主机向Cortex - M处理器上运行的软件传输字符实际上是由调试接口(即串行线调试或JTAG连接)处理的。要使用此功能,需要声明一个名为ITM_RxBuffer的变量,以便调试工具可通过直接访问该变量所在的内存来更新它。若没有数据可接收,ITM_ReceiveChar()函数返回 - 1;若有数据可用,则返回接收到的字符。还有一个用于检查是否接收到字符的函数:

int32_t ITM_CheckChar (void)

若有字符可用,ITM_CheckChar()返回1;否则返回0。

刺激端口在使用前需要启用,这由ITM跟踪启用寄存器(ITM_TER[n])控制。在Cortex - M33处理器中,由于仅实现了32个ITM刺激端口寄存器,因此只有一个ITM_TER寄存器,其中的每一位代表一个刺激端口的启用控制。此外,还可设置ITM刺激端口,使无特权的应用程序也能使用,这由ITM跟踪特权寄存器(ITM_TPR[n])控制。同样,在Cortex - M33处理器中,只有一个ITM跟踪特权寄存器,其每一位代表一个刺激端口的特权级别控制。

3. ITM与DWT的硬件跟踪

ITM负责合并来自DWT的数据包。要启用DWT跟踪,需要设置ITM跟踪控制寄存器中的TXENA位,并配置DWT跟踪设置。通常,跟踪功能(如数据跟踪、事件跟踪)通过调试器的GUI进行配置,配置完成后,调试器会自动设置跟踪设置。

4. ITM时间戳

ITM具备时间戳功能,可让跟踪捕获工具确定时间信息。每次新的跟踪数据包进入ITM内部的FIFO时,会在跟踪中插入时间戳数据包,当时间戳计数器溢出时也会生成时间戳数据包。

在Cortex - M33处理器中,有本地时间戳机制和全局时间戳机制。本地时间戳机制用于重建ITM/DWT数据包之间的时间关系,本地时间戳数据包提供当前跟踪数据包与先前传输数据包之间的时间差(delta),跟踪捕获工具可利用这些delta时间戳数据包确定每个生成数据包的时间,从而重建各种调试事件的时间。全局时间戳机制用于重建ITM/DWT跟踪与其他跟踪源(如ETM)之间的时间关系,可实现不同跟踪源之间的跟踪信息关联。

结合DWT和ITM的跟踪功能,软件开发人员可收集大量有用信息。例如,Keil MDK开发工具中的异常跟踪窗口能够显示已执行的异常以及在异常上花费的时间。

5. 嵌入式跟踪宏单元(Embedded Trace Macrocell, ETM)

ETM用于提供指令跟踪,收集到的信息在以下方面很有用:
- 分析程序失败原因 :通过跟踪指令执行,找出程序崩溃或出错的具体位置。
- 检查代码覆盖率 :了解哪些代码段被执行过,哪些未被执行,有助于优化代码结构。
- 获取应用程序的详细分析信息 :分析程序的性能瓶颈,如哪些函数调用频繁,哪些代码执行时间长等。

ETM是可选组件,一些基于Cortex - M23和Cortex - M33的产品可能没有该组件。启用后,程序流信息(即指令跟踪)会实时生成,并通过TPIU(跟踪端口接口单元)上的并行跟踪端口由调试主机收集。由于调试主机可能有程序映像的副本,因此能够重建程序执行的历史。下图展示了Keil MDK中的指令跟踪显示:

ETM跟踪协议旨在最小化传输跟踪数据所需的带宽。为减少生成的数据量,ETM不会为执行的每条指令生成跟踪数据包,而是仅输出有关程序流的信息,并在需要时(如发生间接分支时)输出完整地址。不过,ETM仍然会生成大量数据,尤其是在频繁发生分支的情况下。为了能够捕获数据跟踪,ETM中提供了一个FIFO缓冲区,以便跟踪端口接口单元(TPIU)有足够的时间处理和重新格式化跟踪数据。

由于所需的跟踪带宽,单引脚SWO跟踪输出模式不适合ETM跟踪。虽然ETM协议允许进行数据跟踪,但Cortex - M23和Cortex - M33处理器的ETM不支持数据跟踪,而是可以使用DWT中的选择性数据跟踪功能来捕获数据。

与接下来要介绍的MTB相比,ETM指令跟踪具有以下优点:
- 无限的跟踪历史 :可以记录程序执行的完整过程,方便进行全面的分析。
- 通过时间戳数据包提供时间信息 :有助于分析程序执行的时间顺序和性能瓶颈。
- 实时操作 :在处理器仍在运行时,调试工具可以收集信息,便于及时发现问题。
- 不占用系统SRAM空间 :不会影响系统的内存使用。

ETM还与其他调试组件(如DWT)进行交互。DWT中的比较器可用于生成触发事件或ETM中的跟踪开始/停止控制功能。由于DWT和ETM之间的交互,ETM不需要专用的跟踪开始/停止控制硬件。

6. 微跟踪缓冲区(Micro Trace Buffer, MTB)

与ETM类似,MTB也用于提供指令跟踪。但与ETM不同的是,MTB解决方案使用片上SRAM的一部分来保存指令跟踪数据,而不是通过TPIU实时输出。MTB是Cortex - M0+、Cortex - M23和Cortex - M33处理器中的可选组件。

在程序执行期间,程序流更改信息会被捕获并存储在SRAM中。当处理器停止时,可通过调试连接检索跟踪缓冲区中的程序流信息并进行重建。

虽然MTB不提供实时指令跟踪,且其跟踪历史有限(受分配用于指令跟踪的SRAM区域大小限制),但MTB指令跟踪解决方案具有以下优点:
- 低成本调试 :软件开发人员可以使用低成本的调试探头来收集MTB跟踪结果,而ETM跟踪需要支持并行跟踪端口捕获的调试探头,通常成本更高。
- 节省引脚资源 :MTB不需要额外的引脚进行并行跟踪输出,这对于引脚数量有限的设备来说是一个重要的考虑因素。
- 降低芯片制造成本 :MTB的整体硅面积小于ETM加上TPIU的面积,且MTB可以使用系统的部分SRAM作为跟踪缓冲区,无需专用的SRAM缓冲区。

MTB是一个位于SRAM和系统总线之间的小型组件。在正常操作中,MTB充当接口模块,将片上SRAM连接到AMBA® AHB。在调试操作期间,调试器会配置MTB,使其分配SRAM的一小部分作为跟踪缓冲区来存储跟踪信息。当然,必须注意确保应用程序不会使用已分配用于跟踪操作的相同SRAM空间。

当发生程序分支或由于中断导致程序流改变时,MTB会将源程序计数器和目标程序计数器存储在SRAM中。每次分支需要总共8字节的跟踪数据来存储每个程序流更改。例如,如果仅分配512字节的SRAM用于指令跟踪,则可以存储最多64个最近的程序流更改。这在调试软件时非常有帮助,例如确定导致HardFault的程序代码序列。

MTB支持两种操作模式:
- 循环缓冲区模式 :MTB以循环缓冲区模式使用分配的SRAM。MTB跟踪持续运行,旧的跟踪数据会不断被新数据覆盖。

以下是MTB与ETM的对比表格:
| 特性 | ETM | MTB |
| — | — | — |
| 实时跟踪 | 支持 | 不支持 |
| 跟踪历史 | 无限 | 有限(受SRAM大小限制) |
| 调试探头成本 | 高 | 低 |
| 引脚需求 | 需要并行跟踪端口 | 无需额外引脚 |
| 硅面积 | 大 | 小 |

通过上述对Cortex - M处理器中ITM、ETM和MTB等调试跟踪组件的详细介绍,我们可以看到它们各自的特点和优势。在实际的软件开发和调试过程中,可以根据具体的需求和场景选择合适的组件,以提高开发效率和程序的稳定性。例如,如果需要实时的指令跟踪和无限的跟踪历史,ETM可能是更好的选择;而如果对成本和引脚资源有严格要求,MTB则是一个不错的替代方案。同时,ITM和DWT的结合使用也能为软件开发提供丰富的调试信息,帮助开发人员更快地定位和解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值