X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Ftcl.c;h=e080279a006563173d1fb65c5dd1b7cfee77db65;hb=55f4e430e8c1c7382d27695c56e8ca95ba7b7dec;hp=d9047ac92087a8910d6c7f921965fa6df7d5cb63;hpb=e961bd14d93a3c4bae5ff52e28e049b1a96dd485;p=openocd.git diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index d9047ac920..e080279a00 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -41,7 +41,8 @@ #endif static const Jim_Nvp nvp_jtag_tap_event[] = { - { .value = JTAG_TAP_EVENT_POST_RESET, .name = "post-reset" }, + { .value = JTAG_TRST_ASSERTED, .name = "post-reset" }, + { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" }, { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" }, { .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" }, @@ -61,6 +62,8 @@ static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *c static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -242,13 +245,15 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi) LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); - /* deal with options */ -#define NTREQ_IRLEN 1 -#define NTREQ_IRCAPTURE 2 -#define NTREQ_IRMASK 4 + /* IEEE specifies that the two LSBs of an IR scan are 01, so make + * that the default. The "-irlen" and "-irmask" options are only + * needed to cope with nonstandard TAPs, or to specify more bits. + */ + pTap->ir_capture_mask = 0x03; + pTap->ir_capture_value = 0x01; - /* clear them as we find them */ - reqbits = (NTREQ_IRLEN | NTREQ_IRCAPTURE | NTREQ_IRMASK); + /* clear flags for "required options" them as we find them */ + reqbits = 1; while (goi->argc) { e = Jim_GetOpt_Nvp(goi, opts, &n); @@ -308,31 +313,39 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi) switch (n->value) { case NTAP_OPT_IRLEN: if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value))) - LOG_WARNING("huge IR length %d", (int) w); + LOG_WARNING("%s: huge IR length %d", + pTap->dotted_name, + (int) w); pTap->ir_length = w; - reqbits &= (~(NTREQ_IRLEN)); + reqbits = 0; break; case NTAP_OPT_IRMASK: if (is_bad_irval(pTap->ir_length, w)) { - LOG_ERROR("IR mask %x too big", + 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; - reqbits &= (~(NTREQ_IRMASK)); break; case NTAP_OPT_IRCAPTURE: if (is_bad_irval(pTap->ir_length, w)) { - LOG_ERROR("IR capture %x too big", + 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; - reqbits &= (~(NTREQ_IRCAPTURE)); break; } } /* switch (n->value) */ @@ -358,38 +371,31 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi) static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e) { jtag_tap_event_action_t * jteap; - int done; - - jteap = tap->event_action; - done = 0; - while (jteap) { + for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) { if (jteap->event == e) { - done = 1; - LOG_DEBUG("JTAG tap: %s event: %d (%s) action: %s\n", + 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 { + } else switch (e) { + case JTAG_TAP_EVENT_ENABLE: + case JTAG_TAP_EVENT_DISABLE: /* NOTE: we currently assume the handlers - * can't fail. That presumes later code - * will be verifying the scan chains ... + * can't fail. Right here is where we should + * really be verifying the scan chains ... */ - if (e == JTAG_TAP_EVENT_ENABLE) - tap->enabled = true; + tap->enabled = (e == JTAG_TAP_EVENT_ENABLE); + LOG_INFO("JTAG tap: %s %s", tap->dotted_name, + tap->enabled ? "enabled" : "disabled"); + break; + default: + break; } } - - jteap = jteap->next; - } - - if (!done) { - LOG_DEBUG("event %d %s - no action", - e, - Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name); } } @@ -404,6 +410,7 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) enum { JTAG_CMD_INTERFACE, + JTAG_CMD_INIT, JTAG_CMD_INIT_RESET, JTAG_CMD_NEWTAP, JTAG_CMD_TAPENABLE, @@ -416,6 +423,7 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) const Jim_Nvp jtag_cmds[] = { { .name = "interface" , .value = JTAG_CMD_INTERFACE }, + { .name = "arp_init" , .value = JTAG_CMD_INIT }, { .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET }, { .name = "newtap" , .value = JTAG_CMD_NEWTAP }, { .name = "tapisenabled" , .value = JTAG_CMD_TAPISENABLED }, @@ -449,6 +457,17 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } Jim_SetResultString(goi.interp, jtag_interface->name, -1); return JIM_OK; + case JTAG_CMD_INIT: + if (goi.argc != 0) { + Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)"); + return JIM_ERR; + } + e = jtag_init_inner(context); + if (e != ERROR_OK) { + Jim_SetResult_sprintf(goi.interp, "error: %d", e); + return JIM_ERR; + } + return JIM_OK; case JTAG_CMD_INIT_RESET: if (goi.argc != 0) { Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)"); @@ -583,13 +602,12 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } -void jtag_notify_reset(void) +void jtag_notify_event(enum jtag_event event) { jtag_tap_t *tap; + for (tap = jtag_all_taps(); tap; tap = tap->next_tap) - { - jtag_tap_handle_event(tap, JTAG_TAP_EVENT_POST_RESET); - } + jtag_tap_handle_event(tap, event); } @@ -613,11 +631,20 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) COMMAND_CONFIG, "(DEPRECATED) jtag_device "); register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command, COMMAND_ANY, - "[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]"); + "reset_config " + "[none|trst_only|srst_only|trst_and_srst] " + "[srst_pulls_trst|trst_pulls_srst|combined|separate] " + "[srst_gates_jtag|srst_nogate] " + "[trst_push_pull|trst_open_drain] " + "[srst_push_pull|srst_open_drain]"); register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command, COMMAND_ANY, "jtag_nsrst_delay - delay after deasserting srst in ms"); register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command, COMMAND_ANY, "jtag_ntrst_delay - delay after deasserting trst in ms"); + register_command(cmd_ctx, NULL, "jtag_nsrst_assert_width", handle_jtag_nsrst_assert_width_command, + COMMAND_ANY, "jtag_nsrst_assert_width - delay after asserting srst in ms"); + register_command(cmd_ctx, NULL, "jtag_ntrst_assert_width", handle_jtag_ntrst_assert_width_command, + COMMAND_ANY, "jtag_ntrst_assert_width - delay after asserting trst in ms"); register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command, COMMAND_EXEC, "print current scan chain configuration"); @@ -829,9 +856,6 @@ static int handle_reset_config_command(struct command_context_s *cmd_ctx, char * int new_cfg = 0; int mask = 0; - if (argc < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - /* Original versions cared about the order of these tokens: * reset_config signals [combination [trst_type [srst_type]]] * They also clobbered the previous configuration even on error. @@ -843,13 +867,21 @@ static int handle_reset_config_command(struct command_context_s *cmd_ctx, char * int tmp = 0; int m; - m = RESET_SRST_GATES_JTAG; - tmp = 0; + /* gating */ + m = RESET_SRST_NO_GATING; if (strcmp(*args, "srst_gates_jtag") == 0) - { - tmp = RESET_SRST_GATES_JTAG; - goto next; + /* default: don't use JTAG while SRST asserted */; + else if (strcmp(*args, "srst_nogate") == 0) + tmp = RESET_SRST_NO_GATING; + else + m = 0; + if (mask & m) { + LOG_ERROR("extra reset_config %s spec (%s)", + "gating", *args); + return ERROR_INVALID_ARGUMENTS; } + if (m) + goto next; /* signals */ m = RESET_HAS_TRST | RESET_HAS_SRST; @@ -936,10 +968,81 @@ next: } /* clear previous values of those bits, save new values */ - enum reset_types old_cfg = jtag_get_reset_config(); - old_cfg &= ~mask; - new_cfg |= old_cfg; - jtag_set_reset_config(new_cfg); + if (mask) { + int old_cfg = jtag_get_reset_config(); + + old_cfg &= ~mask; + new_cfg |= old_cfg; + jtag_set_reset_config(new_cfg); + } else + new_cfg = jtag_get_reset_config(); + + + /* + * Display the (now-)current reset mode + */ + char *modes[5]; + + /* minimal JTAG has neither SRST nor TRST (so that's the default) */ + switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) { + case RESET_HAS_SRST: + modes[0] = "srst_only"; + break; + case RESET_HAS_TRST: + modes[0] = "trst_only"; + break; + case RESET_TRST_AND_SRST: + modes[0] = "trst_and_srst"; + break; + default: + modes[0] = "none"; + break; + } + + /* normally SRST and TRST are decoupled; but bugs happen ... */ + switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) { + case RESET_SRST_PULLS_TRST: + modes[1] = "srst_pulls_trst"; + break; + case RESET_TRST_PULLS_SRST: + modes[1] = "trst_pulls_srst"; + break; + case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST: + modes[1] = "combined"; + break; + default: + modes[1] = "separate"; + break; + } + + /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */ + if (new_cfg & RESET_HAS_TRST) { + if (new_cfg & RESET_TRST_OPEN_DRAIN) + modes[3] = " trst_open_drain"; + else + modes[3] = " trst_push_pull"; + } else + modes[3] = ""; + + /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */ + if (new_cfg & RESET_HAS_SRST) { + if (new_cfg & RESET_SRST_NO_GATING) + modes[2] = " srst_nogate"; + else + modes[2] = " srst_gates_jtag"; + + if (new_cfg & RESET_SRST_PUSH_PULL) + modes[4] = " srst_push_pull"; + else + modes[4] = " srst_open_drain"; + } else { + modes[2] = ""; + modes[4] = ""; + } + + command_print(cmd_ctx, "%s %s%s%s%s", + modes[0], modes[1], + modes[2], modes[3], modes[4]); return ERROR_OK; } @@ -978,6 +1081,40 @@ static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, return ERROR_OK; } +static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) +{ + if (argc > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + if (argc == 1) + { + unsigned delay; + int retval = parse_uint(args[0], &delay); + if (ERROR_OK != retval) + return retval; + jtag_set_nsrst_assert_width(delay); + } + command_print(cmd_ctx, "jtag_nsrst_assert_width: %u", jtag_get_nsrst_assert_width()); + return ERROR_OK; +} + +static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) +{ + if (argc > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + if (argc == 1) + { + unsigned delay; + int retval = parse_uint(args[0], &delay); + if (ERROR_OK != retval) + return retval; + jtag_set_ntrst_assert_width(delay); + } + command_print(cmd_ctx, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width()); + return ERROR_OK; +} + static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int retval = ERROR_OK;