X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=97f60b532ed63c8e5710d198d31c656e866ea79b;hb=cf08b00376cbcddb8e1ba2e1e686c260c7772a1f;hp=efc68f3d99110c9f7526b92b36565d9fb0aea988;hpb=8290a05c2b3284e3820fc95a10c1cc189f1c186f;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index efc68f3d99..97f60b532e 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -71,7 +71,7 @@ static jtag_tap_t *__jtag_all_taps = NULL; * The number of TAPs in the __jtag_all_taps list, used to track the * assigned chain position to new TAPs */ -static int jtag_num_taps = 0; +static unsigned jtag_num_taps = 0; enum reset_types jtag_reset_config = RESET_NONE; tap_state_t cmd_queue_end_state = TAP_RESET; @@ -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); @@ -248,29 +250,26 @@ jtag_tap_t *jtag_all_taps(void) return __jtag_all_taps; }; -int jtag_tap_count(void) +unsigned jtag_tap_count(void) { return jtag_num_taps; } 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_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_position(unsigned 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; } @@ -438,15 +418,6 @@ void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields, } -/** - * Generate an IR SCAN with a list of scan fields with one entry for each enabled TAP. - * - * If the input field list contains an instruction value for a TAP then that is used - * otherwise the TAP is set to bypass. - * - * TAPs for which no fields are passed are marked as bypassed for subsequent DR SCANs. - * - */ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t state) { if (jtag_verify&&jtag_verify_capture_ir) @@ -468,12 +439,6 @@ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t st } } -/** - * Duplicate the scan fields passed into the function into an IR SCAN command - * - * 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) { @@ -552,12 +517,6 @@ 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 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) { @@ -568,11 +527,6 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, jtag_set_error(retval); } -/** - * 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) { @@ -611,7 +565,8 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) 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 (int i = 0; i < num_states; i++) @@ -619,7 +574,8 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) if (path[i] == TAP_RESET) { LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); - exit(-1); + jtag_set_error(ERROR_JTAG_STATE_INVALID); + return; } if ( tap_state_transition(cur_state, true) != path[i] @@ -627,7 +583,8 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[i])); - exit(-1); + jtag_set_error(ERROR_JTAG_TRANSITION_INVALID); + return; } cur_state = path[i]; } @@ -1601,6 +1558,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, @@ -1796,11 +1756,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) { @@ -1809,54 +1767,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) @@ -2566,61 +2524,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); + 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( (unsigned) 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; @@ -2630,24 +2582,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)