jtagonizer

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

commit d8209428eb028a358f41c50ee3200ea5202550ca
parent 5bdbf977007e9c52b171e979f0cbfeae1ec3090d
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 22 Sep 2014 19:27:30 -0700

add enumeration and selection support

Diffstat:
Mjtag-core.c | 148++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mjtag.h | 25+++++++++++++++++++++++++
2 files changed, 161 insertions(+), 12 deletions(-)

diff --git a/jtag-core.c b/jtag-core.c @@ -18,6 +18,30 @@ #include "jtag-driver.h" + +#define ZYNQID(code) ((0x1B<<21)|(0x9<<17)|((code)<<12)|(0x49<<1)|1) +#define ZYNQMASK 0x0FFFFFFF + +static JTAG_INFO LIBRARY[] = { + { 0x4ba00477, 0xFFFFFFFF, 4, "Cortex A9" }, + { ZYNQID(0x02), ZYNQMASK, 6, "xc7x010" }, + { ZYNQID(0x1b), ZYNQMASK, 6, "xc7x015" }, + { ZYNQID(0x07), ZYNQMASK, 6, "xc7x020" }, + { ZYNQID(0x0c), ZYNQMASK, 6, "xc7x030" }, + { ZYNQID(0x11), ZYNQMASK, 6, "xc7x045" }, + { 0x13631093, 0xFFFFFFFF, 6, "xc7a100t" }, +}; + +JTAG_INFO *jtag_lookup_device(unsigned idcode) { + int n; + for (n = 0; n < (sizeof(LIBRARY)/sizeof(LIBRARY[0])); n++) { + if ((idcode & LIBRARY[n].idmask) == LIBRARY[n].idcode) { + return LIBRARY + n; + } + } + return NULL; +} + #define TRACE_STATEMACHINE 0 // configuration and state or IR or DR @@ -30,6 +54,8 @@ typedef struct JREG { u32 idlestate; } JREG; +#define DEVMAX 32 + // configuration and state of JTAG struct JTAG { JDRV *drv; @@ -39,6 +65,9 @@ struct JTAG { JREG dr; u32 state; + + int devcount; + JTAG_INFO devinfo[DEVMAX]; }; #define _setspeed(khz) \ @@ -52,8 +81,22 @@ struct JTAG { #define _close() \ jtag->vt->close(jtag->drv) -static u8 ZEROS[32]; -static u8 ONES[32]; +static u8 ONES[1024]; + +void jtag_clear_state(JTAG *jtag) { + jtag->ir.idlestate = JTAG_IDLE; + jtag->ir.scanstate = JTAG_IRSHIFT; + jtag->dr.idlestate = JTAG_IDLE; + jtag->dr.scanstate = JTAG_DRSHIFT; + jtag->ir.prebits = 0; + jtag->ir.precount = 0; + jtag->ir.postbits = 0; + jtag->ir.postcount = 0; + jtag->dr.prebits = 0; + jtag->dr.precount = 0; + jtag->dr.postbits = 0; + jtag->dr.postcount = 0; +} int jtag_init(JTAG **_jtag, JDRV *drv, JDVT *vt) { JTAG *jtag; @@ -63,13 +106,9 @@ int jtag_init(JTAG **_jtag, JDRV *drv, JDVT *vt) { memset(jtag, 0, sizeof(JTAG)); jtag->drv = drv; jtag->vt = vt; - jtag->ir.idlestate = JTAG_IDLE; - jtag->ir.scanstate = JTAG_IRSHIFT; - jtag->dr.idlestate = JTAG_IDLE; - jtag->dr.scanstate = JTAG_DRSHIFT; + jtag_clear_state(jtag); *_jtag = jtag; - memset(ZEROS, 0x00, 32); - memset(ONES, 0xFF, 32); + memset(ONES, 0xFF, sizeof(ONES)); return 0; } @@ -91,19 +130,19 @@ void jtag_set_dr_idle(JTAG *jtag, unsigned state) { } void jtag_set_ir_prefix(JTAG *jtag, unsigned count, const void *bits) { - jtag->ir.prebits = (u8*) bits; + jtag->ir.prebits = count ? (u8*) bits : 0; jtag->ir.precount = count; } void jtag_set_ir_postfix(JTAG *jtag, unsigned count, const void *bits) { - jtag->ir.postbits = (u8*) bits; + jtag->ir.postbits = count ? (u8*) bits : 0; jtag->ir.postcount = count; } void jtag_set_dr_prefix(JTAG *jtag, unsigned count, const void *bits) { - jtag->dr.prebits = (u8*) bits; + jtag->dr.prebits = count ? (u8*) bits : 0; jtag->dr.precount = count; } void jtag_set_dr_postfix(JTAG *jtag, unsigned count, const void *bits) { - jtag->dr.postbits = (u8*) bits; + jtag->dr.postbits = count ? (u8*) bits : 0; jtag->dr.postcount = count; } @@ -252,3 +291,88 @@ void jtag_dr_io(JTAG *jtag, unsigned count, const void *wbits, void *rbits) { int jtag_commit(JTAG *jtag) { return _commit(); } + +int jtag_enumerate(JTAG *jtag) { + JTAG_INFO *info; + u32 data[DEVMAX]; + int n; + + jtag_clear_state(jtag); + jtag->devcount = 0; + + jtag_goto(jtag, JTAG_RESET); + jtag_goto(jtag, JTAG_RESET); + jtag_goto(jtag, JTAG_RESET); + jtag_dr_io(jtag, DEVMAX * 4 * 8, ONES, data); + if (jtag_commit(jtag)) { + return -1; + } + for (n = 0; n < DEVMAX; n++) { + + if (data[n] == 0xffffffff) { + if (n == 0) { + fprintf(stderr, "no devices found\n"); + return -1; + } + jtag->devcount = n; + return n; + } + if (!(data[n] & 1)) { + fprintf(stderr, "device %d has no idcode\n", n); + return -1; + } + if ((info = jtag_lookup_device(data[n])) == NULL) { + fprintf(stderr, "device %d (id %08x) unknown\n", + n, (unsigned) data[n]); + return -1; + } + memcpy(jtag->devinfo + n, info, sizeof(JTAG_INFO)); + fprintf(stderr, "device %02d idcode %08x '%s'\n", + n, info->idcode, info->name); + } + fprintf(stderr, "too many devices\n"); + return -1; +} + +JTAG_INFO *jtag_get_nth_device(JTAG *jtag, int n) { + if ((n >= jtag->devcount) || (n < 0)) { + return NULL; + } + return jtag->devinfo + n; +} + +int jtag_select_device_nth(JTAG *jtag, int num) { + u32 irpre = 0; + u32 irpost = 0; + u32 drpre = 0; + u32 drpost = 0; + int n; + if ((num >= jtag->devcount) || (num < 0)) { + return -1; + } + for (n = 0; n < jtag->devcount; n++) { + if (n < num) { + irpre += jtag->devinfo[n].irsize; + drpre += 1; + } else if (n > num) { + irpost += jtag->devinfo[n].irsize; + drpost += 1; + } + } + jtag_set_ir_prefix(jtag, irpre, ONES); + jtag_set_ir_postfix(jtag, irpost, ONES); + jtag_set_dr_prefix(jtag, drpre, ONES); + jtag_set_dr_postfix(jtag, drpost, ONES); + return 0; +} + +int jtag_select_device(JTAG *jtag, unsigned idcode) { + int n; + for (n = 0; n < jtag->devcount; n++) { + if (jtag->devinfo[n].idcode == idcode) { + return jtag_select_device_nth(jtag, n); + } + } + return -1; +} + diff --git a/jtag.h b/jtag.h @@ -52,6 +52,10 @@ void jtag_set_ir_postfix(JTAG *jtag, unsigned count, const void *bits); void jtag_set_dr_prefix(JTAG *jtag, unsigned count, const void *bits); void jtag_set_dr_postfix(JTAG *jtag, unsigned count, const void *bits); +// clear all prefix/postfix patterns and return to default +// idle states +void jtag_clear_state(JTAG *jtag); + // Move jtag state machine from current state to new state. // Moving to JTAG_RESET will work even if current state // is out of sync. @@ -69,4 +73,25 @@ void jtag_dr_io(JTAG *jtag, unsigned count, const void *wbits, void *rbits); int jtag_commit(JTAG *jtag); +typedef struct { + unsigned idcode; + unsigned idmask; + unsigned irsize; + const char *name; +} JTAG_INFO; + +// reset the bus and probe it +// returns number of devices detected, negative on error +int jtag_enumerate(JTAG *jtag); + +// get information about the nth device on the chain +JTAG_INFO *jtag_get_nth_device(JTAG *jtag, int n); + +// configure for communication with a single device +// will setup ir/dr prefix and postfix +int jtag_select_device(JTAG *jtag, unsigned idcode); + +// select by position in scan chain +int jtag_select_device_nth(JTAG *jtag, int n); + #endif