#include "interface.h"
#include <transport/transport.h>
#include <helper/jep106.h>
+#include "helper/system.h"
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include "svf/svf.h"
#include "xsvf/xsvf.h"
+/* ipdbg are utilities to debug IP-cores. It uses JTAG for transport. */
+#include "server/ipdbg.h"
+
/** The number of JTAG queue flushes (for profiling and debugging purposes). */
static int jtag_flush_queue_count;
static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
static int jtag_speed;
-static struct jtag_interface *jtag;
+/* FIXME: change name to this variable, it is not anymore JTAG only */
+static struct adapter_driver *jtag;
-/* configuration */
-struct jtag_interface *jtag_interface;
+extern struct adapter_driver *adapter_driver;
void jtag_set_flush_queue_sleep(int ms)
{
}
/** Append a new TAP to the chain of all taps. */
-void jtag_tap_add(struct jtag_tap *t)
+static void jtag_tap_add(struct jtag_tap *t)
{
unsigned jtag_num_taps = 0;
for (int i = 0; i < in_num_fields; i++) {
if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) {
- /* this is synchronous for a minidriver */
jtag_add_callback4(jtag_check_value_mask_callback,
(jtag_callback_data_t)in_fields[i].in_value,
(jtag_callback_data_t)in_fields[i].check_value,
/**
* If supported by the underlying adapter, this clocks a raw bit sequence
- * onto TMS for switching betwen JTAG and SWD modes.
+ * onto TMS for switching between JTAG and SWD modes.
*
* DO NOT use this to bypass the integrity checks and logging provided
* by the jtag_add_pathmove() and jtag_add_statemove() calls.
{
int retval;
- if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
+ if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
return ERROR_JTAG_NOT_IMPLEMENTED;
jtag_checks();
}
}
-void swd_add_reset(int req_srst)
+static int adapter_system_reset(int req_srst)
{
+ int retval;
+
if (req_srst) {
if (!(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("BUG: can't assert SRST");
- jtag_set_error(ERROR_FAIL);
- return;
+ return ERROR_FAIL;
}
req_srst = 1;
}
/* Maybe change SRST signal state */
if (jtag_srst != req_srst) {
+ retval = jtag->reset(0, req_srst);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("SRST error");
+ return ERROR_FAIL;
+ }
+ jtag_srst = req_srst;
+
+ if (req_srst) {
+ LOG_DEBUG("SRST line asserted");
+ if (adapter_nsrst_assert_width)
+ jtag_sleep(adapter_nsrst_assert_width * 1000);
+ } else {
+ LOG_DEBUG("SRST line released");
+ if (adapter_nsrst_delay)
+ jtag_sleep(adapter_nsrst_delay * 1000);
+ }
+ }
+
+ return ERROR_OK;
+}
+
+static void legacy_jtag_add_reset(int req_tlr_or_trst, int req_srst)
+{
+ int trst_with_tlr = 0;
+ int new_srst = 0;
+ int new_trst = 0;
+
+ /* Without SRST, we must use target-specific JTAG operations
+ * on each target; callers should not be requesting SRST when
+ * that signal doesn't exist.
+ *
+ * RESET_SRST_PULLS_TRST is a board or chip level quirk, which
+ * can kick in even if the JTAG adapter can't drive TRST.
+ */
+ if (req_srst) {
+ if (!(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("BUG: can't assert SRST");
+ jtag_set_error(ERROR_FAIL);
+ return;
+ }
+ if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
+ && !req_tlr_or_trst) {
+ LOG_ERROR("BUG: can't assert only SRST");
+ jtag_set_error(ERROR_FAIL);
+ return;
+ }
+ new_srst = 1;
+ }
+
+ /* JTAG reset (entry to TAP_RESET state) can always be achieved
+ * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
+ * state first. TRST accelerates it, and bypasses those states.
+ *
+ * RESET_TRST_PULLS_SRST is a board or chip level quirk, which
+ * can kick in even if the JTAG adapter can't drive SRST.
+ */
+ if (req_tlr_or_trst) {
+ if (!(jtag_reset_config & RESET_HAS_TRST))
+ trst_with_tlr = 1;
+ else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
+ && !req_srst)
+ trst_with_tlr = 1;
+ else
+ new_trst = 1;
+ }
+
+ /* Maybe change TRST and/or SRST signal state */
+ if (jtag_srst != new_srst || jtag_trst != new_trst) {
int retval;
- retval = interface_jtag_add_reset(0, req_srst);
+ retval = interface_jtag_add_reset(new_trst, new_srst);
if (retval != ERROR_OK)
jtag_set_error(retval);
else
LOG_ERROR("TRST/SRST error");
return;
}
+ }
- /* SRST resets everything hooked up to that signal */
- jtag_srst = req_srst;
+ /* SRST resets everything hooked up to that signal */
+ if (jtag_srst != new_srst) {
+ jtag_srst = new_srst;
if (jtag_srst) {
LOG_DEBUG("SRST line asserted");
if (adapter_nsrst_assert_width)
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;
+ /* Maybe enter the JTAG TAP_RESET state ...
+ * - using only TMS, TCK, and the JTAG state machine
+ * - or else more directly, using TRST
+ *
+ * TAP_RESET should be invisible to non-debug parts of the system.
+ */
+ if (trst_with_tlr) {
+ LOG_DEBUG("JTAG reset with TLR instead of TRST");
+ jtag_add_tlr();
+
+ } else if (jtag_trst != new_trst) {
+ jtag_trst = new_trst;
+ 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)
+ 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_event(JTAG_TRST_ASSERTED);
}
}
}
+/* FIXME: name is misleading; we do not plan to "add" reset into jtag queue */
void jtag_add_reset(int req_tlr_or_trst, int req_srst)
{
+ int retval;
int trst_with_tlr = 0;
int new_srst = 0;
int new_trst = 0;
+ if (!jtag->reset) {
+ legacy_jtag_add_reset(req_tlr_or_trst, req_srst);
+ return;
+ }
+
/* Without SRST, we must use target-specific JTAG operations
* on each target; callers should not be requesting SRST when
* that signal doesn't exist.
/* Maybe change TRST and/or SRST signal state */
if (jtag_srst != new_srst || jtag_trst != new_trst) {
- int retval;
-
- retval = interface_jtag_add_reset(new_trst, new_srst);
- if (retval != ERROR_OK)
- jtag_set_error(retval);
- else
- retval = jtag_execute_queue();
+ /* guarantee jtag queue empty before changing reset status */
+ jtag_execute_queue();
+ retval = jtag->reset(new_trst, new_srst);
if (retval != ERROR_OK) {
+ jtag_set_error(retval);
LOG_ERROR("TRST/SRST error");
return;
}
if (trst_with_tlr) {
LOG_DEBUG("JTAG reset with TLR instead of TRST");
jtag_add_tlr();
+ jtag_execute_queue();
} else if (jtag_trst != new_trst) {
jtag_trst = new_trst;
/* 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);
+ captured_str = buf_to_hex_str(captured, bits);
+ in_check_value_str = buf_to_hex_str(in_check_value, bits);
LOG_WARNING("Bad value '%s' captured during DR or IR scan:",
captured_str);
if (in_check_mask) {
char *in_check_mask_str;
- in_check_mask_str = buf_to_str(in_check_mask, bits, 16);
+ in_check_mask_str = buf_to_hex_str(in_check_mask, bits);
LOG_WARNING(" check_mask: 0x%s", in_check_mask_str);
free(in_check_mask_str);
}
return ERROR_FAIL;
}
- return jtag->execute_queue();
+ if (!transport_is_jtag()) {
+ /*
+ * FIXME: This should not happen!
+ * There could be old code that queues jtag commands with non jtag interfaces so, for
+ * the moment simply highlight it by log an error and return on empty execute_queue.
+ * We should fix it quitting with assert(0) because it is an internal error.
+ * The fix can be applied immediately after next release (v0.11.0 ?)
+ */
+ LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface");
+ if (!jtag->jtag_ops || !jtag->jtag_ops->execute_queue)
+ return ERROR_OK;
+ }
+
+ int result = jtag->jtag_ops->execute_queue();
+
+ struct jtag_command *cmd = jtag_command_queue;
+ while (debug_level >= LOG_LVL_DEBUG_IO && 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_hex_str(field->out_value, field->num_bits);
+ LOG_DEBUG_IO(" %db out: %s", field->num_bits, str);
+ free(str);
+ }
+ if (field->in_value) {
+ char *str = buf_to_hex_str(field->in_value, field->num_bits);
+ 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;
+ }
+
+ return result;
}
void jtag_execute_queue_noclear(void)
/* Add room for end-of-chain marker. */
max_taps++;
- uint8_t *idcode_buffer = malloc(max_taps * 4);
+ uint8_t *idcode_buffer = calloc(4, max_taps);
if (idcode_buffer == NULL)
return ERROR_JTAG_INIT_FAILED;
* REVISIT create a jtag_alloc(chip, tap) routine, and
* share it with jim_newtap_cmd().
*/
- tap = calloc(1, sizeof *tap);
+ tap = calloc(1, sizeof(*tap));
if (!tap) {
retval = ERROR_FAIL;
goto out;
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%" PRIx32 ")",
+ tap->dotted_name, idcode);
tap->hasidcode = false;
tap->idcode = 0;
int chain_pos = 0;
int retval;
- /* when autoprobing, accomodate huge IR lengths */
+ /* when autoprobing, accommodate huge IR lengths */
for (tap = NULL, total_ir_length = 0;
(tap = jtag_tap_next_enabled(tap)) != NULL;
total_ir_length += tap->ir_length) {
&& tap->ir_length < JTAG_IRLEN_MAX) {
tap->ir_length++;
}
- LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d "
+ 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);
}
/* verify the '11' sentinel we wrote is returned at the end */
val = buf_get_u64(ir_test, chain_pos, 2);
if (val != 0x3) {
- char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+ char *cbuf = buf_to_hex_str(ir_test, total_ir_length);
LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3",
chain_pos, cbuf);
if (jtag)
return ERROR_OK;
- if (!jtag_interface) {
- /* nothing was previously specified by "interface" command */
+ if (!adapter_driver) {
+ /* nothing was previously specified by "adapter driver" command */
LOG_ERROR("Debug Adapter has to be specified, "
- "see \"interface\" command");
+ "see \"adapter driver\" command");
return ERROR_JTAG_INVALID_INTERFACE;
}
int retval;
- retval = jtag_interface->init();
+ retval = adapter_driver->init();
if (retval != ERROR_OK)
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;
- }
+ jtag = adapter_driver;
if (jtag->speed == NULL) {
LOG_INFO("This adapter doesn't support configurable speed");
if (CLOCK_MODE_UNSELECTED == clock_mode) {
LOG_ERROR("An adapter speed is not selected in the init script."
- " Insert a call to adapter_khz or jtag_rclk to proceed.");
+ " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
return ERROR_JTAG_INIT_FAILED;
}
int swd_init_reset(struct command_context *cmd_ctx)
{
- int retval = adapter_init(cmd_ctx);
+ int retval, retval1;
+
+ retval = adapter_init(cmd_ctx);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("Initializing with hard SRST reset");
if (jtag_reset_config & RESET_HAS_SRST)
- swd_add_reset(1);
- swd_add_reset(0);
- retval = jtag_execute_queue();
- return retval;
+ retval = adapter_system_reset(1);
+ retval1 = adapter_system_reset(0);
+
+ return (retval == ERROR_OK) ? retval1 : retval;
}
int jtag_init_reset(struct command_context *cmd_ctx)
jtag_verify = enable;
}
-bool jtag_will_verify()
+bool jtag_will_verify(void)
{
return jtag_verify;
}
jtag_verify_capture_ir = enable;
}
-bool jtag_will_verify_capture_ir()
+bool jtag_will_verify_capture_ir(void)
{
return jtag_verify_capture_ir;
}
if (retval != ERROR_OK)
return retval;
- return xsvf_register_commands(ctx);
+ retval = xsvf_register_commands(ctx);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ipdbg_register_commands(ctx);
}
static struct transport jtag_transport = {
return get_current_transport() == &jtag_transport;
}
-void adapter_assert_reset(void)
+int adapter_resets(int trst, int srst)
+{
+ if (get_current_transport() == NULL) {
+ LOG_ERROR("transport is not selected");
+ return ERROR_FAIL;
+ }
+
+ if (transport_is_jtag()) {
+ if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+
+ /* adapters without trst signal will eventually use tlr sequence */
+ jtag_add_reset(trst, srst);
+ /*
+ * The jtag queue is still used for reset by some adapter. Flush it!
+ * FIXME: To be removed when all adapter drivers will be updated!
+ */
+ jtag_execute_queue();
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_swd() || transport_is_dapdirect_jtag() ||
+ transport_is_swim()) {
+ if (trst == TRST_ASSERT) {
+ LOG_ERROR("transport %s has no trst signal",
+ get_current_transport()->name);
+ return ERROR_FAIL;
+ }
+
+ if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+ adapter_system_reset(srst);
+ return ERROR_OK;
+ }
+
+ if (trst == TRST_DEASSERT && srst == SRST_DEASSERT)
+ return ERROR_OK;
+
+ LOG_ERROR("reset is not supported on transport %s",
+ get_current_transport()->name);
+
+ return ERROR_FAIL;
+}
+
+int adapter_assert_reset(void)
{
if (transport_is_jtag()) {
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
jtag_add_reset(1, 1);
else
jtag_add_reset(0, 1);
- } else if (transport_is_swd())
- swd_add_reset(1);
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+ transport_is_swim())
+ return adapter_system_reset(1);
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");
+ return ERROR_FAIL;
}
-void adapter_deassert_reset(void)
+int adapter_deassert_reset(void)
{
- if (transport_is_jtag())
+ if (transport_is_jtag()) {
jtag_add_reset(0, 0);
- else if (transport_is_swd())
- swd_add_reset(0);
+ return ERROR_OK;
+ } else if (transport_is_swd() || transport_is_hla() ||
+ transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+ transport_is_swim())
+ return adapter_system_reset(0);
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");
+ return ERROR_FAIL;
}
int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
+ 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;
}