From 3aad5e230856fdd6b8c22a0510eb57927975fb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 24 May 2026 11:39:14 +0200 Subject: [PATCH] jtag: driver-neutral JTAG_TCK_FREQ_KHZ clock (phase A) One clock knob across probes instead of per-driver names: - jtag_open mirrors JTAG_TCK_FREQ_KHZ into PROBE_FTDI_TCK_FREQ_KHZ for the Viveris FTDI driver (read-only at init); unset leaves the existing value untouched - the Digilent driver reads JTAG_TCK_FREQ_KHZ directly instead of hardcoding 4 MHz (falls back to 4 MHz when unset) - documented in probes.yaml; CLAUDE.md design note marks phase A done FTDI path validated on the IGLOO2/FlashPro (250 kHz, mirror confirmed); Digilent path not hardware-tested. Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 7 +++++-- modules/drivers/digilent_jtag/digilent_jtag_drv.c | 9 ++++++++- modules/script/script.c | 14 ++++++++++++++ probes.yaml | 4 ++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b0211ef..42d52b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -183,8 +183,11 @@ fact bounded by both the probe and the board/device. ### Phasing -- **A** — one canonical `tck_khz` honoured by FTDI (shim) + Digilent - (read it): kills the immediate smell, one knob for the two real probes. +- **A (done)** — one canonical `JTAG_TCK_FREQ_KHZ` (kHz): mirrored to + `PROBE_FTDI_TCK_FREQ_KHZ` at `jtag_open` for the Viveris FTDI driver, + read directly by our Digilent driver; unset → each driver's own default + (FTDI 1000, Digilent 4000). Set it via `set`, a `probes.yaml` profile, + or `defaults:`. (FTDI path hardware-validated; Digilent path untested.) - **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). diff --git a/modules/drivers/digilent_jtag/digilent_jtag_drv.c b/modules/drivers/digilent_jtag/digilent_jtag_drv.c index 0a6bf52..fe455ea 100644 --- a/modules/drivers/digilent_jtag/digilent_jtag_drv.c +++ b/modules/drivers/digilent_jtag/digilent_jtag_drv.c @@ -15,6 +15,7 @@ #include "jtag_core/jtag_core.h" #include "jtag_core/dbg_logs.h" #include "config/bs_defines.h" +#include "script/env.h" #include "drivers/drv_loader.h" @@ -209,11 +210,17 @@ static int drv_Digilent_Detect(jtag_core *jc) static int drv_Digilent_Init(jtag_core *jc, int sub_drv, char *params) { - DJ_DWORD frq_req = 4000000; /* 4 MHz — safe and fast enough for IDCODE/IR */ + DJ_DWORD frq_req; DJ_DWORD frq_set = 0; + int tck_khz; (void)params; + /* Driver-neutral JTAG clock (JTAG_TCK_FREQ_KHZ, kHz). Unset/<=0 keeps + * the 4 MHz default — safe and fast enough for IDCODE/IR. */ + tck_khz = jtagcore_getEnvVarValue(jc, "JTAG_TCK_FREQ_KHZ"); + frq_req = (tck_khz > 0) ? (DJ_DWORD)tck_khz * 1000u : 4000000u; + /* Lazy enumeration: jtag_open can be called without going * through jtag_probes first, so make sure Detect ran. */ if (g_dj_num_probes == 0) { diff --git a/modules/script/script.c b/modules/script/script.c index 480c0a2..6b88854 100644 --- a/modules/script/script.c +++ b/modules/script/script.c @@ -1863,6 +1863,20 @@ static int cmd_open_probe(script_ctx *ctx, char *line) ctx->script_printf(ctx, MSG_INFO_0, "Applied probe profile '%s'.\n", profile); } + // Driver-neutral JTAG clock: if JTAG_TCK_FREQ_KHZ is set, feed it to + // the Viveris FTDI driver's own variable (it reads only PROBE_FTDI_*; + // our Digilent driver reads the neutral name directly). Harmless for + // the other drivers, which keep their defaults. + { + int tck_khz = jtagcore_getEnvVarValue(jc, "JTAG_TCK_FREQ_KHZ"); + if (tck_khz > 0) + { + char tck_str[24]; + snprintf(tck_str, sizeof(tck_str), "%d", tck_khz); + setEnvVarDat((envvar_entry *)ctx->env, "PROBE_FTDI_TCK_FREQ_KHZ", tck_str); + } + } + ret = jtagcore_select_and_open_probe(jc, id); if (ret != JTAG_CORE_NO_ERROR) { diff --git a/probes.yaml b/probes.yaml index 4cb1a53..3191551 100644 --- a/probes.yaml +++ b/probes.yaml @@ -15,6 +15,10 @@ defaults: # Baseline for a standalone FT2232H JTAG probe: drive ADBUS4 as the # "JTAG buffer enable" output (matches the built-in default). PROBE_FTDI_SET_PIN_DIR_ADBUS4: 1 + # Driver-neutral JTAG clock in kHz. Honoured by the FTDI driver (mapped + # to PROBE_FTDI_TCK_FREQ_KHZ at open) and our Digilent driver. Leave it + # out to keep each driver's own default (FTDI 1000, Digilent 4000). + # JTAG_TCK_FREQ_KHZ: 1000 profiles: # Embedded FlashPro on Microsemi eval kits (FT4232H, JTAG on channel A