Minor behavior fixes for the two JTAG reset events (C/internal,
[fw/openocd] / src / jtag / core.c
index d278c96bcca83346f58245ca151889d0ebfec06c..6a314ece1d868dfc27932c887a688f06daf2f9d3 100644 (file)
@@ -62,6 +62,7 @@ static const char *jtag_event_strings[] =
 {
        [JTAG_TRST_ASSERTED] = "JTAG controller reset (TLR or TRST)",
        [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
+       [JTAG_TAP_EVENT_POST_RESET] = "post reset",
        [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
 };
 
@@ -339,6 +340,8 @@ 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)
 {
+       assert(state != TAP_RESET);
+
        if (jtag_verify && jtag_verify_capture_ir)
        {
                /* 8 x 32 bit id's is enough for all invocations */
@@ -361,6 +364,8 @@ 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,
                tap_state_t state)
 {
+       assert(state != TAP_RESET);
+
        jtag_prelude(state);
 
        int retval = interface_jtag_add_plain_ir_scan(
@@ -380,7 +385,8 @@ void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
        interface_jtag_add_callback4(f, data0, data1, data2, data3);
 }
 
-int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits);
+static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
+               uint8_t *in_check_mask, int num_bits);
 
 static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
 {
@@ -439,6 +445,8 @@ 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,
                tap_state_t state)
 {
+       assert(state != TAP_RESET);
+
        jtag_prelude(state);
 
        int retval;
@@ -449,6 +457,8 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields,
 void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
                tap_state_t state)
 {
+       assert(state != TAP_RESET);
+
        jtag_prelude(state);
 
        int retval;
@@ -460,6 +470,7 @@ void jtag_add_dr_out(jtag_tap_t* tap,
                int num_fields, const int* num_bits, const uint32_t* value,
                tap_state_t end_state)
 {
+       assert(end_state != TAP_RESET);
        assert(end_state != TAP_INVALID);
 
        cmd_queue_cur_state = end_state;
@@ -473,7 +484,10 @@ void jtag_add_tlr(void)
 {
        jtag_prelude(TAP_RESET);
        jtag_set_error(interface_jtag_add_tlr());
+
+       /* NOTE: order here matches TRST path in jtag_add_reset() */
        jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+       jtag_notify_reset();
 }
 
 void jtag_add_pathmove(int num_states, const tap_state_t *path)
@@ -669,20 +683,20 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        } else if (jtag_trst != new_trst) {
                jtag_trst = new_trst;
                if (jtag_trst) {
-                       /* we just asserted nTRST, so we're now in TAP_RESET;
-                        * inform possible listeners about this
-                        *
-                        * REVISIT asserting TRST is less significant than
-                        * being in TAP_RESET ... both entries (TRST, TLR)
-                        * should trigger a callback.
-                        */
                        LOG_DEBUG("TRST line asserted");
                        tap_set_state(TAP_RESET);
-                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
                } else {
                        LOG_DEBUG("TRST line released");
                        if (jtag_ntrst_delay)
                                jtag_add_sleep(jtag_ntrst_delay * 1000);
+
+                       /* We just asserted nTRST, so we're now in TAP_RESET.
+                        * Inform possible listeners about this, now that
+                        * JTAG instructions and data can be shifted.  This
+                        * sequence must match jtag_add_tlr().
+                        */
+                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       jtag_notify_reset();
                }
        }
 }
@@ -711,7 +725,8 @@ void jtag_add_sleep(uint32_t us)
        jtag_set_error(interface_jtag_add_sleep(us));
 }
 
-int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits)
+static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
+               uint8_t *in_check_mask, int num_bits)
 {
        int retval = ERROR_OK;
 
@@ -723,39 +738,32 @@ int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *
                compare_failed = buf_cmp(captured, in_check_value, num_bits);
 
        if (compare_failed) {
-               /* An error handler could have caught the failing check
-                * only report a problem when there wasn't a handler, or if the handler
-                * acknowledged the error
-                */
-               /*
-               LOG_WARNING("TAP %s:",
-                                       jtag_tap_name(field->tap));
-                                       */
-               if (compare_failed)
-               {
-                       char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
-                       char *in_check_value_char = buf_to_str(in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
+               char *captured_str, *in_check_value_str;
+               int bits = (num_bits > DEBUG_JTAG_IOZ)
+                               ? DEBUG_JTAG_IOZ
+                               : num_bits;
 
-                       if (in_check_mask)
-                       {
-                               char *in_check_mask_char;
-                               in_check_mask_char = buf_to_str(in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
-                               LOG_WARNING("value captured during scan didn't pass the requested check:");
-                               LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s",
-                                                       captured_char, in_check_value_char, in_check_mask_char);
-                               free(in_check_mask_char);
-                       }
-                       else
-                       {
-                               LOG_WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char);
-                       }
+               /* NOTE:  we've lost diagnostic context here -- 'which tap' */
+
+               captured_str = buf_to_str(captured, bits, 16);
+               in_check_value_str = buf_to_str(in_check_value, bits, 16);
+
+               LOG_WARNING("Bad value '%s' captured during DR or IR scan:",
+                               captured_str);
+               LOG_WARNING(" check_value: 0x%s", in_check_value_str);
+
+               free(captured_str);
+               free(in_check_value_str);
 
-                       free(captured_char);
-                       free(in_check_value_char);
+               if (in_check_mask) {
+                       char *in_check_mask_str;
 
-                       retval = ERROR_JTAG_QUEUE_FAILED;
+                       in_check_mask_str = buf_to_str(in_check_mask, bits, 16);
+                       LOG_WARNING(" check_mask: 0x%s", in_check_mask_str);
+                       free(in_check_mask_str);
                }
 
+               retval = ERROR_JTAG_QUEUE_FAILED;
        }
        return retval;
 }
@@ -812,7 +820,8 @@ static int jtag_reset_callback(enum jtag_event event, void *priv)
 {
        jtag_tap_t *tap = priv;
 
-       LOG_DEBUG("-");
+       LOG_DEBUG("TAP %s event %s", tap->dotted_name,
+                       jtag_event_strings[event]);
 
        if (event == JTAG_TRST_ASSERTED)
        {
@@ -851,7 +860,8 @@ 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, 0x000000FF);
 
-       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
+       jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE);
+       jtag_add_tlr();
        return jtag_execute_queue();
 }
 
@@ -939,7 +949,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        /* If none of the expected ids matched, log an error */
        if (ii != tap->expected_ids_cnt)
        {
-               LOG_INFO("JTAG Tap/device matched");
+               LOG_DEBUG("JTAG Tap/device matched");
                return true;
        }
        jtag_examine_chain_display(LOG_LVL_ERROR, "got",
@@ -957,7 +967,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
 
 /* Try to examine chain layout according to IEEE 1149.1 ยง12
  */
-int jtag_examine_chain(void)
+static int jtag_examine_chain(void)
 {
        uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        unsigned device_count = 0;
@@ -975,20 +985,26 @@ int jtag_examine_chain(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+       for (unsigned bit_count = 0;
+                       tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;
+                       tap = jtag_tap_next_enabled(tap))
        {
                uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+
                if ((idcode & 1) == 0)
                {
                        /* LSB must not be 0, this indicates a device in bypass */
                        LOG_WARNING("Tap/Device does not have IDCODE");
                        idcode = 0;
+                       tap->hasidcode = false;
 
                        bit_count += 1;
                }
                else
                {
-                       /*
+                       tap->hasidcode = true;
+
+                       /*
                         * End of chain (invalid manufacturer ID) some devices, such
                         * as AVR will output all 1's instead of TDI input value at
                         * end of chain.
@@ -1013,10 +1029,8 @@ int jtag_examine_chain(void)
                tap->idcode = idcode;
 
                // ensure the TAP ID does matches what was expected
-               if (!jtag_examine_chain_match_tap(tap))
+               if (!jtag_examine_chain_match_tap(tap))
                        return ERROR_JTAG_INIT_FAILED;
-
-               tap = jtag_tap_next_enabled(tap);
        }
 
        /* see if number of discovered devices matches configuration */
@@ -1061,8 +1075,13 @@ int jtag_validate_chain(void)
        field.in_value = ir_test;
 
 
-       jtag_add_plain_ir_scan(1, &field, TAP_RESET);
-       jtag_execute_queue();
+       jtag_add_plain_ir_scan(1, &field, TAP_IRPAUSE);
+       jtag_add_tlr();
+
+       int retval;
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
 
        tap = NULL;
        chain_pos = 0;
@@ -1074,7 +1093,8 @@ int jtag_validate_chain(void)
                }
 
                val = buf_get_u32(ir_test, chain_pos, 2);
-               if (val != 0x1)
+               /* Only fail this check if we have IDCODE for this device */
+               if ((val != 0x1)&&(tap->hasidcode))
                {
                        char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
                        LOG_ERROR("Could not validate JTAG scan chain, IR mismatch, scan returned 0x%s. tap=%s pos=%d expected 0x1 got %0x", cbuf, jtag_tap_name(tap), chain_pos, val);