X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=c1b64bba41b040ae8bdbea7d3dde302cdea6ffa5;hp=48af0406fe74aa954306014f48d7aeb17fafb211;hb=838cd58e24a18102b8a140df9fa993fe65706828;hpb=d0809ac060b35a04e7f0bceb96e1868663bd18df diff --git a/src/jtag/core.c b/src/jtag/core.c index 48af0406fe..c1b64bba41 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -32,18 +32,25 @@ #endif #include "jtag.h" -#include "minidriver.h" #include "interface.h" +#include "transport.h" #ifdef HAVE_STRINGS_H #include #endif +/* SVF and XSVF are higher level JTAG command sets (for boundary scan) */ +#include "svf/svf.h" +#include "xsvf/xsvf.h" /// The number of JTAG queue flushes (for profiling and debugging purposes). static int jtag_flush_queue_count; -static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state), +// Sleep this # of ms after flushing the queue +static int jtag_flush_queue_sleep = 0; + +static void jtag_add_scan_check(struct jtag_tap *active, + void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state), int in_num_fields, struct scan_field *in_fields, tap_state_t state); /** @@ -52,9 +59,9 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s * when an error occurs during processing that should be reported during * jtag_execute_queue(). * - * Tts value may be checked with jtag_get_error() and cleared with - * jtag_error_clear(). This value is returned (and cleared) by - * jtag_execute_queue(). + * The value is set and cleared, but never read by normal application code. + * + * This value is returned (and cleared) by jtag_execute_queue(). */ static int jtag_error = ERROR_OK; @@ -86,27 +93,32 @@ static struct jtag_tap *__jtag_all_taps = NULL; static unsigned jtag_num_taps = 0; static enum reset_types jtag_reset_config = RESET_NONE; -static tap_state_t cmd_queue_end_state = TAP_RESET; tap_state_t cmd_queue_cur_state = TAP_RESET; static bool jtag_verify_capture_ir = true; 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 adapter_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 adapter_nsrst_assert_width = 0; /* width of assertion */ static int jtag_ntrst_assert_width = 0; /* width of assertion */ -typedef struct jtag_event_callback_s -{ - jtag_event_handler_t callback; - void* priv; - struct jtag_event_callback_s* next; -} jtag_event_callback_t; +/** + * Contains a single callback along with a pointer that will be passed + * when an event occurs. + */ +struct jtag_event_callback { + /// a event callback + jtag_event_handler_t callback; + /// the private data to pass to the callback + void* priv; + /// the next callback + struct jtag_event_callback* next; +}; /* callbacks to inform high-level handlers about JTAG state changes */ -static jtag_event_callback_t *jtag_event_callbacks; +static struct jtag_event_callback *jtag_event_callbacks; /* speed in kHz*/ static int speed_khz = 0; @@ -115,10 +127,15 @@ static int rclk_fallback_speed_khz = 0; static enum {CLOCK_MODE_SPEED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; static int jtag_speed = 0; -static struct jtag_interface_s *jtag = NULL; +static struct jtag_interface *jtag = NULL; /* configuration */ -jtag_interface_t *jtag_interface = NULL; +struct jtag_interface *jtag_interface = NULL; + +void jtag_set_flush_queue_sleep(int ms) +{ + jtag_flush_queue_sleep = ms; +} void jtag_set_error(int error) { @@ -126,10 +143,7 @@ void jtag_set_error(int error) return; jtag_error = error; } -int jtag_get_error(void) -{ - return jtag_error; -} + int jtag_error_clear(void) { int temp = jtag_error; @@ -238,17 +252,6 @@ struct jtag_tap *jtag_tap_by_string(const char *s) return t; } -struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) -{ - const char *cp = Jim_GetString(o, NULL); - struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL; - if (NULL == cp) - cp = "(unknown)"; - if (NULL == t) - Jim_SetResult_sprintf(interp, "Tap '%s' could not be found", cp); - return t; -} - struct jtag_tap* jtag_tap_next_enabled(struct jtag_tap* p) { p = p ? p->next_tap : jtag_all_taps(); @@ -269,7 +272,7 @@ const char *jtag_tap_name(const struct jtag_tap *tap) int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) { - jtag_event_callback_t **callbacks_p = &jtag_event_callbacks; + struct jtag_event_callback **callbacks_p = &jtag_event_callbacks; if (callback == NULL) { @@ -283,7 +286,7 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) callbacks_p = &((*callbacks_p)->next); } - (*callbacks_p) = malloc(sizeof(jtag_event_callback_t)); + (*callbacks_p) = malloc(sizeof(struct jtag_event_callback)); (*callbacks_p)->callback = callback; (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; @@ -293,8 +296,8 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv) { - jtag_event_callback_t **callbacks_p; - jtag_event_callback_t **next; + struct jtag_event_callback **callbacks_p; + struct jtag_event_callback **next; if (callback == NULL) { @@ -322,13 +325,13 @@ int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv) int jtag_call_event_callbacks(enum jtag_event event) { - jtag_event_callback_t *callback = jtag_event_callbacks; + struct jtag_event_callback *callback = jtag_event_callbacks; LOG_DEBUG("jtag event: %s", jtag_event_strings[event]); while (callback) { - jtag_event_callback_t *next; + struct jtag_event_callback *next; /* callback may remove itself */ next = callback->next; @@ -358,17 +361,22 @@ void jtag_alloc_in_value32(struct scan_field *field) interface_jtag_alloc_in_value32(field); } -void jtag_add_ir_scan_noverify(int in_count, const struct scan_field *in_fields, +void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields, tap_state_t state) { jtag_prelude(state); - int retval = interface_jtag_add_ir_scan(in_count, in_fields, state); + int retval = interface_jtag_add_ir_scan(active, in_fields, state); jtag_set_error(retval); } +static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active, int dummy, const struct scan_field *in_fields, + tap_state_t state) +{ + jtag_add_ir_scan_noverify(active, in_fields, state); +} -void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state_t state) +void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state) { assert(state != TAP_RESET); @@ -376,45 +384,31 @@ void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state { /* 8 x 32 bit id's is enough for all invocations */ - for (int j = 0; j < in_num_fields; j++) - { - /* if we are to run a verification of the ir scan, we need to get the input back. - * We may have to allocate space if the caller didn't ask for the input back. - */ - in_fields[j].check_value = in_fields[j].tap->expected; - in_fields[j].check_mask = in_fields[j].tap->expected_mask; - } - jtag_add_scan_check(jtag_add_ir_scan_noverify, in_num_fields, in_fields, state); + /* if we are to run a verification of the ir scan, we need to get the input back. + * We may have to allocate space if the caller didn't ask for the input back. + */ + in_fields->check_value = active->expected; + in_fields->check_mask = active->expected_mask; + jtag_add_scan_check(active, jtag_add_ir_scan_noverify_callback, 1, in_fields, state); } else { - jtag_add_ir_scan_noverify(in_num_fields, in_fields, state); + jtag_add_ir_scan_noverify(active, in_fields, state); } } -void jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_fields, +void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { + assert(out_bits != NULL); assert(state != TAP_RESET); jtag_prelude(state); int retval = interface_jtag_add_plain_ir_scan( - in_num_fields, in_fields, state); + num_bits, out_bits, in_bits, state); jtag_set_error(retval); } -void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0) -{ - interface_jtag_add_callback(f, data0); -} - -void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, - jtag_callback_data_t data1, jtag_callback_data_t data2, - jtag_callback_data_t data3) -{ - interface_jtag_add_callback4(f, data0, data1, data2, data3); -} - static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits); @@ -423,7 +417,7 @@ static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callb return jtag_check_value_inner((uint8_t *)data0, (uint8_t *)data1, (uint8_t *)data2, (int)data3); } -static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state), +static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state), int in_num_fields, struct scan_field *in_fields, tap_state_t state) { for (int i = 0; i < in_num_fields; i++) @@ -437,7 +431,7 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s field->modified = 1; } - jtag_add_scan(in_num_fields, in_fields, state); + jtag_add_scan(active, in_num_fields, in_fields, state); for (int i = 0; i < in_num_fields; i++) { @@ -460,19 +454,19 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s } } -void jtag_add_dr_scan_check(int in_num_fields, struct scan_field *in_fields, tap_state_t state) +void jtag_add_dr_scan_check(struct jtag_tap *active, int in_num_fields, struct scan_field *in_fields, tap_state_t state) { if (jtag_verify) { - jtag_add_scan_check(jtag_add_dr_scan, in_num_fields, in_fields, state); + jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state); } else { - jtag_add_dr_scan(in_num_fields, in_fields, state); + jtag_add_dr_scan(active, in_num_fields, in_fields, state); } } -void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields, +void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, tap_state_t state) { assert(state != TAP_RESET); @@ -480,36 +474,23 @@ void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields, jtag_prelude(state); int retval; - retval = interface_jtag_add_dr_scan(in_num_fields, in_fields, state); + retval = interface_jtag_add_dr_scan(active, in_num_fields, in_fields, state); jtag_set_error(retval); } -void jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_fields, +void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) { + assert(out_bits != NULL); assert(state != TAP_RESET); jtag_prelude(state); int retval; - retval = interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state); + retval = interface_jtag_add_plain_dr_scan(num_bits, out_bits, in_bits, state); jtag_set_error(retval); } -void jtag_add_dr_out(struct jtag_tap* tap, - int num_fields, const int* num_bits, const uint32_t* value, - tap_state_t end_state) -{ - assert(end_state != TAP_RESET); - assert(end_state != TAP_INVALID); - - cmd_queue_cur_state = end_state; - - interface_jtag_add_dr_out(tap, - num_fields, num_bits, value, - end_state); -} - void jtag_add_tlr(void) { jtag_prelude(TAP_RESET); @@ -520,6 +501,35 @@ void jtag_add_tlr(void) jtag_notify_event(JTAG_TRST_ASSERTED); } +/** + * If supported by the underlying adapter, this clocks a raw bit sequence + * onto TMS for switching betwen 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. + * + * @param nbits How many bits to clock out. + * @param seq The bit sequence. The LSB is bit 0 of seq[0]. + * @param state The JTAG tap state to record on completion. Use + * TAP_INVALID to represent being in in SWD mode. + * + * @todo Update naming conventions to stop assuming everything is JTAG. + */ +int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) +{ + int retval; + + if (!(jtag->supported & DEBUG_CAP_TMS_SEQ)) + return ERROR_JTAG_NOT_IMPLEMENTED; + + jtag_checks(); + cmd_queue_cur_state = state; + + retval = interface_add_tms_seq(nbits, seq, state); + jtag_set_error(retval); + return retval; +} + void jtag_add_pathmove(int num_states, const tap_state_t *path) { tap_state_t cur_state = cmd_queue_cur_state; @@ -562,10 +572,12 @@ int jtag_add_statemove(tap_state_t goal_state) { tap_state_t cur_state = cmd_queue_cur_state; - LOG_DEBUG("cur_state=%s goal_state=%s", - tap_state_name(cur_state), - tap_state_name(goal_state)); - + if (goal_state != cur_state) + { + LOG_DEBUG("cur_state=%s goal_state=%s", + tap_state_name(cur_state), + tap_state_name(goal_state)); + } /* If goal is RESET, be paranoid and force that that transition * (e.g. five TCK cycles, TMS high). Else trust "cur_state". @@ -580,7 +592,7 @@ int jtag_add_statemove(tap_state_t goal_state) unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); tap_state_t moves[8]; - assert(tms_count < DIM(moves)); + assert(tms_count < ARRAY_SIZE(moves)); for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) { @@ -695,13 +707,13 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) if (jtag_srst) { LOG_DEBUG("SRST line asserted"); - if (jtag_nsrst_assert_width) - jtag_add_sleep(jtag_nsrst_assert_width * 1000); + if (adapter_nsrst_assert_width) + jtag_add_sleep(adapter_nsrst_assert_width * 1000); } else { LOG_DEBUG("SRST line released"); - if (jtag_nsrst_delay) - jtag_add_sleep(jtag_nsrst_delay * 1000); + if (adapter_nsrst_delay) + jtag_add_sleep(adapter_nsrst_delay * 1000); } } @@ -713,7 +725,6 @@ 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_set_end_state(TAP_RESET); jtag_add_tlr(); } else if (jtag_trst != new_trst) { @@ -739,23 +750,6 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) } } -tap_state_t jtag_set_end_state(tap_state_t state) -{ - if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT)) - { - LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field"); - } - - if (state != TAP_INVALID) - cmd_queue_end_state = state; - return cmd_queue_end_state; -} - -tap_state_t jtag_get_end_state(void) -{ - return cmd_queue_end_state; -} - void jtag_add_sleep(uint32_t us) { /// @todo Here, keep_alive() appears to be a layering violation!!! @@ -767,8 +761,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits) { int retval = ERROR_OK; - - int compare_failed = 0; + int compare_failed; if (in_check_mask) compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); @@ -841,6 +834,15 @@ void jtag_execute_queue_noclear(void) { jtag_flush_queue_count++; jtag_set_error(interface_jtag_execute_queue()); + + if (jtag_flush_queue_sleep > 0) + { + /* For debug purposes it can be useful to test performance + * or behavior when delaying after flushing the queue, + * e.g. to simulate long roundtrip times. + */ + usleep(jtag_flush_queue_sleep * 1000); + } } int jtag_get_flush_queue_count(void) @@ -896,7 +898,6 @@ void jtag_sleep(uint32_t us) static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) { struct scan_field field = { - .tap = NULL, .num_bits = num_idcode * 32, .out_value = idcode_buffer, .in_value = idcode_buffer, @@ -906,7 +907,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++) buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG); - jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE); + jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); jtag_add_tlr(); return jtag_execute_queue(); } @@ -991,16 +992,25 @@ 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) { + uint32_t idcode = tap->idcode; + /* ignore expected BYPASS codes; warn otherwise */ - if (0 == tap->expected_ids_cnt && !tap->idcode) + if (0 == tap->expected_ids_cnt && !idcode) return true; + /* optionally ignore the JTAG version field */ + uint32_t mask = tap->ignore_version ? ~(0xff << 24) : ~0; + + 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++) { - if (tap->idcode == tap->expected_ids[ii]) + uint32_t expected = tap->expected_ids[ii] & mask; + + if (idcode == expected) return true; /* treat "-expected-id 0" as a "don't-warn" wildcard */ @@ -1058,7 +1068,7 @@ static int jtag_examine_chain(void) if ((idcode & 1) == 0) { /* Zero for LSB indicates a device in bypass */ - LOG_WARNING("TAP %s does not have IDCODE", + LOG_INFO("TAP %s does not have IDCODE", tap->dotted_name); idcode = 0; tap->hasidcode = false; @@ -1187,19 +1197,18 @@ static int jtag_validate_ircapture(void) /* increase length to add 2 bit sentinel after scan */ total_ir_length += 2; - ir_test = malloc(CEIL(total_ir_length, 8)); + ir_test = malloc(DIV_ROUND_UP(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; field.num_bits = total_ir_length; field.out_value = ir_test; field.in_value = ir_test; - jtag_add_plain_ir_scan(1, &field, TAP_IDLE); + jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, TAP_IDLE); LOG_DEBUG("IR capture validation scan"); retval = jtag_execute_queue(); @@ -1218,7 +1227,14 @@ static int jtag_validate_ircapture(void) /* If we're autoprobing, guess IR lengths. They must be at * 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. + * captured from some conforming TAP are nonzero. Or if + * (c) an IR length is longer than 32 bits -- which is only + * an implementation limit, which could someday be raised. + * + * REVISIT optimization: if there's a *single* TAP we can + * lift restrictions (a) and (b) by scanning a recognizable + * pattern before the all-ones BYPASS. Check for where the + * pattern starts in the result, instead of an 0...01 value. * * REVISIT alternative approach: escape to some tcl code * which could provide more knowledge, based on IDCODE; and @@ -1227,7 +1243,8 @@ static int jtag_validate_ircapture(void) if (tap->ir_length == 0) { tap->ir_length = 2; while ((val = buf_get_u32(ir_test, chain_pos, - tap->ir_length + 1)) == 1) { + tap->ir_length + 1)) == 1 + && tap->ir_length <= 32) { tap->ir_length++; } LOG_WARNING("AUTO %s - use \"... -irlen %d\"", @@ -1287,7 +1304,7 @@ void jtag_tap_init(struct jtag_tap *tap) /* if we're autoprobing, cope with potentially huge ir_length */ ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX; - ir_len_bytes = CEIL(ir_len_bits, 8); + ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8); tap->expected = calloc(1, ir_len_bytes); tap->expected_mask = calloc(1, ir_len_bytes); @@ -1328,7 +1345,11 @@ void jtag_tap_free(struct jtag_tap *tap) free(tap); } -int jtag_interface_init(struct command_context_s *cmd_ctx) +/** + * Do low-level setup like initializing registers, output signals, + * and clocking. + */ +int adapter_init(struct command_context *cmd_ctx) { if (jtag) return ERROR_OK; @@ -1336,7 +1357,8 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) if (!jtag_interface) { /* nothing was previously specified by "interface" command */ - LOG_ERROR("JTAG interface has to be specified, see \"interface\" command"); + LOG_ERROR("Debug Adapter has to be specified, " + "see \"interface\" command"); return ERROR_JTAG_INVALID_INTERFACE; } @@ -1347,13 +1369,27 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) return ERROR_JTAG_INIT_FAILED; } + /* 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); + int retval = allow_transports(cmd_ctx, jtag_only); + if (retval != ERROR_OK) + return retval; + } + int requested_khz = jtag_get_speed_khz(); int actual_khz = requested_khz; int retval = jtag_get_speed_readable(&actual_khz); if (ERROR_OK != retval) - LOG_INFO("interface specific clock speed value %d", jtag_get_speed()); + LOG_INFO("adapter-specific clock speed value %d", jtag_get_speed()); else if (actual_khz) { + /* Adaptive clocking -- JTAG-specific */ if ((CLOCK_MODE_RCLK == clock_mode) || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz)) { @@ -1369,7 +1405,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) return ERROR_OK; } -int jtag_init_inner(struct command_context_s *cmd_ctx) +int jtag_init_inner(struct command_context *cmd_ctx) { struct jtag_tap *tap; int retval; @@ -1409,17 +1445,19 @@ int jtag_init_inner(struct command_context_s *cmd_ctx) case ERROR_OK: /* complete success */ break; - case ERROR_JTAG_INIT_SOFT_FAIL: + default: /* For backward compatibility reasons, try coping with * configuration errors involving only ID mismatches. * We might be able to talk to the devices. + * + * Also the device might be powered down during startup. + * + * After OpenOCD starts, we can try to power on the device + * and run a reset. */ LOG_ERROR("Trying to use configured scan chain anyway..."); issue_setup = false; break; - default: - /* some hard error; already issued diagnostics */ - return retval; } /* Now look at IR values. Problems here will prevent real @@ -1430,7 +1468,13 @@ int jtag_init_inner(struct command_context_s *cmd_ctx) */ retval = jtag_validate_ircapture(); if (retval != ERROR_OK) - return retval; + { + /* The target might be powered down. The user + * can power it up and reset it after firing + * up OpenOCD. + */ + issue_setup = false; + } if (issue_setup) jtag_notify_event(JTAG_TAP_EVENT_SETUP); @@ -1441,7 +1485,7 @@ int jtag_init_inner(struct command_context_s *cmd_ctx) return ERROR_OK; } -int jtag_interface_quit(void) +int adapter_quit(void) { if (!jtag || !jtag->quit) return ERROR_OK; @@ -1455,11 +1499,11 @@ int jtag_interface_quit(void) } -int jtag_init_reset(struct command_context_s *cmd_ctx) +int jtag_init_reset(struct command_context *cmd_ctx) { int retval; - if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK) + if ((retval = adapter_init(cmd_ctx)) != ERROR_OK) return retval; LOG_DEBUG("Initializing with hard TRST+SRST reset"); @@ -1509,11 +1553,11 @@ int jtag_init_reset(struct command_context_s *cmd_ctx) return jtag_init_inner(cmd_ctx); } -int jtag_init(struct command_context_s *cmd_ctx) +int jtag_init(struct command_context *cmd_ctx) { int retval; - if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK) + if ((retval = adapter_init(cmd_ctx)) != ERROR_OK) return retval; /* guard against oddball hardware: force resets to be inactive */ @@ -1521,7 +1565,7 @@ int jtag_init(struct command_context_s *cmd_ctx) if ((retval = jtag_execute_queue()) != ERROR_OK) return retval; - if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) + if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) return ERROR_FAIL; return ERROR_OK; @@ -1532,7 +1576,7 @@ unsigned jtag_get_speed_khz(void) return speed_khz; } -static int jtag_khz_to_speed(unsigned khz, int* speed) +static int adapter_khz_to_speed(unsigned khz, int* speed) { LOG_DEBUG("convert khz to interface specific speed value"); speed_khz = khz; @@ -1552,11 +1596,11 @@ static int jtag_khz_to_speed(unsigned khz, int* speed) static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int* speed) { - int retval = jtag_khz_to_speed(0, speed); + int retval = adapter_khz_to_speed(0, speed); if ((ERROR_OK != retval) && fallback_speed_khz) { LOG_DEBUG("trying fallback speed..."); - retval = jtag_khz_to_speed(fallback_speed_khz, speed); + retval = adapter_khz_to_speed(fallback_speed_khz, speed); } return retval; } @@ -1574,7 +1618,7 @@ int jtag_config_khz(unsigned khz) LOG_DEBUG("handle jtag khz"); clock_mode = CLOCK_MODE_KHZ; int speed = 0; - int retval = jtag_khz_to_speed(khz, &speed); + int retval = adapter_khz_to_speed(khz, &speed); return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); } @@ -1590,21 +1634,20 @@ int jtag_config_rclk(unsigned fallback_speed_khz) int jtag_get_speed(void) { - int speed; + int speed = 0; /* avoid -O3 warning */ switch(clock_mode) { case CLOCK_MODE_SPEED: speed = jtag_speed; break; case CLOCK_MODE_KHZ: - jtag_khz_to_speed(jtag_get_speed_khz(), &speed); + 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"); - speed = 0; break; } return speed; @@ -1637,6 +1680,13 @@ bool jtag_will_verify_capture_ir() int jtag_power_dropout(int *dropout) { + if (jtag == NULL) + { + /* 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); + } return jtag->power_dropout(dropout); } @@ -1665,11 +1715,11 @@ int jtag_get_srst(void) void jtag_set_nsrst_delay(unsigned delay) { - jtag_nsrst_delay = delay; + adapter_nsrst_delay = delay; } unsigned jtag_get_nsrst_delay(void) { - return jtag_nsrst_delay; + return adapter_nsrst_delay; } void jtag_set_ntrst_delay(unsigned delay) { @@ -1683,11 +1733,11 @@ unsigned jtag_get_ntrst_delay(void) void jtag_set_nsrst_assert_width(unsigned delay) { - jtag_nsrst_assert_width = delay; + adapter_nsrst_assert_width = delay; } unsigned jtag_get_nsrst_assert_width(void) { - return jtag_nsrst_assert_width; + return adapter_nsrst_assert_width; } void jtag_set_ntrst_assert_width(unsigned delay) { @@ -1697,3 +1747,44 @@ unsigned jtag_get_ntrst_assert_width(void) { return jtag_ntrst_assert_width; } + +static int jtag_select(struct command_context *ctx) +{ + int retval; + + /* NOTE: interface init must already have been done. + * That works with only C code ... no Tcl glue required. + */ + + retval = jtag_register_commands(ctx); + + if (retval != ERROR_OK) + return retval; + + retval = svf_register_commands(ctx); + + if (retval != ERROR_OK) + return retval; + + return xsvf_register_commands(ctx); +} + +static struct transport jtag_transport = { + .name = "jtag", + .select = jtag_select, + .init = jtag_init, +}; + +static void jtag_constructor(void) __attribute__((constructor)); +static void jtag_constructor(void) +{ + transport_register(&jtag_transport); +} + +/** Returns true if the current debug session + * is using JTAG as its transport. + */ +bool transport_is_jtag(void) +{ + return get_current_transport() == &jtag_transport; +}