Introduced jtag_init and "jtag arp_init" to allow target scripts more control over...
[openocd.git] / src / jtag / core.c
index f9ebb3fa6f50d9ed401fb66f11932832f9ae1901..854236f3d15346d31b5d3bba24e89c4803ff34ea 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,8 +61,8 @@ 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",
 };
 
@@ -93,6 +93,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 +489,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 +663,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 +691,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 +704,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);
                }
        }
 }
@@ -847,6 +855,9 @@ void jtag_sleep(uint32_t us)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
 #define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
 
+/* A reserved manufacturer ID is used in END_OF_CHAIN_FLAG, so we
+ * know that no valid TAP will have it as an IDCODE value.
+ */
 #define END_OF_CHAIN_FLAG      0x000000ff
 
 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
@@ -882,8 +893,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;
@@ -947,10 +959,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++)
        {
@@ -964,6 +980,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
+ * This is called a "blind interrogation" of the scan chain.
  */
 static int jtag_examine_chain(void)
 {
@@ -1012,7 +1029,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;
        }
@@ -1037,26 +1054,37 @@ static int jtag_examine_chain(void)
        return ERROR_OK;
 }
 
-int jtag_validate_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)
 {
        jtag_tap_t *tap;
        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;
@@ -1064,50 +1092,60 @@ int jtag_validate_chain(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) {
                        break;
                }
 
-               val = buf_get_u32(ir_test, chain_pos, 2);
-               /* 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);
-                       free(cbuf);
-                       free(ir_test);
-                       return ERROR_JTAG_INIT_FAILED;
+               /* 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.
+                */
+               val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
+               if ((val & 0x3) != 1) {
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x..1",
+                                       jtag_tap_name(tap),
+                                       (tap->ir_length + 7) / tap->ir_length,
+                                       val);
+
+                       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;
        }
 
+       /* verify the '11' sentinel we wrote is returned at the end */
        val = buf_get_u32(ir_test, chain_pos, 2);
        if (val != 0x3)
        {
                char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-               LOG_ERROR("Could not validate end of JTAG scan chain, IR mismatch, scan returned 0x%s. pos=%d expected 0x3 got %0x", cbuf, chain_pos, val);
+
+               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;
 }
 
 
@@ -1115,6 +1153,7 @@ void jtag_tap_init(jtag_tap_t *tap)
 {
        assert(0 != tap->ir_length);
 
+       /// @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);
@@ -1132,7 +1171,8 @@ void jtag_tap_init(jtag_tap_t *tap)
        LOG_DEBUG("Created Tap: %s @ abs position %d, "
                        "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
                                tap->abs_chain_position, tap->ir_length,
-                         (unsigned int)(tap->ir_capture_value), (unsigned int)(tap->ir_capture_mask));
+                               (unsigned) tap->ir_capture_value,
+                               (unsigned) tap->ir_capture_mask);
        jtag_tap_add(tap);
 }
 
@@ -1141,6 +1181,7 @@ void jtag_tap_free(jtag_tap_t *tap)
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
        /// @todo is anything missing? no memory leaks please
+       free((void *)tap->expected);
        free((void *)tap->expected_ids);
        free((void *)tap->chip);
        free((void *)tap->tapname);
@@ -1189,10 +1230,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");
 
@@ -1209,14 +1251,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_chain() != ERROR_OK)
+       if (jtag_validate_ircapture() != ERROR_OK)
        {
-               LOG_WARNING("Could not validate JTAG chain, continuing anyway...");
+               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;
 }
 
@@ -1284,11 +1334,11 @@ 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);
+
+       if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
 }
 
 unsigned jtag_get_speed_khz(void)
@@ -1450,3 +1500,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)