target/armv7m_trace: Improve SWO frequency auto-detection
[fw/openocd] / src / jtag / core.c
index 8c79eb2302c3b643f3750a400270c0a3bbaea6ad..a498a8cf48f25e0334824e526e569ad9cd8e6264 100644 (file)
@@ -836,7 +836,75 @@ int default_interface_jtag_execute_queue(void)
                return ERROR_FAIL;
        }
 
-       return jtag->execute_queue();
+       int result = jtag->execute_queue();
+
+#if !BUILD_ZY1000
+       /* Only build this if we use a regular driver with a command queue.
+        * Otherwise jtag_command_queue won't be found at compile/link time. Its
+        * definition is in jtag/commands.c, which is only built/linked by
+        * jtag/Makefile.am if MINIDRIVER_DUMMY || !MINIDRIVER, but those variables
+        * aren't accessible here. */
+       struct jtag_command *cmd = jtag_command_queue;
+       while (debug_level >= LOG_LVL_DEBUG && cmd) {
+               switch (cmd->type) {
+                       case JTAG_SCAN:
+                               LOG_DEBUG_IO("JTAG %s SCAN to %s",
+                                               cmd->cmd.scan->ir_scan ? "IR" : "DR",
+                                               tap_state_name(cmd->cmd.scan->end_state));
+                               for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
+                                       struct scan_field *field = cmd->cmd.scan->fields + i;
+                                       if (field->out_value) {
+                                               char *str = buf_to_str(field->out_value, field->num_bits, 16);
+                                               LOG_DEBUG_IO("  %db out: %s", field->num_bits, str);
+                                               free(str);
+                                       }
+                                       if (field->in_value) {
+                                               char *str = buf_to_str(field->in_value, field->num_bits, 16);
+                                               LOG_DEBUG_IO("  %db  in: %s", field->num_bits, str);
+                                               free(str);
+                                       }
+                               }
+                               break;
+                       case JTAG_TLR_RESET:
+                               LOG_DEBUG_IO("JTAG TLR RESET to %s",
+                                               tap_state_name(cmd->cmd.statemove->end_state));
+                               break;
+                       case JTAG_RUNTEST:
+                               LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
+                                               cmd->cmd.runtest->num_cycles,
+                                               tap_state_name(cmd->cmd.runtest->end_state));
+                               break;
+                       case JTAG_RESET:
+                               {
+                                       const char *reset_str[3] = {
+                                               "leave", "deassert", "assert"
+                                       };
+                                       LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
+                                                       reset_str[cmd->cmd.reset->trst + 1],
+                                                       reset_str[cmd->cmd.reset->srst + 1]);
+                               }
+                               break;
+                       case JTAG_PATHMOVE:
+                               LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
+                               break;
+                       case JTAG_SLEEP:
+                               LOG_DEBUG_IO("JTAG SLEEP (TODO)");
+                               break;
+                       case JTAG_STABLECLOCKS:
+                               LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
+                               break;
+                       case JTAG_TMS:
+                               LOG_DEBUG_IO("JTAG TMS (TODO)");
+                               break;
+                       default:
+                               LOG_ERROR("Unknown JTAG command: %d", cmd->type);
+                               break;
+               }
+               cmd = cmd->next;
+       }
+#endif
+
+       return result;
 }
 
 void jtag_execute_queue_noclear(void)
@@ -1007,7 +1075,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
                return true;
 
        /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
-       uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0;
+       uint32_t mask = tap->ignore_version ? ~(0xfU << 28) : ~0U;
        uint32_t idcode = tap->idcode & mask;
 
        /* Loop over the expected identification codes and test for a match */
@@ -1107,7 +1175,8 @@ static int jtag_examine_chain(void)
 
                if ((idcode & 1) == 0) {
                        /* Zero for LSB indicates a device in bypass */
-                       LOG_INFO("TAP %s does not have IDCODE", tap->dotted_name);
+                       LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%x)",
+                                       tap->dotted_name, idcode);
                        tap->hasidcode = false;
                        tap->idcode = 0;
 
@@ -1308,6 +1377,14 @@ void jtag_tap_free(struct jtag_tap *tap)
 {
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
+       struct jtag_tap_event_action *jteap = tap->event_action;
+       while (jteap) {
+               struct jtag_tap_event_action *next = jteap->next;
+               Jim_DecrRefCount(jteap->interp, jteap->body);
+               free(jteap);
+               jteap = next;
+       }
+
        free(tap->expected);
        free(tap->expected_mask);
        free(tap->expected_ids);
@@ -1340,19 +1417,6 @@ int adapter_init(struct command_context *cmd_ctx)
                return retval;
        jtag = jtag_interface;
 
-       /* LEGACY SUPPORT ... adapter drivers  must declare what
-        * transports they allow.  Until they all do so, assume
-        * the legacy drivers are JTAG-only
-        */
-       if (!transports_are_declared()) {
-               LOG_ERROR("Adapter driver '%s' did not declare "
-                       "which transports it allows; assuming "
-                       "JTAG-only", jtag->name);
-               retval = allow_transports(cmd_ctx, jtag_only);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
        if (jtag->speed == NULL) {
                LOG_INFO("This adapter doesn't support configurable speed");
                return ERROR_OK;
@@ -1472,13 +1536,19 @@ 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;
+       }
 
        return ERROR_OK;
 }
@@ -1597,14 +1667,18 @@ static int adapter_khz_to_speed(unsigned khz, int *speed)
 {
        LOG_DEBUG("convert khz to interface specific speed value");
        speed_khz = khz;
-       if (jtag != NULL) {
-               LOG_DEBUG("have interface set up");
-               int speed_div1;
-               int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
-               if (ERROR_OK != retval)
-                       return retval;
-               *speed = speed_div1;
+       if (!jtag)
+               return ERROR_OK;
+       LOG_DEBUG("have interface set up");
+       if (!jtag->khz) {
+               LOG_ERROR("Translation from khz to jtag_speed not implemented");
+               return ERROR_FAIL;
        }
+       int speed_div1;
+       int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
+       if (ERROR_OK != retval)
+               return retval;
+       *speed = speed_div1;
        return ERROR_OK;
 }
 
@@ -1667,7 +1741,13 @@ int jtag_get_speed_readable(int *khz)
        int retval = jtag_get_speed(&jtag_speed_var);
        if (retval != ERROR_OK)
                return retval;
-       return jtag ? jtag->speed_div(jtag_speed_var, khz) : ERROR_OK;
+       if (!jtag)
+               return ERROR_OK;
+       if (!jtag->speed_div) {
+               LOG_ERROR("Translation from jtag_speed to khz not implemented");
+               return ERROR_FAIL;
+       }
+       return jtag->speed_div(jtag_speed_var, khz);
 }
 
 void jtag_set_verify(bool enable)
@@ -1698,12 +1778,20 @@ int jtag_power_dropout(int *dropout)
                LOG_ERROR("No Valid JTAG Interface Configured.");
                exit(-1);
        }
-       return jtag->power_dropout(dropout);
+       if (jtag->power_dropout)
+               return jtag->power_dropout(dropout);
+
+       *dropout = 0; /* by default we can't detect power dropout */
+       return ERROR_OK;
 }
 
 int jtag_srst_asserted(int *srst_asserted)
 {
-       return jtag->srst_asserted(srst_asserted);
+       if (jtag->srst_asserted)
+               return jtag->srst_asserted(srst_asserted);
+
+       *srst_asserted = 0; /* by default we can't detect srst asserted */
+       return ERROR_OK;
 }
 
 enum reset_types jtag_get_reset_config(void)
@@ -1829,13 +1917,14 @@ void adapter_deassert_reset(void)
                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)
+int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
+               uint32_t port_size, unsigned int *trace_freq,
+               unsigned int traceclkin_freq, uint16_t *prescaler)
 {
-       if (jtag->config_trace)
-               return jtag->config_trace(enabled, pin_protocol, port_size,
-                                         trace_freq);
-       else if (enabled) {
+       if (jtag->config_trace) {
+               return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq,
+                       traceclkin_freq, prescaler);
+       else if (enabled) {
                LOG_ERROR("The selected interface does not support tracing");
                return ERROR_FAIL;
        }