initial "transport" framework
[fw/openocd] / src / jtag / core.c
index 4f517c098e0e354659b150ad1e7dce1f327a7ef8..1643d9b64e4827756d499e41902d29c6c4c79c61 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;
 
-static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state),
+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);
 
 /**
@@ -51,9 +56,9 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
  * when an error occurs during processing that should be reported during
  * jtag_execute_queue().
  *
- * Tts value may be checked with jtag_get_error() and cleared with
- * jtag_error_clear().  This value is returned (and cleared) by
- * jtag_execute_queue().
+ * The value is set and cleared, but never read by normal application code.
+ *
+ * This value is returned (and cleared) by jtag_execute_queue().
  */
 static int jtag_error = ERROR_OK;
 
@@ -85,16 +90,15 @@ static struct jtag_tap *__jtag_all_taps = NULL;
 static unsigned jtag_num_taps = 0;
 
 static enum reset_types jtag_reset_config = RESET_NONE;
-static tap_state_t cmd_queue_end_state = TAP_RESET;
 tap_state_t cmd_queue_cur_state = TAP_RESET;
 
 static bool jtag_verify_capture_ir = true;
 static int jtag_verify = 1;
 
 /* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
-static int jtag_nsrst_delay = 0; /* default to no nSRST delay */
+static int adapter_nsrst_delay = 0; /* default to no nSRST delay */
 static int jtag_ntrst_delay = 0; /* default to no nTRST delay */
-static int jtag_nsrst_assert_width = 0; /* width of assertion */
+static int adapter_nsrst_assert_width = 0; /* width of assertion */
 static int jtag_ntrst_assert_width = 0; /* width of assertion */
 
 /**
@@ -131,10 +135,7 @@ void jtag_set_error(int error)
                return;
        jtag_error = error;
 }
-int jtag_get_error(void)
-{
-       return jtag_error;
-}
+
 int jtag_error_clear(void)
 {
        int temp = jtag_error;
@@ -352,17 +353,22 @@ void jtag_alloc_in_value32(struct scan_field *field)
        interface_jtag_alloc_in_value32(field);
 }
 
-void jtag_add_ir_scan_noverify(int in_count, const struct scan_field *in_fields,
+void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields,
                tap_state_t state)
 {
        jtag_prelude(state);
 
-       int retval = interface_jtag_add_ir_scan(in_count, in_fields, state);
+       int retval = interface_jtag_add_ir_scan(active, in_fields, state);
        jtag_set_error(retval);
 }
 
+static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active, int dummy, const struct scan_field *in_fields,
+               tap_state_t state)
+{
+       jtag_add_ir_scan_noverify(active, in_fields, state);
+}
 
-void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
+void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state)
 {
        assert(state != TAP_RESET);
 
@@ -370,30 +376,28 @@ void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state
        {
                /* 8 x 32 bit id's is enough for all invocations */
 
-               for (int j = 0; j < in_num_fields; j++)
-               {
-                       /* if we are to run a verification of the ir scan, we need to get the input back.
-                        * We may have to allocate space if the caller didn't ask for the input back.
-                        */
-                       in_fields[j].check_value = in_fields[j].tap->expected;
-                       in_fields[j].check_mask = in_fields[j].tap->expected_mask;
-               }
-               jtag_add_scan_check(jtag_add_ir_scan_noverify, in_num_fields, in_fields, state);
+               /* if we are to run a verification of the ir scan, we need to get the input back.
+                * We may have to allocate space if the caller didn't ask for the input back.
+                */
+               in_fields->check_value = active->expected;
+               in_fields->check_mask = active->expected_mask;
+               jtag_add_scan_check(active, jtag_add_ir_scan_noverify_callback, 1, in_fields, state);
        } else
        {
-               jtag_add_ir_scan_noverify(in_num_fields, in_fields, state);
+               jtag_add_ir_scan_noverify(active, in_fields, state);
        }
 }
 
-void jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_fields,
+void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
                tap_state_t state)
 {
+       assert(out_bits != NULL);
        assert(state != TAP_RESET);
 
        jtag_prelude(state);
 
        int retval = interface_jtag_add_plain_ir_scan(
-                       in_num_fields, in_fields, state);
+                       num_bits, out_bits, in_bits, state);
        jtag_set_error(retval);
 }
 
@@ -405,7 +409,7 @@ static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callb
        return jtag_check_value_inner((uint8_t *)data0, (uint8_t *)data1, (uint8_t *)data2, (int)data3);
 }
 
-static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state),
+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)
 {
        for (int i = 0; i < in_num_fields; i++)
@@ -419,7 +423,7 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
                field->modified = 1;
        }
 
-       jtag_add_scan(in_num_fields, in_fields, state);
+       jtag_add_scan(active, in_num_fields, in_fields, state);
 
        for (int i = 0; i < in_num_fields; i++)
        {
@@ -442,19 +446,19 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
        }
 }
 
-void jtag_add_dr_scan_check(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
+void jtag_add_dr_scan_check(struct jtag_tap *active, int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        if (jtag_verify)
        {
-               jtag_add_scan_check(jtag_add_dr_scan, in_num_fields, in_fields, state);
+               jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state);
        } else
        {
-               jtag_add_dr_scan(in_num_fields, in_fields, state);
+               jtag_add_dr_scan(active, in_num_fields, in_fields, state);
        }
 }
 
 
-void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields,
+void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -462,19 +466,20 @@ void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields,
        jtag_prelude(state);
 
        int retval;
-       retval = interface_jtag_add_dr_scan(in_num_fields, in_fields, state);
+       retval = interface_jtag_add_dr_scan(active, in_num_fields, in_fields, state);
        jtag_set_error(retval);
 }
 
-void jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_fields,
+void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
                tap_state_t state)
 {
+       assert(out_bits != NULL);
        assert(state != TAP_RESET);
 
        jtag_prelude(state);
 
        int retval;
-       retval = interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state);
+       retval = interface_jtag_add_plain_dr_scan(num_bits, out_bits, in_bits, state);
        jtag_set_error(retval);
 }
 
@@ -488,6 +493,35 @@ void jtag_add_tlr(void)
        jtag_notify_event(JTAG_TRST_ASSERTED);
 }
 
+/**
+ * If supported by the underlying adapter, this clocks a raw bit sequence
+ * onto TMS for switching betwen JTAG and SWD modes.
+ *
+ * DO NOT use this to bypass the integrity checks and logging provided
+ * by the jtag_add_pathmove() and jtag_add_statemove() calls.
+ *
+ * @param nbits How many bits to clock out.
+ * @param seq The bit sequence.  The LSB is bit 0 of seq[0].
+ * @param state The JTAG tap state to record on completion.  Use
+ *     TAP_INVALID to represent being in in SWD mode.
+ *
+ * @todo Update naming conventions to stop assuming everything is JTAG.
+ */
+int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
+{
+       int retval;
+
+       if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
+               return ERROR_JTAG_NOT_IMPLEMENTED;
+
+       jtag_checks();
+       cmd_queue_cur_state = state;
+
+       retval = interface_add_tms_seq(nbits, seq, state);
+       jtag_set_error(retval);
+       return retval;
+}
+
 void jtag_add_pathmove(int num_states, const tap_state_t *path)
 {
        tap_state_t cur_state = cmd_queue_cur_state;
@@ -665,13 +699,13 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                if (jtag_srst)
                {
                        LOG_DEBUG("SRST line asserted");
-                       if (jtag_nsrst_assert_width)
-                               jtag_add_sleep(jtag_nsrst_assert_width * 1000);
+                       if (adapter_nsrst_assert_width)
+                               jtag_add_sleep(adapter_nsrst_assert_width * 1000);
                }
                else {
                        LOG_DEBUG("SRST line released");
-                       if (jtag_nsrst_delay)
-                               jtag_add_sleep(jtag_nsrst_delay * 1000);
+                       if (adapter_nsrst_delay)
+                               jtag_add_sleep(adapter_nsrst_delay * 1000);
                }
        }
 
@@ -683,7 +717,6 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
         */
        if (trst_with_tlr) {
                LOG_DEBUG("JTAG reset with TLR instead of TRST");
-               jtag_set_end_state(TAP_RESET);
                jtag_add_tlr();
 
        } else if (jtag_trst != new_trst) {
@@ -709,23 +742,6 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        }
 }
 
-tap_state_t jtag_set_end_state(tap_state_t state)
-{
-       if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT))
-       {
-               LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field");
-       }
-
-       if (state != TAP_INVALID)
-               cmd_queue_end_state = state;
-       return cmd_queue_end_state;
-}
-
-tap_state_t jtag_get_end_state(void)
-{
-       return cmd_queue_end_state;
-}
-
 void jtag_add_sleep(uint32_t us)
 {
        /// @todo Here, keep_alive() appears to be a layering violation!!!
@@ -865,7 +881,6 @@ void jtag_sleep(uint32_t us)
 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
 {
        struct scan_field field = {
-                       .tap = NULL,
                        .num_bits = num_idcode * 32,
                        .out_value = idcode_buffer,
                        .in_value = idcode_buffer,
@@ -875,7 +890,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
        for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
                buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
 
-       jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
+       jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE);
        jtag_add_tlr();
        return jtag_execute_queue();
 }
@@ -1172,12 +1187,11 @@ static int jtag_validate_ircapture(void)
        /* after this scan, all TAPs will capture BYPASS instructions */
        buf_set_ones(ir_test, total_ir_length);
 
-       field.tap = NULL;
        field.num_bits = total_ir_length;
        field.out_value = ir_test;
        field.in_value = ir_test;
 
-       jtag_add_plain_ir_scan(1, &field, TAP_IDLE);
+       jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, TAP_IDLE);
 
        LOG_DEBUG("IR capture validation scan");
        retval = jtag_execute_queue();
@@ -1314,7 +1328,11 @@ void jtag_tap_free(struct jtag_tap *tap)
        free(tap);
 }
 
-int jtag_interface_init(struct command_context *cmd_ctx)
+/**
+ * Do low-level setup like initializing registers, output signals,
+ * and clocking.
+ */
+int adapter_init(struct command_context *cmd_ctx)
 {
        if (jtag)
                return ERROR_OK;
@@ -1322,7 +1340,8 @@ int jtag_interface_init(struct command_context *cmd_ctx)
        if (!jtag_interface)
        {
                /* nothing was previously specified by "interface" command */
-               LOG_ERROR("JTAG interface has to be specified, see \"interface\" command");
+               LOG_ERROR("Debug Adapter has to be specified, "
+                       "see \"interface\" command");
                return ERROR_JTAG_INVALID_INTERFACE;
        }
 
@@ -1333,13 +1352,29 @@ int jtag_interface_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()) {
+               static const char *jtag_only[] = { "jtag", NULL, };
+               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);
        if (ERROR_OK != retval)
-               LOG_INFO("interface specific clock speed value %d", jtag_get_speed());
+               LOG_INFO("adapter-specific clock speed value %d", jtag_get_speed());
        else if (actual_khz)
        {
+               /* Adaptive clocking -- JTAG-specific */
                if ((CLOCK_MODE_RCLK == clock_mode)
                        || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz))
                {
@@ -1427,7 +1462,7 @@ int jtag_init_inner(struct command_context *cmd_ctx)
        return ERROR_OK;
 }
 
-int jtag_interface_quit(void)
+int adapter_quit(void)
 {
        if (!jtag || !jtag->quit)
                return ERROR_OK;
@@ -1445,7 +1480,7 @@ int jtag_init_reset(struct command_context *cmd_ctx)
 {
        int retval;
 
-       if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
+       if ((retval = adapter_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
        LOG_DEBUG("Initializing with hard TRST+SRST reset");
@@ -1499,7 +1534,7 @@ int jtag_init(struct command_context *cmd_ctx)
 {
        int retval;
 
-       if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
+       if ((retval = adapter_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
        /* guard against oddball hardware: force resets to be inactive */
@@ -1518,7 +1553,7 @@ unsigned jtag_get_speed_khz(void)
        return speed_khz;
 }
 
-static int jtag_khz_to_speed(unsigned khz, int* speed)
+static int adapter_khz_to_speed(unsigned khz, int* speed)
 {
        LOG_DEBUG("convert khz to interface specific speed value");
        speed_khz = khz;
@@ -1538,11 +1573,11 @@ static int jtag_khz_to_speed(unsigned khz, int* speed)
 
 static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int* speed)
 {
-       int retval = jtag_khz_to_speed(0, speed);
+       int retval = adapter_khz_to_speed(0, speed);
        if ((ERROR_OK != retval) && fallback_speed_khz)
        {
                LOG_DEBUG("trying fallback speed...");
-               retval = jtag_khz_to_speed(fallback_speed_khz, speed);
+               retval = adapter_khz_to_speed(fallback_speed_khz, speed);
        }
        return retval;
 }
@@ -1560,7 +1595,7 @@ int jtag_config_khz(unsigned khz)
        LOG_DEBUG("handle jtag khz");
        clock_mode = CLOCK_MODE_KHZ;
        int speed = 0;
-       int retval = jtag_khz_to_speed(khz, &speed);
+       int retval = adapter_khz_to_speed(khz, &speed);
        return (ERROR_OK != retval) ? retval : jtag_set_speed(speed);
 }
 
@@ -1583,7 +1618,7 @@ int jtag_get_speed(void)
                        speed = jtag_speed;
                        break;
                case CLOCK_MODE_KHZ:
-                       jtag_khz_to_speed(jtag_get_speed_khz(), &speed);
+                       adapter_khz_to_speed(jtag_get_speed_khz(), &speed);
                        break;
                case CLOCK_MODE_RCLK:
                        jtag_rclk_to_speed(rclk_fallback_speed_khz, &speed);
@@ -1658,11 +1693,11 @@ int jtag_get_srst(void)
 
 void jtag_set_nsrst_delay(unsigned delay)
 {
-       jtag_nsrst_delay = delay;
+       adapter_nsrst_delay = delay;
 }
 unsigned jtag_get_nsrst_delay(void)
 {
-       return jtag_nsrst_delay;
+       return adapter_nsrst_delay;
 }
 void jtag_set_ntrst_delay(unsigned delay)
 {
@@ -1676,11 +1711,11 @@ unsigned jtag_get_ntrst_delay(void)
 
 void jtag_set_nsrst_assert_width(unsigned delay)
 {
-       jtag_nsrst_assert_width = delay;
+       adapter_nsrst_assert_width = delay;
 }
 unsigned jtag_get_nsrst_assert_width(void)
 {
-       return jtag_nsrst_assert_width;
+       return adapter_nsrst_assert_width;
 }
 void jtag_set_ntrst_assert_width(unsigned delay)
 {
@@ -1690,3 +1725,45 @@ 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;
+}