X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjtag%2Fjtag.c;h=05cfd94801dcf5b4406389d61c80194313124308;hb=0c3e5b50694fcdebc3edccc373fc08adb94d0bb8;hp=2caac53075d313f05f517f83d6bcfc9c874bb94b;hpb=f418fcbff06e04a2ddacef0e0e6dcc329a73eb73;p=fw%2Fopenocd diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 2caac5307..05cfd9480 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -223,6 +223,8 @@ static jtag_interface_t *jtag_interface = NULL; int jtag_speed = 0; /* jtag commands */ +static int handle_interface_list_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc); static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -255,22 +257,19 @@ int jtag_tap_count(void) unsigned jtag_tap_count_enabled(void) { - jtag_tap_t *t; - unsigned n; - - n = 0; - t = jtag_all_taps(); - while(t){ - if( t->enabled ){ + jtag_tap_t *t = jtag_all_taps(); + unsigned n = 0; + while(t) + { + if (t->enabled) n++; - } t = t->next_tap; } return n; } /// Append a new TAP to the chain of all taps. -static void jtag_tap_add(struct jtag_tap_s *t) +void jtag_tap_add(struct jtag_tap_s *t) { t->abs_chain_position = jtag_num_taps++; @@ -280,64 +279,45 @@ static void jtag_tap_add(struct jtag_tap_s *t) *tap = t; } -jtag_tap_t *jtag_tap_by_string( const char *s ) +jtag_tap_t *jtag_tap_by_string(const char *s) { - jtag_tap_t *t; + /* try by name first */ + jtag_tap_t *t = jtag_all_taps(); + while (t) + { + if (0 == strcmp(t->dotted_name, s)) + return t; + t = t->next_tap; + } + + /* no tap found by name, so try to parse the name as a number */ char *cp; + unsigned n = strtoul(s, &cp, 0); + if ((s == cp) || (*cp != 0)) + return NULL; - t = jtag_all_taps(); - /* try name first */ - while(t){ - if( 0 == strcmp( t->dotted_name, s ) ){ - break; - } else { - t = t->next_tap; - } - } - /* backup plan is by number */ - if( t == NULL ){ - /* ok - is "s" a number? */ - int n; - n = strtol( s, &cp, 0 ); - if( (s != cp) && (*cp == 0) ){ - /* Then it is... */ - t = jtag_tap_by_abs_position(n); - } - } - return t; + return jtag_tap_by_abs_position(n); } -jtag_tap_t * jtag_tap_by_jim_obj( Jim_Interp *interp, Jim_Obj *o ) +jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) { - jtag_tap_t *t; - const char *cp; - - cp = Jim_GetString( o, NULL ); - if(cp == NULL){ + const char *cp = Jim_GetString(o, NULL); + jtag_tap_t *t = cp ? jtag_tap_by_string(cp) : NULL; + if (NULL == cp) cp = "(unknown)"; - t = NULL; - } else { - t = jtag_tap_by_string( cp ); - } - if( t == NULL ){ - Jim_SetResult_sprintf(interp,"Tap: %s is unknown", cp ); - } + 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_abs_position( int n ) +jtag_tap_t *jtag_tap_by_abs_position(int n) { - int orig_n; - jtag_tap_t *t; + jtag_tap_t *t = jtag_all_taps(); - orig_n = n; - t = jtag_all_taps(); - - while( t && (n > 0)) { - n--; + while (t && n-- > 0) t = t->next_tap; - } + return t; } @@ -428,15 +408,13 @@ void jtag_alloc_in_value32(scan_field_t *field) interface_jtag_alloc_in_value32(field); } -void jtag_add_ir_scan_noverify(int in_num_fields, const scan_field_t *in_fields, tap_state_t state) +void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields, + tap_state_t state) { - int retval; jtag_prelude(state); - retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, state); - if (retval!=ERROR_OK) - jtag_error=retval; - + int retval = interface_jtag_add_ir_scan(in_count, in_fields, state); + jtag_set_error(retval); } @@ -476,15 +454,14 @@ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t st * This function assumes that the caller handles extra fields for bypassed TAPs * */ -void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state) +void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, + tap_state_t state) { - int retval; - jtag_prelude(state); - retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, state); - if (retval!=ERROR_OK) - jtag_error=retval; + int retval = interface_jtag_add_plain_ir_scan( + in_num_fields, in_fields, state); + jtag_set_error(retval); } void jtag_add_callback(jtag_callback1_t f, u8 *in) @@ -556,42 +533,34 @@ void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_stat /** - * Generate a DR SCAN using the fields passed to the function - * - * For not bypassed TAPs the function checks in_fields and uses fields specified there. - * For bypassed TAPs the function generates a dummy 1bit field. - * - * The bypass status of TAPs is set by jtag_add_ir_scan(). - * + * Generate a DR SCAN using the fields passed to the function. + * For connected TAPs, the function checks in_fields and uses fields + * specified there. For bypassed TAPs, the function generates a dummy + * 1-bit field. The bypass status of TAPs is set by jtag_add_ir_scan(). */ -void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state) +void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, + tap_state_t state) { - int retval; - jtag_prelude(state); - retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, state); - if (retval!=ERROR_OK) - jtag_error=retval; + int retval; + retval = interface_jtag_add_dr_scan(in_num_fields, in_fields, state); + jtag_set_error(retval); } - - /** - * Duplicate the scan fields passed into the function into a DR SCAN command - * - * This function assumes that the caller handles extra fields for bypassed TAPs - * + * Duplicate the scan fields passed into the function into a DR SCAN + * command. Unlike jtag_add_dr_scan(), this function assumes that the + * caller handles extra fields for bypassed TAPs. */ -void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state) +void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields, + tap_state_t state) { - int retval; - jtag_prelude(state); - retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state); - if (retval!=ERROR_OK) - jtag_error=retval; + int retval; + retval = interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state); + jtag_set_error(retval); } void jtag_add_dr_out(jtag_tap_t* tap, @@ -610,92 +579,75 @@ void jtag_add_dr_out(jtag_tap_t* tap, void jtag_add_tlr(void) { jtag_prelude(TAP_RESET); - - int retval; - retval=interface_jtag_add_tlr(); - if (retval!=ERROR_OK) - jtag_error=retval; - + jtag_set_error(interface_jtag_add_tlr()); jtag_call_event_callbacks(JTAG_TRST_ASSERTED); } void jtag_add_pathmove(int num_states, const tap_state_t *path) { tap_state_t cur_state = cmd_queue_cur_state; - int i; - int retval; /* the last state has to be a stable state */ if (!tap_is_state_stable(path[num_states - 1])) { LOG_ERROR("BUG: TAP path doesn't finish in a stable state"); - exit(-1); + jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE); + return; } - for (i=0; i %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[i])); - exit(-1); + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", + tap_state_name(cur_state), tap_state_name(path[i])); + jtag_set_error(ERROR_JTAG_TRANSITION_INVALID); + return; } cur_state = path[i]; } jtag_checks(); - retval = interface_jtag_add_pathmove(num_states, path); + jtag_set_error(interface_jtag_add_pathmove(num_states, path)); cmd_queue_cur_state = path[num_states - 1]; - if (retval!=ERROR_OK) - jtag_error=retval; } void jtag_add_runtest(int num_cycles, tap_state_t state) { - int retval; - jtag_prelude(state); - - /* executed by sw or hw fifo */ - retval=interface_jtag_add_runtest(num_cycles, state); - if (retval!=ERROR_OK) - jtag_error=retval; + jtag_set_error(interface_jtag_add_runtest(num_cycles, state)); } -void jtag_add_clocks( int num_cycles ) +void jtag_add_clocks(int num_cycles) { - int retval; - - if( !tap_is_state_stable(cmd_queue_cur_state) ) + if (!tap_is_state_stable(cmd_queue_cur_state)) { - LOG_ERROR( "jtag_add_clocks() was called with TAP in non-stable state \"%s\"", - tap_state_name(cmd_queue_cur_state) ); - jtag_error = ERROR_JTAG_NOT_STABLE_STATE; + LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"", + tap_state_name(cmd_queue_cur_state)); + jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE); return; } - if( num_cycles > 0 ) + if (num_cycles > 0) { jtag_checks(); - - retval = interface_jtag_add_clocks(num_cycles); - if (retval != ERROR_OK) - jtag_error=retval; + jtag_set_error(interface_jtag_add_clocks(num_cycles)); } } void jtag_add_reset(int req_tlr_or_trst, int req_srst) { int trst_with_tlr = 0; - int retval; /* FIX!!! there are *many* different cases here. A better * approach is needed for legal combinations of transitions... @@ -719,7 +671,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst)) { LOG_ERROR("BUG: requested reset would assert trst"); - jtag_error=ERROR_FAIL; + jtag_set_error(ERROR_FAIL); return; } @@ -732,7 +684,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) if (req_srst && !(jtag_reset_config & RESET_HAS_SRST)) { LOG_ERROR("BUG: requested SRST assertion, but the current configuration doesn't support this"); - jtag_error=ERROR_FAIL; + jtag_set_error(ERROR_FAIL); return; } @@ -752,10 +704,10 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) jtag_srst = req_srst; - retval = interface_jtag_add_reset(jtag_trst, jtag_srst); - if (retval!=ERROR_OK) + int retval = interface_jtag_add_reset(jtag_trst, jtag_srst); + if (retval != ERROR_OK) { - jtag_error=retval; + jtag_set_error(retval); return; } jtag_execute_queue(); @@ -814,11 +766,9 @@ tap_state_t jtag_get_end_state(void) void jtag_add_sleep(u32 us) { - keep_alive(); /* we might be running on a very slow JTAG clk */ - int retval=interface_jtag_add_sleep(us); - if (retval!=ERROR_OK) - jtag_error=retval; - return; + /// @todo Here, keep_alive() appears to be a layering violation!!! + keep_alive(); + jtag_set_error(interface_jtag_add_sleep(us)); } int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits) @@ -914,11 +864,8 @@ int jtag_get_flush_queue_count(void) int jtag_execute_queue(void) { - int retval; jtag_execute_queue_noclear(); - retval=jtag_error; - jtag_error=ERROR_OK; - return retval; + return jtag_error_clear(); } static int jtag_reset_callback(enum jtag_event event, void *priv) @@ -1637,6 +1584,9 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "interface", handle_interface_command, COMMAND_CONFIG, "try to configure interface"); + register_command(cmd_ctx, NULL, + "interface_list", &handle_interface_list_command, + COMMAND_ANY, "list all built-in interfaces"); register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command, COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)"); register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command, @@ -1832,11 +1782,9 @@ static int default_srst_asserted(int *srst_asserted) return ERROR_OK; } -static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int handle_interface_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) { - int i; - int retval; - /* check whether the interface is already configured */ if (jtag_interface) { @@ -1845,54 +1793,54 @@ static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd } /* interface name is a mandatory argument */ - if (argc < 1 || args[0][0] == '\0') - { + if (argc != 1 || args[0][0] == '\0') return ERROR_COMMAND_SYNTAX_ERROR; - } - for (i=0; jtag_interfaces[i]; i++) + for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) { - if (strcmp(args[0], jtag_interfaces[i]->name) == 0) - { - if ((retval = jtag_interfaces[i]->register_commands(cmd_ctx)) != ERROR_OK) - { + if (strcmp(args[0], jtag_interfaces[i]->name) != 0) + continue; + + int retval = jtag_interfaces[i]->register_commands(cmd_ctx); + if (ERROR_OK != retval) return retval; - } - jtag_interface = jtag_interfaces[i]; + jtag_interface = jtag_interfaces[i]; - if (jtag_interface->khz == NULL) - { - jtag_interface->khz = default_khz; - } - if (jtag_interface->speed_div == NULL) - { - jtag_interface->speed_div = default_speed_div; - } - if (jtag_interface->power_dropout == NULL) - { - jtag_interface->power_dropout = default_power_dropout; - } - if (jtag_interface->srst_asserted == NULL) - { - jtag_interface->srst_asserted = default_srst_asserted; - } + if (jtag_interface->khz == NULL) + jtag_interface->khz = default_khz; + if (jtag_interface->speed_div == NULL) + jtag_interface->speed_div = default_speed_div; + if (jtag_interface->power_dropout == NULL) + jtag_interface->power_dropout = default_power_dropout; + if (jtag_interface->srst_asserted == NULL) + jtag_interface->srst_asserted = default_srst_asserted; - return ERROR_OK; - } + return ERROR_OK; } /* no valid interface was found (i.e. the configuration option, * didn't match one of the compiled-in interfaces */ - LOG_ERROR("No valid jtag interface found (%s)", args[0]); - LOG_ERROR("compiled-in jtag interfaces:"); - for (i = 0; jtag_interfaces[i]; i++) + LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]); + handle_interface_list_command(cmd_ctx, cmd, args, argc); + return ERROR_JTAG_INVALID_INTERFACE; +} + +static int handle_interface_list_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) +{ + if (strcmp(cmd, "interface_list") == 0 && argc > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + command_print(cmd_ctx, "The following JTAG interfaces are available:"); + for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) { - LOG_ERROR("%i: %s", i, jtag_interfaces[i]->name); + const char *name = jtag_interfaces[i]->name; + command_print(cmd_ctx, "%u: %s", i + 1, name); } - return ERROR_JTAG_INVALID_INTERFACE; + return ERROR_OK; } static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -2602,61 +2550,55 @@ static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char * } /** - * Function jtag_add_statemove - * moves from the current state to the goal \a state. This needs + * Moves from the current state to the goal \a state. This needs * to be handled according to the xsvf spec, see the XSTATE command * description. + * + * From the XSVF spec, pertaining to XSTATE: + * + * For special states known as stable states (Test-Logic-Reset, + * Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows + * predefined TAP state paths when the starting state is a stable state + * and when the XSTATE specifies a new stable state. See the STATE + * command in the [Ref 5] for the TAP state paths between stable + * states. + * + * For non-stable states, XSTATE should specify a state that is only one + * TAP state transition distance from the current TAP state to avoid + * undefined TAP state paths. A sequence of multiple XSTATE commands can + * be issued to transition the TAP through a specific state path. + * + * @note Unless @a tms_bits holds a path that agrees with [Ref 5] in * + * above spec, then this code is not fully conformant to the xsvf spec. + * This puts a burden on tap_get_tms_path() function from the xsvf spec. + * If in doubt, you should confirm that that burden is being met. + * + * Otherwise, state must be immediately reachable in one clock cycle, + * and does not need to be a stable state. */ int jtag_add_statemove(tap_state_t goal_state) { - int retval = ERROR_OK; - - tap_state_t moves[8]; tap_state_t cur_state = cmd_queue_cur_state; - int i; - int tms_bits; - int tms_count; LOG_DEBUG( "cur_state=%s goal_state=%s", tap_state_name(cur_state), tap_state_name(goal_state) ); - /* From the XSVF spec, pertaining to XSTATE: - - For special states known as stable states (Test-Logic-Reset, - Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows - predefined TAP state paths when the starting state is a stable state and - when the XSTATE specifies a new stable state (see the STATE command in - the [Ref 5] for the TAP state paths between stable states). For - non-stable states, XSTATE should specify a state that is only one TAP - state transition distance from the current TAP state to avoid undefined - TAP state paths. A sequence of multiple XSTATE commands can be issued to - transition the TAP through a specific state path. - */ - if (goal_state==cur_state ) ; /* nothing to do */ - else if( goal_state==TAP_RESET ) { jtag_add_tlr(); } - else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) ) { - /* note: unless tms_bits holds a path that agrees with [Ref 5] in above - spec, then this code is not fully conformant to the xsvf spec. This - puts a burden on tap_get_tms_path() function from the xsvf spec. - If in doubt, you should confirm that that burden is being met. - */ - - tms_bits = tap_get_tms_path(cur_state, goal_state); - tms_count = tap_get_tms_path_len(cur_state, goal_state); - - assert( (unsigned) tms_count < DIM(moves) ); + 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)); - for (i=0; i>=1) + for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) { bool bit = tms_bits & 1; @@ -2666,24 +2608,16 @@ int jtag_add_statemove(tap_state_t goal_state) jtag_add_pathmove(tms_count, moves); } - - /* else state must be immediately reachable in one clock cycle, and does not - need to be a stable state. - */ else if( tap_state_transition(cur_state, true) == goal_state || tap_state_transition(cur_state, false) == goal_state ) { - /* move a single state */ - moves[0] = goal_state; - jtag_add_pathmove( 1, moves ); + jtag_add_pathmove(1, &goal_state); } else - { - retval = ERROR_FAIL; - } + return ERROR_FAIL; - return retval; + return ERROR_OK; } void jtag_set_nsrst_delay(unsigned delay)