jtagonizer

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 3a57395fbd2f921156afc6b83bd4e80966360f53
parent 467f3759def75594b106bd506d2d4d12bbab4446
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun,  5 Oct 2014 02:42:24 -0700

fpga: read status, report some errors

Diffstat:
Mfpga.c | 205++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 193 insertions(+), 12 deletions(-)

diff --git a/fpga.c b/fpga.c @@ -21,6 +21,80 @@ #include "jtag.h" +// See: UG470 Xilinx 7 Series FPGAs Configuration + +// 7-Series JTAG IR +#define IR_LEN 6 +#define IR_CFG_OUT 4 +#define IR_CFG_IN 5 +#define IR_JSHUTDOWN 13 + +// Config Packet Headers +#define CFG_DUMMY 0xFFFFFFFF +#define CFG_SYNC 0xAA995566 +#define CFG_NOP 0x20000000 +#define CFG_RD(addr,n) (0x28000000 | ((addr)<<13) | (n)) +#define CFG_WR(addr,n) (0x30000000 | ((addr)<<13) | (n)) + +// Config Registers +#define CR_CRC 0 +#define CR_FAR 1 +#define CR_FDRI 2 +#define CR_FDRO 3 +#define CR_CMD 4 +#define CR_CTL0 5 +#define CR_MASK 6 +#define CR_STAT 7 +#define CR_LOUT 8 +#define CR_COR0 9 +#define CR_MFWR 10 +#define CR_CBC 11 +#define CR_IDCODE 12 +#define CR_AXSS 13 +#define CR_COR1 14 +#define CR_WBSTAR 16 +#define CR_TIMER 17 +#define CR_BOOTSTS 22 +#define CR_CTL1 24 + +// CR_CMD commands +#define CMD_NULL 0 +#define CMD_WCFG 1 +#define CMD_MFW 2 +#define CMD_LFRM 3 +#define CMD_RCFG 4 +#define CMD_START 5 +#define CMD_RCAP 6 +#define CMD_RCRC 7 +#define CMD_AGHIGH 8 +#define CMD_SWITCH 9 +#define CMD_GRESTORE 10 +#define CMD_SHUTDOWN 11 +#define CMD_GCAPTURE 12 +#define CMD_DESYNC 13 +#define CMD_IPROG 15 +#define CMD_CRCC 16 +#define CMD_LTIMER 17 + +// CR_STAT bits +#define STAT_DEC_ERROR (1 << 16) +#define STAT_ID_ERROR (1 << 15) +#define STAT_DONE (1 << 14) +#define STAT_RELEASE_DONE (1 << 13) +#define STAT_INIT_B (1 << 12) +#define STAT_INIT_COMPLETE (1 << 11) +#define STAT_GHIGH_B (1 << 7) +#define STAT_GWE (1 << 6) +#define STAT_GTS_CFG_B (1 << 5) // 0 = IOs are HIGH-Z +#define STAT_EOS (1 << 4) // EndOfStartup +#define STAT_DCI_MATCH (1 << 3) +#define STAT_MMCM_LOCK (1 << 2) // all used MMCMs have locked +#define STAT_PART_SECURED (1 << 1) +#define STAT_CRC_ERROR (1 << 0) + +#define STAT_STATE(n) (((n) >> 18) & 7) +#define STAT_MODE(n) (((n) >> 8) & 7) + static void *loadfile(const char *fn, u32 *sz) { int fd; off_t end; @@ -47,34 +121,141 @@ static u8 bitrev(u8 x) { return x; } -int main(int argc, char **argv) { - JTAG *jtag; - u8 *data; - u32 sz, n; +static void swizzle(u32 *_data, int count) { + u8 *data = (void*) _data; + u8 a, b, c, d; + while (count-- > 0) { + a = data[0]; + b = data[1]; + c = data[2]; + d = data[3]; + data[0] = bitrev(d); + data[1] = bitrev(c); + data[2] = bitrev(b); + data[3] = bitrev(a); + data += 4; + } +} + +static int txn(JTAG *jtag, u32 *send, int scount, u32 *recv, int rcount) { + u32 n; - if (argc != 2) { - fprintf(stderr, "usage: fpga <bitfile>\n"); + swizzle(send, scount); + + jtag_goto(jtag, JTAG_RESET); + n = IR_CFG_IN; + jtag_ir_wr(jtag, IR_LEN, &n); + jtag_dr_wr(jtag, 32 * scount, send); + if (rcount) { + n = IR_CFG_OUT; + jtag_ir_wr(jtag, IR_LEN, &n); + jtag_dr_rd(jtag, 32 * rcount, recv); + jtag_goto(jtag, JTAG_RESET); + } + + if (jtag_commit(jtag)) { return -1; + } else { + swizzle(recv, rcount); + return 0; } +} + +static int fpga_rd_status(JTAG *jtag, u32 *status) { + u32 tx[5]; + tx[0] = CFG_SYNC; + tx[1] = CFG_NOP; + tx[2] = CFG_RD(CR_STAT, 1); + tx[3] = CFG_NOP; + tx[4] = CFG_NOP; + return txn(jtag, tx, 5, status, 1); +} - if ((data = loadfile(argv[1], &sz)) == NULL) return -1; +// not quite working... +static int fpga_shutdown(JTAG *jtag) { + u32 data[32], n; + u32 *tx = data; - for (n = 0; n < sz; n++) { - data[n] = bitrev(data[n]); + *tx++ = CFG_SYNC; + *tx++ = CFG_NOP; + *tx++ = CFG_WR(CR_MASK, 1); + *tx++ = 1; + *tx++ = CFG_WR(CR_CTL0, 1); + *tx++ = 0; + *tx++ = CFG_WR(CR_CMD, 1); + *tx++ = CMD_AGHIGH; + *tx++ = CFG_WR(CR_FAR, 1); + *tx++ = 0; + *tx++ = CFG_WR(CR_CMD, 1); + *tx++ = CMD_SHUTDOWN; + *tx++ = CFG_WR(CR_FAR, 1); + *tx++ = 0; + *tx++ = CFG_WR(CR_CMD, 1); + *tx++ = CMD_RCRC; + *tx++ = CFG_WR(CR_FAR, 1); + *tx++ = 0; + *tx++ = CFG_NOP; + *tx++ = CFG_NOP; + + if (txn(jtag, data, tx - data, NULL, 0)) return -1; + + n = IR_JSHUTDOWN; + jtag_ir_wr(jtag, IR_LEN, &n); + jtag_idle(jtag, 12); + return jtag_commit(jtag); +} + +int main(int argc, char **argv) { + JTAG *jtag; + u8 *data = NULL; + u32 sz, n; + + if (argc == 2) { + if ((data = loadfile(argv[1], &sz)) == NULL) { + fprintf(stderr, "error: cannot load '%s'\n", argv[1]); + return -1; + } + for (n = 0; n < sz; n++) { + data[n] = bitrev(data[n]); + } } if (jtag_mpsse_open(&jtag)) return -1; if (jtag_enumerate(jtag) < 0) return -1; if (jtag_select_by_family(jtag, "Xilinx 7")) return -1; + n = 0; + if (fpga_rd_status(jtag, &n)) { + fprintf(stderr, "error: failed to read status\n"); + return -1; + } + fprintf(stderr, "status: %08x S%d\n", n, STAT_STATE(n)); + if (data == NULL) return 0; + fprintf(stderr, "begin.\n"); - n = 5; - jtag_ir_wr(jtag, 6, &n); + n = IR_CFG_IN; + jtag_ir_wr(jtag, IR_LEN, &n); jtag_dr_wr(jtag, sz * 8, data); if (jtag_commit(jtag)) return -1; - fprintf(stderr, "done.\n"); + n = 0; + if (fpga_rd_status(jtag, &n)) { + fprintf(stderr, "failed to read status\n"); + return -1; + } + if (n & STAT_CRC_ERROR) { + fprintf(stderr, "error: bitstream CRC error\n"); + return -1; + } + if (n & STAT_ID_ERROR) { + fprintf(stderr, "error: bitstream part ID does not match\n"); + return -1; + } + if (n & STAT_INIT_COMPLETE) { + fprintf(stderr, "init complete\n"); + } + return 0; }