commit a7d29a11b2b18d515f0303071251338960cae5ce
parent 7b0db42e5617040a6873d7af5736bfd6c9fcd570
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 20 Apr 2014 23:58:36 -0700
big pile of work in progress
- added bit level shift transaction tracing (#ifdef TRACE_JTAG)
- fixed bogus bitcount for TMS moves at end of a shift
- fixed bogus bitread paths
- started sketching out AP and DP access
Diffstat:
M | jtag-mpsse.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++------ |
M | jtag.c | | | 117 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
M | zynq.h | | | 57 | ++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
3 files changed, 215 insertions(+), 13 deletions(-)
diff --git a/jtag-mpsse.c b/jtag-mpsse.c
@@ -219,6 +219,22 @@ static int jtag_move(JTAG *jtag, int count, unsigned bits){
if (count > 32)
return -1;
+#if TRACE_JTAG
+ {
+ u64 tmp = bits;
+ int n;
+ fprintf(stderr,"TDI <- ");
+ for (n = 0; n < count; n++) {
+ fprintf(stderr, "X");
+ }
+ fprintf(stderr,"\nTMS <- ");
+ for (n = 0; n < count; n++) {
+ fprintf(stderr,"%c", (tmp & 1) ? '1' : '0');
+ tmp >>= 1;
+ }
+ fprintf(stderr,"\n");
+ }
+#endif
while (count > 0) {
xfer = (count > 6) ? 6 : count;
*p++ = 0x4b;
@@ -251,6 +267,29 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out,
if (count <= 0)
return -1;
+#if TRACE_JTAG
+ {
+ u64 tmp = bits;
+ int n;
+ fprintf(stderr,"TDI <- ");
+ for (n = 0; n < count; n++) {
+ fprintf(stderr,"%c", (tmp & 1) ? '1' : '0');
+ tmp >>= 1;
+ }
+ for (n = 0; n < movebits; n++)
+ fprintf(stderr,"%c", (tmp & 1) ? '1' : '0');
+ fprintf(stderr,"\nTMS <- ");
+ for (n = 0; n < count; n++)
+ fprintf(stderr,"0");
+ tmp = movebits;
+ for (n = 0; n < movebits; n++) {
+ fprintf(stderr,"%c", (tmp & 1) ? '1' : '0');
+ tmp >>= 1;
+ }
+ fprintf(stderr,"\n");
+ }
+#endif
+
bytes = count / 8;
readbytes = bytes;
iobytes = bytes;
@@ -281,7 +320,7 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out,
if (movebits > 6)
return -1; /* TODO */
*p++ = out ? 0x6b : 0x4b;
- *p++ = movebits;
+ *p++ = movecount - 1;
*p++ = ((bits & 1) << 7) | (movebits & 0x3F);
iobytes++;
}
@@ -294,7 +333,7 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out,
return -1;
if (out) {
- u64 n = 0;
+ u64 n = 0, bit;
unsigned shift = 0;
if (ftdi_read(jtag, buf, iobytes, 1000))
return -1;
@@ -305,12 +344,15 @@ int _jtag_shift(JTAG *jtag, int count, u64 bits, u64 *out,
}
while (readbits > 0) {
xfer = (readbits > 6) ? 6 : readbits;
- n |= ((*p++ & bitxfermask[xfer]) << shift);
- shift <<= xfer;
+ bit = ((*p++) >> (8 - xfer)) & bitxfermask[xfer];
+ n |= (bit << shift);
+ shift += xfer;
readbits -= xfer;
}
if (movecount) {
- n |= ((*p++ & bitxfermask[movecount]) << shift);
+ /* we only ever care about the first bit */
+ bit = ((*p++) >> (8 - movecount)) & 1;
+ n |= (bit << shift);
}
*out = n;
}
@@ -364,7 +406,7 @@ static int jtag_shift_ir(JTAG *jtag, int count, u64 bits,
#define MOVE_ANY_TO_RESET_IDLE 8,0b01111111
#define MOVE_IDLE_TO_SHIFTDR 3,0b001
#define MOVE_IDLE_TO_SHIFTIR 4,0b0011
-#define MOVE_SHIFTxR_TO_IDLE 2,0b011
+#define MOVE_SHIFTxR_TO_IDLE 3,0b011
void jtag_close(JTAG *jtag) {
diff --git a/jtag.c b/jtag.c
@@ -18,10 +18,84 @@
#include "jtag.h"
#include "zynq.h"
+void pause(const char *msg) {
+ char crap[1024];
+ fprintf(stderr,">>> %s <<<\n", msg);
+ fgets(crap, sizeof(crap), stdin);
+}
+
+int jtag_dp_rd(JTAG *jtag, u32 addr, u32 *val) {
+ int retry = 30;
+ u64 u;
+ jtag_ir_wr(jtag, DAP_IR_DPACC);
+ jtag_dr_io(jtag, 35, XPACC_RD(addr), NULL);
+ while (retry-- > 0) {
+ jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ switch (XPACC_STATUS(u)) {
+ case XPACC_OK:
+ *val = u >> 3;
+ return 0;
+ case XPACC_WAIT:
+ fprintf(stderr,"!");
+ continue;
+ default:
+ return -1;
+ }
+ }
+ return -1;
+}
+
+int jtag_dp_wr(JTAG *jtag, u32 addr, u32 val) {
+ int retry = 30;
+ u64 u;
+ u = XPACC_WR(addr);
+ u |= (((u64) val) << 3);
+ jtag_ir_wr(jtag, DAP_IR_DPACC);
+ jtag_dr_io(jtag, 35, u, NULL);
+ while (retry-- > 0) {
+ jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ switch (XPACC_STATUS(u)) {
+ case XPACC_OK:
+ return 0;
+ case XPACC_WAIT:
+ fprintf(stderr,"!");
+ continue;
+ default:
+ return -1;
+ }
+ }
+ return -1;
+}
+
+/* TODO: cache state, check errors */
+int jtag_ap_rd(JTAG *jtag, u32 addr, u32 *val) {
+ u64 u;
+ jtag_dp_wr(jtag, DPACC_SELECT, DPSEL_APSEL(0) | DPSEL_APBANKSEL(addr));
+ jtag_ir_wr(jtag, DAP_IR_APACC);
+ jtag_dr_io(jtag, 35, XPACC_RD(addr), NULL);
+ jtag_ir_wr(jtag, DAP_IR_DPACC);
+ jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ *val = (u >> 3);
+ return 0;
+}
+
+int jtag_ap_wr(JTAG *jtag, u32 addr, u32 val) {
+ u64 u;
+ jtag_dp_wr(jtag, DPACC_SELECT, DPSEL_APSEL(0) | DPSEL_APBANKSEL(addr));
+ jtag_ir_wr(jtag, DAP_IR_APACC);
+ u = XPACC_WR(addr);
+ u |= (((u64) val) << 3);
+ jtag_dr_io(jtag, 35, u, NULL);
+ jtag_ir_wr(jtag, DAP_IR_DPACC);
+ jtag_dr_io(jtag, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ return 0;
+}
+
int main(int argc, char **argv) {
JTAG *jtag;
unsigned n;
u64 u;
+ u32 x;
if (!(jtag = jtag_open()))
return -1;
@@ -31,11 +105,50 @@ int main(int argc, char **argv) {
if (jtag_select(jtag, 0x4ba00477))
return -1;
- if (jtag_ir_wr(jtag, DAP_IDCODE))
+ if (jtag_ir_wr(jtag, DAP_IR_IDCODE))
return -1;
if (jtag_dr_io(jtag, 32, 0, &u))
return -1;
-
fprintf(stderr,"idcode? %08lx\n", u);
+
+ jtag_dp_rd(jtag, DPACC_CSW, &x);
+ fprintf(stderr,"CSW %08x\n", x);
+
+ jtag_dp_wr(jtag, DPACC_CSW, DPCSW_CSYSPWRUPREQ | DPCSW_CDBGPWRUPREQ);
+ do {
+ jtag_dp_rd(jtag, DPACC_CSW, &x);
+ fprintf(stderr,"CSW %08x\n", x);
+ } while ((x & (DPCSW_CSYSPWRUPACK | DPCSW_CDBGPWRUPACK)) != (DPCSW_CSYSPWRUPACK | DPCSW_CDBGPWRUPACK));
+
+ jtag_ap_rd(jtag, APACC_BASE, &x);
+ fprintf(stderr,"base %08x\n", x);
+
+ jtag_ap_rd(jtag, APACC_IDR, &x);
+ fprintf(stderr,"idr %08x\n", x);
+
+#if STRESSTEST
+ for (n = 0; n < 0xFFFFFFFF; n++) {
+ u32 z = (n >> 16) | (n << 16);
+ x = 0xeeeeeeee;
+ jtag_ap_wr(jtag, APACC_TAR, z);
+ jtag_ap_rd(jtag, APACC_TAR, &x);
+ if (z != x) {
+ fprintf(stderr,"%08x != %08x\n", z, x);
+ }
+ //if ((n & 0xFFF) == 0)
+ fprintf(stderr,"%08x\r", z);
+ }
+
+ jtag_ap_wr(jtag, APACC_TAR, 0x12345678);
+#endif
+
+ jtag_ap_rd(jtag, APACC_TAR, &x);
+ fprintf(stderr,"tar %08x\n", x);
+
+#if 0
+ fprintf(stderr,"done\n");
+ jtag_dp_wr(jtag, DPACC_CSW, 0);
+#endif
+
return 0;
}
diff --git a/zynq.h b/zynq.h
@@ -2,11 +2,58 @@
/* ARM DAP Controller (4bit IR) */
#define DAP_IR_SIZE 4
-#define DAP_ABORT 0x08
-#define DAP_DPACC 0x0A
-#define DAP_APACC 0x0B
-#define DAP_IDCODE 0x0E
-#define DAP_BYPASS 0x0F
+#define DAP_IR_ABORT 0x08
+#define DAP_IR_DPACC 0x0A
+#define DAP_IR_APACC 0x0B
+#define DAP_IR_IDCODE 0x0E
+#define DAP_IR_BYPASS 0x0F
+
+#define XPACC_STATUS(n) ((n) & 0x3)
+#define XPACC_WAIT 0x1
+#define XPACC_OK 0x2
+#define XPACC_RD(n) (0x1 | (((n) >> 1) & 6))
+#define XPACC_WR(n) (0x0 | (((n) >> 1) & 6))
+
+#define DPACC_RESERVED 0x0
+#define DPACC_CSW 0x4
+#define DPACC_SELECT 0x8
+#define DPACC_RDBUFF 0xC
+
+#define DPCSW_CSYSPWRUPACK (1 << 31)
+#define DPCSW_CSYSPWRUPREQ (1 << 30)
+#define DPCSW_CDBGPWRUPACK (1 << 29)
+#define DPCSW_CDBGPWRUPREQ (1 << 28)
+#define DPCSW_CDBGRSTACK (1 << 27)
+#define DPCSW_CDBGRSTREQ (1 << 26)
+#define DPCSW_TRNCNT(n) (((n) & 0x3FF) << 12)
+#define DPCSW_MASKLANE(n) (((n) & 0xF) << 8) // pushed verify or compare
+#define DPCSW_WDATAERR (1 << 7) // reserved on jtag
+#define DPCSW_READOK (1 << 6) // reserved on jtag
+#define DPCSW_STICKYERR (1 << 5)
+#define DPCSW_STICKYCMP (1 << 4)
+#define DPCSW_TRNMODE_NORMAL (0 << 2)
+#define DPCSW_TRNMODE_PUSH_VRFY (1 << 2)
+#define DPCSW_TRNMODE_PUSH_CMP (2 << 2)
+#define DPCSW_STICKYORUN (1 << 1)
+#define DPCSW_ORUNDETECT (1 << 0)
+
+#define DPSEL_APSEL(n) (((n) & 0xFF) << 24)
+#define DPSEL_APBANKSEL(a) ((a) & 0xF0)
+#define DPSEL_CTRLSEL (1 << 0) // reserved on jtag
+
+/* Reading RDBUFF returns 0, has no side effects */
+/* Can be used to obtain final read result and ack values at end of seq */
+
+#define APACC_CSW 0x00
+#define APACC_TAR 0x04
+#define APACC_DRW 0x0C
+#define APACC_BD0 0x10
+#define APACC_BD1 0x14
+#define APACC_BD2 0x18
+#define APACC_BD3 0x1C
+#define APACC_CFG 0xF4
+#define APACC_BASE 0xF8
+#define APACC_IDR 0xFC
/* Xilinx TAP Controller (6bit IR) */