* 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
#include "swd.h"
#include "interface.h"
#include <transport/transport.h>
+#include <helper/jep106.h>
+#include <jtag/hla/hla_transport.h>
+#include <jtag/hla/hla_interface.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
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;
+ }
}
}
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)
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)
};
/* 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);
{
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));
}
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 mask = tap->ignore_version ? ~(0xfU << 28) : ~0U;
+ 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)
/* 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]);
}
*/
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 valid IDCODE (idcode=0x%x)",
+ tap->dotted_name, idcode);
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;
}
* 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
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.
{
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);
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;
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;
}
{
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;
}
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)
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)
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)
return get_current_transport() == &jtag_transport;
}
+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);
+ return ERROR_OK;
+ } else if (transport_is_swd()) {
+ if (trst == TRST_ASSERT) {
+ LOG_ERROR("transport swd has no trst signal");
+ return ERROR_FAIL;
+ }
+
+ if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+ LOG_ERROR("adapter has no srst signal");
+ return ERROR_FAIL;
+ }
+ swd_add_reset(srst);
+ return ERROR_OK;
+ } else if (transport_is_hla()) {
+ 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;
+ }
+ return hl_interface_reset(srst);
+ }
+
+ 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;
+}
+
void adapter_assert_reset(void)
{
if (transport_is_jtag()) {
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);
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 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,
+ traceclkin_freq, prescaler);
+ } 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;
+}