Force sane SRST and TRST initialization
[openocd.git] / src / jtag / core.c
index b1d3ca0f1abb107b0aa1d4067ed7b83b79fe9151..f7d55b79301624e889e909d41537593c6b5e66d2 100644 (file)
@@ -1,16 +1,16 @@
 /***************************************************************************
- *   Copyright (C) 2005 by Dominic Rath                                    *
- *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2009 Zachary T Welch                                    *
+ *   zw@superlucidity.net                                                  *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
+ *   Copyright (C) 2007,2008,2009 Øyvind Harboe                            *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   Copyright (C) 2009 SoftPLC Corporation                                *
  *       http://softplc.com                                                *
  *   dick@softplc.com                                                      *
  *                                                                         *
- *   Copyright (C) 2009 Zachary T Welch                                    *
- *   zw@superlucidity.net                                                  *
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -61,17 +61,19 @@ static int jtag_error = ERROR_OK;
 static const char *jtag_event_strings[] =
 {
        [JTAG_TRST_ASSERTED] = "TAP reset",
+       [JTAG_TAP_EVENT_SETUP] = "TAP setup",
        [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
-       [JTAG_TAP_EVENT_POST_RESET] = "TAP post reset",
        [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
 };
 
 /*
  * JTAG adapters must initialize with TRST and SRST de-asserted
- * (they're negative logic, so that means *high*)
+ * (they're negative logic, so that means *high*).  But some
+ * hardware doesn't necessarily work that way ... so set things
+ * up so that jtag_init() always forces that state.
  */
-static int jtag_trst = 0;
-static int jtag_srst = 0;
+static int jtag_trst = -1;
+static int jtag_srst = -1;
 
 /**
  * List all TAPs that have been created.
@@ -93,6 +95,8 @@ 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 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
 {
@@ -487,7 +491,7 @@ void jtag_add_tlr(void)
 
        /* NOTE: order here matches TRST path in jtag_add_reset() */
        jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-       jtag_notify_reset();
+       jtag_notify_event(JTAG_TRST_ASSERTED);
 }
 
 void jtag_add_pathmove(int num_states, const tap_state_t *path)
@@ -661,7 +665,11 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (jtag_srst != new_srst) {
                jtag_srst = new_srst;
                if (jtag_srst)
+               {
                        LOG_DEBUG("SRST line asserted");
+                       if (jtag_nsrst_assert_width)
+                               jtag_add_sleep(jtag_nsrst_assert_width * 1000);
+               }
                else {
                        LOG_DEBUG("SRST line released");
                        if (jtag_nsrst_delay)
@@ -685,6 +693,8 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                if (jtag_trst) {
                        LOG_DEBUG("TRST line asserted");
                        tap_set_state(TAP_RESET);
+                       if (jtag_ntrst_assert_width)
+                               jtag_add_sleep(jtag_ntrst_assert_width * 1000);
                } else {
                        LOG_DEBUG("TRST line released");
                        if (jtag_ntrst_delay)
@@ -696,7 +706,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                         * sequence must match jtag_add_tlr().
                         */
                        jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-                       jtag_notify_reset();
+                       jtag_notify_event(JTAG_TRST_ASSERTED);
                }
        }
 }
@@ -885,8 +895,9 @@ static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
         * the scan is not valid */
        if (zero_check == 0x00 || one_check == 0xff)
        {
-               LOG_ERROR("JTAG communication failure: check connection, "
-                       "JTAG interface, target power etc.");
+               LOG_ERROR("JTAG scan chain interrogation failed: all %s",
+                               (zero_check == 0x00) ? "zeroes" : "ones");
+               LOG_ERROR("Check JTAG interface, timings, target power, etc.");
                return false;
        }
        return true;
@@ -950,10 +961,14 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        {
                if (tap->idcode == tap->expected_ids[ii])
                        return true;
+
+               /* treat "-expected-id 0" as a "don't-warn" wildcard */
+               if (0 == tap->expected_ids[ii])
+                       return true;
        }
 
-       /* If none of the expected ids matched, log an error */
-       jtag_examine_chain_display(LOG_LVL_ERROR, "UNEXPECTED",
+       /* 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++)
        {
@@ -1016,7 +1031,7 @@ static int jtag_examine_chain(void)
                }
                tap->idcode = idcode;
 
-               // ensure the TAP ID does matches what was expected
+               /* ensure the TAP ID matches what was expected */
                if (!jtag_examine_chain_match_tap(tap))
                        return ERROR_JTAG_INIT_FAILED;
        }
@@ -1045,6 +1060,9 @@ static int jtag_examine_chain(void)
  * Validate the date loaded by entry to the Capture-IR state, to help
  * find errors related to scan chain configuration (wrong IR lengths)
  * or communication.
+ *
+ * Entry state can be anything.  On non-error exit, all TAPs are in
+ * bypass mode.  On error exits, the scan chain is reset.
  */
 static int jtag_validate_ircapture(void)
 {
@@ -1052,24 +1070,23 @@ static int jtag_validate_ircapture(void)
        int total_ir_length = 0;
        uint8_t *ir_test = NULL;
        scan_field_t field;
+       int val;
        int chain_pos = 0;
+       int retval;
 
-       tap = NULL;
-       total_ir_length = 0;
-       for (;;) {
-               tap = jtag_tap_next_enabled(tap);
-               if (tap == NULL) {
-                       break;
-               }
-               total_ir_length += tap->ir_length;
-       }
+       for (tap = NULL, total_ir_length = 0;
+                       (tap = jtag_tap_next_enabled(tap)) != NULL;
+                       total_ir_length += tap->ir_length)
+               continue;
 
+       /* increase length to add 2 bit sentinel after scan */
        total_ir_length += 2;
 
        ir_test = malloc(CEIL(total_ir_length, 8));
        if (ir_test == NULL)
                return ERROR_FAIL;
 
+       /* after this scan, all TAPs will capture BYPASS instructions */
        buf_set_ones(ir_test, total_ir_length);
 
        field.tap = NULL;
@@ -1077,18 +1094,16 @@ static int jtag_validate_ircapture(void)
        field.out_value = ir_test;
        field.in_value = ir_test;
 
+       jtag_add_plain_ir_scan(1, &field, TAP_IDLE);
 
-       jtag_add_plain_ir_scan(1, &field, TAP_IRPAUSE);
-       jtag_add_tlr();
-
-       int retval;
+       LOG_DEBUG("IR capture validation scan");
        retval = jtag_execute_queue();
        if (retval != ERROR_OK)
-               return retval;
+               goto done;
 
        tap = NULL;
        chain_pos = 0;
-       int val;
+
        for (;;) {
                tap = jtag_tap_next_enabled(tap);
                if (tap == NULL) {
@@ -1096,25 +1111,26 @@ static int jtag_validate_ircapture(void)
                }
 
                /* Validate the two LSBs, which must be 01 per JTAG spec.
-                * REVISIT we might be able to verify some MSBs too, using
-                * ircapture/irmask attributes.
+                *
+                * Or ... more bits could be provided by TAP declaration.
+                * Plus, some taps (notably in i.MX series chips) violate
+                * this part of the JTAG spec, so their capture mask/value
+                * attributes might disable this test.
                 */
-               val = buf_get_u32(ir_test, chain_pos, 2);
-               if (val != 1) {
-                       char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-
-                       LOG_ERROR("%s: IR capture error; saw 0x%s not 0x..1",
-                                       jtag_tap_name(tap), cbuf);
-
-                       /* Fail only if we have IDCODE for this device.
-                        * REVISIT -- why not fail-always?
-                        */
-                       if (tap->hasidcode) {
-                               free(cbuf);
-                               free(ir_test);
-                               return ERROR_JTAG_INIT_FAILED;
-                       }
+               val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
+               if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
+                                       jtag_tap_name(tap),
+                                       (tap->ir_length + 7) / tap->ir_length,
+                                       val,
+                                       (tap->ir_length + 7) / tap->ir_length,
+                                       tap->ir_capture_value);
+
+                       retval = ERROR_JTAG_INIT_FAILED;
+                       goto done;
                }
+               LOG_DEBUG("%s: IR capture 0x%0*x", jtag_tap_name(tap),
+                               (tap->ir_length + 7) / tap->ir_length, val);
                chain_pos += tap->ir_length;
        }
 
@@ -1127,13 +1143,16 @@ static int jtag_validate_ircapture(void)
                LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3",
                                chain_pos, cbuf);
                free(cbuf);
-               free(ir_test);
-               return ERROR_JTAG_INIT_FAILED;
+               retval = ERROR_JTAG_INIT_FAILED;
        }
 
+done:
        free(ir_test);
-
-       return ERROR_OK;
+       if (retval != ERROR_OK) {
+               jtag_add_tlr();
+               jtag_execute_queue();
+       }
+       return retval;
 }
 
 
@@ -1218,10 +1237,11 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
-static int jtag_init_inner(struct command_context_s *cmd_ctx)
+int jtag_init_inner(struct command_context_s *cmd_ctx)
 {
        jtag_tap_t *tap;
        int retval;
+       bool issue_setup = true;
 
        LOG_DEBUG("Init JTAG chain");
 
@@ -1238,14 +1258,22 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
        /* examine chain first, as this could discover the real chain layout */
        if (jtag_examine_chain() != ERROR_OK)
        {
-               LOG_ERROR("trying to validate configured JTAG chain anyway...");
+               LOG_ERROR("Trying to use configured scan chain anyway...");
+               issue_setup = false;
        }
 
        if (jtag_validate_ircapture() != ERROR_OK)
        {
                LOG_WARNING("Errors during IR capture, continuing anyway...");
+               issue_setup = false;
        }
 
+       if (issue_setup)
+               jtag_notify_event(JTAG_TAP_EVENT_SETUP);
+       else
+               LOG_WARNING("Bypassing JTAG setup events due to errors");
+
+
        return ERROR_OK;
 }
 
@@ -1311,13 +1339,19 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
 int jtag_init(struct command_context_s *cmd_ctx)
 {
        int retval;
+
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
-       if (jtag_init_inner(cmd_ctx) == ERROR_OK)
-       {
-               return ERROR_OK;
-       }
-       return jtag_init_reset(cmd_ctx);
+
+       /* guard against oddball hardware: force resets to be inactive */
+       jtag_add_reset(0, 0);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+
+       if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
 }
 
 unsigned jtag_get_speed_khz(void)
@@ -1479,3 +1513,21 @@ unsigned jtag_get_ntrst_delay(void)
 {
        return jtag_ntrst_delay;
 }
+
+
+void jtag_set_nsrst_assert_width(unsigned delay)
+{
+       jtag_nsrst_assert_width = delay;
+}
+unsigned jtag_get_nsrst_assert_width(void)
+{
+       return jtag_nsrst_assert_width;
+}
+void jtag_set_ntrst_assert_width(unsigned delay)
+{
+       jtag_ntrst_assert_width = delay;
+}
+unsigned jtag_get_ntrst_assert_width(void)
+{
+       return jtag_ntrst_assert_width;
+}

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)