X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=c06244a0065ce70dfb41667e8c9d2e37c7e18af1;hb=5a90a66aa35ba898df0ccebef34f0b350930512c;hp=0b70c0f14bfce3aaadd3fb01f28cdf1e792bccac;hpb=bcde5b3830147c131afacf836cb24698039b9f84;p=openocd.git diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 0b70c0f14b..c06244a006 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -4,6 +4,10 @@ * * * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * + * + * Copyright (C) 2009 SoftPLC Corporation + * http://softplc.com + * dick@softplc.com * * * 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 * @@ -41,14 +45,6 @@ int jtag_error=ERROR_OK; -char* tap_state_strings[16] = -{ - "tlr", - "sds", "cd", "sd", "e1d", "pd", "e2d", "ud", - "rti", - "sis", "ci", "si", "e1i", "pi", "e2i", "ui" -}; - typedef struct cmd_queue_page_s { void *address; @@ -59,64 +55,18 @@ typedef struct cmd_queue_page_s #define CMD_QUEUE_PAGE_SIZE (1024 * 1024) static cmd_queue_page_t *cmd_queue_pages = NULL; -/* tap_move[i][j]: tap movement command to go from state i to state j - * 0: Test-Logic-Reset - * 1: Run-Test/Idle - * 2: Shift-DR - * 3: Pause-DR - * 4: Shift-IR - * 5: Pause-IR - * - * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code - */ -u8 tap_move[6][6] = -{ -/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ - { 0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16}, /* RESET */ - { 0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b}, /* IDLE */ - { 0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f}, /* DRSHIFT */ - { 0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f}, /* DRPAUSE */ - { 0x7f, 0x31, 0x07, 0x17, 0x00, 0x01}, /* IRSHIFT */ - { 0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f} /* IRPAUSE */ -}; - -int tap_move_map[16] = { - 0, -1, -1, 2, -1, 3, -1, -1, - 1, -1, -1, 4, -1, 5, -1, -1 -}; - -tap_transition_t tap_transitions[16] = -{ - {TAP_RESET, TAP_IDLE}, /* RESET */ - {TAP_IRSELECT, TAP_DRCAPTURE}, /* DRSELECT */ - {TAP_DREXIT1, TAP_DRSHIFT}, /* DRCAPTURE */ - {TAP_DREXIT1, TAP_DRSHIFT}, /* DRSHIFT */ - {TAP_DRUPDATE, TAP_DRPAUSE}, /* DREXIT1 */ - {TAP_DREXIT2, TAP_DRPAUSE}, /* DRPAUSE */ - {TAP_DRUPDATE, TAP_DRSHIFT}, /* DREXIT2 */ - {TAP_DRSELECT, TAP_IDLE}, /* DRUPDATE */ - {TAP_DRSELECT, TAP_IDLE}, /* IDLE */ - {TAP_RESET, TAP_IRCAPTURE}, /* IRSELECT */ - {TAP_IREXIT1, TAP_IRSHIFT}, /* IRCAPTURE */ - {TAP_IREXIT1, TAP_IRSHIFT}, /* IRSHIFT */ - {TAP_IRUPDATE, TAP_IRPAUSE}, /* IREXIT1 */ - {TAP_IREXIT2, TAP_IRPAUSE}, /* IRPAUSE */ - {TAP_IRUPDATE, TAP_IRSHIFT}, /* IREXIT2 */ - {TAP_DRSELECT, TAP_IDLE} /* IRUPDATE */ -}; - char* jtag_event_strings[] = { "JTAG controller reset (RESET or TRST)" }; -/* kludge!!!! these are just global variables that the - * interface use internally. They really belong - * inside the drivers, but we don't want to break - * linking the drivers!!!! - */ -enum tap_state end_state = TAP_RESET; -enum tap_state cur_state = TAP_RESET; +const Jim_Nvp nvp_jtag_tap_event[] = { + { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" }, + { .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" }, + + { .name = NULL, .value = -1 } +}; + int jtag_trst = 0; int jtag_srst = 0; @@ -125,8 +75,8 @@ jtag_command_t **last_comand_pointer = &jtag_command_queue; static jtag_tap_t *jtag_all_taps = NULL; enum reset_types jtag_reset_config = RESET_NONE; -enum tap_state cmd_queue_end_state = TAP_RESET; -enum tap_state cmd_queue_cur_state = TAP_RESET; +tap_state_t cmd_queue_end_state = TAP_RESET; +tap_state_t cmd_queue_cur_state = TAP_RESET; int jtag_verify_capture_ir = 1; @@ -197,6 +147,14 @@ static int hasKHz = 0; extern jtag_interface_t jlink_interface; #endif +#if BUILD_VSLLINK == 1 + extern jtag_interface_t vsllink_interface; +#endif + +#if BUILD_RLINK == 1 + extern jtag_interface_t rlink_interface; +#endif + jtag_interface_t *jtag_interfaces[] = { #if BUILD_ECOSBOARD == 1 &zy1000_interface, @@ -233,6 +191,12 @@ jtag_interface_t *jtag_interfaces[] = { #endif #if BUILD_JLINK == 1 &jlink_interface, +#endif +#if BUILD_VSLLINK == 1 + &vsllink_interface, +#endif +#if BUILD_RLINK == 1 + &rlink_interface, #endif NULL, }; @@ -243,12 +207,10 @@ jtag_interface_t *jtag = NULL; jtag_interface_t *jtag_interface = NULL; int jtag_speed = 0; - - /* forward declarations */ -void jtag_add_pathmove(int num_states, enum tap_state *path); -void jtag_add_runtest(int num_cycles, enum tap_state endstate); -void jtag_add_end_state(enum tap_state endstate); +void jtag_add_pathmove(int num_states, tap_state_t *path); +void jtag_add_runtest(int num_cycles, tap_state_t endstate); +void jtag_add_end_state(tap_state_t endstate); void jtag_add_sleep(u32 us); int jtag_execute_queue(void); @@ -272,14 +234,12 @@ int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv); int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); - jtag_tap_t *jtag_AllTaps(void) { - return jtag_all_taps; + return jtag_all_taps; }; -int -jtag_NumTotalTaps(void) +int jtag_NumTotalTaps(void) { jtag_tap_t *t; int n; @@ -293,8 +253,7 @@ jtag_NumTotalTaps(void) return n; } -int -jtag_NumEnabledTaps(void) +int jtag_NumEnabledTaps(void) { jtag_tap_t *t; int n; @@ -338,8 +297,7 @@ jtag_tap_t *jtag_TapByString( const char *s ) return t; } -jtag_tap_t * -jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o ) +jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o ) { jtag_tap_t *t; const char *cp; @@ -358,8 +316,7 @@ jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o ) } /* returns a pointer to the n-th device in the scan chain */ -jtag_tap_t * -jtag_TapByAbsPosition( int n ) +jtag_tap_t * jtag_TapByAbsPosition( int n ) { int orig_n; jtag_tap_t *t; @@ -370,11 +327,10 @@ jtag_TapByAbsPosition( int n ) while( t && (n > 0)) { n--; t = t->next_tap; - } + } return t; } - int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv) { jtag_event_callback_t **callbacks_p = &jtag_event_callbacks; @@ -456,7 +412,6 @@ jtag_command_t** jtag_get_last_command_p(void) return last_comand_pointer; } - void* cmd_queue_alloc(size_t size) { cmd_queue_page_t **p_page = &cmd_queue_pages; @@ -484,17 +439,16 @@ void* cmd_queue_alloc(size_t size) * */ union worse_case_align { - int i; - long l; - float f; - void *v; + int i; + long l; + float f; + void *v; }; #define ALIGN_SIZE (sizeof(union worse_case_align)) - // The alignment process. + /* The alignment process. */ size = (size + ALIGN_SIZE -1) & (~(ALIGN_SIZE-1)); - // Done... - + /* Done... */ if (*p_page) { @@ -547,7 +501,7 @@ static void jtag_prelude1(void) jtag_call_event_callbacks(JTAG_TRST_ASSERTED); } -static void jtag_prelude(enum tap_state state) +static void jtag_prelude(tap_state_t state) { jtag_prelude1(); @@ -557,7 +511,7 @@ static void jtag_prelude(enum tap_state state) cmd_queue_cur_state = cmd_queue_end_state; } -void jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state) +void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state) { int retval; @@ -568,7 +522,7 @@ void jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, enum tap_state state) +int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state) { jtag_command_t **last_cmd; jtag_tap_t *tap; @@ -645,7 +599,6 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, (*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size); (*last_cmd)->cmd.scan->fields[nth_tap].out_mask = NULL; tap->bypass = 1; - } /* update device information */ @@ -655,7 +608,7 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, return ERROR_OK; } -void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state) +void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state) { int retval; @@ -666,7 +619,7 @@ void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *fields, enum tap_state state) +int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state) { int i; jtag_command_t **last_cmd; @@ -702,7 +655,7 @@ int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *f return ERROR_OK; } -void jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) +void jtag_add_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state) { int retval; @@ -713,7 +666,7 @@ void jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, enum tap_state state) +int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state) { int j; int nth_tap; @@ -816,7 +769,7 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap, int num_fields, const int *num_bits, const u32 *value, - enum tap_state end_state) + tap_state_t end_state) { int nth_tap; int field_count = 0; @@ -910,7 +863,7 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap, } } -void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) +void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state) { int retval; @@ -921,7 +874,7 @@ void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *fields, enum tap_state state) +int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state) { int i; jtag_command_t **last_cmd = jtag_get_last_command_p(); @@ -967,9 +920,9 @@ void jtag_add_tlr(void) jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_tlr)() +int MINIDRIVER(interface_jtag_add_tlr)(void) { - enum tap_state state = TAP_RESET; + tap_state_t state = TAP_RESET; jtag_command_t **last_cmd = jtag_get_last_command_p(); /* allocate memory for a new list member */ @@ -981,18 +934,17 @@ int MINIDRIVER(interface_jtag_add_tlr)() (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); (*last_cmd)->cmd.statemove->end_state = state; - return ERROR_OK; } -void jtag_add_pathmove(int num_states, enum tap_state *path) +void jtag_add_pathmove(int num_states, tap_state_t *path) { - enum tap_state cur_state=cmd_queue_cur_state; + tap_state_t cur_state=cmd_queue_cur_state; int i; int retval; /* the last state has to be a stable state */ - if (tap_move_map[path[num_states - 1]] == -1) + if (!tap_is_state_stable(path[num_states - 1])) { LOG_ERROR("BUG: TAP path doesn't finish in a stable state"); exit(-1); @@ -1005,10 +957,10 @@ void jtag_add_pathmove(int num_states, enum tap_state *path) LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); exit(-1); } - if ((tap_transitions[cur_state].low != path[i])&& - (tap_transitions[cur_state].high != 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", tap_state_strings[cur_state], tap_state_strings[path[i]]); + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[i])); exit(-1); } cur_state = path[i]; @@ -1016,14 +968,13 @@ void jtag_add_pathmove(int num_states, enum tap_state *path) jtag_prelude1(); - retval=interface_jtag_add_pathmove(num_states, path); cmd_queue_cur_state = path[num_states - 1]; if (retval!=ERROR_OK) jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, enum tap_state *path) +int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, tap_state_t *path) { jtag_command_t **last_cmd = jtag_get_last_command_p(); int i; @@ -1036,7 +987,7 @@ int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, enum tap_state *path (*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t)); (*last_cmd)->cmd.pathmove->num_states = num_states; - (*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states); + (*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states); for (i = 0; i < num_states; i++) (*last_cmd)->cmd.pathmove->path[i] = path[i]; @@ -1044,7 +995,7 @@ int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, enum tap_state *path return ERROR_OK; } -int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, enum tap_state state) +int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, tap_state_t state) { jtag_command_t **last_cmd = jtag_get_last_command_p(); @@ -1061,7 +1012,7 @@ int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, enum tap_state state) return ERROR_OK; } -void jtag_add_runtest(int num_cycles, enum tap_state state) +void jtag_add_runtest(int num_cycles, tap_state_t state) { int retval; @@ -1073,6 +1024,44 @@ void jtag_add_runtest(int num_cycles, enum tap_state state) jtag_error=retval; } + +int MINIDRIVER(interface_jtag_add_clocks)( int num_cycles ) +{ + jtag_command_t **last_cmd = jtag_get_last_command_p(); + + /* allocate memory for a new list member */ + *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); + (*last_cmd)->next = NULL; + last_comand_pointer = &((*last_cmd)->next); + (*last_cmd)->type = JTAG_STABLECLOCKS; + + (*last_cmd)->cmd.stableclocks = cmd_queue_alloc(sizeof(stableclocks_command_t)); + (*last_cmd)->cmd.stableclocks->num_cycles = num_cycles; + return ERROR_OK; +} + +void jtag_add_clocks( int num_cycles ) +{ + int retval; + + 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; + return; + } + + if( num_cycles > 0 ) + { + jtag_prelude1(); + + retval = interface_jtag_add_clocks(num_cycles); + if (retval != ERROR_OK) + jtag_error=retval; + } +} + void jtag_add_reset(int req_tlr_or_trst, int req_srst) { int trst_with_tlr = 0; @@ -1193,7 +1182,7 @@ int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst) return ERROR_OK; } -void jtag_add_end_state(enum tap_state state) +void jtag_add_end_state(tap_state_t state) { cmd_queue_end_state = state; if ((cmd_queue_end_state == TAP_DRSHIFT)||(cmd_queue_end_state == TAP_IRSHIFT)) @@ -1251,16 +1240,20 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) bit_count = 0; +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("num_fields: %i",cmd->num_fields); +#endif + for (i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].out_value) { #ifdef _DEBUG_JTAG_IO_ - char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16); + char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits, 16); #endif buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); #ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("fields[%i].out_value: 0x%s", i, char_buf); + LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); #endif } @@ -1291,10 +1284,8 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits); #ifdef _DEBUG_JTAG_IO_ - char *char_buf; - - char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); - LOG_DEBUG("fields[%i].in_value: 0x%s", i, char_buf); + char *char_buf = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); + LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf); free(char_buf); #endif @@ -1306,7 +1297,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) { if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK) { - LOG_WARNING("in_handler reported a failed check"); + LOG_WARNING("in_handler: with \"in_value\", mismatch in %s", cmd->ir_scan ? "SIR" : "SDR" ); retval = ERROR_JTAG_QUEUE_FAILED; } } @@ -1320,7 +1311,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) /* We're going to call the error:handler later, but if the in_handler * reported an error we report this failure upstream */ - LOG_WARNING("in_handler reported a failed check"); + LOG_WARNING("in_handler: w/o \"in_value\", mismatch in %s", cmd->ir_scan ? "SIR" : "SDR" ); retval = ERROR_JTAG_QUEUE_FAILED; } } @@ -1333,6 +1324,11 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) return retval; } +static const char *jtag_tap_name(jtag_tap_t *tap) +{ + return (tap == NULL) ? "(unknown)" : tap->dotted_name; +} + int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) { int retval = ERROR_OK; @@ -1351,16 +1347,16 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) * acknowledged the error */ LOG_WARNING("TAP %s:", - (field->tap == NULL) ? "(unknown)" : field->tap->dotted_name ); + jtag_tap_name(field->tap)); if (compare_failed) { - char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); - char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16); + 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(field->in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); if (field->in_check_mask) { char *in_check_mask_char; - in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16); + in_check_mask_char = buf_to_str(field->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); @@ -1667,17 +1663,18 @@ int jtag_validate_chain(void) tap = NULL; chain_pos = 0; + int val; for(;;){ tap = jtag_NextEnabledTap(tap); if( tap == NULL ){ break; } - - if (buf_get_u32(ir_test, chain_pos, 2) != 0x1) + 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("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + 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; @@ -1685,10 +1682,11 @@ int jtag_validate_chain(void) chain_pos += tap->ir_length; } - if (buf_get_u32(ir_test, chain_pos, 2) != 0x3) + 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("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + 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); free(cbuf); free(ir_test); return ERROR_JTAG_INIT_FAILED; @@ -1699,9 +1697,106 @@ int jtag_validate_chain(void) return ERROR_OK; } +enum jtag_tap_cfg_param { + JCFG_EVENT +}; + +static Jim_Nvp nvp_config_opts[] = { + { .name = "-event", .value = JCFG_EVENT }, + + { .name = NULL, .value = -1 } +}; static int -jim_newtap_cmd( Jim_GetOptInfo *goi ) +jtag_tap_configure_cmd( Jim_GetOptInfo *goi, + jtag_tap_t * tap) +{ + Jim_Nvp *n; + Jim_Obj *o; + int e; + + /* parse config or cget options */ + while (goi->argc > 0) { + Jim_SetEmptyResult (goi->interp); + + e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); + return e; + } + + switch (n->value) { + case JCFG_EVENT: + if (goi->argc == 0) { + Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ..." ); + return JIM_ERR; + } + + e = Jim_GetOpt_Nvp( goi, nvp_jtag_tap_event, &n ); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1); + return e; + } + + if (goi->isconfigure) { + if (goi->argc != 1) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); + return JIM_ERR; + } + } else { + if (goi->argc != 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); + return JIM_ERR; + } + } + + { + jtag_tap_event_action_t *jteap; + + jteap = tap->event_action; + /* replace existing? */ + while (jteap) { + if (jteap->event == n->value) { + break; + } + jteap = jteap->next; + } + + if (goi->isconfigure) { + if (jteap == NULL) { + /* create new */ + jteap = calloc(1, sizeof (*jteap)); + } + jteap->event = n->value; + Jim_GetOpt_Obj( goi, &o); + if (jteap->body) { + Jim_DecrRefCount(interp, jteap->body); + } + jteap->body = Jim_DuplicateObj(goi->interp, o); + Jim_IncrRefCount(jteap->body); + + /* add to head of event list */ + jteap->next = tap->event_action; + tap->event_action = jteap; + Jim_SetEmptyResult(goi->interp); + } else { + /* get */ + if (jteap == NULL) { + Jim_SetEmptyResult(goi->interp); + } else { + Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body)); + } + } + } + /* loop for more */ + break; + } + } /* while (goi->argc) */ + + return JIM_OK; +} + +static int jim_newtap_cmd( Jim_GetOptInfo *goi ) { jtag_tap_t *pTap; jtag_tap_t **ppTap; @@ -1719,24 +1814,23 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) #define NTAP_OPT_IRCAPTURE 2 { .name = "-ircapture" , .value = NTAP_OPT_IRCAPTURE }, #define NTAP_OPT_ENABLED 3 - { .name = "-enable" , .value = NTAP_OPT_ENABLED }, + { .name = "-enable" , .value = NTAP_OPT_ENABLED }, #define NTAP_OPT_DISABLED 4 - { .name = "-disable" , .value = NTAP_OPT_DISABLED }, + { .name = "-disable" , .value = NTAP_OPT_DISABLED }, #define NTAP_OPT_EXPECTED_ID 5 - { .name = "-expected-id" , .value = NTAP_OPT_EXPECTED_ID }, - { .name = NULL , .value = -1 }, + { .name = "-expected-id" , .value = NTAP_OPT_EXPECTED_ID }, + { .name = NULL , .value = -1 }, }; - pTap = malloc( sizeof(jtag_tap_t) ); memset( pTap, 0, sizeof(*pTap) ); if( !pTap ){ Jim_SetResult_sprintf( goi->interp, "no memory"); return JIM_ERR; } - // - // we expect CHIP + TAP + OPTIONS - // + /* + * we expect CHIP + TAP + OPTIONS + * */ if( goi->argc < 3 ){ Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ...."); return JIM_ERR; @@ -1747,7 +1841,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) Jim_GetOpt_String( goi, &cp, NULL ); pTap->tapname = strdup(cp); - // name + dot + name + null + /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; cp = malloc( x ); sprintf( cp, "%s.%s", pTap->chip, pTap->tapname ); @@ -1756,16 +1850,15 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); - - // default is enabled + /* default is enabled */ pTap->enabled = 1; - // deal with options + /* deal with options */ #define NTREQ_IRLEN 1 #define NTREQ_IRCAPTURE 2 #define NTREQ_IRMASK 4 - // clear them as we find them + /* clear them as we find them */ reqbits = (NTREQ_IRLEN | NTREQ_IRCAPTURE | NTREQ_IRMASK); while( goi->argc ){ @@ -1816,7 +1909,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) return e; } if( (w < 0) || (w > 0xffff) ){ - // wacky value + /* wacky value */ Jim_SetResult_sprintf( goi->interp, "option: %s - wacky value: %d (0x%x)", n->name, (int)(w), (int)(w)); return JIM_ERR; @@ -1835,17 +1928,17 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) reqbits &= (~(NTREQ_IRCAPTURE)); break; } - } // switch(n->value) - } // while( goi->argc ) + } /* switch(n->value) */ + } /* while( goi->argc ) */ - // Did we get all the options? + /* Did we get all the options? */ if( reqbits ){ // no Jim_SetResult_sprintf( goi->interp, "newtap: %s missing required parameters", pTap->dotted_name); - // fixme: Tell user what is missing :-( - // no memory leaks pelase + /* TODO: Tell user what is missing :-( */ + /* no memory leaks pelase */ free(((void *)(pTap->expected_ids))); free(((void *)(pTap->chip))); free(((void *)(pTap->tapname))); @@ -1871,7 +1964,6 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) pTap->bypass = 1; - jtag_register_event_callback(jtag_reset_callback, pTap ); ppTap = &(jtag_all_taps); @@ -1884,23 +1976,21 @@ jim_newtap_cmd( Jim_GetOptInfo *goi ) pTap->abs_chain_position = n_taps++; } LOG_DEBUG( "Created Tap: %s @ abs position %d, irlen %d, capture: 0x%x mask: 0x%x", - (*ppTap)->dotted_name, - (*ppTap)->abs_chain_position, - (*ppTap)->ir_length, - (*ppTap)->ir_capture_value, - (*ppTap)->ir_capture_mask ); - + (*ppTap)->dotted_name, + (*ppTap)->abs_chain_position, + (*ppTap)->ir_length, + (*ppTap)->ir_capture_value, + (*ppTap)->ir_capture_mask ); return ERROR_OK; } - -static int -jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) +static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) { Jim_GetOptInfo goi; int e; Jim_Nvp *n; + Jim_Obj *o; struct command_context_s *context; enum { @@ -1909,7 +1999,9 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) JTAG_CMD_NEWTAP, JTAG_CMD_TAPENABLE, JTAG_CMD_TAPDISABLE, - JTAG_CMD_TAPISENABLED + JTAG_CMD_TAPISENABLED, + JTAG_CMD_CONFIGURE, + JTAG_CMD_CGET }; const Jim_Nvp jtag_cmds[] = { @@ -1919,12 +2011,14 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) { .name = "tapisenabled" , .value = JTAG_CMD_TAPISENABLED }, { .name = "tapenable" , .value = JTAG_CMD_TAPENABLE }, { .name = "tapdisable" , .value = JTAG_CMD_TAPDISABLE }, + { .name = "configure" , .value = JTAG_CMD_CONFIGURE }, + { .name = "cget" , .value = JTAG_CMD_CGET }, { .name = NULL, .value = -1 }, }; context = Jim_GetAssocData(interp, "context"); - // go past the command + /* go past the command */ Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 ); e = Jim_GetOpt_Nvp( &goi, jtag_cmds, &n ); @@ -1935,9 +2029,9 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) Jim_SetEmptyResult( goi.interp ); switch( n->value ){ case JTAG_CMD_INTERFACE: - // return the name of the interface - // TCL code might need to know the exact type... - // FUTURE: we allow this as a means to "set" the interface. + /* return the name of the interface */ + /* TCL code might need to know the exact type... */ + /* FUTURE: we allow this as a means to "set" the interface. */ if( goi.argc != 0 ){ Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)"); return JIM_ERR; @@ -1974,13 +2068,15 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) } switch( n->value ){ case JTAG_CMD_TAPISENABLED: - // below + e = t->enabled; break; case JTAG_CMD_TAPENABLE: + jtag_tap_handle_event( t, JTAG_TAP_EVENT_ENABLE); e = 1; t->enabled = e; break; case JTAG_CMD_TAPDISABLE: + jtag_tap_handle_event( t, JTAG_TAP_EVENT_DISABLE); e = 0; t->enabled = e; break; @@ -1988,8 +2084,47 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) Jim_SetResult( goi.interp, Jim_NewIntObj( goi.interp, e ) ); return JIM_OK; } - } + break; + + case JTAG_CMD_CGET: + if( goi.argc < 2 ){ + Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ..."); + return JIM_ERR; + } + + { + jtag_tap_t *t; + + Jim_GetOpt_Obj(&goi, &o); + t = jtag_TapByJimObj( goi.interp, o ); + if( t == NULL ){ + return JIM_ERR; + } + + goi.isconfigure = 0; + return jtag_tap_configure_cmd( &goi, t); + } + break; + + case JTAG_CMD_CONFIGURE: + if( goi.argc < 3 ){ + Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ?VALUE? ..."); + return JIM_ERR; + } + + { + jtag_tap_t *t; + Jim_GetOpt_Obj(&goi, &o); + t = jtag_TapByJimObj( goi.interp, o ); + if( t == NULL ){ + return JIM_ERR; + } + + goi.isconfigure = 1; + return jtag_tap_configure_cmd( &goi, t); + } + } return JIM_ERR; } @@ -2007,7 +2142,8 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command, COMMAND_CONFIG, "jtag_device "); register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command, - COMMAND_CONFIG, NULL); + COMMAND_ANY, + "[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]"); register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command, COMMAND_ANY, "jtag_nsrst_delay - delay after deasserting srst in ms"); register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command, @@ -2051,8 +2187,6 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) if (jtag_interface->init() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; - - jtag = jtag_interface; return ERROR_OK; } @@ -2064,7 +2198,6 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx) LOG_DEBUG("Init JTAG chain"); - tap = jtag_NextEnabledTap(NULL); if( tap == NULL ){ LOG_ERROR("There are no enabled taps?"); @@ -2083,7 +2216,7 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx) if (jtag_validate_chain() != ERROR_OK) { - LOG_ERROR("Could not validate JTAG chain, continuing anyway..."); + LOG_WARNING("Could not validate JTAG chain, continuing anyway..."); } return ERROR_OK; @@ -2238,14 +2371,14 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha int e; char buf[1024]; Jim_Obj *newargs[ 10 ]; - // - // CONVERT SYNTAX - // - // argv[-1] = command - // argv[ 0] = ir length - // argv[ 1] = ir capture - // argv[ 2] = ir mask - // argv[ 3] = not actually used by anything but in the docs + /* + * CONVERT SYNTAX + * argv[-1] = command + * argv[ 0] = ir length + * argv[ 1] = ir capture + * argv[ 2] = ir mask + * argv[ 3] = not actually used by anything but in the docs + */ if( argc < 4 ){ command_print( cmd_ctx, "OLD DEPRECATED SYNTAX: Please use the NEW syntax"); @@ -2261,8 +2394,6 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha command_print( cmd_ctx, "jtag newtap stm32 boundry ....., and the tap: \"stm32.boundery\""); command_print( cmd_ctx, "And then refer to the taps by the dotted name."); - - newargs[0] = Jim_NewStringObj( interp, "jtag", -1 ); newargs[1] = Jim_NewStringObj( interp, "newtap", -1 ); sprintf( buf, "chip%d", jtag_NumTotalTaps() ); @@ -2289,8 +2420,6 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha Jim_GetString( newargs[8], NULL ), Jim_GetString( newargs[9], NULL ) ); - - e = jim_jtag_command( interp, 10, newargs ); if( e != JIM_OK ){ command_print( cmd_ctx, "%s", Jim_GetString( Jim_GetResult(interp), NULL ) ); @@ -2298,7 +2427,6 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha return e; } - int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { jtag_tap_t *tap; @@ -2522,7 +2650,7 @@ int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char * int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - enum tap_state state; + tap_state_t state; if (argc < 1) { @@ -2532,14 +2660,14 @@ int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char * { for (state = 0; state < 16; state++) { - if (strcmp(args[0], tap_state_strings[state]) == 0) + if (strcmp(args[0], tap_state_name(state)) == 0) { jtag_add_end_state(state); jtag_execute_queue(); } } } - command_print(cmd_ctx, "current endstate: %s", tap_state_strings[cmd_queue_end_state]); + command_print(cmd_ctx, "current endstate: %s", tap_state_name(cmd_queue_end_state)); return ERROR_OK; } @@ -2683,7 +2811,6 @@ int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args) Jim_GetLong(interp, args[i], &bits); str = Jim_GetString(args[i+1], &len); - fields[field_count].tap = tap; fields[field_count].num_bits = bits; fields[field_count].out_value = malloc(CEIL(bits, 8)); @@ -2752,7 +2879,6 @@ int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd return ERROR_OK; } - int jtag_power_dropout(int *dropout) { return jtag->power_dropout(dropout); @@ -2763,3 +2889,300 @@ int jtag_srst_asserted(int *srst_asserted) return jtag->srst_asserted(srst_asserted); } +void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e) +{ + jtag_tap_event_action_t * jteap; + int done; + + jteap = tap->event_action; + + done = 0; + while (jteap) { + if (jteap->event == e) { + done = 1; + LOG_DEBUG( "JTAG tap: %s event: %d (%s) action: %s\n", + tap->dotted_name, + e, + Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name, + Jim_GetString(jteap->body, NULL) ); + if (Jim_EvalObj(interp, jteap->body) != JIM_OK) { + Jim_PrintErrorMessage(interp); + } + } + + jteap = jteap->next; + } + + if (!done) { + LOG_DEBUG( "event %d %s - no action", + e, + Jim_Nvp_value2name_simple( nvp_jtag_tap_event, e)->name); + } +} + +/*--------------------------------------------*/ + +/* these Cable Helper API functions are all documented in the jtag.h header file, + using a Doxygen format. And since Doxygen's configuration file "Doxyfile", + is setup to prefer its docs in the header file, no documentation is here, for + if it were, it would have to be doubly maintained. +*/ + +/** + * @see tap_set_state() and tap_get_state() accessors. + * Actual name is not important since accessors hide it. + */ +static tap_state_t state_follower = TAP_RESET; + +void tap_set_state_impl( tap_state_t new_state ) +{ + /* this is the state we think the TAPs are in now, was cur_state */ + state_follower = new_state; +} + +tap_state_t tap_get_state() +{ + return state_follower; +} + +/** + * @see tap_set_end_state() and tap_get_end_state() accessors. + * Actual name is not important because accessors hide it. + */ +static tap_state_t end_state_follower = TAP_RESET; + +void tap_set_end_state( tap_state_t new_end_state ) +{ + /* this is the state we think the TAPs will be in at completion of the + current TAP operation, was end_state + */ + end_state_follower = new_end_state; +} + +tap_state_t tap_get_end_state() +{ + return end_state_follower; +} + +int tap_move_ndx( tap_state_t astate ) +{ + /* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */ + + /* old version + const static int move_map[16] = + { + 0, -1, -1, 2, -1, 3, -1, -1, + 1, -1, -1, 4, -1, 5, -1, -1 + }; + */ + + int ndx; + + switch( astate ) + { + case TAP_RESET: ndx = 0; break; + case TAP_DRSHIFT: ndx = 2; break; + case TAP_DRPAUSE: ndx = 3; break; + case TAP_IDLE: ndx = 1; break; + case TAP_IRSHIFT: ndx = 4; break; + case TAP_IRPAUSE: ndx = 5; break; + default: + LOG_ERROR( "fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate) ); + exit(1); + } + + return ndx; +} + +int tap_get_tms_path( tap_state_t from, tap_state_t to ) +{ + /* tap_move[i][j]: tap movement command to go from state i to state j + * 0: Test-Logic-Reset + * 1: Run-Test/Idle + * 2: Shift-DR + * 3: Pause-DR + * 4: Shift-IR + * 5: Pause-IR + * + * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code + */ + const static u8 tms_seqs[6][6] = + { + /* value clocked to TMS to move from one of six stable states to another */ + + /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ + { 0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16 }, /* RESET */ + { 0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b }, /* IDLE */ + { 0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f }, /* DRSHIFT */ + { 0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f }, /* DRPAUSE */ + { 0x7f, 0x31, 0x07, 0x17, 0x00, 0x01 }, /* IRSHIFT */ + { 0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f } /* IRPAUSE */ + }; + + if( !tap_is_state_stable(from) ) + { + LOG_ERROR( "fatal: tap_state \"from\" (=%s) is not stable", tap_state_name(from) ); + exit(1); + } + + if( !tap_is_state_stable(to) ) + { + LOG_ERROR( "fatal: tap_state \"to\" (=%s) is not stable", tap_state_name(to) ); + exit(1); + } + + /* @todo: support other than 7 clocks ? */ + return tms_seqs[tap_move_ndx(from)][tap_move_ndx(to)]; +} + +int tap_is_state_stable(tap_state_t astate) +{ + int is_stable; + + /* A switch() is used because it is symbol dependent + (not value dependent like an array), and can also check bounds. + */ + switch( astate ) + { + case TAP_RESET: + case TAP_IDLE: + case TAP_DRSHIFT: + case TAP_DRPAUSE: + case TAP_IRSHIFT: + case TAP_IRPAUSE: + is_stable = 1; + break; + default: + is_stable = 0; + } + + return is_stable; +} + +tap_state_t tap_state_transition(tap_state_t cur_state, int tms) +{ + tap_state_t new_state; + + /* A switch is used because it is symbol dependent and not value dependent + like an array. Also it can check for out of range conditions. + */ + + if (tms) + { + switch (cur_state) + { + case TAP_RESET: + new_state = cur_state; + break; + case TAP_IDLE: + case TAP_DRUPDATE: + case TAP_IRUPDATE: + new_state = TAP_DRSELECT; + break; + case TAP_DRSELECT: + new_state = TAP_IRSELECT; + break; + case TAP_DRCAPTURE: + case TAP_DRSHIFT: + new_state = TAP_DREXIT1; + break; + case TAP_DREXIT1: + case TAP_DREXIT2: + new_state = TAP_DRUPDATE; + break; + case TAP_DRPAUSE: + new_state = TAP_DREXIT2; + break; + case TAP_IRSELECT: + new_state = TAP_RESET; + break; + case TAP_IRCAPTURE: + case TAP_IRSHIFT: + new_state = TAP_IREXIT1; + break; + case TAP_IREXIT1: + case TAP_IREXIT2: + new_state = TAP_IRUPDATE; + break; + case TAP_IRPAUSE: + new_state = TAP_IREXIT2; + break; + default: + LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state ); + exit(1); + break; + } + } + else + { + switch (cur_state) + { + case TAP_RESET: + case TAP_IDLE: + case TAP_DRUPDATE: + case TAP_IRUPDATE: + new_state = TAP_IDLE; + break; + case TAP_DRSELECT: + new_state = TAP_DRCAPTURE; + break; + case TAP_DRCAPTURE: + case TAP_DRSHIFT: + case TAP_DREXIT2: + new_state = TAP_DRSHIFT; + break; + case TAP_DREXIT1: + case TAP_DRPAUSE: + new_state = TAP_DRPAUSE; + break; + case TAP_IRSELECT: + new_state = TAP_IRCAPTURE; + break; + case TAP_IRCAPTURE: + case TAP_IRSHIFT: + case TAP_IREXIT2: + new_state = TAP_IRSHIFT; + break; + case TAP_IREXIT1: + case TAP_IRPAUSE: + new_state = TAP_IRPAUSE; + break; + default: + LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state ); + exit(1); + break; + } + } + + return new_state; +} + +const char* tap_state_name(tap_state_t state) +{ + const char* ret; + + switch( state ) + { + case TAP_RESET: ret = "RESET"; break; + case TAP_IDLE: ret = "IDLE"; break; + case TAP_DRSELECT: ret = "DRSELECT"; break; + case TAP_DRCAPTURE: ret = "DRCAPTURE"; break; + case TAP_DRSHIFT: ret = "DRSHIFT"; break; + case TAP_DREXIT1: ret = "DREXIT1"; break; + case TAP_DRPAUSE: ret = "DRPAUSE"; break; + case TAP_DREXIT2: ret = "DREXIT2"; break; + case TAP_DRUPDATE: ret = "DRUPDATE"; break; + case TAP_IRSELECT: ret = "IRSELECT"; break; + case TAP_IRCAPTURE: ret = "IRCAPTURE"; break; + case TAP_IRSHIFT: ret = "IRSHIFT"; break; + case TAP_IREXIT1: ret = "IREXIT1"; break; + case TAP_IRPAUSE: ret = "IRPAUSE"; break; + case TAP_IREXIT2: ret = "IREXIT2"; break; + case TAP_IRUPDATE: ret = "IRUPDATE"; break; + default: ret = "???"; + } + + return ret; +} + +/*-------------------------------------------*/