Rust in Everything
基于 probe-rs 0.32.0

PROBE_RS_TARGETS_DIR 设了,芯片还是找不到

主线位置:命令主线「attach」之前按芯片名查目标的那一步。目标描述怎么从 YAML 变成注册表,在目标描述:YAML 到注册表里讲过;本页讲两个名字很像、时机完全不同的入口。

flowchart TB
  dir["PROBE_RS_TARGETS_DIR"] -->|"只在 cargo build probe-rs 时"| br["build.rs:一起编进 targets.bincode"]
  br --> bin["新编出的 probe-rs 二进制"]
  inst["已经装好的 probe-rs"] -.->|"运行时不读这个变量"| miss["ChipNotFound"]
  cdp["--chip-description-path 或 PROBE_RS_CHIP_DESCRIPTION_PATH"] -->|"运行时"| add["add_target_family_from_yaml"]
  add --> ok["注册表里有了"]

现象

一个最小的自定义目标(一个 Cortex-M3 核、一块 RAM、一块 NVM,没有 flash 算法),放在 targets/my_board.yaml。设了环境变量再起 gdb server:

$ PROBE_RS_TARGETS_DIR=targets probe-rs gdb --dry-run --chip MYCHIP_F103 --gdb-connection-string 127.0.0.1:13601
Error: The chip 'MYCHIP_F103' was not found in the database.

Caused by:
    The requested chip 'MYCHIP_F103' was not found in the list of known targets.

同一个文件换成命令行参数,或者换成另一个环境变量:

$ probe-rs gdb --dry-run --chip MYCHIP_F103 --chip-description-path targets/my_board.yaml --gdb-connection-string 127.0.0.1:13601
Read  DHCSR: 0xe000edf0 = 0x10000
Write DHCSR = 0xa05f0001
...
Firing up GDB stub for Armv7m cores at [127.0.0.1:13601]
$ PROBE_RS_CHIP_DESCRIPTION_PATH=targets/my_board.yaml probe-rs gdb --dry-run --chip MYCHIP_F103 --gdb-connection-string 127.0.0.1:13602
...
Firing up GDB stub for Armv7m cores at [127.0.0.1:13602]

(用 gdb --dry-run 是因为它是本机没有探针时唯一能走到 attach 的命令,见 No connected probes were found.。)

从哪来

PROBE_RS_TARGETS_DIR 在整个仓库里只出现在核心库的 build.rs 里:

// probe-rs/build.rs
    let mut source_paths = vec![PathBuf::from("targets")];

    // Check if there are any additional targets to generate for
    if let Ok(additional_target_dir) = env::var("PROBE_RS_TARGETS_DIR") {
        println!("cargo:rerun-if-changed={additional_target_dir}");
        source_paths.push(PathBuf::from(&additional_target_dir));
    }

    probe_rs_target::process_targets(&source_paths, &dest_path);

它是编译 probe-rs 这个 crate 时的输入:设了它再 cargo build,那个目录里的 YAML 会和内置的 242 个一起编进 targets.bincode、include_bytes! 进二进制(目标描述)。对一个已经装好的 probe-rs 可执行文件,或者一个已经编好的、依赖 probe-rs 的程序,运行时设它没有任何作用。build.rs 还登记了 rerun-if-env-changed,所以改这个变量会让 probe-rs 重新编译,这是它唯一的「运行时」痕迹。

报错有两层:外层「The chip … was not found in the database.」是命令行的 OperationError::ChipNotFound,Caused by 里是库的 RegistryError::ChipNotFound。和库用户找不到 esp32c3是同一个错误,原因不同。

运行时的入口是 --chip-description-path(common_options.rs:97),它绑定的环境变量叫 PROBE_RS_CHIP_DESCRIPTION_PATH。两条路径读它的地方不一样:

入口怎么加进注册表
gdb、cargo-embed 等直接调库的命令maybe_load_chip_desc 读文件、add_target_family_from_yaml
run、download 等走 RPC 的命令客户端读成字符串,用 chips/load 发给服务端的注册表(cli.rs:75,CLI 的 RPC 架构)
VS Codelaunch.json 的 chipDescriptionPath(VS Code 调试配置)
自己的程序Registry::add_target_family_from_yaml,再 attach_with_registry

注意一个参数只能给一个文件,一个文件是一个家族;add_target_family 按家族名替换同名的旧家族,所以也能用来覆盖内置目标的定义(目标描述)。

怎么办

  • 用装好的 probe-rs:--chip-description-path my_board.yaml,或在 shell 里设 PROBE_RS_CHIP_DESCRIPTION_PATH,也可以写进配置文件的预设(--preset)。
  • 想让自定义目标成为「内置」:设 PROBE_RS_TARGETS_DIR 后从源码编译 probe-rs(或者编译依赖它的自己的程序),YAML 写错时构建直接失败。
  • 自己写的工具:Registry::from_builtin_families() 之后 add_target_family_from_yaml,用 attach_with_registry 而不是 attach(后者每次新建一个只有内置目标的注册表)。
  • 没有 flash 算法的目标能 attach、调试、往 RAM 下载,不能烧 flash;要烧录,用 target-gen 从 CMSIS-Pack 或自己的算法 ELF 生成完整的 YAML。

小结

  • PROBE_RS_TARGETS_DIR 是 probe-rs 的编译期输入,只在 build.rs 里读,对装好的二进制无效,结果是「The chip … was not found in the database.」。
  • 运行时加目标用 --chip-description-path / PROBE_RS_CHIP_DESCRIPTION_PATH,库里用 add_target_family_from_yaml 加 attach_with_registry。
  • 走 RPC 的命令把 YAML 发给服务端注册,直接调库的命令就地注册,VS Code 用 chipDescriptionPath。

💬 关联讨论

发起讨论
加载中...