jtag: jtag_add_ir_scan() now takes a single field
[fw/openocd] / src / jtag / tcl.c
index cc890801e6eaf3365771f632f766fc48e87e0566..1073abc024887bc4ffb9420058efa4cd8070adf0 100644 (file)
@@ -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)
@@ -164,7 +175,6 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
                Jim_GetLong(interp, args[i], &bits);
                str = Jim_GetString(args[i + 1], &len);
 
-               fields[field_count].tap = tap;
                fields[field_count].num_bits = bits;
                fields[field_count].out_value = malloc(DIV_ROUND_UP(bits, 8));
                str_to_buf(str, len, fields[field_count].out_value, bits, 0);
@@ -172,7 +182,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
                field_count++;
        }
 
-       jtag_add_dr_scan(num_fields, fields, endstate);
+       jtag_add_dr_scan(tap, num_fields, fields, endstate);
 
        retval = jtag_execute_queue();
        if (retval != ERROR_OK)
@@ -258,26 +268,39 @@ static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const
        return JIM_OK;
 }
 
+/* REVISIT Just what about these should "move" ... ?
+ * These registrations, into the main JTAG table?
+ *
+ * There's a minor compatibility issue, these all show up twice;
+ * that's not desirable:
+ *  - jtag drscan ... NOT DOCUMENTED!
+ *  - drscan ...
+ *
+ * The "irscan" command (for example) doesn't show twice.
+ */
 static const struct command_registration jtag_command_handlers_to_move[] = {
        {
                .name = "drscan",
                .mode = COMMAND_EXEC,
-               .jim_handler = &Jim_Command_drscan,
-               .help = "execute DR scan <device> "
-                       "<num_bits> <value> <num_bits1> <value2> ...",
+               .jim_handler = Jim_Command_drscan,
+               .help = "Execute Data Register (DR) scan for one TAP.  "
+                       "Other TAPs must be in BYPASS mode.",
+               .usage = "tap_name [num_bits value]* ['-endstate' state_name]",
        },
        {
                .name = "flush_count",
                .mode = COMMAND_EXEC,
-               .jim_handler = &Jim_Command_flush_count,
-               .help = "returns number of times the JTAG queue has been flushed",
+               .jim_handler = Jim_Command_flush_count,
+               .help = "Returns the number of times the JTAG queue "
+                       "has been flushed.",
        },
        {
                .name = "pathmove",
                .mode = COMMAND_EXEC,
-               .jim_handler = &Jim_Command_pathmove,
-               .usage = "<state1>,<state2>,<state3>... ",
-               .help = "move JTAG to state1 then to state2, state3, etc.",
+               .jim_handler = Jim_Command_pathmove,
+               .usage = "start_state state1 [state2 [state3 ...]]",
+               .help = "Move JTAG state machine from current state "
+                       "(start_state) to state1, then state2, state3, etc.",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -443,6 +466,7 @@ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
 #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)
@@ -509,6 +533,7 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
                { .name = "-enable"                     ,       .value = NTAP_OPT_ENABLED },
                { .name = "-disable"            ,       .value = NTAP_OPT_DISABLED },
                { .name = "-expected-id"        ,       .value = NTAP_OPT_EXPECTED_ID },
+               { .name = "-ignore-version"     ,       .value = NTAP_OPT_VERSION },
                { .name = NULL                          ,       .value = -1 },
        };
 
@@ -584,6 +609,9 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
                                return e;
                        }
                        break;
+               case NTAP_OPT_VERSION:
+                       pTap->ignore_version = true;
+                       break;
                } /* switch (n->value) */
        } /* while (goi->argc) */
 
@@ -594,7 +622,7 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
        if (pTap->ir_length != 0)
        {
                jtag_tap_init(pTap);
-               return ERROR_OK;
+               return JIM_OK;
        }
 
        Jim_SetResult_sprintf(goi->interp,
@@ -642,7 +670,8 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
        }
 }
 
-static int jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int
+jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        Jim_GetOptInfo goi;
        Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
@@ -828,74 +857,89 @@ COMMAND_HANDLER(handle_jtag_init_command)
 static const struct command_registration jtag_subcommand_handlers[] = {
        {
                .name = "init",
-               .mode = COMMAND_CONFIG,
-               .handler = &handle_jtag_init_command,
+               .mode = COMMAND_ANY,
+               .handler = handle_jtag_init_command,
                .help = "initialize jtag scan chain",
        },
        {
                .name = "interface",
                .mode = COMMAND_ANY,
-               .jim_handler = &jim_jtag_interface,
-               .help = "Returns the selected interface",
+               .jim_handler = jim_jtag_interface,
+               .help = "Returns the name of the currently selected interface.",
        },
        {
                .name = "arp_init",
                .mode = COMMAND_ANY,
-               .jim_handler = &jim_jtag_arp_init,
+               .jim_handler = jim_jtag_arp_init,
+               .help = "Validates JTAG scan chain against the list of "
+                       "declared TAPs using just the four standard JTAG "
+                       "signals.",
        },
        {
                .name = "arp_init-reset",
                .mode = COMMAND_ANY,
-               .jim_handler = &jim_jtag_arp_init_reset,
+               .jim_handler = jim_jtag_arp_init_reset,
+               .help = "Uses TRST and SRST to try resetting everything on "
+                       "the JTAG scan chain, then performs 'jtag arp_init'."
        },
        {
                .name = "newtap",
                .mode = COMMAND_CONFIG,
-               .jim_handler = &jim_jtag_newtap,
-               .help = "Create a new TAP instance",
-               .usage = "<name> <type> -irlen <count> [-ircapture <count>] "
-                       "[-irmask <count>] [-enable|-disable]",
+               .jim_handler = jim_jtag_newtap,
+               .help = "Create a new TAP instance named basename.tap_type, "
+                       "and appends it to the scan chain.",
+               .usage = "basename tap_type '-irlen' count "
+                       "['-enable'|'-disable'] "
+                       "['-expected_id' number] "
+                       "['-ignore-version'] "
+                       "['-ircapture' number] "
+                       "['-mask' number] ",
        },
        {
                .name = "tapisenabled",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_jtag_tap_enabler,
-               .help = "Returns a integer indicating TAP state (0/1)",
-               .usage = "<name>",
+               .jim_handler = jim_jtag_tap_enabler,
+               .help = "Returns a Tcl boolean (0/1) indicating whether "
+                       "the TAP is enabled (1) or not (0).",
+               .usage = "tap_name",
        },
        {
                .name = "tapenable",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_jtag_tap_enabler,
-               .help = "Enable the specified TAP",
-               .usage = "<name>",
+               .jim_handler = jim_jtag_tap_enabler,
+               .help = "Try to enable the specified TAP using the "
+                       "'tap-enable' TAP event.",
+               .usage = "tap_name",
        },
        {
                .name = "tapdisable",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_jtag_tap_enabler,
-               .help = "Enable the specified TAP",
-               .usage = "<name>",
+               .jim_handler = jim_jtag_tap_enabler,
+               .help = "Try to disable the specified TAP using the "
+                       "'tap-disable' TAP event.",
+               .usage = "tap_name",
        },
        {
                .name = "configure",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_jtag_configure,
-               .help = "Enable the specified TAP",
-               .usage = "<name> [<key> <value> ...]",
+               .jim_handler = jim_jtag_configure,
+               .help = "Provide a Tcl handler for the specified "
+                       "TAP event.",
+               .usage = "tap_name '-event' event_name handler",
        },
        {
                .name = "cget",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_jtag_configure,
-               .help = "Enable the specified TAP",
-               .usage = "<name> [<key> <value> ...]",
+               .jim_handler = jim_jtag_configure,
+               .help = "Return any Tcl handler for the specified "
+                       "TAP event.",
+               .usage = "tap_name '-event' event_name",
        },
        {
                .name = "names",
                .mode = COMMAND_ANY,
-               .jim_handler = &jim_jtag_names,
-               .help = "Returns list of all JTAG tap names",
+               .jim_handler = jim_jtag_names,
+               .help = "Returns list of all JTAG tap names.",
        },
        {
                .chain = jtag_command_handlers_to_move,
@@ -1002,32 +1046,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;
@@ -1402,7 +1461,7 @@ COMMAND_HANDLER(handle_irscan_command)
 {
        int i;
        struct scan_field *fields;
-       struct jtag_tap *tap;
+       struct jtag_tap *tap = NULL;
        tap_state_t endstate;
 
        if ((CMD_ARGC < 2) || (CMD_ARGC % 2))
@@ -1431,6 +1490,15 @@ COMMAND_HANDLER(handle_irscan_command)
        }
 
        int num_fields = CMD_ARGC / 2;
+       if (num_fields > 1)
+       {
+               /* we really should be looking at plain_ir_scan if we want
+                * anything more fancy.
+                */
+               LOG_ERROR("Specify a single value for tap");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
        size_t fields_len = sizeof(struct scan_field) * num_fields;
        fields = malloc(fields_len);
        memset(fields, 0, fields_len);
@@ -1450,7 +1518,6 @@ COMMAND_HANDLER(handle_irscan_command)
                        return ERROR_FAIL;
                }
                int field_size = tap->ir_length;
-               fields[i].tap = tap;
                fields[i].num_bits = field_size;
                fields[i].out_value = malloc(DIV_ROUND_UP(field_size, 8));
 
@@ -1463,7 +1530,7 @@ COMMAND_HANDLER(handle_irscan_command)
        }
 
        /* did we have an endstate? */
-       jtag_add_ir_scan(num_fields, fields, endstate);
+       jtag_add_ir_scan(tap, fields, endstate);
 
        retval = jtag_execute_queue();
 
@@ -1543,34 +1610,38 @@ COMMAND_HANDLER(handle_tms_sequence_command)
 static const struct command_registration jtag_command_handlers[] = {
        {
                .name = "interface",
-               .handler = &handle_interface_command,
+               .handler = handle_interface_command,
                .mode = COMMAND_CONFIG,
-               .help = "select a JTAG interface",
-               .usage = "<driver_name>",
+               .help = "Select a JTAG interface",
+               .usage = "driver_name",
        },
        {
                .name = "interface_list",
-               .handler = &handle_interface_list_command,
+               .handler = handle_interface_list_command,
                .mode = COMMAND_ANY,
-               .help = "list all built-in interfaces",
+               .help = "List all built-in interfaces",
        },
        {
                .name = "jtag_khz",
-               .handler = &handle_jtag_khz_command,
+               .handler = handle_jtag_khz_command,
                .mode = COMMAND_ANY,
-               .help = "set maximum jtag speed (if supported)",
-               .usage = "<khz:0=rtck>",
+               .help = "With an argument, change to the specified maximum "
+                       "jtag speed.  Pass 0 to require adaptive clocking. "
+                       "With or without argument, display current setting.",
+               .usage = "[khz]",
        },
        {
                .name = "jtag_rclk",
-               .handler = &handle_jtag_rclk_command,
+               .handler = handle_jtag_rclk_command,
                .mode = COMMAND_ANY,
-               .help = "set JTAG speed to RCLK or use fallback speed",
-               .usage = "<fallback_speed_khz>",
+               .help = "With an argument, change to to use adaptive clocking "
+                       "if possible; else to use the fallback speed.  "
+                       "With or without argument, display current setting.",
+               .usage = "[fallback_speed_khz]",
        },
        {
                .name = "reset_config",
-               .handler = &handle_reset_config_command,
+               .handler = handle_reset_config_command,
                .mode = COMMAND_ANY,
                .help = "configure JTAG reset behavior",
                .usage = "[none|trst_only|srst_only|trst_and_srst] "
@@ -1581,79 +1652,87 @@ static const struct command_registration jtag_command_handlers[] = {
        },
        {
                .name = "jtag_nsrst_delay",
-               .handler = &handle_jtag_nsrst_delay_command,
+               .handler = handle_jtag_nsrst_delay_command,
                .mode = COMMAND_ANY,
                .help = "delay after deasserting srst in ms",
-               .usage = "<ms>",
+               .usage = "[milliseconds]",
        },
        {
                .name = "jtag_ntrst_delay",
-               .handler = &handle_jtag_ntrst_delay_command,
+               .handler = handle_jtag_ntrst_delay_command,
                .mode = COMMAND_ANY,
                .help = "delay after deasserting trst in ms",
-               .usage = "<ms>"
+               .usage = "[milliseconds]",
        },
        {
                .name = "jtag_nsrst_assert_width",
-               .handler = &handle_jtag_nsrst_assert_width_command,
+               .handler = handle_jtag_nsrst_assert_width_command,
                .mode = COMMAND_ANY,
                .help = "delay after asserting srst in ms",
-               .usage = "<ms>"
+               .usage = "[milliseconds]",
        },
        {
                .name = "jtag_ntrst_assert_width",
-               .handler = &handle_jtag_ntrst_assert_width_command,
+               .handler = handle_jtag_ntrst_assert_width_command,
                .mode = COMMAND_ANY,
                .help = "delay after asserting trst in ms",
-               .usage = "<ms>"
+               .usage = "[milliseconds]",
        },
        {
                .name = "scan_chain",
-               .handler = &handle_scan_chain_command,
-               .mode = COMMAND_EXEC,
+               .handler = handle_scan_chain_command,
+               .mode = COMMAND_ANY,
                .help = "print current scan chain configuration",
        },
        {
                .name = "jtag_reset",
-               .handler = &handle_jtag_reset_command,
+               .handler = handle_jtag_reset_command,
                .mode = COMMAND_EXEC,
-               .help = "toggle reset lines",
-               .usage = "<trst> <srst>",
+               .help = "Set reset line values.  Value '1' is active, "
+                       "value '0' is inactive.",
+               .usage = "trst_active srst_active",
        },
        {
                .name = "runtest",
-               .handler = &handle_runtest_command,
+               .handler = handle_runtest_command,
                .mode = COMMAND_EXEC,
-               .help = "move to Run-Test/Idle, and execute <num_cycles>",
-               .usage = "<num_cycles>"
+               .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
+               .usage = "num_cycles"
        },
        {
                .name = "irscan",
-               .handler = &handle_irscan_command,
+               .handler = handle_irscan_command,
                .mode = COMMAND_EXEC,
-               .help = "execute IR scan",
-               .usage = "<device> <instr> [dev2] [instr2] ...",
+               .help = "Execute Instruction Register (DR) scan.  The "
+                       "specified opcodes are put into each TAP's IR, "
+                       "and other TAPs are put in BYPASS.",
+               .usage = "[tap_name instruction]* ['-endstate' state_name]",
        },
        {
                .name = "verify_ircapture",
-               .handler = &handle_verify_ircapture_command,
+               .handler = handle_verify_ircapture_command,
                .mode = COMMAND_ANY,
-               .help = "verify value captured during Capture-IR",
-               .usage = "<enable | disable>",
+               .help = "Display or assign flag controlling whether to "
+                       "verify values captured during Capture-IR.",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "verify_jtag",
-               .handler = &handle_verify_jtag_command,
+               .handler = handle_verify_jtag_command,
                .mode = COMMAND_ANY,
-               .help = "verify value capture",
-               .usage = "<enable | disable>",
+               .help = "Display or assign flag controlling whether to "
+                       "verify values captured during IR and DR scans.",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "tms_sequence",
-               .handler = &handle_tms_sequence_command,
+               .handler = handle_tms_sequence_command,
                .mode = COMMAND_ANY,
-               .help = "choose short(default) or long tms_sequence",
-               .usage = "<short | long>",
+               .help = "Display or change what style TMS sequences to use "
+                       "for JTAG state transitions:  short (default) or "
+                       "long.  Only for working around JTAG bugs.",
+                       /* Specifically for working around DRIVER bugs... */
+               .usage = "['short'|'long']",
        },
        {
                .name = "jtag",