X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=9792280b20d78e3e1f086f94c237bdc401a7c01d;hp=5bf7295ec78c33e60dec22407d286125db34a555;hb=1bd3ae398646da1107e00e0651abbf9691d2d9ff;hpb=40d7e81c45d112522f021205f7f1b46f025b8984 diff --git a/src/jtag/core.c b/src/jtag/core.c index 5bf7295ec7..9792280b20 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 * @@ -32,7 +32,6 @@ #endif #include "jtag.h" -#include "minidriver.h" #include "interface.h" #ifdef HAVE_STRINGS_H @@ -43,8 +42,9 @@ /// 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 scan_field_t *in_fields, tap_state_t state), - int in_num_fields, scan_field_t *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); /** * The jtag_error variable is set when an error occurs while executing @@ -60,18 +60,25 @@ static int jtag_error = ERROR_OK; static const char *jtag_event_strings[] = { - [JTAG_TRST_ASSERTED] = "JTAG controller reset (RESET or TRST)", + [JTAG_TRST_ASSERTED] = "TAP reset", + [JTAG_TAP_EVENT_SETUP] = "TAP setup", [JTAG_TAP_EVENT_ENABLE] = "TAP enabled", [JTAG_TAP_EVENT_DISABLE] = "TAP disabled", }; -static int jtag_trst = 0; -static int jtag_srst = 0; +/* + * JTAG adapters must initialize with TRST and SRST de-asserted + * (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 = -1; +static int jtag_srst = -1; /** * List all TAPs that have been created. */ -static jtag_tap_t *__jtag_all_taps = NULL; +static struct jtag_tap *__jtag_all_taps = NULL; /** * The number of TAPs in the __jtag_all_taps list, used to track the * assigned chain position to new TAPs @@ -86,29 +93,38 @@ 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 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; -/* flag if the kHz speed was defined */ -static bool hasKHz = false; +/* speed to fallback to when RCLK is requested but not supported */ +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_error(int error) { @@ -127,8 +143,34 @@ 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; +} -jtag_tap_t *jtag_all_taps(void) +void jtag_poll_set_enabled(bool value) +{ + jtag_poll = value; +} + +/************/ + +struct jtag_tap *jtag_all_taps(void) { return __jtag_all_taps; }; @@ -140,9 +182,9 @@ unsigned jtag_tap_count(void) unsigned jtag_tap_count_enabled(void) { - jtag_tap_t *t = jtag_all_taps(); + struct jtag_tap *t = jtag_all_taps(); unsigned n = 0; - while(t) + while (t) { if (t->enabled) n++; @@ -152,20 +194,32 @@ unsigned jtag_tap_count_enabled(void) } /// Append a new TAP to the chain of all taps. -void jtag_tap_add(struct jtag_tap_s *t) +void jtag_tap_add(struct jtag_tap *t) { t->abs_chain_position = jtag_num_taps++; - jtag_tap_t **tap = &__jtag_all_taps; - while(*tap != NULL) + struct jtag_tap **tap = &__jtag_all_taps; + while (*tap != NULL) tap = &(*tap)->next_tap; *tap = t; } -jtag_tap_t *jtag_tap_by_string(const char *s) +/* returns a pointer to the n-th device in the scan chain */ +static inline struct jtag_tap *jtag_tap_by_position(unsigned n) +{ + struct jtag_tap *t = jtag_all_taps(); + + while (t && n-- > 0) + t = t->next_tap; + + return t; +} + +struct jtag_tap *jtag_tap_by_string(const char *s) { /* try by name first */ - jtag_tap_t *t = jtag_all_taps(); + struct jtag_tap *t = jtag_all_taps(); + while (t) { if (0 == strcmp(t->dotted_name, s)) @@ -178,32 +232,19 @@ jtag_tap_t *jtag_tap_by_string(const char *s) if (parse_uint(s, &n) != ERROR_OK) return NULL; - return jtag_tap_by_position(n); -} - -jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) -{ - const char *cp = Jim_GetString(o, NULL); - jtag_tap_t *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; -} - -/* returns a pointer to the n-th device in the scan chain */ -jtag_tap_t *jtag_tap_by_position(unsigned n) -{ - jtag_tap_t *t = jtag_all_taps(); - - while (t && n-- > 0) - t = t->next_tap; + /* FIXME remove this numeric fallback code late June 2010, along + * with all info in the User's Guide that TAPs have numeric IDs. + * Also update "scan_chain" output to not display the numbers. + */ + t = jtag_tap_by_position(n); + if (t) + LOG_WARNING("Specify TAP '%s' by name, not number %u", + t->dotted_name, n); return t; } -jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p) +struct jtag_tap* jtag_tap_next_enabled(struct jtag_tap* p) { p = p ? p->next_tap : jtag_all_taps(); while (p) @@ -215,7 +256,7 @@ jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p) return NULL; } -const char *jtag_tap_name(const jtag_tap_t *tap) +const char *jtag_tap_name(const struct jtag_tap *tap) { return (tap == NULL) ? "(unknown)" : tap->dotted_name; } @@ -223,7 +264,7 @@ const char *jtag_tap_name(const jtag_tap_t *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) { @@ -237,7 +278,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; @@ -247,8 +288,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) { @@ -276,13 +317,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; @@ -302,82 +343,78 @@ static void jtag_prelude(tap_state_t state) { jtag_checks(); - assert(state!=TAP_INVALID); + assert(state != TAP_INVALID); cmd_queue_cur_state = state; } -void jtag_alloc_in_value32(scan_field_t *field) +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 scan_field_t *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, scan_field_t *in_fields, tap_state_t state) +void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state) { - if (jtag_verify&&jtag_verify_capture_ir) + assert(state != TAP_RESET); + + if (jtag_verify && jtag_verify_capture_ir) { /* 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 scan_field_t *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); -} - -int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits); +static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, + uint8_t *in_check_mask, int num_bits); static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { 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 scan_field_t *in_fields, tap_state_t state), - int in_num_fields, scan_field_t *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++) { - struct scan_field_s *field = &in_fields[i]; + struct scan_field *field = &in_fields[i]; field->allocated = 0; field->modified = 0; if (field->check_value || field->in_value) @@ -386,7 +423,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++) { @@ -409,56 +446,80 @@ 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, scan_field_t *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 scan_field_t *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); + 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 scan_field_t *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(jtag_tap_t* tap, - int num_fields, const int* num_bits, const uint32_t* value, - tap_state_t end_state) -{ - 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); jtag_set_error(interface_jtag_add_tlr()); + + /* NOTE: order here matches TRST path in jtag_add_reset() */ jtag_call_event_callbacks(JTAG_TRST_ASSERTED); + 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) @@ -482,7 +543,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) return; } - if ( tap_state_transition(cur_state, true) != path[i] + if (tap_state_transition(cur_state, true) != path[i] && tap_state_transition(cur_state, false) != path[i]) { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", @@ -503,23 +564,27 @@ 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 ) - ; /* nothing to do */ - else if( goal_state==TAP_RESET ) + if (goal_state != cur_state) { - jtag_add_tlr(); + LOG_DEBUG("cur_state=%s goal_state=%s", + tap_state_name(cur_state), + tap_state_name(goal_state)); } - else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) ) + + /* 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); 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) { @@ -531,8 +596,8 @@ int jtag_add_statemove(tap_state_t goal_state) jtag_add_pathmove(tms_count, moves); } - else if( tap_state_transition(cur_state, true) == goal_state - || tap_state_transition(cur_state, false) == goal_state ) + else if (tap_state_transition(cur_state, true) == goal_state + || tap_state_transition(cur_state, false) == goal_state) { jtag_add_pathmove(1, &goal_state); } @@ -570,102 +635,111 @@ void jtag_add_clocks(int num_cycles) void jtag_add_reset(int req_tlr_or_trst, int req_srst) { int trst_with_tlr = 0; + int new_srst = 0; + int new_trst = 0; - /* FIX!!! there are *many* different cases here. A better - * approach is needed for legal combinations of transitions... + /* 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 ((jtag_reset_config & RESET_HAS_SRST)&& - (jtag_reset_config & RESET_HAS_TRST)&& - ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)) - { - if (((req_tlr_or_trst&&!jtag_trst)|| - (!req_tlr_or_trst&&jtag_trst))&& - ((req_srst&&!jtag_srst)|| - (!req_srst&&jtag_srst))) - { - /* FIX!!! srst_pulls_trst allows 1,1 => 0,0 transition.... */ - //LOG_ERROR("BUG: transition of req_tlr_or_trst and req_srst in the same jtag_add_reset() call is undefined"); + 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; } - /* Make sure that jtag_reset_config allows the requested reset */ - /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */ - if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst)) - { - LOG_ERROR("BUG: requested reset would assert trst"); - jtag_set_error(ERROR_FAIL); - return; + /* 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; } - /* if TRST pulls SRST, we reset with TAP T-L-R */ - if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_tlr_or_trst)) && (req_srst == 0)) - { - trst_with_tlr = 1; - } + /* Maybe change TRST and/or SRST signal state */ + if (jtag_srst != new_srst || jtag_trst != new_trst) { + int retval; - if (req_srst && !(jtag_reset_config & RESET_HAS_SRST)) - { - LOG_ERROR("BUG: requested SRST assertion, but the current configuration doesn't support this"); - jtag_set_error(ERROR_FAIL); - return; - } + retval = interface_jtag_add_reset(new_trst, new_srst); + if (retval != ERROR_OK) + jtag_set_error(retval); + else + retval = jtag_execute_queue(); - if (req_tlr_or_trst) - { - if (!trst_with_tlr && (jtag_reset_config & RESET_HAS_TRST)) - { - jtag_trst = 1; - } else - { - trst_with_tlr = 1; + if (retval != ERROR_OK) { + LOG_ERROR("TRST/SRST error %d", retval); + return; } - } else - { - jtag_trst = 0; - } - - jtag_srst = req_srst; - - int retval = interface_jtag_add_reset(jtag_trst, jtag_srst); - if (retval != ERROR_OK) - { - jtag_set_error(retval); - return; } - jtag_execute_queue(); - if (jtag_srst) - { - LOG_DEBUG("SRST line asserted"); - } - else - { - LOG_DEBUG("SRST line released"); - if (jtag_nsrst_delay) - jtag_add_sleep(jtag_nsrst_delay * 1000); + /* 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) + jtag_add_sleep(adapter_nsrst_assert_width * 1000); + } + else { + LOG_DEBUG("SRST line released"); + if (adapter_nsrst_delay) + jtag_add_sleep(adapter_nsrst_delay * 1000); + } } - if (trst_with_tlr) - { - LOG_DEBUG("JTAG reset with RESET instead of TRST"); + /* 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_set_end_state(TAP_RESET); jtag_add_tlr(); - return; - } - if (jtag_trst) - { - /* we just asserted nTRST, so we're now in Test-Logic-Reset, - * and inform possible listeners about this - */ - LOG_DEBUG("TRST line asserted"); - tap_set_state(TAP_RESET); - jtag_call_event_callbacks(JTAG_TRST_ASSERTED); - } - else - { - if (jtag_ntrst_delay) - jtag_add_sleep(jtag_ntrst_delay * 1000); + } 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); + } } } @@ -676,7 +750,7 @@ tap_state_t jtag_set_end_state(tap_state_t state) LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field"); } - if (state!=TAP_INVALID) + if (state != TAP_INVALID) cmd_queue_end_state = state; return cmd_queue_end_state; } @@ -693,60 +767,53 @@ void jtag_add_sleep(uint32_t us) jtag_set_error(interface_jtag_add_sleep(us)); } -int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits) +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); else compare_failed = buf_cmp(captured, in_check_value, num_bits); - if (compare_failed){ - /* An error handler could have caught the failing check - * only report a problem when there wasn't a handler, or if the handler - * acknowledged the error - */ - /* - LOG_WARNING("TAP %s:", - jtag_tap_name(field->tap)); - */ - if (compare_failed) - { - char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); - char *in_check_value_char = buf_to_str(in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); - - if (in_check_mask) - { - char *in_check_mask_char; - in_check_mask_char = buf_to_str(in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); - LOG_WARNING("value captured during scan didn't pass the requested check:"); - LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s", - captured_char, in_check_value_char, in_check_mask_char); - free(in_check_mask_char); - } - else - { - LOG_WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char); - } + if (compare_failed) { + char *captured_str, *in_check_value_str; + int bits = (num_bits > DEBUG_JTAG_IOZ) + ? DEBUG_JTAG_IOZ + : num_bits; + + /* 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); + + LOG_WARNING("Bad value '%s' captured during DR or IR scan:", + captured_str); + LOG_WARNING(" check_value: 0x%s", in_check_value_str); - free(captured_char); - free(in_check_value_char); + free(captured_str); + free(in_check_value_str); - retval = ERROR_JTAG_QUEUE_FAILED; + if (in_check_mask) { + char *in_check_mask_str; + + in_check_mask_str = buf_to_str(in_check_mask, bits, 16); + LOG_WARNING(" check_mask: 0x%s", in_check_mask_str); + free(in_check_mask_str); } + retval = ERROR_JTAG_QUEUE_FAILED; } return retval; } -void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask) +void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask) { assert(field->in_value != NULL); - if (value==NULL) + if (value == NULL) { /* no checking to do */ return; @@ -754,7 +821,7 @@ void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask) jtag_execute_queue_noclear(); - int retval=jtag_check_value_inner(field->in_value, value, mask, field->num_bits); + int retval = jtag_check_value_inner(field->in_value, value, mask, field->num_bits); jtag_set_error(retval); } @@ -792,14 +859,13 @@ int jtag_execute_queue(void) static int jtag_reset_callback(enum jtag_event event, void *priv) { - jtag_tap_t *tap = priv; - - LOG_DEBUG("-"); + struct jtag_tap *tap = priv; if (event == JTAG_TRST_ASSERTED) { tap->enabled = !tap->disabled_after_reset; + /* current instruction is either BYPASS or IDCODE */ buf_set_ones(tap->cur_instr, tap->ir_length); tap->bypass = 1; } @@ -812,17 +878,27 @@ 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 + +/* a larger IR length than we ever expect to autoprobe */ +#define JTAG_IRLEN_MAX 60 + static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) { - scan_field_t field = { - .tap = NULL, + struct scan_field field = { .num_bits = num_idcode * 32, .out_value = idcode_buffer, .in_value = idcode_buffer, @@ -830,9 +906,10 @@ 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_RESET); + jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); + jtag_add_tlr(); return jtag_execute_queue(); } @@ -848,11 +925,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; @@ -864,16 +950,21 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg, log_printf_lf(level, __FILE__, __LINE__, __FUNCTION__, "JTAG tap: %s %16.16s: 0x%08x " "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)", - name, msg, + name, msg, (unsigned int)idcode, - (unsigned int)EXTRACT_MFG(idcode), - (unsigned int)EXTRACT_PART(idcode), - (unsigned int)EXTRACT_VER(idcode) ); + (unsigned int)EXTRACT_MFG(idcode), + (unsigned int)EXTRACT_PART(idcode), + (unsigned int)EXTRACT_VER(idcode)); } 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; } /** @@ -881,55 +972,61 @@ 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) + 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) +static bool jtag_examine_chain_match_tap(const struct jtag_tap *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 + uint32_t idcode = tap->idcode; + + /* ignore expected BYPASS codes; warn otherwise */ + 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 */ - uint8_t ii; - for (ii = 0; ii < tap->expected_ids_cnt; ii++) - { - if (tap->idcode == tap->expected_ids[ii]) - break; - } + unsigned ii, limit = tap->expected_ids_cnt; - /* If none of the expected ids matched, log an error */ - if (ii != tap->expected_ids_cnt) + for (ii = 0; ii < limit; ii++) { - LOG_INFO("JTAG Tap/device matched"); - return true; + uint32_t expected = tap->expected_ids[ii] & mask; + + if (idcode == expected) + 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]); } @@ -937,181 +1034,311 @@ 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. */ -int jtag_examine_chain(void) +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; + int tapcount = 0; + bool autoprobe = false; + /* 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; /* point at the 1st tap */ - jtag_tap_t *tap = jtag_tap_next_enabled(NULL); - if (tap == NULL) - { - LOG_ERROR("JTAG: No taps enabled?"); - return ERROR_JTAG_INIT_FAILED; - } + struct jtag_tap *tap = jtag_tap_next_enabled(NULL); + + if (!tap) + autoprobe = true; - for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;) + for (bit_count = 0; + tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31; + tap = jtag_tap_next_enabled(tap)) { uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32); + 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_INFO("TAP %s does not have IDCODE", + tap->dotted_name); idcode = 0; + tap->hasidcode = false; bit_count += 1; } else { - /* - * 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); + /* Friendly devices support IDCODE */ + tap->hasidcode = true; + jtag_examine_chain_display(LOG_LVL_INFO, + "tap/device found", + tap->dotted_name, idcode); bit_count += 32; } - device_count++; + 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) - continue; + return ERROR_FAIL; - tap->idcode = idcode; + sprintf(buf, "auto%d", tapcount++); + tap->chip = strdup(buf); + tap->tapname = strdup("tap"); - // ensure the TAP ID does matches what was expected - if (!jtag_examine_chain_match_tap(tap)) - return ERROR_JTAG_INIT_FAILED; + sprintf(buf, "%s.%s", tap->chip, tap->tapname); + tap->dotted_name = strdup(buf); - tap = jtag_tap_next_enabled(tap); + /* 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); } - /* 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, ...)"); + /* 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 ERROR_OK; + /* 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; + struct jtag_tap *tap; int total_ir_length = 0; uint8_t *ir_test = NULL; - scan_field_t field; + struct scan_field 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; + /* when autoprobing, accomodate huge IR lengths */ + for (tap = NULL, total_ir_length = 0; + (tap = jtag_tap_next_enabled(tap)) != NULL; + total_ir_length += tap->ir_length) { + if (tap->ir_length == 0) + total_ir_length += JTAG_IRLEN_MAX; } + /* 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(field.num_bits, field.out_value, field.in_value, TAP_IDLE); - jtag_add_plain_ir_scan(1, &field, TAP_RESET); - jtag_execute_queue(); + LOG_DEBUG("IR capture validation scan"); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) + goto done; tap = NULL; chain_pos = 0; - int val; - for(;;){ + + for (;;) { tap = jtag_tap_next_enabled(tap); - if( tap == NULL ){ + if (tap == NULL) { break; } - val = buf_get_u32(ir_test, chain_pos, 2); - if (val != 0x1) - { - 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; + /* 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. 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 + * only guess when that has no success. + */ + 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 <= 32) { + tap->ir_length++; + } + LOG_WARNING("AUTO %s - use \"... -irlen %d\"", + jtag_tap_name(tap), tap->ir_length); } + + /* 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) +void jtag_tap_init(struct jtag_tap *tap) { - assert(0 != tap->ir_length); + unsigned ir_len_bits; + unsigned ir_len_bytes; - tap->expected = malloc(tap->ir_length); - tap->expected_mask = malloc(tap->ir_length); - tap->cur_instr = malloc(tap->ir_length); + /* if we're autoprobing, cope with potentially huge ir_length */ + ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX; + ir_len_bytes = DIV_ROUND_UP(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); } -void jtag_tap_free(jtag_tap_t *tap) +void jtag_tap_free(struct jtag_tap *tap) { jtag_unregister_event_callback(&jtag_reset_callback, tap); - /// @todo is anything missing? no memory leaks please + /// @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); @@ -1119,7 +1346,11 @@ void jtag_tap_free(jtag_tap_t *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; @@ -1127,54 +1358,114 @@ 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; } - if(hasKHz) - { - jtag_interface->khz(jtag_get_speed_khz(), &jtag_speed); - hasKHz = false; - } + jtag = jtag_interface; if (jtag_interface->init() != ERROR_OK) + { + jtag = NULL; return ERROR_JTAG_INIT_FAILED; + } + + 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("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)) + { + 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)"); - jtag = jtag_interface; return ERROR_OK; } -static int jtag_init_inner(struct command_context_s *cmd_ctx) +int jtag_init_inner(struct command_context *cmd_ctx) { - jtag_tap_t *tap; + struct jtag_tap *tap; int retval; + bool issue_setup = true; LOG_DEBUG("Init JTAG chain"); tap = jtag_tap_next_enabled(NULL); - if( tap == NULL ){ - LOG_ERROR("There are no enabled taps?"); - return ERROR_JTAG_INIT_FAILED; + if (tap == NULL) { + /* Once JTAG itself is properly set up, and the scan chain + * isn't absurdly large, IDCODE autoprobe should work fine. + * + * But ... IRLEN autoprobe can fail even on systems which + * are fully conformant to JTAG. Also, JTAG setup can be + * quite finicky on some systems. + * + * REVISIT: if TAP autoprobe works OK, then in many cases + * we could escape to tcl code and set up targets based on + * the TAP's IDCODE values. + */ + LOG_WARNING("There are no enabled taps. " + "AUTO PROBING MIGHT NOT WORK!!"); + + /* REVISIT default clock will often be too fast ... */ } jtag_add_tlr(); - if ((retval=jtag_execute_queue())!=ERROR_OK) + 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; } -int jtag_interface_quit(void) +int adapter_quit(void) { if (!jtag || !jtag->quit) return ERROR_OK; @@ -1188,35 +1479,44 @@ 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("Trying to bring the JTAG controller to life by asserting TRST / RESET"); + LOG_DEBUG("Initializing with hard TRST+SRST reset"); - /* Reset can happen after a power cycle. - * - * Ideally we would only assert TRST or run RESET 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); /* RESET or TRST */ + jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */ if (jtag_reset_config & RESET_HAS_SRST) { jtag_add_reset(1, 1); - if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0) + if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) jtag_add_reset(0, 1); } jtag_add_reset(0, 0); @@ -1233,32 +1533,33 @@ 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; - if (jtag_init_inner(cmd_ctx)==ERROR_OK) - { - return ERROR_OK; - } - return jtag_init_reset(cmd_ctx); -} -void jtag_set_speed_khz(unsigned khz) -{ - speed_khz = khz; + /* 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(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) + return ERROR_FAIL; + + return ERROR_OK; } + unsigned jtag_get_speed_khz(void) { return speed_khz; } -int jtag_config_khz(unsigned khz) -{ - LOG_DEBUG("handle jtag khz"); - jtag_set_speed_khz(khz); - int cur_speed = 0; +static int adapter_khz_to_speed(unsigned khz, int* speed) +{ + LOG_DEBUG("convert khz to interface specific speed value"); + speed_khz = khz; if (jtag != NULL) { LOG_DEBUG("have interface set up"); @@ -1266,33 +1567,77 @@ int jtag_config_khz(unsigned khz) int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1); if (ERROR_OK != retval) { - jtag_set_speed_khz(0); return retval; } - cur_speed = speed_div1; + *speed = speed_div1; } - return jtag_set_speed(cur_speed); + return ERROR_OK; } -int jtag_get_speed(void) +static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int* speed) { - return jtag_speed; + int retval = adapter_khz_to_speed(0, speed); + if ((ERROR_OK != retval) && fallback_speed_khz) + { + LOG_DEBUG("trying fallback speed..."); + retval = adapter_khz_to_speed(fallback_speed_khz, speed); + } + return retval; } -int jtag_set_speed(int speed) +static int jtag_set_speed(int speed) { jtag_speed = speed; /* this command can be called during CONFIG, * in which case jtag isn't initialized */ - hasKHz = !jtag; return jtag ? jtag->speed(speed) : ERROR_OK; } -int jtag_get_speed_readable(int *speed) +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 (ERROR_OK != retval) ? 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 (ERROR_OK != retval) ? retval : jtag_set_speed(speed); +} + +int jtag_get_speed(void) { - return jtag ? jtag->speed_div(jtag_get_speed(), speed) : ERROR_OK; + int speed; + switch(clock_mode) + { + case CLOCK_MODE_SPEED: + speed = jtag_speed; + break; + 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"); + speed = 0; + break; + } + return speed; } +int jtag_get_speed_readable(int *khz) +{ + return jtag ? jtag->speed_div(jtag_get_speed(), khz) : ERROR_OK; +} void jtag_set_verify(bool enable) { @@ -1316,6 +1661,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); } @@ -1344,11 +1696,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) { @@ -1358,3 +1710,21 @@ unsigned jtag_get_ntrst_delay(void) { return jtag_ntrst_delay; } + + +void jtag_set_nsrst_assert_width(unsigned delay) +{ + adapter_nsrst_assert_width = delay; +} +unsigned jtag_get_nsrst_assert_width(void) +{ + return adapter_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; +}