probes: add probe-config profiles loaded from probes.yaml

- new modules/probes/ parses probes.yaml (libyaml): a defaults: map
  applied on every jtag_open + named profiles: selected with
  `jtag_open <idx> <profile>` (jtag_profiles lists them); each value is
  pushed into the script envvar store the driver reads at open time
- ships a flashpro profile (ADBUS4 high-Z) that lets the IGLOO2 kit's
  embedded FlashPro (FT4232H, port 0) detect the chain
- CLAUDE.md: decision entry for probes.yaml + a design note on the
  probe / JTAG-link / device config strategy (driver-neutral link layer)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 11:22:19 +02:00
parent 00320d87ec
commit 4ee1c2b631
7 changed files with 419 additions and 2 deletions

View File

@@ -116,6 +116,21 @@ probe" if the libs are absent), it costs nothing to build in:
disable with `-DBS_ENABLE_DIGILENT=OFF`. Adept Runtime is only needed
at runtime to actually drive such a probe.
### Probe config profiles (probes.yaml)
Probe wiring/electrical settings live in `probes.yaml` (parsed by
`modules/probes/`, libyaml), layered on top of the built-in
`config.script` defaults: a `defaults:` map applied on every `jtag_open`
(so opening without a profile is deterministic) plus named `profiles:`
selected with `jtag_open <idx> <profile>` (`jtag_profiles` lists them).
Each key/value is pushed into the script envvar store the driver reads at
open time. The mechanism is driver-agnostic (any `set`-able probe var),
but today only the FTDI driver (and minimally the Linux-GPIO one) reads
config envvars, so profiles mostly tune FTDI. Motivating case: the
embedded FlashPro on Microsemi kits (FT4232H ch.A) needs ADBUS4 high-Z —
the `flashpro` profile sets `PROBE_FTDI_SET_PIN_DIR_ADBUS4: 0`. See the
config-strategy design note below for where this is headed.
### Xilinx caveats
On 7-Series / UltraScale / UltraScale+, `CCLK` is not a regular I/O
@@ -127,6 +142,57 @@ The FPGA must be in a configurable state before loading the proxy.
Issue `JPROGRAM` first to reset, then `CFG_IN` + shift the bitstream,
then `JSTART` and check `DONE`.
## Probe / JTAG-link / device config strategy (design note)
Partly built, partly planned. Guiding idea: **separate three concerns
that are conflated today, and express the shared JTAG-link settings in
driver-neutral terms that get resolved per session.**
### The three concerns
| Layer | What it owns | Where it lives | Applied |
|-------|-------------|----------------|---------|
| **Probe (sonde)** | driver + interface, pin map, buffer-enable, TRST/SRST pins, level-shift, *max TCK the adapter supports* | `probes.yaml` (done) | at `jtag_open` |
| **JTAG link** | TCK freq, RTCK, reset behaviour, chain layout — **driver-neutral names**, resolved to effective values | *missing today* | open, then refined after detect |
| **Device** | IDCODE/BSDL/IR/proxy/caveats, programming method, *max TCK the part/board tolerates* | `fpga_registry.yaml` (done) | after IDCODE match |
### The smell that motivated this
Frequency has no single home. Only the FTDI driver reads
`PROBE_FTDI_TCK_FREQ_KHZ`; our Digilent driver **hardcodes 4 MHz**
(`digilent_jtag_drv.c`); J-Link/LPT read nothing. And the `PROBE_FTDI_*`
namespace mixes probe *wiring* (pin map, ADBUS4) with *link* properties
(freq, RTCK, TRST timing). Frequency isn't an FTDI fact — it's a link
fact bounded by both the probe and the board/device.
### Target model
- **Driver-neutral link vars** (`tck_khz`, `rtck`, `reset`, …) set once
(by user / probe defaults / device). Each driver consumes them: our
Digilent driver reads them directly; the Viveris FTDI driver is fed
`PROBE_FTDI_TCK_FREQ_KHZ` via a thin translation shim at open (no
Viveris edit). J-Link/LPT can stay on their defaults.
- **Resolution**: effective `tck = min(user request, probe max, device/
board max)`. A small session step computes it at open, and re-applies
after `jtag_autoinit` once the device (hence its cap / programming
method) is known — using the `jtag_close`→reopen seam if a re-init is
needed. This also dissolves the chicken-and-egg: a conservative link
default gets you to detection, then the device refines it.
- `probes.yaml` gains an optional `max_tck_khz`; `fpga_registry.yaml`
gains optional `max_tck_khz` + a `prog` method tag (`proxy_spi`/`svf`).
### Phasing
- **A** — one canonical `tck_khz` honoured by FTDI (shim) + Digilent
(read it): kills the immediate smell, one knob for the two real probes.
- **B** — device `max_tck_khz` + resolution after `jtag_autoinit`.
- **C** — generalise the other link settings (reset/RTCK) and wire the
`prog` method tag into backend dispatch (ties into the SVF player).
What exists already: the **probe layer** (`probes.yaml`) and the
**device layer** (`fpga_registry.yaml`). The new work is the **JTAG-link
layer** in the middle.
## Programming backends: beyond Xilinx external flash (design note)
Not yet implemented — captured so the design is ready. Guiding vision: