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:
M | fpga.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;
}