语法
全局选项
命令
命令参考
gdbserver
启动用于远程调试的 GDB 服务器。这是建立调试连接的主要命令。
Box 根据探针选择后端。J-Link 探针使用 JLinkGDBServer,其他受支持的探针使用 OpenOCD。请参阅受支持的调试探针。
--box TEXT- Lager Box 名称或 IP--force / --no-force- 强制建立新连接(默认复用已有连接)--halt / --no-halt- 连接时让设备停住(默认 no-halt)--speed KHZ- SWD/JTAG 速度,单位 kHz(例如 100、4000),或 “adaptive”--quiet- 抑制提示性信息--json- 以 JSON 格式输出结果--rtt- 启动 GDB 服务器之后自动串流 RTT 日志--rtt-reset- 复位设备之后串流 RTT(可以捕获启动过程)-i, --interactive- 双向 RTT:把 stdin 转发到目标的 RTT 下行通道,同时把上行通道串流到 stdout(需要--rtt或--rtt-reset)--rtt-channel N- 要串流的 RTT 通道,两个方向都用它(默认0)--reset- 启动 GDB 服务器之后复位设备--gdb-port PORT- 覆盖自动分配的 GDB 服务器端口。默认情况下,Box 按探针槽位选择端口(第一个探针为 2331,第二个为 2334)。只有在需要特定端口时才传它。在多探针的 Box 上请避免使用。--rtt-search-addr HEX- 搜索 RTT 控制块的 RAM 起始地址(十六进制,例如0x20020000)--rtt-search-size HEX- 搜索 RTT 控制块的 RAM 区域大小(十六进制,例如0x4000)--rtt-chunk-size HEX- RTT 搜索的读取块大小(十六进制,例如0x1000)--local-port PORT- 在网关之后的 Box 上,隧道使用的本地端口(默认与 Box 上 GDB 服务器的端口相同)--no-tunnel- 在网关之后的 Box 上,启动 GDB 服务器后直接返回,不建立隧道
lager login)。网关会检查每个连接的登录状态。这类 Box 的 GDB 端口不对网络开放,因此 GDB 无法直接连接到 Box。
在这类 Box 上,gdbserver 启动 GDB 服务器之后,会通过网关建立一条隧道。隧道只在 localhost 上监听,端口号与 Box 上 GDB 服务器的端口相同。隧道打开期间,命令保持在前台运行:
- 命令会针对每台 Box 自行判断是否需要隧道,您不需要为此设置任何选项。
- 隧道打开期间,GDB 可以断开后重新连接,也可以有多个客户端同时连接。
- Ctrl-C 只关闭隧道,GDB 服务器继续在 Box 上运行。要停止它,请使用
lager debug <NET> disconnect。 - 如果本地端口已被占用,命令会报错并停止。请用
--local-port选择其他本地端口。 - 使用
--rtt、--rtt-reset或--interactive时,隧道在 RTT 串流期间保持打开。RTT 本身不经过隧道,而是作为普通 HTTP 通过网关。 - 使用
--json时,输出中带有一个tunnel对象,包含local_host和local_port,之后命令保持在前台运行。 - 如果脚本需要在 GDB 服务器启动后继续执行,可以使用
--no-tunnel。这时命令直接返回,不建立隧道。 - 如果管理员撤销了您对该 Box 的访问权限,网关会在大约一分钟内关闭隧道,命令会提示您。之后的下一个连接会收到访问错误。
disconnect
停止 GDB 服务器(JLinkGDBServer 或 OpenOCD)并释放调试资源。
--box TEXT- Lager Box 名称或 IP--keep-server- 让 GDB 服务器继续运行,供外部连接使用
flash
把固件烧录到目标。支持 Intel HEX、ELF 和二进制文件格式。
--box TEXT- Lager Box 名称或 IP--hex FILE- Intel HEX 文件的路径--elf FILE- ELF 可执行文件的路径--bin FILE,ADDRESS- 二进制文件及其加载地址,作为一个参数(例如build/app.bin,0x08000000)--verbose- 显示详细的 J-Link 输出--force-reconnect- 烧录前强制干净重连--no-erase- 跳过擦除步骤(默认情况下flash会先擦除再编程,以获得干净状态)--erase-start ADDR- 编程前擦除的起始地址,十六进制(0x16000000)或十进制。必须与--erase-size一起给出。--erase-size BYTES- 从--erase-start起擦除的字节数:十进制、0x十六进制,或带K/M后缀(例如2M)。--halt / --no-halt- 烧录之后让设备停住(默认 no-halt)
flash 默认会先擦除再编程,因此不需要任何标志就能得到干净状态(这正是 RTT 初始化所需要的)。只有当您有意保留现有闪存内容时才传 --no-erase。旧的 --erase 标志现在是空操作,仅为向后兼容而保留。--erase-start 和 --erase-size 设定这次擦除的范围,在两种后端上都有效。不带它们时,flash 擦除整片,在 DA1469x 上则从 0x16000000 擦除 1 MiB。下面的 erase 一节说明了范围的规则,以及它需要的 Box 版本。
失败输出:
- 如果编程前的擦除失败,
flash会打印Flash erase failed:和错误,然后以 1 退出。它不会对目标编程。 - 如果编程失败,
flash会打印Flash failed:和出错的那一行,然后打印The target was NOT programmed. If this ran without --no-erase it is now erased.,并以 1 退出。 - 如果回读比对失败,
flash会打印Flash failed:和出错的那一行,然后打印Flash does not read back as the image: the target holds a bad or partial image. Flash it again.,并以 1 退出。 - 在 J-Link 上,由探针的输出决定结果。以下几类行会使命令失败:连接失败、探针被另一个客户端占用、RAMCode 下载失败。例如
Selected interface (SWD) is not supported by the connected probe.和Failed to download RAMCode!。下面的erase一节列出了连接失败的行。成功还需要 J-Link 自己的证据:Downloading file之后要有J-Link: Flash download:行(或O.K.)。没有证据的烧录并没有对目标编程,命令会失败。 - J-Link 回读比对失败的行也会使命令失败:
Verification failed @ address 0x...、ERROR: Verify failed.或Error while programming flash: Verify failed.。DA1469x 是例外。它的比对经过带缓存的 XIP 窗口读取,对已经正确编程的器件也可能报告失败。在 DA1469x 上,只有 Box 的无缓存回读才会使命令失败。在 Box 上设置LAGER_DA1469_UNCACHED_VERIFY=1即可开启它。 - J-Link 烧录失败时,会追加
Diagnosis:行。这些行列出烧录期间使用该探针的其他 J-Link 程序。在 DA1469x 上,还会说明目标在编程期间是否复位。 - 如果您的目标的 J-Link 输出中没有这些证据行,请在 CLI 的环境中设置
LAGER_JLINK_REQUIRE_EVIDENCE=0。这样flash和erase就不再要求它们。失败行仍会使命令失败。
reset
复位目标设备。
--box TEXT- Lager Box 名称或 IP--halt / --no-halt- 复位后让设备停住(默认 no-halt)--force-reconnect- 复位前强制干净重连
erase
擦除目标上的闪存:全部,或用 --erase-start 和 --erase-size 给定的范围。这是一个破坏性操作。
在 DA1469x 上,erase 只擦除外部 QSPI 闪存的一段范围。请参阅
DA1469x 目标。
--box TEXT- Lager Box 名称或 IP--speed KHZ- SWD/JTAG 速度,单位 kHz(默认 4000)--yes- 跳过确认提示--quiet- 抑制警告信息。它同时也会跳过确认提示。--json- 以 JSON 格式输出结果。它同时也会跳过确认提示。--erase-start ADDR- 擦除的起始地址,十六进制(0x16000000)或十进制。必须与--erase-size一起给出。--erase-size BYTES- 从--erase-start起擦除的字节数:十进制、0x十六进制,或带K/M后缀(例如2M)。--halt / --no-halt- 擦除后让设备停住(默认 no-halt)
--erase-start 和 --erase-size 必须一起给出。--erase-start 接受十六进制(0x16000000)或十进制。--erase-size 接受十进制、0x 十六进制,或带 K/M 后缀(例如 2M,以 1024 为基数)。范围必须落在 32 位地址空间内。在 DA1469x 上,范围必须位于 0x16000000–0x17FFFFFF 之内,并且会取代 1 MiB 的默认值和 JLinkScript 中的 LAGER_ERASE_RANGE 行。在其他目标上,该范围取代全片擦除:J-Link 运行 erase <start> <end>,OpenOCD 运行 flash erase_address。无效的范围会在 CLI 联系 Box 之前就被拒绝。
0.50.0 及以上版本的 Box 接受该范围。在较旧的 Box 上,CLI 会在擦除之前拒绝这两个选项,并给出提到 lager update 的信息。Box 不会收到请求,因此也不会改为擦除它的默认范围。
成功时 CLI 会打印 Erase complete: 和 Box 实际擦除的范围,例如 Erase complete: 0x16000000-0x161FFFFF (2 MiB),或 Erase complete: full chip。早于 0.50.0 的 Box 不报告范围,此时 CLI 打印 Erase complete!。使用 --json 时,erase_range 字段包含 start、end(闭区间)、length、source 和 text。source 为 request、script 或 default。全片擦除时该字段为 null。
失败输出:
如果擦除失败,erase 会打印 Erase failed: 和错误,然后以 1 退出。
0.42.0 及以上版本的 Box 会自己识别 J-Link 连接失败并返回错误,CLI 会在 Erase failed: 之后打印该错误。
较旧的 Box 会返回探针输出而不报错。此时 CLI 会逐行检查那段输出。当某一行是、以下列信息开头,或以它们结尾时,该行判定为擦除失败:
ERROR: Could not connect to target.Could not connect to target.Could not connect to the target device.Cannot connect to target.Failed to power up DAP
Erase failed: 和该行,然后打印
The target was NOT erased. Check that it is connected and powered.
如果输出中没有这些行,erase 以 0 退出。
示例:
memrd
从目标设备读取内存。
START_ADDR- 起始内存地址(例如 0x20000000)LENGTH- 要读取的字节数
--box TEXT- Lager Box 名称或 IP--json- 以 JSON 格式输出结果--halt / --no-halt- 读取期间让设备停住(默认 no-halt)。--no-halt会覆盖 DA1469x QSPI XIP 的自动停住--no-reset- 仅 DA1469x。 跳过 Box 在读取之前执行的复位+停住。运行中的 DA1469x 会禁用 SWD,因此不做复位读取就会失败 —— 只有在芯片空白/已唤醒、且您不想重启它时才使用它
status
显示调试 Net 的状态和配置信息。
--box TEXT- Lager Box 名称或 IP
GDB server running 说的是 Box 上的那个进程。Target attached 说的是芯片本身:
Box 会去读取目标来回答它。这两个字段不同,因此 CLI 分开报告。
gdbserver 可能比它驱动的设备活得更久,而烧录或擦除类命令关心的是第二个字段,而不是第一个。
为了回答 Target attached,status 会通过正在运行的 GDB 服务器读取
Cortex-M 的 CPUID 寄存器。这次读取不会让内核停住。探针较慢时,
status 可能耗时多达 20 秒。
Target attached 在两种情况下显示 No:
- 该探针没有运行 GDB 服务器。
- GDB 服务器的日志记录了一次连接失败。
Target attached 显示 Unknown。以下情况会得到这个结果:
- Box 版本早于这个字段。
- 探针无法运行,因为已有调试器占用了该会话。
- 读取寄存器超时。
- OpenOCD 返回了空回复。
Unknown 并不表示目标不存在。
health
检查调试服务的健康状况和资源使用情况。
输出中包含一行 Features:Box 调试服务在原有请求之外支持的能力,例如支持 --erase-start 和 --erase-size 的 erase_range。早于该列表的 Box 会打印 none reported。
--box TEXT- Lager Box 名称或 IP--verbose- 显示详细的健康信息
列出调试 Net
只带--box 而不带子命令调用时,列出该 Lager Box 上的全部调试 Net:
RTT(实时传输)日志
RTT 通过调试探针提供低延迟的日志。请在gdbserver 上使用 --rtt 或 --rtt-reset 标志:
解码 defmt 日志
大多数 Rust 固件(以及不少 C 固件)通过 defmt 打日志,这是一种压缩的二进制格式。 来自 defmt 固件的原始 RTT 字节不是人类可读的。 必须由defmt-print 解码,而且它需要目标上烧录的那个确切的 ELF 文件。
- 请重定向 stderr。 RTT 负载写入 stdout,状态信息(
JLinkGDBServer started!等)写入 stderr。请只用管道传 stdout —— 追加2>/dev/null(或2>debug.log),这样状态行就绝不会污染defmt-print的输入。 - 这个流不会结束。
--rtt会一直运行,直到进程被终止。在脚本或非交互式会话中,请用timeout <seconds>把它包起来,以捕获一个固定的时间窗口。当您终止lager进程时,管道关闭,defmt-print会在 EOF 时退出。
.elf 的那台)用
cargo install defmt-print 安装 defmt-print。
交互式(双向)RTT
加上--interactive 可以在读取目标数据的同时向目标发送数据。您在 stdin 上输入的任何内容都会被转发到目标的 RTT 下行通道,通过 RTT 提供命令控制台的固件就是这样驱动的:
defmt-print 的组合方式和普通的 --rtt 完全一样:
--rtt-channel N 可以使用 0 以外的通道;两个方向使用同一个通道。
--interactive 需要终端。在脚本和其他非交互式场景中,请继续使用普通的 --rtt 加 timeout。
同一个探针和通道上同一时刻只能连接一个交互式会话,因为底层的 RTT 连接只接受一个客户端。第二次尝试会被拒绝,而不是悄悄地把数据流从第一个会话那里抢走。
典型工作流程
开发循环
RTT 调试
内存检查
清理
JLinkScript 支持
JLinkScript 文件让您可以为特定硬件配置定制 J-Link 调试探针的行为。它们可以处理自定义复位序列、时钟初始化、引脚配置,以及标准 J-Link 连接流程未覆盖的其他设备专有操作。配置 JLinkScript
有三种方式可以把 J-Link 脚本附加到调试 Net 上: 1. 创建 Net 时:.lager 配置中按项目设置:
脚本优先级
当 Net 级脚本(通过set-script 保存在 Box 上)和项目级脚本(位于 .lager 配置中)同时存在时,项目级脚本优先。这样您就可以为特定项目覆盖 Box 上保存的脚本。
管理脚本
DA1469x 目标
设备名称中含有DA1469 时会启用 DA1469x 专用处理。在这个系列上,
flash 和 erase 作用于外部 QSPI 闪存。CPU 把该闪存映射到 0x16000000
以便就地执行(XIP)。
- 地址。 请传入绝对的 XIP 地址,例如
--bin build/app.bin,0x16000000。不要传闪存偏移量。 - 擦除。 默认情况下,
erase以及flash之前的擦除,在两种后端上都从0x16000000擦除 1 MiB。这个系列从不做全片擦除。 - 擦除范围。
--erase-start和--erase-size在两种后端上设定范围,该范围必须位于0x16000000–0x17FFFFFF之内。在 J-Link 上,当这两个选项缺省时,该 Net 的 JLinkScript 中类似LAGER_ERASE_RANGE: 0x16000000 0x160FFFFF的一行会设定范围。J-Link 后端随后会擦除这个闭区间。选项优先于脚本行,脚本行优先于默认值。
- 超出
0x16000000–0x17FFFFFF的地址,在 Box 碰探针之前就会被拒绝。 - 请使用
--bin。加载器原样写入文件中的字节,因此它不解码.hex或.elf文件。 - 请把
flash_loader.elf和flash_loader.elf.bin放在 Box 宿主机的~/third_party/customer-binaries/openocd/flash-loaders/da1469x/中。容器把该目录看作/home/www-data/customer-binaries/openocd/flash-loaders/da1469x/。 - 若要使用其他父目录,请用
lager box-config env set把LAGER_FLASH_LOADERS_DIR设为一个容器内路径,然后运行lager box-config apply。 - OpenOCD 没有这个系列的内置目标配置。请用
lager nets set-script或lager nets add --openocd-config为该 Net 附加一份配置。 - 一次丢失的调试读取不会中止加载器。加载器会重试读取,直到该步骤的截止时间。截止时间为:启动 10 秒,擦除每 MiB 60 秒,每个编程块 30 秒。
受支持的调试探针
Box 根据探针的 USB 厂商 ID 选择后端。受支持的设备系列
Lager 支持 70 多个 ARM Cortex-M 设备系列,并能自动识别架构。创建调试 Net 时,设备型号作为通道给出(例如STM32F407VG、nRF52840)。
Cortex-M0/M0+(ARMv6-M)
Cortex-M3(ARMv7-M)
Cortex-M4/M7(ARMv7E-M)
Cortex-M23(ARMv8-M Base)
Cortex-M33/M55(ARMv8-M Main)
不在上表中的设备默认按 Cortex-M4(ARMv7E-M)架构处理。如果您的设备没有被正确识别,请在创建调试 Net 时给出完整的设备型号(例如
STM32F407VG,而不是只写 STM32F4)。说明
- 调试 Net 用
lager nets add <name> debug <device_type> <address>创建 - 对
flash和reset之类的命令,系统会在需要时自动连接 - 在
flash、erase和reset运行之前,CLI 会检查目标是否响应。如果 GDB 服务器已启动但目标没有响应,CLI 会打印The debug session is up, but the target does not answer; reconnecting...并开始一个新会话。如果重连失败,命令以 1 退出。 flash默认先擦除再编程,从而为 RTT 初始化提供干净状态(用--no-erase退出这一行为)- RTT 串流要求设备固件中具备 RTT 支持
- 用
--halt暂停 CPU 时,内存读取更可靠 - 用
lager debug health --verbose诊断连接问题 - JLinkScript 文件以 base64 编码保存,并在 Box 上自动解码
参见
- Python Debug API — 在 Python 脚本中自动完成烧录和调试
- Python 命令 — 在 Box 上运行测试脚本
- 术语表 — GDB、SWD 及其他术语的定义

