jtagonizer

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

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:
MMakefile | 4++--
Mdap.c | 379+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mdap.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