X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=57480118758bc56e3226ae2a1102f7f0cf7fc7b1;hp=3d63fddc835c31b0ac329c0e768ca09e61a167ba;hb=HEAD;hpb=08ee7bb982b16742f52cfdc6c649d82ffa2eb177 diff --git a/src/jtag/core.c b/src/jtag/core.c index 3d63fddc83..c84d5aa3d3 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /*************************************************************************** * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * @@ -11,25 +13,13 @@ * * * 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 * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * 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, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "adapter.h" #include "jtag.h" #include "swd.h" #include "interface.h" @@ -123,16 +113,6 @@ struct jtag_event_callback { /* callbacks to inform high-level handlers about JTAG state changes */ static struct jtag_event_callback *jtag_event_callbacks; -/* speed in kHz*/ -static int speed_khz; -/* speed to fallback to when RCLK is requested but not supported */ -static int rclk_fallback_speed_khz; -static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; -static int jtag_speed; - -/* FIXME: change name to this variable, it is not anymore JTAG only */ -static struct adapter_driver *jtag; - extern struct adapter_driver *adapter_driver; void jtag_set_flush_queue_sleep(int ms) @@ -156,14 +136,19 @@ int jtag_error_clear(void) /************/ -static bool jtag_poll = 1; +static bool jtag_poll = true; +static bool jtag_poll_en = true; bool is_jtag_poll_safe(void) { /* Polling can be disabled explicitly with set_enabled(false). + * It can also be masked with mask(). * It is also implicitly disabled while TRST is active and * while SRST is gating the JTAG clock. */ + if (!jtag_poll_en) + return false; + if (!transport_is_jtag()) return jtag_poll; @@ -182,6 +167,18 @@ void jtag_poll_set_enabled(bool value) jtag_poll = value; } +bool jtag_poll_mask(void) +{ + bool retval = jtag_poll_en; + jtag_poll_en = false; + return retval; +} + +void jtag_poll_unmask(bool saved) +{ + jtag_poll_en = saved; +} + /************/ struct jtag_tap *jtag_all_taps(void) @@ -218,7 +215,7 @@ static void jtag_tap_add(struct jtag_tap *t) unsigned jtag_num_taps = 0; struct jtag_tap **tap = &__jtag_all_taps; - while (*tap != NULL) { + while (*tap) { jtag_num_taps++; tap = &(*tap)->next_tap; } @@ -243,7 +240,7 @@ struct jtag_tap *jtag_tap_by_string(const char *s) struct jtag_tap *t = jtag_all_taps(); while (t) { - if (0 == strcmp(t->dotted_name, s)) + if (strcmp(t->dotted_name, s) == 0) return t; t = t->next_tap; } @@ -429,7 +426,7 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( jtag_add_scan(active, in_num_fields, in_fields, state); for (int i = 0; i < in_num_fields; i++) { - if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) { + if ((in_fields[i].check_value) && (in_fields[i].in_value)) { 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, @@ -506,7 +503,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) { int retval; - if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ)) + if (!(adapter_driver->jtag_ops->supported & DEBUG_CAP_TMS_SEQ)) return ERROR_JTAG_NOT_IMPLEMENTED; jtag_checks(); @@ -628,7 +625,7 @@ static int adapter_system_reset(int req_srst) /* Maybe change SRST signal state */ if (jtag_srst != req_srst) { - retval = jtag->reset(0, req_srst); + retval = adapter_driver->reset(0, req_srst); if (retval != ERROR_OK) { LOG_ERROR("SRST error"); return ERROR_FAIL; @@ -765,7 +762,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) int new_srst = 0; int new_trst = 0; - if (!jtag->reset) { + if (!adapter_driver->reset) { legacy_jtag_add_reset(req_tlr_or_trst, req_srst); return; } @@ -814,7 +811,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) /* guarantee jtag queue empty before changing reset status */ jtag_execute_queue(); - retval = jtag->reset(new_trst, new_srst); + retval = adapter_driver->reset(new_trst, new_srst); if (retval != ERROR_OK) { jtag_set_error(retval); LOG_ERROR("TRST/SRST error"); @@ -934,7 +931,7 @@ void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *ma int default_interface_jtag_execute_queue(void) { - if (!jtag) { + if (!is_adapter_initialized()) { LOG_ERROR("No JTAG interface configured yet. " "Issue 'init' command in startup scripts " "before communicating with targets."); @@ -950,13 +947,13 @@ int default_interface_jtag_execute_queue(void) * 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) + if (!adapter_driver->jtag_ops || !adapter_driver->jtag_ops->execute_queue) return ERROR_OK; } - int result = jtag->jtag_ops->execute_queue(); + struct jtag_command *cmd = jtag_command_queue_get(); + int result = adapter_driver->jtag_ops->execute_queue(cmd); - struct jtag_command *cmd = jtag_command_queue; while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { switch (cmd->type) { case JTAG_SCAN: @@ -1052,7 +1049,7 @@ static int jtag_reset_callback(enum jtag_event event, void *priv) /* current instruction is either BYPASS or IDCODE */ buf_set_ones(tap->cur_instr, tap->ir_length); - tap->bypass = 1; + tap->bypass = true; } return ERROR_OK; @@ -1072,8 +1069,6 @@ void jtag_sleep(uint32_t us) #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) @@ -1141,7 +1136,7 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg, name, msg, (unsigned int)idcode, (unsigned int)EXTRACT_MFG(idcode), - jep106_manufacturer(EXTRACT_JEP106_BANK(idcode), EXTRACT_JEP106_ID(idcode)), + jep106_manufacturer(EXTRACT_MFG(idcode)), (unsigned int)EXTRACT_PART(idcode), (unsigned int)EXTRACT_VER(idcode)); } @@ -1182,7 +1177,7 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) { - if (tap->expected_ids_cnt == 0 || !tap->hasidcode) + if (tap->expected_ids_cnt == 0 || !tap->has_idcode) return true; /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */ @@ -1197,7 +1192,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) return true; /* treat "-expected-id 0" as a "don't-warn" wildcard */ - if (0 == tap->expected_ids[ii]) + if (tap->expected_ids[ii] == 0) return true; } @@ -1284,17 +1279,17 @@ static int jtag_examine_chain(void) jtag_tap_init(tap); } - if ((idcode & 1) == 0) { + if ((idcode & 1) == 0 && !tap->ignore_bypass) { /* Zero for LSB indicates a device in bypass */ LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")", tap->dotted_name, idcode); - tap->hasidcode = false; + tap->has_idcode = false; tap->idcode = 0; bit_count += 1; } else { /* Friendly devices support IDCODE */ - tap->hasidcode = true; + tap->has_idcode = true; tap->idcode = idcode; jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode); @@ -1336,19 +1331,18 @@ out: static int jtag_validate_ircapture(void) { struct jtag_tap *tap; - int total_ir_length = 0; uint8_t *ir_test = NULL; struct scan_field field; - uint64_t val; int chain_pos = 0; int retval; /* 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) { + int total_ir_length = 0; + for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) { if (tap->ir_length == 0) total_ir_length += JTAG_IRLEN_MAX; + else + total_ir_length += tap->ir_length; } /* increase length to add 2 bit sentinel after scan */ @@ -1398,7 +1392,7 @@ static int jtag_validate_ircapture(void) */ if (tap->ir_length == 0) { tap->ir_length = 2; - while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1 + while (buf_get_u64(ir_test, chain_pos, tap->ir_length + 1) == 1 && tap->ir_length < JTAG_IRLEN_MAX) { tap->ir_length++; } @@ -1414,7 +1408,7 @@ static int jtag_validate_ircapture(void) * this part of the JTAG spec, so their capture mask/value * attributes might disable this test. */ - val = buf_get_u64(ir_test, chain_pos, tap->ir_length); + uint64_t val = buf_get_u64(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*" PRIx64 " not 0x%0*" PRIx32, jtag_tap_name(tap), @@ -1430,7 +1424,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); + uint64_t val = buf_get_u64(ir_test, chain_pos, 2); if (val != 0x3) { char *cbuf = buf_to_hex_str(ir_test, total_ir_length); @@ -1470,7 +1464,7 @@ void jtag_tap_init(struct jtag_tap *tap) 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; + tap->bypass = true; buf_set_ones(tap->cur_instr, tap->ir_length); /* register the reset callback for the TAP */ @@ -1506,65 +1500,6 @@ void jtag_tap_free(struct jtag_tap *tap) free(tap); } -/** - * Do low-level setup like initializing registers, output signals, - * and clocking. - */ -int adapter_init(struct command_context *cmd_ctx) -{ - if (jtag) - return ERROR_OK; - - if (!adapter_driver) { - /* nothing was previously specified by "adapter driver" command */ - LOG_ERROR("Debug Adapter has to be specified, " - "see \"adapter driver\" command"); - return ERROR_JTAG_INVALID_INTERFACE; - } - - int retval; - retval = adapter_driver->init(); - if (retval != ERROR_OK) - return retval; - jtag = adapter_driver; - - if (!jtag->speed) { - LOG_INFO("This adapter doesn't support configurable speed"); - return ERROR_OK; - } - - if (clock_mode == CLOCK_MODE_UNSELECTED) { - LOG_ERROR("An adapter speed is not selected in the init script." - " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed."); - return ERROR_JTAG_INIT_FAILED; - } - - int requested_khz = jtag_get_speed_khz(); - int actual_khz = requested_khz; - int jtag_speed_var = 0; - retval = jtag_get_speed(&jtag_speed_var); - if (retval != ERROR_OK) - return retval; - retval = jtag->speed(jtag_speed_var); - if (retval != ERROR_OK) - return retval; - retval = jtag_get_speed_readable(&actual_khz); - if (retval != ERROR_OK) - LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var); - else if (actual_khz) { - /* Adaptive clocking -- JTAG-specific */ - if ((clock_mode == CLOCK_MODE_RCLK) - || ((clock_mode == CLOCK_MODE_KHZ) && !requested_khz)) { - LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz" - , actual_khz); - } else - LOG_INFO("clock speed %d kHz", actual_khz); - } else - LOG_INFO("RCLK (adaptive clock speed)"); - - return ERROR_OK; -} - int jtag_init_inner(struct command_context *cmd_ctx) { struct jtag_tap *tap; @@ -1645,25 +1580,6 @@ int jtag_init_inner(struct command_context *cmd_ctx) return ERROR_OK; } -int adapter_quit(void) -{ - if (jtag && jtag->quit) { - /* close the JTAG interface */ - int result = jtag->quit(); - if (result != ERROR_OK) - 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; -} - int swd_init_reset(struct command_context *cmd_ctx) { int retval, retval1; @@ -1771,98 +1687,6 @@ int jtag_init(struct command_context *cmd_ctx) return ERROR_OK; } -unsigned jtag_get_speed_khz(void) -{ - return speed_khz; -} - -static int adapter_khz_to_speed(unsigned khz, int *speed) -{ - LOG_DEBUG("convert khz to interface specific speed value"); - speed_khz = khz; - 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 (retval != ERROR_OK) - return retval; - *speed = speed_div1; - return ERROR_OK; -} - -static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed) -{ - int retval = adapter_khz_to_speed(0, speed); - if ((retval != ERROR_OK) && fallback_speed_khz) { - LOG_DEBUG("trying fallback speed..."); - retval = adapter_khz_to_speed(fallback_speed_khz, speed); - } - return retval; -} - -static int jtag_set_speed(int speed) -{ - jtag_speed = speed; - /* this command can be called during CONFIG, - * in which case jtag isn't initialized */ - return jtag ? jtag->speed(speed) : ERROR_OK; -} - -int jtag_config_khz(unsigned khz) -{ - LOG_DEBUG("handle jtag khz"); - clock_mode = CLOCK_MODE_KHZ; - int speed = 0; - int retval = adapter_khz_to_speed(khz, &speed); - return (retval != ERROR_OK) ? retval : jtag_set_speed(speed); -} - -int jtag_config_rclk(unsigned fallback_speed_khz) -{ - LOG_DEBUG("handle jtag rclk"); - clock_mode = CLOCK_MODE_RCLK; - rclk_fallback_speed_khz = fallback_speed_khz; - int speed = 0; - int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed); - return (retval != ERROR_OK) ? retval : jtag_set_speed(speed); -} - -int jtag_get_speed(int *speed) -{ - switch (clock_mode) { - case CLOCK_MODE_KHZ: - adapter_khz_to_speed(jtag_get_speed_khz(), speed); - break; - case CLOCK_MODE_RCLK: - jtag_rclk_to_speed(rclk_fallback_speed_khz, speed); - break; - default: - LOG_ERROR("BUG: unknown jtag clock mode"); - return ERROR_FAIL; - } - return ERROR_OK; -} - -int jtag_get_speed_readable(int *khz) -{ - int jtag_speed_var = 0; - int retval = jtag_get_speed(&jtag_speed_var); - if (retval != ERROR_OK) - return retval; - 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) { jtag_verify = enable; @@ -1885,14 +1709,14 @@ bool jtag_will_verify_capture_ir(void) int jtag_power_dropout(int *dropout) { - if (!jtag) { + if (!is_adapter_initialized()) { /* TODO: as the jtag interface is not valid all * we can do at the moment is exit OpenOCD */ LOG_ERROR("No Valid JTAG Interface Configured."); exit(-1); } - if (jtag->power_dropout) - return jtag->power_dropout(dropout); + if (adapter_driver->power_dropout) + return adapter_driver->power_dropout(dropout); *dropout = 0; /* by default we can't detect power dropout */ return ERROR_OK; @@ -1900,8 +1724,8 @@ int jtag_power_dropout(int *dropout) int jtag_srst_asserted(int *srst_asserted) { - if (jtag->srst_asserted) - return jtag->srst_asserted(srst_asserted); + if (adapter_driver->srst_asserted) + return adapter_driver->srst_asserted(srst_asserted); *srst_asserted = 0; /* by default we can't detect srst asserted */ return ERROR_OK; @@ -2008,7 +1832,7 @@ bool transport_is_jtag(void) int adapter_resets(int trst, int srst) { - if (get_current_transport() == NULL) { + if (!get_current_transport()) { LOG_ERROR("transport is not selected"); return ERROR_FAIL; } @@ -2065,7 +1889,7 @@ int adapter_assert_reset(void) transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() || transport_is_swim()) return adapter_system_reset(1); - else if (get_current_transport() != NULL) + else if (get_current_transport()) LOG_ERROR("reset is not supported on %s", get_current_transport()->name); else @@ -2082,7 +1906,7 @@ int adapter_deassert_reset(void) transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() || transport_is_swim()) return adapter_system_reset(0); - else if (get_current_transport() != NULL) + else if (get_current_transport()) LOG_ERROR("reset is not supported on %s", get_current_transport()->name); else @@ -2094,8 +1918,8 @@ 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, + if (adapter_driver->config_trace) { + return adapter_driver->config_trace(enabled, pin_protocol, port_size, trace_freq, traceclkin_freq, prescaler); } else if (enabled) { LOG_ERROR("The selected interface does not support tracing"); @@ -2107,8 +1931,8 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, int adapter_poll_trace(uint8_t *buf, size_t *size) { - if (jtag->poll_trace) - return jtag->poll_trace(buf, size); + if (adapter_driver->poll_trace) + return adapter_driver->poll_trace(buf, size); return ERROR_FAIL; }