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>
73 lines
3.0 KiB
C
73 lines
3.0 KiB
C
#ifndef _BSCAN_H
|
|
#define _BSCAN_H
|
|
|
|
/*
|
|
* Single-device JTAG primitives and BSCAN-proxy operations.
|
|
*
|
|
* Provides:
|
|
* - low-level JTAG TAP primitives (set_ir, shift_ir, shift_dr,
|
|
* idle_cycles, tap_reset) that operate directly on jc->io_functions,
|
|
* leaving jtag_core untouched. These are the building blocks the SVF
|
|
* player and the proxy paths share;
|
|
* - bitstream loading via CFG_IN to install a BSCAN proxy in the FPGA
|
|
* fabric (Xilinx);
|
|
* - a fast SPI transfer routine via USER1 once the proxy is loaded.
|
|
*
|
|
* (Was modules/bscan_spi/ — renamed once it grew past the SPI bridge
|
|
* into general TAP primitives.)
|
|
*
|
|
* Current assumption: single device on the JTAG chain. Multi-device
|
|
* support requires knowing the IR length of bypassed devices; defer.
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include "jtag_core/jtag_core.h"
|
|
#include "fpga/fpga.h"
|
|
|
|
/* --- Low-level primitives (single-device chain) -------------------- */
|
|
|
|
/* Shift `opcode` into IR. `ir_length` is the IR width in bits. */
|
|
int bscan_set_ir(jtag_core *jc, unsigned int opcode, int ir_length);
|
|
|
|
/* Shift `nbits` through DR. `tdi` may be NULL (shifts zeros).
|
|
* `tdo` may be NULL (write only). Both buffers are LSB-first per byte. */
|
|
int bscan_shift_dr(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits);
|
|
|
|
/* Like bscan_shift_dr but through Shift-IR — a general IR scan with TDO
|
|
* capture (bscan_set_ir is opcode-only). Single-device chain; buffers
|
|
* LSB-first per byte. Both ends in Run-Test/Idle. */
|
|
int bscan_shift_ir(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits);
|
|
|
|
/* Emit `ncycles` TCK cycles while staying in Run-Test/Idle. */
|
|
int bscan_idle_cycles(jtag_core *jc, int ncycles);
|
|
|
|
/* Force Test-Logic-Reset (5 TCK with TMS=1) and land in Run-Test/Idle. */
|
|
int bscan_tap_reset(jtag_core *jc);
|
|
|
|
/* --- High-level operations ---------------------------------------- */
|
|
|
|
/* Load a raw bitstream payload (no .bit container header) into the
|
|
* FPGA via JPROGRAM -> CFG_IN -> shift -> JSTART. Bit-reverses each
|
|
* byte before shifting (Xilinx convention). */
|
|
int bscan_load_bitstream(jtag_core *jc, const fpga_target *t,
|
|
const uint8_t *data, size_t nbytes);
|
|
|
|
/* Convenience wrapper: read a file and load it. Detects the Xilinx
|
|
* .bit header and skips it; otherwise treats the file as raw payload. */
|
|
int bscan_load_bitstream_file(jtag_core *jc, const fpga_target *t,
|
|
const char *path);
|
|
|
|
/* One CS-framed SPI transaction through the BSCAN proxy (USER1 DR):
|
|
* clock out `txlen` MOSI bytes (e.g. command + address + write data),
|
|
* then read `rxlen` MISO bytes into `rx`. Either length may be 0.
|
|
* Bytes are MSB-first on the wire; bit-order juggling is internal.
|
|
* Follows the quartiq/OpenOCD jtagspi proxy framing. Single-device
|
|
* chain only. Requires a proxy bitstream already loaded (USER1 live). */
|
|
int bscan_spi_xfer(jtag_core *jc, const fpga_target *t,
|
|
const uint8_t *tx, size_t txlen,
|
|
uint8_t *rx, size_t rxlen);
|
|
|
|
#endif
|