#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 #include #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