一、调试类型
Debug按侵入性(invasive)可以分为两大类:
- 侵入式调试(Invasive Debug ):暂停处理器执行,干预程序运行,包括停机调试(Halting Debug)和调试监控异常(DebugMonitor Exception)两种模式。
- 非侵入式调试(Non-invasive Debug ):不中断程序运行,仅采集运行数据,包括指令跟踪、数据跟踪、性能统计三类。
Halting Debug 会使PE进入halt状态,也就是处于Debug state 。当PE没有处于halt状态,它就处于Non-debug state。Halting Debug下,调试器可通过调试接口读写通用寄存器、特殊寄存器、内存与外部资源,支持断点、单步、变量查看等经典在线调试操作,是常规IDE调试的底层基础。当PE处于Debug state时:
- PE停止从PC指示的位置执行指令,而是由外部调试接口控制;
- PE不会服务任何中断;
以下几个行为可以使PE退出debug state:
- 当调试器将0写入DHCSR.C_HALT;
- 接收到外部restart请求;
- Warm reset;
DebugMonitor Exception会进入异常,由软件异常处理程序完成调试交互,适合实时性要求高、外设不能暂停的场景,在不冻结系统的前提下完成调试动作。
Embedded Trace Macrocell (ETM)、Instrumentation Trace Macrocell (ITM)、Data Watchpoint and Trace (DWT) Unit、Performance Monitoring Unit (PMU)可用于生成trace数据。

二、调试资源
在System Address Map中,debug资源位于Private Peripheral Bus (PPB)区域。除了SCS中的资源外,每个debug组件占用固定的4KB地址区域。SCS中的debug资源有:
- Debug Control Block (DCB)
- 在System Control Block (SCB)中的Debug controls
SCB的debug功能包括:
- 两个处理程序相关的标志位ICSR.ISRPREEMPT和ICSR.ISRPENDING:
- DFSR寄存器;
Debug 资源的地址分布如下:

上图中最后一个是ROM table的地址空间,调试器通过读取 ROM 表自动识别芯片内所有调试模块(DWT/ITM/ETM/CTI 等)的基地址与类型,实现通用工具适配。
ROM table是一个表项,它提供了一种机制来标识实现所支持的debug基础结构。ROM table指示实现的调试组件有哪些,以及这些组件在内存映射中的位置。ROM table的格式如下:

三、调试安全认证
Debug authentication interface提供了4个伪函数:
- ExternalInvasiveDebugEnabled().
- ExternalSecureInvasiveDebugEnabled().
- ExternalNoninvasiveDebugEnabled().
- ExternalSecureNoninvasiveDebugEnabled().
对于使用CoreSight信号DBGEN、NIDEN、SPIDEN和SPNIDEN的实现来说:
- 如果ExternalInvasiveDebugEnabled()为真,那么DBGEN为1;
- 如果ExternalSecureInvasiveDebugEnabled()为真,那么DBGEN和SPIDEN都为1;
- 如果ExternalNoninvasiveDebugEnabled()为真,那么NIDEN或DBGEN为1;
- 如果ExternalSecureNoninvasiveDebugEnabled()为真,那么以下使用以下两者条件:
- NIDEN或DBGEN为1;
- SPNIDEN或SPIDEN为1;
配合 TrustZone 安全扩展,对调试权限做分级管控,防止非授权调试泄露安全域数据:
- Halting debug认证:控制外部调试器能否让内核进入hating状态;
- Non-invasive debug认证:控制trace、profiling等non-invasive功能的访问权限;
- DebugMonitor exception认证:控制DebugMonitor exception的触发权限;
- DAP access权限:配置调试访问端口(DAP)对安全 / 非安全地址空间的访问边界。当HaltingDebugAllowed()为TRUE时,外部调试器可以通过DAP向整个物理地址空间发出请求。DAUTHCTRL.UIDAPEN指示软件允许外部调试器通过DAP对所选PPB寄存器进行非特权访问。
四、调试事件
由于调试原因而触发的事件称为debug event,它们定义所有可触发debug行为的硬件事件,是断点、单步等功能的底层依据。Debug event会使PE发生以下情况之一:
- 如果Halting debug实现且启用了,那么会进入Debug state;
- DebugMonitor exception发生;
- 产生HardFault exception;
- Lockup;
上面两种通常是debug event想要触发来进行调试PE的。下面两种是可能debug event无法正常处理而产生的,比如:当PE既不能进入Halting debug也不能产生DebugMonitor exception时,这时候执行BKPT指令就会进入下面两种情况的了。

debug event如下所示:

这些event导致PE halt或产生DebugMonitor exception时,会更新DFSR寄存器中对应的bit,这些bit是通过写1来清理的。下表显示了为每个debug event设置的位。

Debug events可以是synchronous或是asynchronous。Synchronous的debug events有:
- 由BKPT指令的执行或FPB中的匹配引起的breakpoint debug events。
- Vector catch debug events,由一个或多个DEMCRVC_*位被设置为1引起的,PE进入相应的异常。
- Step debug events,由DHCSR.C_STEP或DEMCR.MON_STEP引起。
一条指令可以生成多个synchronous debug events。synchronous debug events与生成它们的指令相关联,并被采用而不是执行该指令。PE不会生成任何其他可能由于执行指令而发生的synchronous exception或debug event。
4.1 Debug stepping
Armv8-M体系结构在halting debug和DebugMonitor exception中都支持debug stepping。
- Halting debug stepping:调试器可以使用halting debug stepping退出调试状态,执行单个指令,然后重新进入调试状态。
- debug monitor stepping:调试器可以使用debug monitor stepping从DebugMonitor异常处理程序返回,执行单个指令,然后重新进入DebugMonitor异常处理程序。
Step debug event发生在被stepped的指令之后的指令上。这意味着event的优先级适用于后续指令的任何其他exception或debug events,而不是正在执行的指令。
4.2 Vector catch
Vector catch是生成debug event并在进入特定exception处理程序或复位时进入debug状态的机制。Vector catching只支持halting debug,用于异常入口调试;
4.3 Breakpoint instructions
BKPT指令,软件断点指令,执行 BKPT 时触发调试事件,是软件断点的硬件基础。
4.4 External debug request
当PE处于non-debug state时,外部agent可以发出外部debug请求的信号。外部调试请求可能触发debug event,导致以下两种情况:
- 进入debug state。
- 如果Main extension被实现,DebugMonitor异常。
PE处于debug state时,忽略外部调试请求。
五、调试与跟踪功能组件
调试与跟踪功能组件(Debug and Trace Components)是实现breakpoint、watchpoint、trace输出的实体模块,全部为内存映射寄存器,可通过 DAP 或特权软件配置。
5.1 ITM(Instrumentation Trace Macrocell)
定位:软件插入式跟踪,轻量级非侵入调试
核心功能:
- 支持 32 个stimulus端口,软件通过写寄存器输出调试数据,实现类似 printf 的打印调试;如果ITM实现支持超过32个stimulus端口,则使用分页来指示stimulus端口号。
- 硬件事件跟踪:可上报异常进入 / 退出、PC 采样、数据观察点匹配等硬件事件;
- 时间戳功能:为跟踪数据包添加时间标记,支持时序分析;
- 同步包机制:周期性插入同步帧,保证跟踪数据解析的准确性。
特点:软件可控、开销低,适合应用层日志输出与事件打点。
5.2 DWT(Data Watchpoint and Trace)
定位:数据访问监控 + 基础性能统计
核心功能:
- 地址比较器:实现数据观察点,可配置为监控指令取指、内存读、内存写三类访问,地址匹配时触发调试事件或跟踪包;
- 支持地址范围匹配、数据值匹配(部分实现),满足条件断点、变量监控需求;
- 性能计数器:内置多个硬件计数器,可统计时钟周期、指令执行数、休眠周期、异常次数等,用于代码性能分析;
- 可生成跟踪数据包,将观察点命中事件、采样信息输出到跟踪链路。
特点:通用比较器资源,兼顾数据断点和性能统计。
5.3 ETM(Embedded Trace Macrocell)
定位:全量指令流跟踪,non-invasive程序路径trace,它是Armv8-M架构可选的non-invasive调试特性。
核心功能:
- 实时记录内核执行的全部指令流,支持压缩编码输出,调试器可重构完整程序执行路径;
- 支持触发控制:可配置开始 / 停止跟踪的条件(如地址匹配、外部触发),只捕获关注的代码段;
- 带时间戳标记,支持指令级时序分析;
- 完全non-invasive,不影响程序正常运行时序。
特点:适合排查偶发异常、时序相关问题,是高端调试的核心组件。
5.4 FPB(Flash Patch and Breakpoint)
定位:硬件指令断点 + Flash 在线热补丁
核心功能:
- 硬件指令断点:比较取指地址,匹配时触发断点,无需修改指令,适合 Flash 代码调试;
- Flash 补丁重定向:将指定 Flash 地址的取指 / 读操作,硬件重定向到 RAM 中的替代代码 / 数据,实现不擦写 Flash 的在线补丁;(该功能已废弃)
特点:是 IDE 硬件断点的底层实现,也是 Flash 在线升级 / 修复的硬件基础。
5.5 TPU(Trace Port Interface Unit)
Armv8-M的跟踪端口接口单元(TPIU)支持为来自DWT、ITM和ETM的trace data提供输出路径。TPIU是一个跟踪接收器。TPIU是否支持并行跟踪端口输出是由IMPLEMENTATION定义的。Arm建议TPIU同时提供并行和异步串行端口,以获得与外部捕获设备的最大灵活性。
5.6 PMU(Performance Monitor Unit)
性能监视器扩展描述了一个可选的非侵入性调试组件,它允许识别和计数性能事件。性能监视器扩展的一个实现称为性能监视单元(PMU)。
定位:系统级硬件事件统计,面向性能优化与调优
核心功能:
- 提供多个可编程计数器,可选择统计不同的硬件事件;最多可容纳31个IMPLEMENTATION DEFINED事件计数器(event counter)。每个性能事件计数器是一个16位的通用计数器。通过成对链接计数器,计数器范围可以通过将计数器数量减半来增加。如果实现了PMU,则至少需要2个16位的性能事件计数器和1个32位的cycle计数器。
- 标准化事件编号:规范定义了必选事件和可选事件,包括:
- 指令执行类:指令提交数、分支指令数、异常次数;
- 缓存类:指令缓存命中 / 失效、数据缓存命中 / 失效、缓存写回;
- 总线类:总线访问周期、内存访问等待周期;
- 调试类:DWT 比较器匹配事件、跟踪外部事件;
- 支持计数器溢出中断,可实现事件阈值告警、周期采样。
意义:为代码性能分析、瓶颈定位提供硬件级准确数据,无需软件插桩。
PMU提供广泛准确和统计上有用的计数信息。为了保持较低的实现和验证成本,计数中的合理程度的不准确性是可以接受的。PMU的常见事件列表如下。event类型有两大类:
Arch:
- Architecture event。这些事件在所有实现中都是相同的。
uArch:
- Microarchitecture event。这些事件在不同的实现中可能有所不同。
