TCL scripts: replace "puts" with "echo"
[fw/openocd] / src / jtag / core.c
index 782f10f78d7e29dffd6344b3cb62054821f92739..c1b64bba41b040ae8bdbea7d3dde302cdea6ffa5 100644 (file)
 
 #include "jtag.h"
 #include "interface.h"
+#include "transport.h"
 
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
 
+/* SVF and XSVF are higher level JTAG command sets (for boundary scan) */
+#include "svf/svf.h"
+#include "xsvf/xsvf.h"
 
 /// The number of JTAG queue flushes (for profiling and debugging purposes).
 static int jtag_flush_queue_count;
 
+// Sleep this # of ms after flushing the queue
+static int jtag_flush_queue_sleep = 0;
+
 static void jtag_add_scan_check(struct jtag_tap *active,
                void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state),
                int in_num_fields, struct scan_field *in_fields, tap_state_t state);
@@ -125,6 +132,11 @@ static struct jtag_interface *jtag = NULL;
 /* configuration */
 struct jtag_interface *jtag_interface = NULL;
 
+void jtag_set_flush_queue_sleep(int ms)
+{
+       jtag_flush_queue_sleep = ms;
+}
+
 void jtag_set_error(int error)
 {
        if ((error == ERROR_OK) || (jtag_error != ERROR_OK))
@@ -822,6 +834,15 @@ void jtag_execute_queue_noclear(void)
 {
        jtag_flush_queue_count++;
        jtag_set_error(interface_jtag_execute_queue());
+
+       if (jtag_flush_queue_sleep > 0)
+       {
+               /* For debug purposes it can be useful to test performance
+                * or behavior when delaying after flushing the queue,
+                * e.g. to simulate long roundtrip times.
+                */
+               usleep(jtag_flush_queue_sleep * 1000);
+       }
 }
 
 int jtag_get_flush_queue_count(void)
@@ -1348,6 +1369,19 @@ int adapter_init(struct command_context *cmd_ctx)
                return ERROR_JTAG_INIT_FAILED;
        }
 
+       /* LEGACY SUPPORT ... adapter drivers  must declare what
+        * transports they allow.  Until they all do so, assume
+        * the legacy drivers are JTAG-only
+        */
+       if (!transports_are_declared()) {
+               LOG_ERROR("Adapter driver '%s' did not declare "
+                       "which transports it allows; assuming "
+                       "JTAG-only", jtag->name);
+               int retval = allow_transports(cmd_ctx, jtag_only);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
        int requested_khz = jtag_get_speed_khz();
        int actual_khz = requested_khz;
        int retval = jtag_get_speed_readable(&actual_khz);
@@ -1411,17 +1445,19 @@ int jtag_init_inner(struct command_context *cmd_ctx)
        case ERROR_OK:
                /* complete success */
                break;
-       case ERROR_JTAG_INIT_SOFT_FAIL:
+       default:
                /* For backward compatibility reasons, try coping with
                 * configuration errors involving only ID mismatches.
                 * We might be able to talk to the devices.
+                *
+                * Also the device might be powered down during startup.
+                *
+                * After OpenOCD starts, we can try to power on the device
+                * and run a reset.
                 */
                LOG_ERROR("Trying to use configured scan chain anyway...");
                issue_setup = false;
                break;
-       default:
-               /* some hard error; already issued diagnostics */
-               return retval;
        }
 
        /* Now look at IR values.  Problems here will prevent real
@@ -1432,7 +1468,13 @@ int jtag_init_inner(struct command_context *cmd_ctx)
         */
        retval = jtag_validate_ircapture();
        if (retval != ERROR_OK)
-               return retval;
+       {
+               /* The target might be powered down. The user
+                * can power it up and reset it after firing
+                * up OpenOCD.
+                */
+               issue_setup = false;
+       }
 
        if (issue_setup)
                jtag_notify_event(JTAG_TAP_EVENT_SETUP);
@@ -1592,7 +1634,7 @@ int jtag_config_rclk(unsigned fallback_speed_khz)
 
 int jtag_get_speed(void)
 {
-       int speed;
+       int speed = 0; /* avoid -O3 warning */
        switch(clock_mode)
        {
                case CLOCK_MODE_SPEED:
@@ -1606,7 +1648,6 @@ int jtag_get_speed(void)
                        break;
                default:
                        LOG_ERROR("BUG: unknown jtag clock mode");
-                       speed = 0;
                        break;
        }
        return speed;
@@ -1706,3 +1747,44 @@ unsigned jtag_get_ntrst_assert_width(void)
 {
        return jtag_ntrst_assert_width;
 }
+
+static int jtag_select(struct command_context *ctx)
+{
+       int retval;
+
+       /* NOTE:  interface init must already have been done.
+        * That works with only C code ... no Tcl glue required.
+        */
+
+       retval = jtag_register_commands(ctx);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = svf_register_commands(ctx);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       return xsvf_register_commands(ctx);
+}
+
+static struct transport jtag_transport = {
+       .name = "jtag",
+       .select = jtag_select,
+       .init = jtag_init,
+};
+
+static void jtag_constructor(void) __attribute__((constructor));
+static void jtag_constructor(void)
+{
+       transport_register(&jtag_transport);
+}
+
+/** Returns true if the current debug session
+ * is using JTAG as its transport.
+ */
+bool transport_is_jtag(void)
+{
+       return get_current_transport() == &jtag_transport;
+}