target: restructure dap support
[openocd.git] / src / jtag / core.c
index 04b0fc669e8fe06cb9e1a034596124b22e39670e..0fbd327fe6ece8c3d674fd98a4ad5d3f46ecf834 100644 (file)
@@ -23,9 +23,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -36,6 +34,7 @@
 #include "swd.h"
 #include "interface.h"
 #include <transport/transport.h>
+#include <helper/jep106.h>
 
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
@@ -649,6 +648,12 @@ void swd_add_reset(int req_srst)
                        if (adapter_nsrst_delay)
                                jtag_add_sleep(adapter_nsrst_delay * 1000);
                }
+
+               retval = jtag_execute_queue();
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("SRST timings error");
+                       return;
+               }
        }
 }
 
@@ -886,12 +891,10 @@ void jtag_sleep(uint32_t us)
                alive_sleep((us+999)/1000);
 }
 
-/* Maximum number of enabled JTAG devices we expect in the scan chain,
- * plus one (to detect garbage at the end).  Devices that don't support
- * IDCODE take up fewer bits, possibly allowing a few more devices.
- */
-#define JTAG_MAX_CHAIN_SIZE 20
+#define JTAG_MAX_AUTO_TAPS 20
 
+#define EXTRACT_JEP106_BANK(X) (((X) & 0xf00) >> 8)
+#define EXTRACT_JEP106_ID(X)   (((X) & 0xfe) >> 1)
 #define EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
 #define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
@@ -913,7 +916,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
        };
 
        /* initialize to the end of chain ID value */
-       for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+       for (unsigned i = 0; i < num_idcode; i++)
                buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
 
        jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE);
@@ -955,10 +958,11 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg,
 {
        log_printf_lf(level, __FILE__, __LINE__, __func__,
                "JTAG tap: %s %16.16s: 0x%08x "
-               "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+               "(mfg: 0x%3.3x (%s), part: 0x%4.4x, ver: 0x%1.1x)",
                name, msg,
                (unsigned int)idcode,
                (unsigned int)EXTRACT_MFG(idcode),
+               jep106_manufacturer(EXTRACT_JEP106_BANK(idcode), EXTRACT_JEP106_ID(idcode)),
                (unsigned int)EXTRACT_PART(idcode),
                (unsigned int)EXTRACT_VER(idcode));
 }
@@ -998,21 +1002,16 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
 
 static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
 {
-       uint32_t idcode = tap->idcode;
 
-       /* ignore expected BYPASS codes; warn otherwise */
-       if (0 == tap->expected_ids_cnt && !idcode)
+       if (tap->expected_ids_cnt == 0 || !tap->hasidcode)
                return true;
 
        /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
        uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0;
-
-       idcode &= mask;
+       uint32_t idcode = tap->idcode & mask;
 
        /* Loop over the expected identification codes and test for a match */
-       unsigned ii, limit = tap->expected_ids_cnt;
-
-       for (ii = 0; ii < limit; ii++) {
+       for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
                uint32_t expected = tap->expected_ids[ii] & mask;
 
                if (idcode == expected)
@@ -1026,10 +1025,10 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *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 < limit; ii++) {
+       for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
                char msg[32];
 
-               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
+               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt);
                jtag_examine_chain_display(LOG_LVL_ERROR, msg,
                        tap->dotted_name, tap->expected_ids[ii]);
        }
@@ -1041,130 +1040,108 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
  */
 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;
+       unsigned max_taps = jtag_tap_count();
+
+       /* Autoprobe up to this many. */
+       if (max_taps < JTAG_MAX_AUTO_TAPS)
+               max_taps = JTAG_MAX_AUTO_TAPS;
+
+       /* Add room for end-of-chain marker. */
+       max_taps++;
+
+       uint8_t *idcode_buffer = malloc(max_taps * 4);
+       if (idcode_buffer == NULL)
+               return ERROR_JTAG_INIT_FAILED;
 
        /* DR scan to collect BYPASS or IDCODE register contents.
         * Then make sure the scan data has both ones and zeroes.
         */
        LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
-       retval = jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       retval = jtag_examine_chain_execute(idcode_buffer, max_taps);
        if (retval != ERROR_OK)
-               return retval;
-       if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
-               return ERROR_JTAG_INIT_FAILED;
+               goto out;
+       if (!jtag_examine_chain_check(idcode_buffer, max_taps)) {
+               retval = ERROR_JTAG_INIT_FAILED;
+               goto out;
+       }
 
-       /* point at the 1st tap */
+       /* Point at the 1st predefined tap, if any */
        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;
-            tap = jtag_tap_next_enabled(tap)) {
+       unsigned bit_count = 0;
+       unsigned autocount = 0;
+       for (unsigned i = 0; i < max_taps; i++) {
+               assert(bit_count < max_taps * 32);
                uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
 
+               /* No predefined TAP? Auto-probe. */
+               if (tap == NULL) {
+                       /* Is there another TAP? */
+                       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) {
+                               retval = ERROR_FAIL;
+                               goto out;
+                       }
+
+                       tap->chip = alloc_printf("auto%u", autocount++);
+                       tap->tapname = strdup("tap");
+                       tap->dotted_name = alloc_printf("%s.%s", tap->chip, tap->tapname);
+
+                       tap->ir_length = 0; /* ... signifying irlen autoprobe */
+                       tap->ir_capture_mask = 0x03;
+                       tap->ir_capture_value = 0x01;
+
+                       tap->enabled = true;
+
+                       jtag_tap_init(tap);
+               }
+
                if ((idcode & 1) == 0) {
                        /* Zero for LSB indicates a device in bypass */
-                       LOG_INFO("TAP %s does not have IDCODE",
-                               tap->dotted_name);
-                       idcode = 0;
+                       LOG_INFO("TAP %s does not have IDCODE", tap->dotted_name);
                        tap->hasidcode = false;
+                       tap->idcode = 0;
 
                        bit_count += 1;
                } else {
                        /* Friendly devices support IDCODE */
                        tap->hasidcode = true;
-                       jtag_examine_chain_display(LOG_LVL_INFO,
-                               "tap/device found",
-                               tap->dotted_name, idcode);
+                       tap->idcode = idcode;
+                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode);
 
                        bit_count += 32;
                }
-               tap->idcode = idcode;
 
                /* ensure the TAP ID matches what was expected */
                if (!jtag_examine_chain_match_tap(tap))
                        retval = ERROR_JTAG_INIT_SOFT_FAIL;
-       }
-
-       /* Fail if too many TAPs were enabled for us to verify them all. */
-       if (tap) {
-               LOG_ERROR("Too many TAPs enabled; '%s' ignored.",
-                       tap->dotted_name);
-               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);
+               tap = jtag_tap_next_enabled(tap);
        }
 
        /* After those IDCODE or BYPASS register values should be
         * only the data we fed into the scan chain.
         */
-       if (jtag_examine_chain_end(idcode_buffer, bit_count,
-                   8 * sizeof(idcode_buffer))) {
-               LOG_ERROR("double-check your JTAG setup (interface, "
-                       "speed, missing TAPs, ...)");
-               return ERROR_JTAG_INIT_FAILED;
+       if (jtag_examine_chain_end(idcode_buffer, bit_count, max_taps * 32)) {
+               LOG_ERROR("double-check your JTAG setup (interface, speed, ...)");
+               retval = ERROR_JTAG_INIT_FAILED;
+               goto out;
        }
 
        /* Return success or, for backwards compatibility if only
         * some IDCODE values mismatched, a soft/continuable fault.
         */
+out:
+       free(idcode_buffer);
        return retval;
 }
 
@@ -1227,7 +1204,7 @@ static int jtag_validate_ircapture(void)
                 * 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.  Or if
-                * (c) an IR length is longer than 32 bits -- which is only
+                * (c) an IR length is longer than JTAG_IRLEN_MAX bits,
                 * an implementation limit, which could someday be raised.
                 *
                 * REVISIT optimization:  if there's a *single* TAP we can
@@ -1242,11 +1219,12 @@ static int jtag_validate_ircapture(void)
                if (tap->ir_length == 0) {
                        tap->ir_length = 2;
                        while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1
-                                       && tap->ir_length <= 64) {
+                                       && tap->ir_length < JTAG_IRLEN_MAX) {
                                tap->ir_length++;
                        }
-                       LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
-                               jtag_tap_name(tap), tap->ir_length);
+                       LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d "
+                                       "-expected-id 0x%08" PRIx32 "\"",
+                                       tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
                }
 
                /* Validate the two LSBs, which must be 01 per JTAG spec.
@@ -1494,13 +1472,21 @@ int jtag_init_inner(struct command_context *cmd_ctx)
 
 int adapter_quit(void)
 {
-       if (!jtag || !jtag->quit)
-               return ERROR_OK;
+       if (jtag && jtag->quit) {
+               /* close the JTAG interface */
+               int result = jtag->quit();
+               if (ERROR_OK != result)
+                       LOG_ERROR("failed: %d", result);
+       }
 
-       /* close the JTAG interface */
-       int result = jtag->quit();
-       if (ERROR_OK != result)
-               LOG_ERROR("failed: %d", result);
+       struct jtag_tap *t = jtag_all_taps();
+       while (t) {
+               struct jtag_tap *n = t->next_tap;
+               jtag_tap_free(t);
+               t = n;
+       }
+
+       dap_cleanup_all();
 
        return ERROR_OK;
 }
@@ -1552,11 +1538,12 @@ int jtag_init_reset(struct command_context *cmd_ctx)
         * 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) {
                jtag_add_reset(1, 1);
                if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
                        jtag_add_reset(0, 1);
+       } else {
+               jtag_add_reset(1, 0);   /* TAP_RESET, using TMS+TCK or TRST */
        }
 
        /* some targets enable us to connect with srst asserted */
@@ -1738,11 +1725,11 @@ void jtag_set_reset_config(enum reset_types type)
 
 int jtag_get_trst(void)
 {
-       return jtag_trst;
+       return jtag_trst == 1;
 }
 int jtag_get_srst(void)
 {
-       return jtag_srst;
+       return jtag_srst == 1;
 }
 
 void jtag_set_nsrst_delay(unsigned delay)
@@ -1830,8 +1817,6 @@ void adapter_assert_reset(void)
                        jtag_add_reset(0, 1);
        } else if (transport_is_swd())
                swd_add_reset(1);
-       else if (transport_is_cmsis_dap())
-               swd_add_reset(1);  /* FIXME */
        else if (get_current_transport() != NULL)
                LOG_ERROR("reset is not supported on %s",
                        get_current_transport()->name);
@@ -1845,11 +1830,31 @@ void adapter_deassert_reset(void)
                jtag_add_reset(0, 0);
        else if (transport_is_swd())
                swd_add_reset(0);
-       else if (transport_is_cmsis_dap())
-               swd_add_reset(0);  /* FIXME */
        else if (get_current_transport() != NULL)
                LOG_ERROR("reset is not supported on %s",
                        get_current_transport()->name);
        else
                LOG_ERROR("transport is not selected");
 }
+
+int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
+                        uint32_t port_size, unsigned int *trace_freq)
+{
+       if (jtag->config_trace)
+               return jtag->config_trace(enabled, pin_protocol, port_size,
+                                         trace_freq);
+       else if (enabled) {
+               LOG_ERROR("The selected interface does not support tracing");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+int adapter_poll_trace(uint8_t *buf, size_t *size)
+{
+       if (jtag->poll_trace)
+               return jtag->poll_trace(buf, size);
+
+       return ERROR_FAIL;
+}

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)