X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=08cfe436b236a41b94a009ef2a72b3abc6bfc404;hp=6a314ece1d868dfc27932c887a688f06daf2f9d3;hb=e98817c4636f45b45db4332d2a5fbf36676f2f39;hpb=2d3bcddf0490620cb17089bdfe523eb547b41aa3 diff --git a/src/jtag/core.c b/src/jtag/core.c index 6a314ece1d..08cfe436b2 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -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 * @@ -60,18 +60,20 @@ static int jtag_error = ERROR_OK; static const char *jtag_event_strings[] = { - [JTAG_TRST_ASSERTED] = "JTAG controller reset (TLR or TRST)", + [JTAG_TRST_ASSERTED] = "TAP reset", + [JTAG_TAP_EVENT_SETUP] = "TAP setup", [JTAG_TAP_EVENT_ENABLE] = "TAP enabled", - [JTAG_TAP_EVENT_POST_RESET] = "post reset", [JTAG_TAP_EVENT_DISABLE] = "TAP disabled", }; /* * JTAG adapters must initialize with TRST and SRST de-asserted - * (they're negative logic, so that means *high*) + * (they're negative logic, so that means *high*). But some + * hardware doesn't necessarily work that way ... so set things + * up so that jtag_init() always forces that state. */ -static int jtag_trst = 0; -static int jtag_srst = 0; +static int jtag_trst = -1; +static int jtag_srst = -1; /** * List all TAPs that have been created. @@ -93,6 +95,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 { @@ -133,6 +137,32 @@ int jtag_error_clear(void) return temp; } +/************/ + +static bool jtag_poll = 1; + +bool is_jtag_poll_safe(void) +{ + /* Polling can be disabled explicitly with set_enabled(false). + * It is also implicitly disabled while TRST is active and + * while SRST is gating the JTAG clock. + */ + if (!jtag_poll || jtag_trst != 0) + return false; + return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING); +} + +bool jtag_poll_get_enabled(void) +{ + return jtag_poll; +} + +void jtag_poll_set_enabled(bool value) +{ + jtag_poll = value; +} + +/************/ jtag_tap_t *jtag_all_taps(void) { @@ -487,7 +517,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) @@ -537,12 +567,14 @@ int jtag_add_statemove(tap_state_t goal_state) tap_state_name(goal_state)); - if (goal_state == cur_state) - ; /* nothing to do */ - else if (goal_state == TAP_RESET) - { + /* If goal is RESET, be paranoid and force that that transition + * (e.g. five TCK cycles, TMS high). Else trust "cur_state". + */ + if (goal_state == TAP_RESET) jtag_add_tlr(); - } + else if (goal_state == cur_state) + /* nothing to do */ ; + else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) { unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); @@ -661,7 +693,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 +721,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 +734,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); } } } @@ -820,9 +858,6 @@ static int jtag_reset_callback(enum jtag_event event, void *priv) { jtag_tap_t *tap = priv; - LOG_DEBUG("TAP %s event %s", tap->dotted_name, - jtag_event_strings[event]); - if (event == JTAG_TRST_ASSERTED) { tap->enabled = !tap->disabled_after_reset; @@ -840,13 +875,21 @@ void jtag_sleep(uint32_t us) alive_sleep(us/1000); } -/// maximum number of JTAG devices expected in the chain +/* 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 EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #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) { scan_field_t field = { @@ -858,7 +901,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++) - buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF); + buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG); jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE); jtag_add_tlr(); @@ -877,11 +920,20 @@ static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count) } /* if there wasn't a single non-zero bit or if all bits were one, - * the scan is not valid */ + * the scan is not valid. We wrote a mix of both values; either + * + * - There's a hardware issue (almost certainly): + * + all-zeroes can mean a target stuck in JTAG reset + * + all-ones tends to mean no target + * - The scan chain is WAY longer than we can handle, *AND* either + * + there are several hundreds of TAPs in bypass, or + * + at least a few dozen TAPs all have an all-ones IDCODE + */ 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; @@ -902,7 +954,12 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg, static bool jtag_idcode_is_final(uint32_t idcode) { - return idcode == 0x000000FF || idcode == 0xFFFFFFFF; + /* + * Some devices, such as AVR8, will output all 1's instead + * of TDI input value at end of chain. Allow those values + * instead of failing. + */ + return idcode == END_OF_CHAIN_FLAG || idcode == 0xFFFFFFFF; } /** @@ -910,55 +967,52 @@ static bool jtag_idcode_is_final(uint32_t idcode) * all as expected, but a single JTAG device requires only 64 bits to be * read back correctly. This can help identify and diagnose problems * with the JTAG chain earlier, gives more helpful/explicit error messages. + * Returns TRUE iff garbage was found. */ -static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) +static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) { bool triggered = false; for (; count < max - 31; count += 32) { uint32_t idcode = buf_get_u32(idcodes, count, 32); - // do not trigger the warning if the data looks good - if (!triggered && jtag_idcode_is_final(idcode)) + + /* do not trigger the warning if the data looks good */ + if (jtag_idcode_is_final(idcode)) continue; LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x", count, (unsigned int)idcode); triggered = true; } + return triggered; } static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap) { - if (0 == tap->expected_ids_cnt) - { - /// @todo Enable LOG_INFO to ask for reports about unknown TAP IDs. -#if 0 - LOG_INFO("Uknown JTAG TAP ID: 0x%08x", tap->idcode) - LOG_INFO("Please report the chip name and reported ID code to the openocd project"); -#endif + /* ignore expected BYPASS codes; warn otherwise */ + if (0 == tap->expected_ids_cnt && !tap->idcode) return true; - } /* Loop over the expected identification codes and test for a match */ - uint8_t ii; - for (ii = 0; ii < tap->expected_ids_cnt; ii++) + unsigned ii, limit = tap->expected_ids_cnt; + + for (ii = 0; ii < limit; ii++) { if (tap->idcode == tap->expected_ids[ii]) - break; - } + return true; - /* If none of the expected ids matched, log an error */ - if (ii != tap->expected_ids_cnt) - { - LOG_DEBUG("JTAG Tap/device matched"); - return true; + /* treat "-expected-id 0" as a "don't-warn" wildcard */ + if (0 == tap->expected_ids[ii]) + return true; } - jtag_examine_chain_display(LOG_LVL_ERROR, "got", + + /* 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++) + for (ii = 0; ii < limit; ii++) { char msg[32]; - snprintf(msg, sizeof(msg), "expected %hhu of %hhu", - ii + 1, tap->expected_ids_cnt); + + snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit); jtag_examine_chain_display(LOG_LVL_ERROR, msg, tap->dotted_name, tap->expected_ids[ii]); } @@ -966,14 +1020,21 @@ 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) { uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4]; - unsigned device_count = 0; - - jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE); + unsigned bit_count; + int retval; + /* 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); + if (retval != ERROR_OK) + return retval; if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE)) return ERROR_JTAG_INIT_FAILED; @@ -985,7 +1046,7 @@ static int jtag_examine_chain(void) return ERROR_JTAG_INIT_FAILED; } - for (unsigned bit_count = 0; + for (bit_count = 0; tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31; tap = jtag_tap_next_enabled(tap)) { @@ -993,8 +1054,9 @@ static int jtag_examine_chain(void) if ((idcode & 1) == 0) { - /* LSB must not be 0, this indicates a device in bypass */ - LOG_WARNING("Tap/Device does not have IDCODE"); + /* Zero for LSB indicates a device in bypass */ + LOG_WARNING("TAP %s does not have IDCODE", + tap->dotted_name); idcode = 0; tap->hasidcode = false; @@ -1002,71 +1064,75 @@ static int jtag_examine_chain(void) } else { + /* Friendly devices support IDCODE */ tap->hasidcode = true; - - /* - * End of chain (invalid manufacturer ID) some devices, such - * as AVR will output all 1's instead of TDI input value at - * end of chain. - */ - if (jtag_idcode_is_final(idcode)) - { - jtag_examine_chain_end(idcode_buffer, - bit_count + 32, JTAG_MAX_CHAIN_SIZE * 32); - break; - } - - jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", - tap ? tap->dotted_name : "(not-named)", - idcode); + jtag_examine_chain_display(LOG_LVL_INFO, + "tap/device found", + tap->dotted_name, idcode); bit_count += 32; } - device_count++; - if (!tap) - continue; - 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; + retval = ERROR_JTAG_INIT_SOFT_FAIL; } - /* see if number of discovered devices matches configuration */ - if (device_count != jtag_tap_count_enabled()) - { - LOG_ERROR("number of discovered devices in JTAG chain (%i) " - "does not match (enabled) configuration (%i), total taps: %d", - device_count, jtag_tap_count_enabled(), jtag_tap_count()); - LOG_ERROR("check the config file and ensure proper JTAG communication" - " (connections, speed, ...)"); + /* 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; } - return ERROR_OK; + /* 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; + } + + /* Return success or, for backwards compatibility if only + * some IDCODE values mismatched, a soft/continuable fault. + */ + return retval; } -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; @@ -1074,75 +1140,101 @@ 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. + * + * Or ... more bits could be provided by TAP declaration. + * Plus, some taps (notably in i.MX series chips) violate + * this part of the JTAG spec, so their capture mask/value + * attributes might disable this test. + */ + val = buf_get_u32(ir_test, chain_pos, tap->ir_length); + if ((val & tap->ir_capture_mask) != tap->ir_capture_value) { + LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x", + jtag_tap_name(tap), + (tap->ir_length + 7) / tap->ir_length, + val, + (tap->ir_length + 7) / tap->ir_length, + (unsigned) tap->ir_capture_value); + + 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; } void jtag_tap_init(jtag_tap_t *tap) { + unsigned ir_len_bits; + unsigned ir_len_bytes; + assert(0 != tap->ir_length); - tap->expected = malloc(tap->ir_length); - tap->expected_mask = malloc(tap->ir_length); - tap->cur_instr = malloc(tap->ir_length); + ir_len_bits = tap->ir_length; + ir_len_bytes = CEIL(ir_len_bits, 8); - /// @todo cope sanely with ir_length bigger than 32 bits - buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value); - buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask); - buf_set_ones(tap->cur_instr, tap->ir_length); + tap->expected = calloc(1, ir_len_bytes); + tap->expected_mask = calloc(1, ir_len_bytes); + tap->cur_instr = malloc(ir_len_bytes); + + /// @todo cope better with ir_length bigger than 32 bits + if (ir_len_bits > 32) + ir_len_bits = 32; - // place TAP in bypass mode + buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value); + buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask); + + // TAP will be in bypass mode after jtag_validate_ircapture() tap->bypass = 1; + buf_set_ones(tap->cur_instr, tap->ir_length); + // register the reset callback for the TAP jtag_register_event_callback(&jtag_reset_callback, 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); } @@ -1151,6 +1243,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); @@ -1199,10 +1292,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"); @@ -1216,16 +1310,43 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx) if ((retval = jtag_execute_queue()) != ERROR_OK) return retval; - /* 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..."); + /* Examine DR values first. This discovers problems which will + * prevent communication ... hardware issues like TDO stuck, or + * configuring the wrong number of (enabled) TAPs. + */ + retval = jtag_examine_chain(); + switch (retval) { + case ERROR_OK: + /* complete success */ + break; + case ERROR_JTAG_INIT_SOFT_FAIL: + /* For backward compatibility reasons, try coping with + * configuration errors involving only ID mismatches. + * We might be able to talk to the devices. + */ + LOG_ERROR("Trying to use configured scan chain anyway..."); + issue_setup = false; + break; + default: + /* some hard error; already issued diagnostics */ + return retval; } - if (jtag_validate_chain() != ERROR_OK) - { - LOG_WARNING("Could not validate JTAG chain, continuing anyway..."); - } + /* Now look at IR values. Problems here will prevent real + * communication. They mostly mean that the IR length is + * wrong ... or that the IR capture value is wrong. (The + * latter is uncommon, but easily worked around: provide + * ircapture/irmask values during TAP setup.) + */ + retval = jtag_validate_ircapture(); + if (retval != ERROR_OK) + return retval; + + if (issue_setup) + jtag_notify_event(JTAG_TAP_EVENT_SETUP); + else + LOG_WARNING("Bypassing JTAG setup events due to errors"); + return ERROR_OK; } @@ -1251,22 +1372,31 @@ int jtag_init_reset(struct command_context_s *cmd_ctx) if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK) return retval; - LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR"); + LOG_DEBUG("Initializing with hard TRST+SRST reset"); - /* Reset can happen after a power cycle. - * - * Ideally we would only assert TRST or run TLR before the target reset. + /* + * This procedure is used by default when OpenOCD triggers a reset. + * It's now done through an overridable Tcl "init_reset" wrapper. * - * However w/srst_pulls_trst, trst is asserted together with the target - * reset whether we want it or not. + * This started out as a more powerful "get JTAG working" reset than + * jtag_init_inner(), applying TRST because some chips won't activate + * JTAG without a TRST cycle (presumed to be async, though some of + * those chips synchronize JTAG activation using TCK). * - * NB! Some targets have JTAG circuitry disabled until a - * trst & srst has been asserted. + * But some chips only activate JTAG as part of an SRST cycle; SRST + * got mixed in. So it became a hard reset routine, which got used + * in more places, and which coped with JTAG reset being forced as + * part of SRST (srst_pulls_trst). * - * NB! here we assume nsrst/ntrst delay are sufficient! + * And even more corner cases started to surface: TRST and/or SRST + * assertion timings matter; some chips need other JTAG operations; + * TRST/SRST sequences can need to be different from these, etc. * - * NB! order matters!!!! srst *can* disconnect JTAG circuitry + * Systems should override that wrapper to support system-specific + * requirements that this not-fully-generic code doesn't handle. * + * 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) @@ -1292,13 +1422,19 @@ int jtag_init_reset(struct command_context_s *cmd_ctx) 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); + + /* guard against oddball hardware: force resets to be inactive */ + jtag_add_reset(0, 0); + if ((retval = jtag_execute_queue()) != ERROR_OK) + return retval; + + if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) + return ERROR_FAIL; + + return ERROR_OK; } unsigned jtag_get_speed_khz(void) @@ -1460,3 +1596,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; +}