The Olimex ARM-USB-OCD (and any FT2232 with a custom USB id) couldn't be
enumerated by libftd2xx and needed a manual ftdi_sio unbind. libftdi1
(libusb) opens any VID:PID and auto-detaches the kernel driver.
- rewrite drivers/ftdi_jtag on libftdi1: enumerate a known VID:PID list
(incl. Olimex 15ba:0003/002b) with per-chip channel counts, open by
bus/addr + interface, MPSSE via ftdi_write_data/ftdi_read_data (+
SEND_IMMEDIATE for deterministic reads). MPSSE command building, pin
map and clocking unchanged.
- CMake: link libftdi1 + libusb-1.0 (pkg-config), drop FTDILIB/FTD2XX
defines and the libftd2xx.a link; remove the vendored src/libs/libftd2xx.
- registry: NXP LPC2103 (ARM7TDMI-S) entry, IDCODE 0x4F1F0F0F.
- docs updated (deps, layout, decision note, roadmap phase 8).
Validated on hardware: ARM-USB-OCD enumerates, jtag_scan reads the
LPC2103 IDCODE 0x4F1F0F0F, target_info -> [cpu, ARM7] prog: arm_flash.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Restructure in anticipation of programming ARM CPUs (ARM7/9 via
EmbeddedICE, e.g. over an Olimex ARM-USB-OCD); FPGA path unchanged.
- modules/fpga -> modules/target; fpga_target -> jtag_target with a
`kind` (fpga|cpu) and grouped fpga/cpu sub-structs; data/targets.yaml
(env BS_TARGETS); API target_*; commands target_list/target_info
(kind-aware). Add arm7/arm9 families, arm_flash prog, embeddedice
debug, and cpu fields (ram_base/size, flash_base/size).
- new program/: `program <dev> <file>` dispatches by the target's prog
(svf wired; proxy_spi points at the flash workflow; arm_flash -> arm_debug).
- new arm_debug/: EmbeddedICE halt/resume/mem + arm_flash backend
declared, not implemented yet.
- bscan_* take const jtag_target* and read the fpga sub-struct.
- data/probes.yaml: arm-usb-ocd profile slot; data/targets.yaml: an ARM7
example entry. Docs + an ARM-debug design note in CLAUDE.md.
Builds; FPGA path re-validated on the IGLOO2 (target_list shows the CPU
example; jtag_open/autoinit/program 0 <svf> all work).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Separate the two concerns the repo root was mixing:
- src/ — bs/, modules/, libs/ (code + vendored libs)
- data/ — fpga_registry.yaml, probes.yaml, bsdl_files/, bscan_proxies/,
scripts/ (everything the tool reads at runtime, CWD-relative)
- doc/ — kept at the root
CMake: repoint DIR_MODULES/DIR_LIBS and add_subdirectory at src/; emit
the binary at the build/ root (build/bs) via CMAKE_RUNTIME_OUTPUT_DIRECTORY
instead of the nested build/src/bs/. The jtag_core ../../libs path still
resolves since modules and libs moved together.
Runtime default paths now point under data/ (fpga.c, probes.c, script.c
bsdl_files lookup, init.c config.script). Docs (README/tutorial/CLAUDE)
updated for the new layout, src/ module paths, and ./build/bs.
Validated on the IGLOO2/FlashPro: profiles, autoinit, and svf_play all
work run from the repo root.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bring the docs up to date and keep each in its lane:
- README (overview): both programming paths (Xilinx proxy flash + SVF),
probe profiles, neutral JTAG clock + per-device cap, runtime YAML
registry, IGLOO2 bundled; run-from-repo-root fixed
- tutorial (user view): probe profiles + jtag_close, the prog tag, a
JTAG-clock section, a new "Programming via SVF" section, prog/max_tck
in the add-a-target table, troubleshooting rows
- CLAUDE.md (design): architecture tree lists the project modules + YAML
data files; roadmap gains phases 5 (probes/JTAG-link) and 6 (SVF)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New modules/svf/ plays the single-device SVF subset over the bscan_*
primitives: SIR/SDR with masked TDO compare, RUNTEST (TCK/SEC), STATE
(RESET/IDLE), ENDIR/ENDDR (IDLE only), HIR/HDR/TIR/TDR (length 0), TRST,
FREQUENCY. Exposed as `svf_play <file>`. It warms up the FTDI link
first — the MPSSE's first data read after open returns stale FIFO
content, normally hidden because jtag_scan runs before anything.
Also adds the bscan_tap_reset prototype. Validated on the live IGLOO2
M2GL010T: a hand-written IDCODE-check SVF passes (masked compare) and a
deliberately wrong one is caught at the mismatching bit. A generic
program dispatch off the prog tag, multi-device chains and non-IDLE end
states are still TODO.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The module outgrew its "SPI bridge" name — it's mostly generic
single-device JTAG TAP primitives now. Rename modules/bscan_spi ->
modules/bscan (dir, files, library target, includes, doc paths);
bscan_* function names and bscan_spi_xfer() kept.
Add the two primitives the SVF player needs beyond shift_dr:
- bscan_shift_ir: general IR scan with TDO capture (bscan_set_ir is
opcode-only, no readback)
- bscan_tap_reset: force Test-Logic-Reset, land in Run-Test/Idle
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 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>
Lets a session hand a probe back (frees its USB handle) without opening
another, e.g. to flash two FPGAs on different probes in turn:
jtag_close, then jtag_open the next one and jtag_autoinit. Mirrors the
DeInit teardown jtagcore_loaddriver already does when switching drivers.
Also fix the help printer: no-arg commands (whose params slot is "")
printed an empty body because "" was treated as the terminator. Params
are now optional and the description always shows.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- registry moves from the array in fpga.c to fpga_registry.yaml at the
repo root, parsed via libyaml (pkg-config yaml-0.1); adding a part is
now a YAML edit, no rebuild
- looked up CWD-relative (like bsdl_files/), overridable with
$BS_FPGA_REGISTRY, loaded lazily once; public API unchanged
- fpga_list shows the source file (fpga_registry_source())
- add microsemi_igloo2/smartfusion2 and lattice_machxo2/3 families,
ready for the non-Xilinx targets
- docs updated: CLAUDE.md, README, tutorial "add a target" walkthrough
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reflect what now works: per-FPGA registry, BSCAN proxy SPI bridge, and
flash detect/read/erase/program/verify (~100 KB/s). Switch the typical
flow to the proxy path, add the fpga/bscan/flash command rows, note
persistent history, the KU040 BSDL, the new modules + bscan_proxies/ in
the layout, and the quartiq MIT proxies in the license section.
The driver dlopen's libdjtg/libdmgr and degrades to "no probe" if
they're absent, so building it in has no cost or dependency.
BS_ENABLE_DIGILENT now defaults ON on UNIX (needs <dlfcn.h>); disable
with -DBS_ENABLE_DIGILENT=OFF. Docs updated; also fixes the quartiq
license note in CLAUDE.md (MIT, not BSD-2).
Drop the get_/set_/_pin/_list noise from the JTAG commands (e.g.
jtag_get_probes_list -> jtag_probes, jtag_set_spi_cs_pin -> jtag_spi_cs,
jtag_spi_rd_wr -> jtag_spi_xfer). jtag_open_probe -> jtag_open (not
jtag_probe, which would clash with jtag_probes under tab-completion).
Hard rename, no aliases. Updates the state-dump emitter, help text,
example script and docs accordingly.
CLAUDE.md/README/tutorial: optional BS_ENABLE_DIGILENT backend, why
SMT2 modules need libdjtg, and the new jtag_open_probe index. Mark
phases 2 and 2.5 done.
doc/tutorial.md walks from probe detection to JEDEC ID over EXTEST and
forward-references the BSCAN proxy path. Includes:
- prerequisites and build/launch
- chain scan, FPGA identification, registry lookup
- IR/DR primitive sanity check via the IDCODE register
- SPI JEDEC ID over EXTEST (with the speed caveat)
- recipe to add a new FPGA target
- troubleshooting cheat sheet
README and CLAUDE.md updated to point at it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>