X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fjtag%2Ftcl.c;h=00b1038e250d5a54ffb550fca9a85094a73d3489;hb=12c143d5948355b3b54c9c0decc779177b22d5d9;hp=929c784e2280765fa8569ac946809bfc6b29323d;hpb=0377e5b54d6db196cfeeaaa70824c581317e2290;p=fw%2Fopenocd diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 929c784e2..00b1038e2 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -51,6 +51,17 @@ static const Jim_Nvp nvp_jtag_tap_event[] = { extern struct jtag_interface *jtag_interface; +struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) +{ + const char *cp = Jim_GetString(o, NULL); + struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL; + if (NULL == cp) + cp = "(unknown)"; + if (NULL == t) + Jim_SetResult_sprintf(interp, "Tap '%s' could not be found", cp); + return t; +} + static bool scan_is_safe(tap_state_t state) { switch (state) @@ -293,94 +304,107 @@ static Jim_Nvp nvp_config_opts[] = { { .name = NULL, .value = -1 } }; -static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, struct jtag_tap * tap) +static int jtag_tap_configure_event(Jim_GetOptInfo *goi, struct jtag_tap * tap) { + if (goi->argc == 0) + { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ..."); + return JIM_ERR; + } + Jim_Nvp *n; - Jim_Obj *o; - int e; + int e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n); + if (e != JIM_OK) + { + Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1); + return e; + } + + if (goi->isconfigure) { + if (goi->argc != 1) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event "); + return JIM_ERR; + } + } else { + if (goi->argc != 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event "); + return JIM_ERR; + } + } + + struct jtag_tap_event_action *jteap = tap->event_action; + /* replace existing event body */ + bool found = false; + while (jteap) + { + if (jteap->event == (enum jtag_event)n->value) + { + found = true; + break; + } + jteap = jteap->next; + } + + Jim_SetEmptyResult(goi->interp); + + if (goi->isconfigure) + { + if (!found) + jteap = calloc(1, sizeof(*jteap)); + else if (NULL != jteap->body) + Jim_DecrRefCount(goi->interp, jteap->body); + + jteap->interp = goi->interp; + jteap->event = n->value; + + Jim_Obj *o; + Jim_GetOpt_Obj(goi, &o); + jteap->body = Jim_DuplicateObj(goi->interp, o); + Jim_IncrRefCount(jteap->body); + + if (!found) + { + /* add to head of event list */ + jteap->next = tap->event_action; + tap->event_action = jteap; + } + } + else if (found) + { + jteap->interp = goi->interp; + Jim_SetResult(goi->interp, + Jim_DuplicateObj(goi->interp, jteap->body)); + } + return JIM_OK; +} +static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, struct jtag_tap * tap) +{ /* parse config or cget options */ - while (goi->argc > 0) { + while (goi->argc > 0) + { Jim_SetEmptyResult (goi->interp); - e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); - if (e != JIM_OK) { + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); + if (e != JIM_OK) + { Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); return e; } - switch (n->value) { - case JCFG_EVENT: - if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); - return JIM_ERR; - } - - e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1); - return e; - } - - if (goi->isconfigure) { - if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); - return JIM_ERR; - } - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); - return JIM_ERR; - } - } - - { - struct jtag_tap_event_action *jteap; - - jteap = tap->event_action; - /* replace existing? */ - while (jteap) { - if (jteap->event == (enum jtag_event)n->value) { - break; - } - jteap = jteap->next; - } - - if (goi->isconfigure) { - bool replace = true; - if (jteap == NULL) { - /* create new */ - jteap = calloc(1, sizeof (*jteap)); - replace = false; - } - jteap->event = n->value; - Jim_GetOpt_Obj(goi, &o); - if (jteap->body) { - Jim_DecrRefCount(interp, jteap->body); - } - jteap->body = Jim_DuplicateObj(goi->interp, o); - Jim_IncrRefCount(jteap->body); - - if (!replace) - { - /* add to head of event list */ - jteap->next = tap->event_action; - tap->event_action = jteap; - } - Jim_SetEmptyResult(goi->interp); - } else { - /* get */ - if (jteap == NULL) { - Jim_SetEmptyResult(goi->interp); - } else { - Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body)); - } - } - } - /* loop for more */ - break; + switch (n->value) + { + case JCFG_EVENT: + e = jtag_tap_configure_event(goi, tap); + if (e != JIM_OK) + return e; + break; + default: + Jim_SetResult_sprintf(goi->interp, "unknown event: %s", n->name); + return JIM_ERR; } - } /* while (goi->argc) */ + } return JIM_OK; } @@ -395,27 +419,109 @@ static int is_bad_irval(int ir_length, jim_wide w) return (w & v) != 0; } +static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, + struct jtag_tap *pTap) +{ + jim_wide w; + int e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) { + Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name); + return e; + } + + unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt; + uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t)); + if (new_expected_ids == NULL) + { + Jim_SetResult_sprintf(goi->interp, "no memory"); + return JIM_ERR; + } + + memcpy(new_expected_ids, pTap->expected_ids, expected_len); + + new_expected_ids[pTap->expected_ids_cnt] = w; + + free(pTap->expected_ids); + pTap->expected_ids = new_expected_ids; + pTap->expected_ids_cnt++; + + return JIM_OK; +} + +#define NTAP_OPT_IRLEN 0 +#define NTAP_OPT_IRMASK 1 +#define NTAP_OPT_IRCAPTURE 2 +#define NTAP_OPT_ENABLED 3 +#define NTAP_OPT_DISABLED 4 +#define NTAP_OPT_EXPECTED_ID 5 +#define NTAP_OPT_VERSION 6 + +static int jim_newtap_ir_param(Jim_Nvp *n, Jim_GetOptInfo *goi, + struct jtag_tap *pTap) +{ + jim_wide w; + int e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + { + Jim_SetResult_sprintf(goi->interp, + "option: %s bad parameter", n->name); + free((void *)pTap->dotted_name); + return e; + } + switch (n->value) { + case NTAP_OPT_IRLEN: + if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value))) + { + LOG_WARNING("%s: huge IR length %d", + pTap->dotted_name, (int) w); + } + pTap->ir_length = w; + break; + case NTAP_OPT_IRMASK: + if (is_bad_irval(pTap->ir_length, w)) + { + LOG_ERROR("%s: IR mask %x too big", + pTap->dotted_name, + (int) w); + return JIM_ERR; + } + if ((w & 3) != 3) + LOG_WARNING("%s: nonstandard IR mask", pTap->dotted_name); + pTap->ir_capture_mask = w; + break; + case NTAP_OPT_IRCAPTURE: + if (is_bad_irval(pTap->ir_length, w)) + { + LOG_ERROR("%s: IR capture %x too big", + pTap->dotted_name, (int) w); + return JIM_ERR; + } + if ((w & 3) != 1) + LOG_WARNING("%s: nonstandard IR value", + pTap->dotted_name); + pTap->ir_capture_value = w; + break; + default: + return JIM_ERR; + } + return JIM_OK; +} + static int jim_newtap_cmd(Jim_GetOptInfo *goi) { struct jtag_tap *pTap; - jim_wide w; int x; int e; Jim_Nvp *n; char *cp; const Jim_Nvp opts[] = { -#define NTAP_OPT_IRLEN 0 { .name = "-irlen" , .value = NTAP_OPT_IRLEN }, -#define NTAP_OPT_IRMASK 1 { .name = "-irmask" , .value = NTAP_OPT_IRMASK }, -#define NTAP_OPT_IRCAPTURE 2 { .name = "-ircapture" , .value = NTAP_OPT_IRCAPTURE }, -#define NTAP_OPT_ENABLED 3 { .name = "-enable" , .value = NTAP_OPT_ENABLED }, -#define NTAP_OPT_DISABLED 4 { .name = "-disable" , .value = NTAP_OPT_DISABLED }, -#define NTAP_OPT_EXPECTED_ID 5 { .name = "-expected-id" , .value = NTAP_OPT_EXPECTED_ID }, + { .name = "-ignore-version" , .value = NTAP_OPT_VERSION }, { .name = NULL , .value = -1 }, }; @@ -472,81 +578,28 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi) pTap->disabled_after_reset = true; break; case NTAP_OPT_EXPECTED_ID: - { - uint32_t *new_expected_ids; - - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) { - Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name); + e = jim_newtap_expected_id(n, goi, pTap); + if (JIM_OK != e) + { free((void *)pTap->dotted_name); free(pTap); return e; } - - new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1)); - if (new_expected_ids == NULL) { - Jim_SetResult_sprintf(goi->interp, "no memory"); - free((void *)pTap->dotted_name); - free(pTap); - return JIM_ERR; - } - - memcpy(new_expected_ids, pTap->expected_ids, sizeof(uint32_t) * pTap->expected_ids_cnt); - - new_expected_ids[pTap->expected_ids_cnt] = w; - - free(pTap->expected_ids); - pTap->expected_ids = new_expected_ids; - pTap->expected_ids_cnt++; break; - } case NTAP_OPT_IRLEN: case NTAP_OPT_IRMASK: case NTAP_OPT_IRCAPTURE: - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) { - Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name); + e = jim_newtap_ir_param(n, goi, pTap); + if (JIM_OK != e) + { free((void *)pTap->dotted_name); free(pTap); return e; } - switch (n->value) { - case NTAP_OPT_IRLEN: - if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value))) - LOG_WARNING("%s: huge IR length %d", - pTap->dotted_name, - (int) w); - pTap->ir_length = w; - break; - case NTAP_OPT_IRMASK: - if (is_bad_irval(pTap->ir_length, w)) { - LOG_ERROR("%s: IR mask %x too big", - pTap->dotted_name, - (int) w); - free((void *)pTap->dotted_name); - free(pTap); - return ERROR_FAIL; - } - if ((w & 3) != 3) - LOG_WARNING("%s: nonstandard IR mask", - pTap->dotted_name); - pTap->ir_capture_mask = w; - break; - case NTAP_OPT_IRCAPTURE: - if (is_bad_irval(pTap->ir_length, w)) { - LOG_ERROR("%s: IR capture %x too big", - pTap->dotted_name, - (int) w); - free((void *)pTap->dotted_name); - free(pTap); - return ERROR_FAIL; - } - if ((w & 3) != 1) - LOG_WARNING("%s: nonstandard IR value", - pTap->dotted_name); - pTap->ir_capture_value = w; - break; - } + break; + case NTAP_OPT_VERSION: + pTap->ignore_version = true; + break; } /* switch (n->value) */ } /* while (goi->argc) */ @@ -571,29 +624,36 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e) { struct jtag_tap_event_action * jteap; - for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) { - if (jteap->event == e) { - LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s", - tap->dotted_name, - e, - Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name, - Jim_GetString(jteap->body, NULL)); - if (Jim_EvalObj(interp, jteap->body) != JIM_OK) { - Jim_PrintErrorMessage(interp); - } else switch (e) { - case JTAG_TAP_EVENT_ENABLE: - case JTAG_TAP_EVENT_DISABLE: - /* NOTE: we currently assume the handlers - * can't fail. Right here is where we should - * really be verifying the scan chains ... - */ - tap->enabled = (e == JTAG_TAP_EVENT_ENABLE); - LOG_INFO("JTAG tap: %s %s", tap->dotted_name, - tap->enabled ? "enabled" : "disabled"); - break; - default: - break; - } + for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) + { + if (jteap->event != e) + continue; + + Jim_Nvp *nvp = Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e); + LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s", + tap->dotted_name, e, nvp->name, + Jim_GetString(jteap->body, NULL)); + + if (Jim_EvalObj(jteap->interp, jteap->body) != JIM_OK) + { + Jim_PrintErrorMessage(jteap->interp); + continue; + } + + switch (e) + { + case JTAG_TAP_EVENT_ENABLE: + case JTAG_TAP_EVENT_DISABLE: + /* NOTE: we currently assume the handlers + * can't fail. Right here is where we should + * really be verifying the scan chains ... + */ + tap->enabled = (e == JTAG_TAP_EVENT_ENABLE); + LOG_INFO("JTAG tap: %s %s", tap->dotted_name, + tap->enabled ? "enabled" : "disabled"); + break; + default: + break; } } } @@ -764,7 +824,30 @@ static int jim_jtag_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } +COMMAND_HANDLER(handle_jtag_init_command) +{ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + static bool jtag_initialized = false; + if (jtag_initialized) + { + LOG_INFO("'jtag init' has already been called"); + return ERROR_OK; + } + jtag_initialized = true; + + LOG_DEBUG("Initializing jtag devices..."); + return jtag_init(CMD_CTX); +} + static const struct command_registration jtag_subcommand_handlers[] = { + { + .name = "init", + .mode = COMMAND_ANY, + .handler = &handle_jtag_init_command, + .help = "initialize jtag scan chain", + }, { .name = "interface", .mode = COMMAND_ANY, @@ -935,32 +1018,47 @@ COMMAND_HANDLER(handle_interface_command) COMMAND_HANDLER(handle_scan_chain_command) { struct jtag_tap *tap; + char expected_id[12]; tap = jtag_all_taps(); - command_print(CMD_CTX, " TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr "); - command_print(CMD_CTX, "---|--------------------|---------|------------|------------|------|------|------|---------"); + command_print(CMD_CTX, +" TapName Enabled IdCode Expected IrLen IrCap IrMask"); + command_print(CMD_CTX, +"-- ------------------- -------- ---------- ---------- ----- ----- ------"); while (tap) { - uint32_t expected, expected_mask, cur_instr, ii; + uint32_t expected, expected_mask, ii; + + snprintf(expected_id, sizeof expected_id, "0x%08x", + (unsigned)((tap->expected_ids_cnt > 0) + ? tap->expected_ids[0] + : 0)); + if (tap->ignore_version) + expected_id[2] = '*'; + expected = buf_get_u32(tap->expected, 0, tap->ir_length); expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length); - cur_instr = buf_get_u32(tap->cur_instr, 0, tap->ir_length); command_print(CMD_CTX, - "%2d | %-18s | %c | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x", + "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", tap->abs_chain_position, tap->dotted_name, tap->enabled ? 'Y' : 'n', (unsigned int)(tap->idcode), - (unsigned int)(tap->expected_ids_cnt > 0 ? tap->expected_ids[0] : 0), + expected_id, (unsigned int)(tap->ir_length), (unsigned int)(expected), - (unsigned int)(expected_mask), - (unsigned int)(cur_instr)); + (unsigned int)(expected_mask)); for (ii = 1; ii < tap->expected_ids_cnt; ii++) { - command_print(CMD_CTX, " | | | | 0x%08x | | | | ", - (unsigned int)(tap->expected_ids[ii])); + snprintf(expected_id, sizeof expected_id, "0x%08x", + (unsigned) tap->expected_ids[1]); + if (tap->ignore_version) + expected_id[2] = '*'; + + command_print(CMD_CTX, + " %s", + expected_id); } tap = tap->next_tap;