phase 2.5: add bscan_spi/ — BSCAN proxy infrastructure
Low-level JTAG primitives operating directly on jc->io_functions (single-device chain assumed), independent of jtag_core: - bscan_set_ir - bscan_shift_dr (TDI/TDO, LSB-first packing) - bscan_idle_cycles High-level operations driven by an fpga_target descriptor: - bscan_load_bitstream: JPROGRAM -> CFG_IN -> shift (bit-reversed for Xilinx) -> JSTART -> idle -> BYPASS - bscan_load_bitstream_file: parses the Xilinx .bit container header (sections a/b/c/d/e), falls back to raw .bin bscan_spi_xfer is stubbed: the quartiq jtagspi protocol details will be wired once we have a proxy .bit to validate against (OpenOCD src/flash/nor/jtagspi.c is the host-side reference). Three new script commands: - bscan_set_ir <opcode_hex> <ir_length> - bscan_shift_dr <nbits> (writes zeros, prints captured TDO) - bscan_load_bitstream <device> <path> The sanity check for a healthy primitive on KU15P: jtag_init_scan; bscan_set_ir 9 6; bscan_shift_dr 32 -> 04 A5 60 93 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
#include "os_interface/os_interface.h"
|
||||
#include "fpga/fpga.h"
|
||||
#include "bscan_spi/bscan_spi.h"
|
||||
|
||||
#include "env.h"
|
||||
|
||||
@@ -2793,6 +2794,116 @@ static int cmd_fpga_info(script_ctx *ctx, char *line)
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
const char *cmd_bscan_set_ir_help[] = {
|
||||
"<opcode_hex> <ir_length>",
|
||||
"Shifts <opcode_hex> into the IR (single-device chain).",
|
||||
"Useful for testing the low-level JTAG primitives.",
|
||||
""};
|
||||
static int cmd_bscan_set_ir(script_ctx *ctx, char *line)
|
||||
{
|
||||
char op_txt[DEFAULT_BUFLEN];
|
||||
char len_txt[DEFAULT_BUFLEN];
|
||||
unsigned int opcode;
|
||||
int ir_length, ret;
|
||||
jtag_core *jc = (jtag_core *)ctx->app_ctx;
|
||||
|
||||
if (get_param(ctx, line, 1, op_txt) < 0 || get_param(ctx, line, 2, len_txt) < 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_set_ir <opcode_hex> <ir_length>\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
opcode = (unsigned int)strtoul(op_txt, NULL, 16);
|
||||
ir_length = (int)strtoul(len_txt, NULL, 0);
|
||||
|
||||
ret = bscan_set_ir(jc, opcode, ir_length);
|
||||
if (ret < 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "bscan_set_ir failed (%d)\n", ret);
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
ctx->script_printf(ctx, MSG_INFO_0, "IR <- 0x%X (%d bits)\n", opcode, ir_length);
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
const char *cmd_bscan_shift_dr_help[] = {
|
||||
"<nbits>",
|
||||
"Shifts <nbits> zeros into DR, prints the captured TDO in hex (LSB first).",
|
||||
"Run after bscan_set_ir to read a register (e.g. IDCODE -> shift 32 bits).",
|
||||
""};
|
||||
static int cmd_bscan_shift_dr(script_ctx *ctx, char *line)
|
||||
{
|
||||
char nb_txt[DEFAULT_BUFLEN];
|
||||
int nbits, nbytes, i, ret;
|
||||
uint8_t *tdo;
|
||||
jtag_core *jc = (jtag_core *)ctx->app_ctx;
|
||||
|
||||
if (get_param(ctx, line, 1, nb_txt) < 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_shift_dr <nbits>\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
nbits = (int)strtoul(nb_txt, NULL, 0);
|
||||
if (nbits <= 0 || nbits > 8 * DEFAULT_BUFLEN) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "Invalid nbits\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
nbytes = (nbits + 7) / 8;
|
||||
tdo = calloc(1, (size_t)nbytes);
|
||||
if (!tdo) return JTAG_CORE_MEM_ERROR;
|
||||
|
||||
ret = bscan_shift_dr(jc, NULL, tdo, nbits);
|
||||
if (ret < 0) {
|
||||
free(tdo);
|
||||
ctx->script_printf(ctx, MSG_ERROR, "bscan_shift_dr failed (%d)\n", ret);
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
ctx->script_printf(ctx, MSG_INFO_0, "DR =");
|
||||
for (i = nbytes - 1; i >= 0; i--) {
|
||||
ctx->script_printf(ctx, MSG_NONE, " %.2X", tdo[i]);
|
||||
}
|
||||
ctx->script_printf(ctx, MSG_NONE, "\n");
|
||||
free(tdo);
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
const char *cmd_bscan_load_bitstream_help[] = {
|
||||
"<device> <path>",
|
||||
"Loads a bitstream (.bit or raw .bin) into device <device> via JPROGRAM/CFG_IN/JSTART.",
|
||||
"Device must be matched in the FPGA registry (run fpga_info to check).",
|
||||
""};
|
||||
static int cmd_bscan_load_bitstream(script_ctx *ctx, char *line)
|
||||
{
|
||||
char dev_txt[DEFAULT_BUFLEN];
|
||||
char path[DEFAULT_BUFLEN];
|
||||
int device, ret;
|
||||
unsigned long idcode;
|
||||
const fpga_target *t;
|
||||
jtag_core *jc = (jtag_core *)ctx->app_ctx;
|
||||
|
||||
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, path) < 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_load_bitstream <device> <path>\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
device = (int)strtoul(dev_txt, NULL, 0);
|
||||
|
||||
if (jtagcore_get_number_of_devices(jc) <= 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "No device on the chain. Run jtag_autoinit first.\n");
|
||||
return JTAG_CORE_NOT_FOUND;
|
||||
}
|
||||
idcode = jtagcore_get_dev_id(jc, device);
|
||||
t = fpga_lookup_by_idcode(idcode);
|
||||
if (!t) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "Device %d IDCODE 0x%.8lX not in FPGA registry\n", device, idcode);
|
||||
return JTAG_CORE_NOT_FOUND;
|
||||
}
|
||||
|
||||
ctx->script_printf(ctx, MSG_INFO_0, "Loading %s on device %d (%s)...\n", path, device, t->name);
|
||||
ret = bscan_load_bitstream_file(jc, t, path);
|
||||
if (ret < 0) {
|
||||
ctx->script_printf(ctx, MSG_ERROR, "bscan_load_bitstream_file failed (%d)\n", ret);
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
ctx->script_printf(ctx, MSG_INFO_0, "Bitstream loaded.\n");
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
cmd_list script_commands_list[] =
|
||||
{
|
||||
{"print", cmd_print, cmd_print_help},
|
||||
@@ -2837,6 +2948,9 @@ cmd_list script_commands_list[] =
|
||||
{"jtag_spi_rd_wr", cmd_spi_rd_wr, cmd_spi_rd_wr_help},
|
||||
{"fpga_list", cmd_fpga_list, cmd_fpga_list_help},
|
||||
{"fpga_info", cmd_fpga_info, cmd_fpga_info_help},
|
||||
{"bscan_set_ir", cmd_bscan_set_ir, cmd_bscan_set_ir_help},
|
||||
{"bscan_shift_dr", cmd_bscan_shift_dr, cmd_bscan_shift_dr_help},
|
||||
{"bscan_load_bitstream", cmd_bscan_load_bitstream, cmd_bscan_load_bitstream_help},
|
||||
{0, 0}};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user