Files
bs_explorer/modules/bscan_spi/bscan_spi.h
François 0c9cc679f1 bscan_spi: implement bscan_spi_xfer over the jtagspi proxy
One CS-framed transaction: marker + 32-bit count + MOSI + read-latency
skip + MISO, MSB-first on the wire, matching OpenOCD's jtagspi so the
quartiq proxy bitstreams work unchanged. Half-duplex (tx,txlen,rx,rxlen)
signature, single-device chain.

NOT yet validated on hardware — protocol follows the OpenOCD reference
but has not been confirmed against a live proxy + flash. Validation
(read JEDEC ID on the KCU105) is the next step.
2026-05-23 17:16:19 +02:00

64 lines
2.6 KiB
C

#ifndef _BSCAN_SPI_H
#define _BSCAN_SPI_H
/*
* BSCAN-proxy SPI bridge (Phase 2.5).
*
* Provides:
* - low-level JTAG primitives (set_ir, shift_dr, idle_cycles) that
* operate directly on jc->io_functions, leaving jtag_core untouched;
* - bitstream loading via CFG_IN to install a BSCAN proxy in the FPGA
* fabric;
* - a fast SPI transfer routine via USER1 once the proxy is loaded.
*
* Current assumption: single device on the JTAG chain. Multi-device
* support requires knowing the IR length of bypassed devices; defer.
*
* The SPI transfer entry point is wired against the quartiq jtagspi
* proxy convention but the protocol header still needs to be confirmed
* against an actual proxy bitstream (see openocd src/flash/nor/jtagspi.c).
*/
#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);
/* Emit `ncycles` TCK cycles while staying in Run-Test/Idle. */
int bscan_idle_cycles(jtag_core *jc, int ncycles);
/* --- 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