commit d2b56ad246d06155a345a18e5180010340acf983
parent 1e97450d418e9f688eccc4c9cf365a0fd2d6570c
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 27 Sep 2014 05:51:03 -0700
dap: cleanup
1MB/s read/write doable across DAP but zynq appears to only handle
half that rate at least fresh out of reset.
Diffstat:
M | Makefile | | | 4 | ++-- |
M | dap.c | | | 379 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
M | dap.h | | | 4 | ++-- |
3 files changed, 203 insertions(+), 184 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
-CFLAGS := -Wall -O2 -g
+CFLAGS := -Wall -O0 -g
-LIBS := -lusb-1.0
+LIBS := -lusb-1.0 -lrt
all: jtag dap
diff --git a/dap.c b/dap.c
@@ -13,165 +13,226 @@
// limitations under the License.
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "jtag.h"
#include "dap.h"
+#include <time.h>
+static u64 NOW(void) {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) return 0;
+ return (((u64) ts.tv_sec) * ((u64)1000000000)) + ((u64) ts.tv_nsec);
+}
+
typedef struct {
JTAG *jtag;
- u32 cache_ir;
- u32 cache_apnum;
- u32 cache_apaddr;
} DAP;
-int dap_ir_wr(DAP *dap, u32 ir) {
- if (dap->cache_ir != ir) {
- jtag_ir_wr(dap->jtag, 4, &ir);
- if (jtag_commit(dap->jtag)) {
- dap->cache_ir = 0xFFFFFFFF;
- return -1;
- }
- }
- return 0;
+static void q_dap_ir_wr(DAP *dap, u32 ir) {
+ jtag_ir_wr(dap->jtag, 4, &ir);
}
-int dap_dr_io(DAP *dap, u32 bitcount, u64 wdata, u64 *rdata) {
+static void q_dap_dr_io(DAP *dap, u32 bitcount, u64 wdata, u64 *rdata) {
if (rdata) {
*rdata = 0;
jtag_dr_io(dap->jtag, bitcount, &wdata, rdata);
} else {
jtag_dr_wr(dap->jtag, bitcount, &wdata);
}
- return jtag_commit(dap->jtag);
+}
+
+static void q_dap_abort(DAP *dap) {
+ u32 x;
+ u64 u;
+ x = DAP_IR_ABORT;
+ u = 8;
+ jtag_ir_wr(dap->jtag, 4, &x);
+ jtag_dr_wr(dap->jtag, 35, &u);
}
int dap_dp_rd(DAP *dap, u32 addr, u32 *val) {
- int retry = 30;
u64 u;
- dap_ir_wr(dap, DAP_IR_DPACC);
- dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
- while (retry-- > 0) {
- dap_dr_io(dap, 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;
- }
+ q_dap_ir_wr(dap, DAP_IR_DPACC);
+ q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
+ q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ if (jtag_commit(dap->jtag)) {
+ return -1;
}
- return -1;
+ if (XPACC_STATUS(u) != XPACC_OK) {
+ return -1;
+ }
+ *val = u >> 3;
+ return 0;
+}
+
+static void q_dap_dp_wr(DAP *dap, u32 addr, u32 val) {
+ q_dap_ir_wr(dap, DAP_IR_DPACC);
+ q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL);
+ //q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &s->u);
}
int dap_dp_wr(DAP *dap, u32 addr, u32 val) {
- int retry = 100;
- u64 u;
- u = XPACC_WR(addr);
- u |= (((u64) val) << 3);
- dap_ir_wr(dap, DAP_IR_DPACC);
- dap_dr_io(dap, 35, u, NULL);
- while (retry-- > 0) {
- dap_dr_io(dap, 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;
+ q_dap_dp_wr(dap, addr, val);
+ return jtag_commit(dap->jtag);
}
/* TODO: cache state, check errors */
int dap_ap_rd(DAP *dap, u32 apnum, u32 addr, u32 *val) {
u64 u;
- if ((dap->cache_apnum != apnum) || (dap->cache_apaddr != (addr & 0xFFFFFFF0))) {
- if (dap_dp_wr(dap, DPACC_SELECT,
- DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr))) {
- dap->cache_apnum = 0xFFFFFFFF;
- dap->cache_apaddr = 0xFFFFFFFF;
- return -1;
- }
- dap->cache_apnum = apnum;
- dap->cache_apaddr = addr;
+ q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr));
+ q_dap_ir_wr(dap, DAP_IR_APACC);
+ q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
+ q_dap_ir_wr(dap, DAP_IR_DPACC);
+ q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ if (jtag_commit(dap->jtag)) {
+ return -1;
+ }
+ if (XPACC_STATUS(u) != XPACC_OK) {
+ return -1;
}
- dap_ir_wr(dap, DAP_IR_APACC);
- dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
- dap_ir_wr(dap, DAP_IR_DPACC);
- dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
*val = (u >> 3);
return 0;
}
-int dap_ap_wr(DAP *dap, u32 apnum, u32 addr, u32 val) {
- u64 u;
- if ((dap->cache_apnum != apnum) || (dap->cache_apaddr != (addr & 0xFFFFFFF0))) {
- if (dap_dp_wr(dap, DPACC_SELECT,
- DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr))) {
- dap->cache_apnum = 0xFFFFFFFF;
- dap->cache_apaddr = 0xFFFFFFFF;
- return -1;
- }
- dap->cache_apnum = apnum;
- dap->cache_apaddr = addr;
- }
- dap_ir_wr(dap, DAP_IR_APACC);
- u = XPACC_WR(addr);
- u |= (((u64) val) << 3);
- dap_dr_io(dap, 35, u, NULL);
- dap_ir_wr(dap, DAP_IR_DPACC);
- dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
+int q_dap_ap_wr(DAP *dap, u32 apnum, u32 addr, u32 val) {
+ q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr));
+ q_dap_ir_wr(dap, DAP_IR_APACC);
+ q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL);
+ //q_dap_ir_wr(dap, DAP_IR_DPACC);
+ //q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
+ return 0;
+}
+
+int dap_mem_wr32(DAP *dap, u32 n, u32 addr, u32 val) {
+ if (addr & 3)
+ return -1;
+ if (q_dap_ap_wr(dap, n, APACC_TAR, addr))
+ return -1;
+ if (q_dap_ap_wr(dap, n, APACC_DRW, val))
+ return -1;
+ return jtag_commit(dap->jtag);
+}
+
+int dap_mem_rd32(DAP *dap, u32 n, u32 addr, u32 *val) {
+ if (addr & 3)
+ return -1;
+ if (q_dap_ap_wr(dap, n, APACC_TAR, addr))
+ return -1;
+ if (dap_ap_rd(dap, n, APACC_DRW, val))
+ return -1;
return 0;
}
-int dap_ap_wr_x(DAP *dap, u32 apnum, u32 addr, u32 val) {
- if ((dap->cache_apnum != apnum) || (dap->cache_apaddr != (addr & 0xFFFFFFF0))) {
- if (dap_dp_wr(dap, DPACC_SELECT,
- DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr))) {
- dap->cache_apnum = 0xFFFFFFFF;
- dap->cache_apaddr = 0xFFFFFFFF;
+int dap_mem_wr32x(DAP *dap, u32 n, u32 addr, u32 *val, u32 count) {
+#if 0
+ q_dap_ap_wr
+ dap_ap_wr(dap, 0, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32);
+ dap_ap_wr(dap, 0xf0000000, APACC_TAR, n);
+ dap_ap_wr_x(dap, 0, APACC_DRW, val);
+ u = XPACC_WR(APACC_DRW);
+ u |= (((u64) val) << 3);
+ for (i = 0; i < 1024; i++) {
+ for (n = 0; n < 1024; n++) {
+ jtag_dr_wr(dap->jtag, 35, &u);
+ }
+ jtag_commit(dap->jtag);
+ }
+ dap_ap_rd(dap, 0, APACC_CSW, &x);
+ dap_dp_rd(dap, DPACC_CSW, &y);
+ fprintf(stderr, "APCSW=%08x DPCSW=%08x\n", x, y);
+#endif
+ return -1;
+}
+
+int dap_mem_read(DAP *dap, u32 apnum, u32 addr, void *data, u32 len) {
+ u64 scratch[1024];
+ u32 *x = data;
+ u32 n;
+
+ if ((addr & 3) || (((u64) data) & 3)) {
+ // base and length must be aligned
+ return -1;
+ }
+
+ while (len > 0) {
+ // max transfer is 1K
+ // transfer may not cross 1K boundary
+ u32 xfer = 1024 - (addr & 0x3FF);
+ if (xfer > len) {
+ xfer = len;
+ }
+ q_dap_ap_wr(dap, apnum, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32);
+ q_dap_dr_io(dap, 35, XPACC_WR(APACC_TAR, addr), NULL);
+ // read txn will be returned on the next txn
+ q_dap_dr_io(dap, 35, XPACC_RD(APACC_DRW), NULL);
+ for (n = 0; n < (xfer-4); n += 4) {
+ q_dap_dr_io(dap, 35, XPACC_RD(APACC_DRW), &scratch[n/4]);
+ }
+ // dummy read of TAR to pick up last read value
+ q_dap_dr_io(dap, 35, XPACC_RD(APACC_TAR), &scratch[n/4]);
+ if (jtag_commit(dap->jtag)) {
return -1;
}
- dap->cache_apnum = apnum;
- dap->cache_apaddr = addr;
+ for (n = 0; n < xfer; n += 4) {
+ switch(XPACC_STATUS(scratch[n/4])) {
+ case XPACC_WAIT: fprintf(stderr,"w"); break;
+ case XPACC_OK: fprintf(stderr,"o"); break;
+ default: fprintf(stderr,"?"); break;
+ }
+ *x++ = scratch[n/4] >> 3;
+ }
+ fprintf(stderr,"\n");
+ len -= xfer;
+ addr += xfer;
}
- dap_ir_wr(dap, DAP_IR_APACC);
return 0;
}
+int dap_mem_write(DAP *dap, u32 apnum, u32 addr, void *data, u32 len) {
+ u32 *x = data;
+ u32 n;
-void dap_flush_cache(DAP *dap) {
- dap->cache_ir = 0xFFFFFFFF;
- dap->cache_apnum = 0xFFFFFFFF;
- dap->cache_apaddr = 0xFFFFFFFF;
+ if ((addr & 3) || (((u64) data) & 3)) {
+ // base and length must be aligned
+ return -1;
+ }
+
+ while (len > 0) {
+ // max transfer is 1K
+ // transfer may not cross 1K boundary
+ u32 xfer = 1024 - (addr & 0x3FF);
+ if (xfer > len) {
+ xfer = len;
+ }
+ q_dap_ap_wr(dap, apnum, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32);
+ q_dap_dr_io(dap, 35, XPACC_WR(APACC_TAR, addr), NULL);
+ for (n = 0; n < xfer; n += 4) {
+ q_dap_dr_io(dap, 35, XPACC_WR(APACC_DRW, *x++), NULL);
+ }
+ if (jtag_commit(dap->jtag)) {
+ return -1;
+ }
+ len -= xfer;
+ addr += xfer;
+ }
+ return 0;
}
DAP *dap_init(JTAG *jtag) {
DAP *dap = malloc(sizeof(DAP));
memset(dap, 0, sizeof(DAP));
dap->jtag = jtag;
- dap_flush_cache(dap);
return dap;
}
int dap_attach(DAP *dap) {
unsigned n;
u32 x;
- u64 u;
// make sure we abort any ongoing transactions first
- x = DAP_IR_ABORT;
- u = 8;
- jtag_ir_wr(dap->jtag, 4, &x);
- jtag_dr_wr(dap->jtag, 35, &u);
- dap_flush_cache(dap);
+ q_dap_abort(dap);
// attempt to power up and clear errors
for (n = 0; n < 100; n++) {
@@ -193,30 +254,7 @@ int dap_attach(DAP *dap) {
return -1;
}
-/// ap0csw 43800042 read okay
-/// ap0csw 438000c2 after fail and stuck
-
-int dap_mem_wr32(DAP *dap, u32 n, u32 addr, u32 val) {
- if (addr & 3)
- return -1;
- if (dap_ap_wr(dap, n, APACC_TAR, addr))
- return -1;
- if (dap_ap_wr(dap, n, APACC_DRW, val))
- return -1;
- return 0;
-}
-
-int dap_mem_rd32(DAP *dap, u32 n, u32 addr, u32 *val) {
- if (addr & 3)
- return -1;
- if (dap_ap_wr(dap, n, APACC_TAR, addr))
- return -1;
- if (dap_ap_rd(dap, n, APACC_DRW, val))
- return -1;
- return 0;
-}
-
-int read4xid(DAP *dap, u32 n, u32 addr, u32 *val) {
+static int read4xid(DAP *dap, u32 n, u32 addr, u32 *val) {
u32 a,b,c,d;
if (dap_mem_rd32(dap, n, addr + 0x00, &a)) return -1;
if (dap_mem_rd32(dap, n, addr + 0x04, &b)) return -1;
@@ -226,20 +264,20 @@ int read4xid(DAP *dap, u32 n, u32 addr, u32 *val) {
return 0;
}
-int readinfo(DAP *dap, u32 n, u32 base, u32 *cid, u32 *pid0, u32 *pid1) {
+static int readinfo(DAP *dap, u32 n, u32 base, u32 *cid, u32 *pid0, u32 *pid1) {
if (read4xid(dap, n, base + 0xFF0, cid)) return -1;
if (read4xid(dap, n, base + 0xFE0, pid0)) return -1;
if (read4xid(dap, n, base + 0xFD0, pid1)) return -1;
return 0;
}
-void dumptable(DAP *dap, u32 n, u32 base) {
+static void dumptable(DAP *dap, u32 n, u32 base) {
u32 cid, pid0, pid1, memtype;
u32 x, addr;
int i;
printf("TABLE @%08x ", base);
- if (readinfo(dap, n, addr, &cid, &pid0, &pid1)) {
+ if (readinfo(dap, n, base, &cid, &pid0, &pid1)) {
printf("<error reading cid & pid>\n");
return;
}
@@ -268,25 +306,9 @@ void dumptable(DAP *dap, u32 n, u32 base) {
}
}
-int main(int argc, char **argv) {
- JTAG *jtag;
- DAP *dap;
+int dap_probe(DAP *dap) {
unsigned n;
- u64 u;
u32 x, y;
- int i;
- u32 val = 0xbbbbbbbb;
-
- if (jtag_mpsse_open(&jtag)) return -1;
- if (jtag_enumerate(jtag) < 0) return -1;
- if (jtag_select_device(jtag, 0x4ba00477)) return -1;
-
- dap = dap_init(jtag);
- if (dap_attach(dap))
- return -1;
-
- dap_dp_rd(dap, DPACC_CSW, &x);
- printf("DPCSW=%08x\n", x);
for (n = 0; n < 256; n++) {
if (dap_ap_rd(dap, n, APACC_IDR, &x))
@@ -302,57 +324,54 @@ int main(int argc, char **argv) {
if (dap_ap_rd(dap, n, APACC_CSW, &x) == 0)
printf("AP%d CSW=%08x\n", n, x);
}
+ return 0;
+}
+
+u32 DATA[1024*1024];
+
+int main(int argc, char **argv) {
+ JTAG *jtag;
+ DAP *dap;
+ unsigned n;
+ u32 x;
+
+ if (jtag_mpsse_open(&jtag)) return -1;
+ if (jtag_enumerate(jtag) < 0) return -1;
+ if (jtag_select_device(jtag, 0x4ba00477)) return -1;
+
+ dap = dap_init(jtag);
+ if (dap_attach(dap))
+ return -1;
dap_dp_rd(dap, DPACC_CSW, &x);
printf("DPCSW=%08x\n", x);
+ dap_probe(dap);
+
#if 1
for (n = 0; n < 8; n++) {
x = 0xefefefef;
- dap_mem_rd32(dap, 1, 0x80090FE0 + n*4, &x);
+ //dap_mem_rd32(dap, 1, 0x80090FE0 + n*4, &x);
+ dap_mem_rd32(dap, 0, 0x00000000 + n*4, &x);
printf("%08x: %08x\n", n*4, x);
}
#endif
- dap_dp_rd(dap, DPACC_CSW, &x);
- printf("DPCSW=%08x\n", x);
-
-#if 0
- for (n = 0; n < 4096; n++) {
- dap_mem_wr32(dap, n*4, 0xeeeeeeee);
- }
- return 0;
-#endif
#if 0
-
- dap_ap_rd(dap, 0, APACC_CSW, &x);
- dap_dp_rd(dap, DPACC_CSW, &y);
- fprintf(stderr, "APCSW=%08x DPCSW=%08x\n", x, y);
-
- dap_ap_wr(dap, 0, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32);
- dap_ap_wr(dap, 0xf0000000, APACC_TAR, n);
- dap_ap_wr_x(dap, 0, APACC_DRW, val);
- u = XPACC_WR(APACC_DRW);
- u |= (((u64) val) << 3);
- for (i = 0; i < 1024; i++) {
- for (n = 0; n < 1024; n++) {
- jtag_dr_wr(dap->jtag, 35, &u);
- }
- jtag_commit(dap->jtag);
- }
- dap_ap_rd(dap, 0, APACC_CSW, &x);
- dap_dp_rd(dap, DPACC_CSW, &y);
- fprintf(stderr, "APCSW=%08x DPCSW=%08x\n", x, y);
-
+ //memset(DATA, 0xEE, sizeof(DATA));
+ for (n = 0; n < 1024*1024; n++) DATA[n] = n;
+ //for (n = 0; n < 10; n++)
+ dap_mem_write(dap, 0, 0, DATA, 192*1024);
#endif
-#if 0
- dap_ap_wr(dap, 0, APACC_CSW, APCSW_DBGSWEN | APCSW_INCR_SINGLE | APCSW_SIZE32);
- dap_ap_wr(dap, 0, APACC_TAR, n);
- for (n = 0; n < 4096; n++) {
- dap_ap_wr_x(dap, 0, APACC_DRW, 0xaaaaaaaa);
+#if 0
+ if (dap_mem_read(dap, 0, 0, DATA, 4096) == 0) {
+ for (n = 0; n < 16; n++) printf("%08x ",DATA[n]);
+ printf("\n");
}
- return 0;
+ //dap_mem_wr32(dap, 0, 0x10, 0x805038a1);
+ dap_dp_rd(dap, DPACC_CSW, &x);
+ printf("DPCSW=%08x\n", x);
#endif
return 0;
}
diff --git a/dap.h b/dap.h
@@ -12,8 +12,8 @@
#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 XPACC_RD(a) (0x1 | (((a) >> 1) & 6))
+#define XPACC_WR(a,v) ((((u64)(v)) << 3) | (0x0 | (((a) >> 1) & 6)))
/* DP addresses */
#define DPACC_RESERVED 0x0