X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=6604c5ae84f94ede3020d7fe9afe8d83a44288a5;hb=25218e8935037367e419219f8c855d92a3163023;hp=871b4d2bd07b83fe6010c3d63d5a787747ee945c;hpb=fafe6dfc9cd882f5cee4f4fa2b3971991d9e97b9;p=openocd.git diff --git a/src/jtag/core.c b/src/jtag/core.c index 871b4d2bd0..6604c5ae84 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -35,8 +35,6 @@ #include "interface.h" #include #include -#include -#include #ifdef HAVE_STRINGS_H #include @@ -128,10 +126,10 @@ static int rclk_fallback_speed_khz; 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) { @@ -211,7 +209,7 @@ unsigned jtag_tap_count_enabled(void) } /** 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; @@ -428,7 +426,6 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( 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, @@ -505,7 +502,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) { 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(); @@ -613,22 +610,91 @@ void jtag_add_clocks(int num_cycles) } } -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 @@ -638,9 +704,11 @@ void swd_add_reset(int req_srst) 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) @@ -650,21 +718,54 @@ 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; + /* 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. @@ -706,15 +807,12 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) /* 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; } @@ -743,6 +841,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) 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; @@ -791,8 +890,8 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, /* 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); @@ -804,7 +903,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, 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); } @@ -838,16 +937,23 @@ int default_interface_jtag_execute_queue(void) return ERROR_FAIL; } - int result = 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(); -#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) { + while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { switch (cmd->type) { case JTAG_SCAN: LOG_DEBUG_IO("JTAG %s SCAN to %s", @@ -856,12 +962,12 @@ int default_interface_jtag_execute_queue(void) 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); + 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_str(field->in_value, field->num_bits, 16); + char *str = buf_to_hex_str(field->in_value, field->num_bits); LOG_DEBUG_IO(" %db in: %s", field->num_bits, str); free(str); } @@ -904,7 +1010,6 @@ int default_interface_jtag_execute_queue(void) } cmd = cmd->next; } -#endif return result; } @@ -1120,7 +1225,7 @@ static int jtag_examine_chain(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; @@ -1156,7 +1261,7 @@ static int jtag_examine_chain(void) * 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; @@ -1177,7 +1282,7 @@ 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 valid IDCODE (idcode=0x%x)", + LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")", tap->dotted_name, idcode); tap->hasidcode = false; tap->idcode = 0; @@ -1293,7 +1398,7 @@ static int jtag_validate_ircapture(void) && 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); } @@ -1323,7 +1428,7 @@ static int jtag_validate_ircapture(void) /* 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); @@ -1406,18 +1511,18 @@ int adapter_init(struct command_context *cmd_ctx) 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; + jtag = adapter_driver; if (jtag->speed == NULL) { LOG_INFO("This adapter doesn't support configurable speed"); @@ -1426,7 +1531,7 @@ int adapter_init(struct command_context *cmd_ctx) 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; } @@ -1557,17 +1662,19 @@ int adapter_quit(void) 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) @@ -1757,7 +1864,7 @@ void jtag_set_verify(bool enable) jtag_verify = enable; } -bool jtag_will_verify() +bool jtag_will_verify(void) { return jtag_verify; } @@ -1767,7 +1874,7 @@ void jtag_set_verify_capture_ir(bool enable) jtag_verify_capture_ir = enable; } -bool jtag_will_verify_capture_ir() +bool jtag_will_verify_capture_ir(void) { return jtag_verify_capture_ir; } @@ -1905,20 +2012,15 @@ int adapter_resets(int trst, int srst) /* 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()) { - 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()) { + } 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); @@ -1929,7 +2031,8 @@ int adapter_resets(int trst, int srst) LOG_ERROR("adapter has no srst signal"); return ERROR_FAIL; } - return hl_interface_reset(srst); + adapter_system_reset(srst); + return ERROR_OK; } if (trst == TRST_DEASSERT && srst == SRST_DEASSERT) @@ -1941,33 +2044,41 @@ int adapter_resets(int trst, int srst) return ERROR_FAIL; } -void adapter_assert_reset(void) +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,