rename CEIL as DIV_ROUND_UP
[openocd.git] / src / jtag / core.c
index 1c9d13c94801ef344c5bc6604ab90c9f1a7fac05..c8a76e885e550aa8d3a07a0bb25c926a99fef984 100644 (file)
@@ -43,8 +43,8 @@
 /// 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 scan_field_t *in_fields, tap_state_t state),
-               int in_num_fields, scan_field_t *in_fields, tap_state_t state);
+static void jtag_add_scan_check(void (*jtag_add_scan)(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);
 
 /**
  * The jtag_error variable is set when an error occurs while executing
@@ -78,7 +78,7 @@ static int jtag_srst = -1;
 /**
  * List all TAPs that have been created.
  */
-static jtag_tap_t *__jtag_all_taps = NULL;
+static struct jtag_tap *__jtag_all_taps = NULL;
 /**
  * The number of TAPs in the __jtag_all_taps list, used to track the
  * assigned chain position to new TAPs
@@ -98,15 +98,21 @@ static int jtag_ntrst_delay = 0; /* default to no nTRST delay */
 static int jtag_nsrst_assert_width = 0; /* width of assertion */
 static int jtag_ntrst_assert_width = 0; /* width of assertion */
 
-typedef struct jtag_event_callback_s
-{
-       jtag_event_handler_t          callback;
-       void*                         priv;
-       struct jtag_event_callback_s* next;
-} jtag_event_callback_t;
+/**
+ * Contains a single callback along with a pointer that will be passed
+ * when an event occurs.
+ */
+struct jtag_event_callback {
+       /// a event callback
+       jtag_event_handler_t callback;
+       /// the private data to pass to the callback
+       void* priv;
+       /// the next callback
+       struct jtag_event_callback* next;
+};
 
 /* callbacks to inform high-level handlers about JTAG state changes */
-static jtag_event_callback_t *jtag_event_callbacks;
+static struct jtag_event_callback *jtag_event_callbacks;
 
 /* speed in kHz*/
 static int speed_khz = 0;
@@ -115,10 +121,10 @@ static int rclk_fallback_speed_khz = 0;
 static enum {CLOCK_MODE_SPEED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
 static int jtag_speed = 0;
 
-static struct jtag_interface_s *jtag = NULL;
+static struct jtag_interface *jtag = NULL;
 
 /* configuration */
-jtag_interface_t *jtag_interface = NULL;
+struct jtag_interface *jtag_interface = NULL;
 
 void jtag_set_error(int error)
 {
@@ -164,7 +170,7 @@ void jtag_poll_set_enabled(bool value)
 
 /************/
 
-jtag_tap_t *jtag_all_taps(void)
+struct jtag_tap *jtag_all_taps(void)
 {
        return __jtag_all_taps;
 };
@@ -176,7 +182,7 @@ unsigned jtag_tap_count(void)
 
 unsigned jtag_tap_count_enabled(void)
 {
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
        unsigned n = 0;
        while (t)
        {
@@ -188,20 +194,20 @@ unsigned jtag_tap_count_enabled(void)
 }
 
 /// Append a new TAP to the chain of all taps.
-void jtag_tap_add(struct jtag_tap_s *t)
+void jtag_tap_add(struct jtag_tap *t)
 {
        t->abs_chain_position = jtag_num_taps++;
 
-       jtag_tap_t **tap = &__jtag_all_taps;
+       struct jtag_tap **tap = &__jtag_all_taps;
        while (*tap != NULL)
                tap = &(*tap)->next_tap;
        *tap = t;
 }
 
 /* returns a pointer to the n-th device in the scan chain */
-static inline jtag_tap_t *jtag_tap_by_position(unsigned n)
+static inline struct jtag_tap *jtag_tap_by_position(unsigned n)
 {
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
 
        while (t && n-- > 0)
                t = t->next_tap;
@@ -209,10 +215,10 @@ static inline jtag_tap_t *jtag_tap_by_position(unsigned n)
        return t;
 }
 
-jtag_tap_t *jtag_tap_by_string(const char *s)
+struct jtag_tap *jtag_tap_by_string(const char *s)
 {
        /* try by name first */
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
 
        while (t)
        {
@@ -238,10 +244,10 @@ jtag_tap_t *jtag_tap_by_string(const char *s)
        return t;
 }
 
-jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
+struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
 {
        const char *cp = Jim_GetString(o, NULL);
-       jtag_tap_t *t = cp ? jtag_tap_by_string(cp) : NULL;
+       struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL;
        if (NULL == cp)
                cp = "(unknown)";
        if (NULL == t)
@@ -249,7 +255,7 @@ jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
        return t;
 }
 
-jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p)
+struct jtag_tap* jtag_tap_next_enabled(struct jtag_tap* p)
 {
        p = p ? p->next_tap : jtag_all_taps();
        while (p)
@@ -261,7 +267,7 @@ jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p)
        return NULL;
 }
 
-const char *jtag_tap_name(const jtag_tap_t *tap)
+const char *jtag_tap_name(const struct jtag_tap *tap)
 {
        return (tap == NULL) ? "(unknown)" : tap->dotted_name;
 }
@@ -269,7 +275,7 @@ const char *jtag_tap_name(const jtag_tap_t *tap)
 
 int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
 {
-       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+       struct jtag_event_callback **callbacks_p = &jtag_event_callbacks;
 
        if (callback == NULL)
        {
@@ -283,7 +289,7 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
                callbacks_p = &((*callbacks_p)->next);
        }
 
-       (*callbacks_p) = malloc(sizeof(jtag_event_callback_t));
+       (*callbacks_p) = malloc(sizeof(struct jtag_event_callback));
        (*callbacks_p)->callback = callback;
        (*callbacks_p)->priv = priv;
        (*callbacks_p)->next = NULL;
@@ -293,8 +299,8 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
 
 int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv)
 {
-       jtag_event_callback_t **callbacks_p;
-       jtag_event_callback_t **next;
+       struct jtag_event_callback **callbacks_p;
+       struct jtag_event_callback **next;
 
        if (callback == NULL)
        {
@@ -322,13 +328,13 @@ int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv)
 
 int jtag_call_event_callbacks(enum jtag_event event)
 {
-       jtag_event_callback_t *callback = jtag_event_callbacks;
+       struct jtag_event_callback *callback = jtag_event_callbacks;
 
        LOG_DEBUG("jtag event: %s", jtag_event_strings[event]);
 
        while (callback)
        {
-               jtag_event_callback_t *next;
+               struct jtag_event_callback *next;
 
                /* callback may remove itself */
                next = callback->next;
@@ -353,12 +359,12 @@ static void jtag_prelude(tap_state_t state)
        cmd_queue_cur_state = state;
 }
 
-void jtag_alloc_in_value32(scan_field_t *field)
+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 scan_field_t *in_fields,
+void jtag_add_ir_scan_noverify(int in_count, const struct scan_field *in_fields,
                tap_state_t state)
 {
        jtag_prelude(state);
@@ -368,7 +374,7 @@ void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields,
 }
 
 
-void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t state)
+void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        assert(state != TAP_RESET);
 
@@ -391,7 +397,7 @@ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t st
        }
 }
 
-void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -423,12 +429,12 @@ 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 scan_field_t *in_fields, tap_state_t state),
-               int in_num_fields, scan_field_t *in_fields, tap_state_t state)
+static void jtag_add_scan_check(void (*jtag_add_scan)(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++)
        {
-               struct scan_field_s *field = &in_fields[i];
+               struct scan_field *field = &in_fields[i];
                field->allocated = 0;
                field->modified = 0;
                if (field->check_value || field->in_value)
@@ -460,7 +466,7 @@ 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, scan_field_t *in_fields, tap_state_t state)
+void jtag_add_dr_scan_check(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        if (jtag_verify)
        {
@@ -472,7 +478,7 @@ void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_stat
 }
 
 
-void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -484,7 +490,7 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields,
        jtag_set_error(retval);
 }
 
-void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -496,7 +502,7 @@ void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
        jtag_set_error(retval);
 }
 
-void jtag_add_dr_out(jtag_tap_t* tap,
+void jtag_add_dr_out(struct jtag_tap* tap,
                int num_fields, const int* num_bits, const uint32_t* value,
                tap_state_t end_state)
 {
@@ -567,12 +573,14 @@ int jtag_add_statemove(tap_state_t goal_state)
                tap_state_name(goal_state));
 
 
-       if (goal_state == cur_state)
-               ;       /* nothing to do */
-       else if (goal_state == TAP_RESET)
-       {
+       /* If goal is RESET, be paranoid and force that that transition
+        * (e.g. five TCK cycles, TMS high).  Else trust "cur_state".
+        */
+       if (goal_state == TAP_RESET)
                jtag_add_tlr();
-       }
+       else if (goal_state == cur_state)
+               /* nothing to do */ ;
+
        else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state))
        {
                unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
@@ -804,7 +812,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
        return retval;
 }
 
-void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask)
+void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask)
 {
        assert(field->in_value != NULL);
 
@@ -854,7 +862,7 @@ int jtag_execute_queue(void)
 
 static int jtag_reset_callback(enum jtag_event event, void *priv)
 {
-       jtag_tap_t *tap = priv;
+       struct jtag_tap *tap = priv;
 
        if (event == JTAG_TRST_ASSERTED)
        {
@@ -888,9 +896,12 @@ void jtag_sleep(uint32_t us)
  */
 #define END_OF_CHAIN_FLAG      0x000000ff
 
+/* a larger IR length than we ever expect to autoprobe */
+#define JTAG_IRLEN_MAX         60
+
 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
 {
-       scan_field_t field = {
+       struct scan_field field = {
                        .tap = NULL,
                        .num_bits = num_idcode * 32,
                        .out_value = idcode_buffer,
@@ -984,15 +995,16 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
        return triggered;
 }
 
-static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
+static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
 {
        /* ignore expected BYPASS codes; warn otherwise */
        if (0 == tap->expected_ids_cnt && !tap->idcode)
                return true;
 
        /* Loop over the expected identification codes and test for a match */
-       uint8_t ii;
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       unsigned ii, limit = tap->expected_ids_cnt;
+
+       for (ii = 0; ii < limit; ii++)
        {
                if (tap->idcode == tap->expected_ids[ii])
                        return true;
@@ -1005,11 +1017,11 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        /* If none of the expected ids matched, warn */
        jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
                        tap->dotted_name, tap->idcode);
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       for (ii = 0; ii < limit; ii++)
        {
                char msg[32];
-               snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
-                               ii + 1, tap->expected_ids_cnt);
+
+               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
                jtag_examine_chain_display(LOG_LVL_ERROR, msg,
                                tap->dotted_name, tap->expected_ids[ii]);
        }
@@ -1024,6 +1036,8 @@ static int jtag_examine_chain(void)
        uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        unsigned bit_count;
        int retval;
+       int tapcount = 0;
+       bool autoprobe = false;
 
        /* DR scan to collect BYPASS or IDCODE register contents.
         * Then make sure the scan data has both ones and zeroes.
@@ -1036,12 +1050,10 @@ static int jtag_examine_chain(void)
                return ERROR_JTAG_INIT_FAILED;
 
        /* point at the 1st tap */
-       jtag_tap_t *tap = jtag_tap_next_enabled(NULL);
-       if (tap == NULL)
-       {
-               LOG_ERROR("JTAG: No taps enabled?");
-               return ERROR_JTAG_INIT_FAILED;
-       }
+       struct jtag_tap *tap = jtag_tap_next_enabled(NULL);
+
+       if (!tap)
+               autoprobe = true;
 
        for (bit_count = 0;
                        tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;
@@ -1083,6 +1095,59 @@ static int jtag_examine_chain(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
+       /* if autoprobing, the tap list is still empty ... populate it! */
+       while (autoprobe && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31) {
+               uint32_t idcode;
+               char buf[12];
+
+               /* Is there another TAP? */
+               idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+               if (jtag_idcode_is_final(idcode))
+                       break;
+
+               /* Default everything in this TAP except IR length.
+                *
+                * REVISIT create a jtag_alloc(chip, tap) routine, and
+                * share it with jim_newtap_cmd().
+                */
+               tap = calloc(1, sizeof *tap);
+               if (!tap)
+                       return ERROR_FAIL;
+
+               sprintf(buf, "auto%d", tapcount++);
+               tap->chip = strdup(buf);
+               tap->tapname = strdup("tap");
+
+               sprintf(buf, "%s.%s", tap->chip, tap->tapname);
+               tap->dotted_name = strdup(buf);
+
+               /* tap->ir_length == 0 ... signifying irlen autoprobe */
+               tap->ir_capture_mask = 0x03;
+               tap->ir_capture_value = 0x01;
+
+               tap->enabled = true;
+
+               if ((idcode & 1) == 0) {
+                       bit_count += 1;
+                       tap->hasidcode = false;
+               } else {
+                       bit_count += 32;
+                       tap->hasidcode = true;
+                       tap->idcode = idcode;
+
+                       tap->expected_ids_cnt = 1;
+                       tap->expected_ids = malloc(sizeof(uint32_t));
+                       tap->expected_ids[0] = idcode;
+               }
+
+               LOG_WARNING("AUTO %s - use \"jtag newtap "
+                               "%s %s -expected-id 0x%8.8" PRIx32 " ...\"",
+                               tap->dotted_name, tap->chip, tap->tapname,
+                               tap->idcode);
+
+               jtag_tap_init(tap);
+       }
+
        /* After those IDCODE or BYPASS register values should be
         * only the data we fed into the scan chain.
         */
@@ -1109,23 +1174,26 @@ static int jtag_examine_chain(void)
  */
 static int jtag_validate_ircapture(void)
 {
-       jtag_tap_t *tap;
+       struct jtag_tap *tap;
        int total_ir_length = 0;
        uint8_t *ir_test = NULL;
-       scan_field_t field;
+       struct scan_field field;
        int val;
        int chain_pos = 0;
        int retval;
 
+       /* when autoprobing, accomodate huge IR lengths */
        for (tap = NULL, total_ir_length = 0;
                        (tap = jtag_tap_next_enabled(tap)) != NULL;
-                       total_ir_length += tap->ir_length)
-               continue;
+                       total_ir_length += tap->ir_length) {
+               if (tap->ir_length == 0)
+                       total_ir_length += JTAG_IRLEN_MAX;
+       }
 
        /* increase length to add 2 bit sentinel after scan */
        total_ir_length += 2;
 
-       ir_test = malloc(CEIL(total_ir_length, 8));
+       ir_test = malloc(DIV_ROUND_UP(total_ir_length, 8));
        if (ir_test == NULL)
                return ERROR_FAIL;
 
@@ -1153,6 +1221,25 @@ static int jtag_validate_ircapture(void)
                        break;
                }
 
+               /* If we're autoprobing, guess IR lengths.  They must be at
+                * least two bits.  Guessing will fail if (a) any TAP does
+                * not conform to the JTAG spec; or (b) when the upper bits
+                * captured from some conforming TAP are nonzero.
+                *
+                * REVISIT alternative approach: escape to some tcl code
+                * which could provide more knowledge, based on IDCODE; and
+                * only guess when that has no success.
+                */
+               if (tap->ir_length == 0) {
+                       tap->ir_length = 2;
+                       while ((val = buf_get_u32(ir_test, chain_pos,
+                                               tap->ir_length + 1)) == 1) {
+                               tap->ir_length++;
+                       }
+                       LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
+                                       jtag_tap_name(tap), tap->ir_length);
+               }
+
                /* Validate the two LSBs, which must be 01 per JTAG spec.
                 *
                 * Or ... more bits could be provided by TAP declaration.
@@ -1167,7 +1254,7 @@ static int jtag_validate_ircapture(void)
                                        (tap->ir_length + 7) / tap->ir_length,
                                        val,
                                        (tap->ir_length + 7) / tap->ir_length,
-                                       tap->ir_capture_value);
+                                       (unsigned) tap->ir_capture_value);
 
                        retval = ERROR_JTAG_INIT_FAILED;
                        goto done;
@@ -1199,22 +1286,30 @@ done:
 }
 
 
-void jtag_tap_init(jtag_tap_t *tap)
+void jtag_tap_init(struct jtag_tap *tap)
 {
-       assert(0 != tap->ir_length);
+       unsigned ir_len_bits;
+       unsigned ir_len_bytes;
 
-       /// @todo fix, this allocates one byte per bit for all three fields!
-       tap->expected = malloc(tap->ir_length);
-       tap->expected_mask = malloc(tap->ir_length);
-       tap->cur_instr = malloc(tap->ir_length);
+       /* if we're autoprobing, cope with potentially huge ir_length */
+       ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX;
+       ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8);
 
-       /// @todo cope sanely with ir_length bigger than 32 bits
-       buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value);
-       buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask);
-       buf_set_ones(tap->cur_instr, tap->ir_length);
+       tap->expected = calloc(1, ir_len_bytes);
+       tap->expected_mask = calloc(1, ir_len_bytes);
+       tap->cur_instr = malloc(ir_len_bytes);
 
-       // place TAP in bypass mode
+       /// @todo cope better with ir_length bigger than 32 bits
+       if (ir_len_bits > 32)
+               ir_len_bits = 32;
+
+       buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value);
+       buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
+
+       // TAP will be in bypass mode after jtag_validate_ircapture()
        tap->bypass = 1;
+       buf_set_ones(tap->cur_instr, tap->ir_length);
+
        // register the reset callback for the TAP
        jtag_register_event_callback(&jtag_reset_callback, tap);
 
@@ -1226,7 +1321,7 @@ void jtag_tap_init(jtag_tap_t *tap)
        jtag_tap_add(tap);
 }
 
-void jtag_tap_free(jtag_tap_t *tap)
+void jtag_tap_free(struct jtag_tap *tap)
 {
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
@@ -1239,7 +1334,7 @@ void jtag_tap_free(jtag_tap_t *tap)
        free(tap);
 }
 
-int jtag_interface_init(struct command_context_s *cmd_ctx)
+int jtag_interface_init(struct command_context *cmd_ctx)
 {
        if (jtag)
                return ERROR_OK;
@@ -1280,9 +1375,9 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
-int jtag_init_inner(struct command_context_s *cmd_ctx)
+int jtag_init_inner(struct command_context *cmd_ctx)
 {
-       jtag_tap_t *tap;
+       struct jtag_tap *tap;
        int retval;
        bool issue_setup = true;
 
@@ -1290,8 +1385,21 @@ int jtag_init_inner(struct command_context_s *cmd_ctx)
 
        tap = jtag_tap_next_enabled(NULL);
        if (tap == NULL) {
-               LOG_ERROR("There are no enabled taps?");
-               return ERROR_JTAG_INIT_FAILED;
+               /* Once JTAG itself is properly set up, and the scan chain
+                * isn't absurdly large, IDCODE autoprobe should work fine.
+                *
+                * But ... IRLEN autoprobe can fail even on systems which
+                * are fully conformant to JTAG.  Also, JTAG setup can be
+                * quite finicky on some systems.
+                *
+                * REVISIT: if TAP autoprobe works OK, then in many cases
+                * we could escape to tcl code and set up targets based on
+                * the TAP's IDCODE values.
+                */
+               LOG_WARNING("There are no enabled taps.  "
+                               "AUTO PROBING MIGHT NOT WORK!!");
+
+               /* REVISIT default clock will often be too fast ... */
        }
 
        jtag_add_tlr();
@@ -1353,29 +1461,38 @@ int jtag_interface_quit(void)
 }
 
 
-int jtag_init_reset(struct command_context_s *cmd_ctx)
+int jtag_init_reset(struct command_context *cmd_ctx)
 {
        int retval;
 
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
-       LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR");
+       LOG_DEBUG("Initializing with hard TRST+SRST reset");
 
-       /* Reset can happen after a power cycle.
-        *
-        * Ideally we would only assert TRST or run TLR before the target reset.
+       /*
+        * This procedure is used by default when OpenOCD triggers a reset.
+        * It's now done through an overridable Tcl "init_reset" wrapper.
         *
-        * However w/srst_pulls_trst, trst is asserted together with the target
-        * reset whether we want it or not.
+        * This started out as a more powerful "get JTAG working" reset than
+        * jtag_init_inner(), applying TRST because some chips won't activate
+        * JTAG without a TRST cycle (presumed to be async, though some of
+        * those chips synchronize JTAG activation using TCK).
         *
-        * NB! Some targets have JTAG circuitry disabled until a
-        * trst & srst has been asserted.
+        * But some chips only activate JTAG as part of an SRST cycle; SRST
+        * got mixed in.  So it became a hard reset routine, which got used
+        * in more places, and which coped with JTAG reset being forced as
+        * part of SRST (srst_pulls_trst).
         *
-        * NB! here we assume nsrst/ntrst delay are sufficient!
+        * And even more corner cases started to surface:  TRST and/or SRST
+        * assertion timings matter; some chips need other JTAG operations;
+        * TRST/SRST sequences can need to be different from these, etc.
         *
-        * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+        * Systems should override that wrapper to support system-specific
+        * requirements that this not-fully-generic code doesn't handle.
         *
+        * REVISIT once Tcl code can read the reset_config modes, this won't
+        * need to be a C routine at all...
         */
        jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
        if (jtag_reset_config & RESET_HAS_SRST)
@@ -1398,7 +1515,7 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
        return jtag_init_inner(cmd_ctx);
 }
 
-int jtag_init(struct command_context_s *cmd_ctx)
+int jtag_init(struct command_context *cmd_ctx)
 {
        int retval;
 
@@ -1458,13 +1575,6 @@ static int jtag_set_speed(int speed)
        return jtag ? jtag->speed(speed) : ERROR_OK;
 }
 
-int jtag_config_speed(int speed)
-{
-       LOG_DEBUG("handle jtag speed");
-       clock_mode = CLOCK_MODE_SPEED;
-       return jtag_set_speed(speed);
-}
-
 int jtag_config_khz(unsigned khz)
 {
        LOG_DEBUG("handle jtag khz");

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)