X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=6199ed29cdb3381387d2b7e9f2047f25e6802431;hp=fc89d2489060d0436b6c8429a388e6795e19cb2b;hb=dfbb9f3e89ae6a3769d0df2167208c7c07e22e3c;hpb=9bf081192f2a1ad8c3ef424c9564b0c1f733461d diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index fc89d24890..6199ed29cd 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -27,13 +27,11 @@ #include "command.h" #include "log.h" -#include "interpreter.h" #include "stdlib.h" #include "string.h" #include - /* note that this is not marked as static as it must be available from outside jtag.c for those that implement the jtag_xxx() minidriver layer */ @@ -106,9 +104,14 @@ tap_transition_t tap_transitions[16] = char* jtag_event_strings[] = { - "JTAG controller reset(tms or TRST)" + "JTAG controller reset (TLR 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_TLR; enum tap_state cur_state = TAP_TLR; int jtag_trst = 0; @@ -136,6 +139,11 @@ int jtag_ntrst_delay = 0; /* default to no nTRST delay */ /* callbacks to inform high-level handlers about JTAG state changes */ jtag_event_callback_t *jtag_event_callbacks; +/* speed in kHz*/ +static int speed_khz = 0; +/* flag if the kHz speed was defined */ +static int hasKHz = 0; + /* jtag interfaces (parport, FTDI-USB, TI-USB, ...) */ @@ -146,7 +154,11 @@ jtag_event_callback_t *jtag_event_callbacks; #if BUILD_PARPORT == 1 extern jtag_interface_t parport_interface; #endif - + +#if BUILD_DUMMY == 1 + extern jtag_interface_t dummy_interface; +#endif + #if BUILD_FT2232_FTD2XX == 1 extern jtag_interface_t ft2232_interface; #endif @@ -179,6 +191,10 @@ jtag_event_callback_t *jtag_event_callbacks; extern jtag_interface_t usbprog_interface; #endif +#if BUILD_JLINK == 1 + extern jtag_interface_t jlink_interface; +#endif + jtag_interface_t *jtag_interfaces[] = { #if BUILD_ECOSBOARD == 1 &eCosBoard_interface, @@ -186,6 +202,9 @@ jtag_interface_t *jtag_interfaces[] = { #if BUILD_PARPORT == 1 &parport_interface, #endif +#if BUILD_DUMMY == 1 + &dummy_interface, +#endif #if BUILD_FT2232_FTD2XX == 1 &ft2232_interface, #endif @@ -209,6 +228,9 @@ jtag_interface_t *jtag_interfaces[] = { #endif #if BUILD_USBPROG == 1 &usbprog_interface, +#endif +#if BUILD_JLINK == 1 + &jlink_interface, #endif NULL, }; @@ -218,14 +240,12 @@ jtag_interface_t *jtag = NULL; /* configuration */ jtag_interface_t *jtag_interface = NULL; int jtag_speed = 0; -int jtag_speed_post_reset = 0; + /* forward declarations */ -void jtag_add_statemove(enum tap_state endstate); void jtag_add_pathmove(int num_states, enum tap_state *path); void jtag_add_runtest(int num_cycles, enum tap_state endstate); -int jtag_add_reset(int trst, int srst); void jtag_add_end_state(enum tap_state endstate); void jtag_add_sleep(u32 us); int jtag_execute_queue(void); @@ -245,9 +265,8 @@ int handle_scan_chain_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); int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +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); @@ -302,7 +321,7 @@ int jtag_call_event_callbacks(enum jtag_event event) { jtag_event_callback_t *callback = jtag_event_callbacks; - DEBUG("jtag event: %s", jtag_event_strings[event]); + LOG_DEBUG("jtag event: %s", jtag_event_strings[event]); while (callback) { @@ -346,7 +365,7 @@ jtag_device_t* jtag_get_device(int num) i++; } - ERROR("jtag device number %d not defined", num); + LOG_ERROR("jtag device number %d not defined", num); exit(-1); } @@ -354,6 +373,7 @@ void* cmd_queue_alloc(size_t size) { cmd_queue_page_t **p_page = &cmd_queue_pages; int offset; + u8 *t; if (*p_page) { @@ -374,7 +394,7 @@ void* cmd_queue_alloc(size_t size) offset = (*p_page)->used; (*p_page)->used += size; - u8 *t=(u8 *)((*p_page)->address); + t=(u8 *)((*p_page)->address); return t + offset; } @@ -397,7 +417,7 @@ static void jtag_prelude1() { if (jtag_trst == 1) { - WARNING("JTAG command queued, while TRST is low (TAP in reset)"); + LOG_WARNING("JTAG command queued, while TRST is low (TAP in reset)"); jtag_error=ERROR_JTAG_TRST_ASSERTED; return; } @@ -411,16 +431,18 @@ static void jtag_prelude(enum tap_state state) jtag_prelude1(); if (state != -1) - cmd_queue_end_state = state; + jtag_add_end_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) { + int retval; + jtag_prelude(state); - int retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state); + retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -504,9 +526,11 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state) { + int retval; + jtag_prelude(state); - int retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state); + retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -550,9 +574,11 @@ int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *f void jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) { + int retval; + jtag_prelude(state); - int retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state); + retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -574,6 +600,11 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, bypass_devices++; device = device->next; } + if (bypass_devices >= jtag_num_devices) + { + LOG_ERROR("all devices in bypass"); + return ERROR_JTAG_DEVICE_ERROR; + } /* allocate memory for a new list member */ *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); @@ -615,7 +646,7 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, /* if a device isn't listed, the BYPASS register should be selected */ if (!jtag_get_device(i)->bypass) { - ERROR("BUG: no scan data for a device not in BYPASS"); + LOG_ERROR("BUG: no scan data for a device not in BYPASS"); exit(-1); } #endif @@ -635,7 +666,7 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, /* if a device is listed, the BYPASS register must not be selected */ if (jtag_get_device(i)->bypass) { - ERROR("BUG: scan data for a device in BYPASS"); + LOG_ERROR("BUG: scan data for a device in BYPASS"); exit(-1); } #endif @@ -646,8 +677,8 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, int num_fields, - int *num_bits, - u32 *value, + const int *num_bits, + const u32 *value, enum tap_state end_state) { int i; @@ -689,7 +720,7 @@ void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, /* if a device is listed, the BYPASS register must not be selected */ if (jtag_get_device(i)->bypass) { - ERROR("BUG: scan data for a device in BYPASS"); + LOG_ERROR("BUG: scan data for a device in BYPASS"); exit(-1); } #endif @@ -713,7 +744,7 @@ void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, /* if a device isn't listed, the BYPASS register should be selected */ if (!jtag_get_device(i)->bypass) { - ERROR("BUG: no scan data for a device not in BYPASS"); + LOG_ERROR("BUG: no scan data for a device not in BYPASS"); exit(-1); } #endif @@ -730,14 +761,13 @@ void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, } } - - - void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state) { + int retval; + jtag_prelude(state); - int retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state); + retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; } @@ -777,18 +807,20 @@ int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *f return ERROR_OK; } -void jtag_add_statemove(enum tap_state state) -{ - jtag_prelude(state); +void jtag_add_tlr() +{ + jtag_prelude(TAP_TLR); + int retval; - retval=interface_jtag_add_statemove(cmd_queue_end_state); + retval=interface_jtag_add_tlr(); if (retval!=ERROR_OK) jtag_error=retval; } -int MINIDRIVER(interface_jtag_add_statemove)(enum tap_state state) +int MINIDRIVER(interface_jtag_add_tlr)() { + enum tap_state state = TAP_TLR; jtag_command_t **last_cmd = jtag_get_last_command_p(); /* allocate memory for a new list member */ @@ -806,21 +838,23 @@ int MINIDRIVER(interface_jtag_add_statemove)(enum tap_state state) void jtag_add_pathmove(int num_states, enum tap_state *path) { + enum tap_state 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) { - ERROR("BUG: TAP path doesn't finish in a stable state"); + LOG_ERROR("BUG: TAP path doesn't finish in a stable state"); exit(-1); } - enum tap_state cur_state=cmd_queue_cur_state; - int i; for (i=0; i %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_strings[cur_state], tap_state_strings[path[i]]); exit(-1); } cur_state = path[i]; @@ -830,12 +864,11 @@ void jtag_add_pathmove(int num_states, enum tap_state *path) cmd_queue_cur_state = path[num_states - 1]; - int retval=interface_jtag_add_pathmove(num_states, path); + retval=interface_jtag_add_pathmove(num_states, path); if (retval!=ERROR_OK) jtag_error=retval; } - int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, enum tap_state *path) { jtag_command_t **last_cmd = jtag_get_last_command_p(); @@ -876,80 +909,101 @@ int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, enum tap_state state) void jtag_add_runtest(int num_cycles, enum tap_state state) { + int retval; + jtag_prelude(state); /* executed by sw or hw fifo */ - int retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state); + retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state); if (retval!=ERROR_OK) jtag_error=retval; } -int jtag_add_reset(int req_trst, int req_srst) +void jtag_add_reset(int req_tlr_or_trst, int req_srst) { - int trst_with_tms = 0; + int trst_with_tlr = 0; int retval; - if (req_trst == -1) - req_trst = jtag_trst; + /* FIX!!! there are *many* different cases here. A better + * approach is needed for legal combinations of transitions... + */ + 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 == -1) - req_srst = jtag_srst; - /* 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_trst == 0)) + if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst)) { - ERROR("requested reset would assert trst"); - return ERROR_JTAG_RESET_WOULD_ASSERT_TRST; + LOG_ERROR("BUG: requested reset would assert trst"); + jtag_error=ERROR_FAIL; + return; } /* if TRST pulls SRST, we reset with TAP T-L-R */ - if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_trst == 1)) && (req_srst == 0)) + if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_tlr_or_trst)) && (req_srst == 0)) { - req_trst = 0; - trst_with_tms = 1; + trst_with_tlr = 1; } if (req_srst && !(jtag_reset_config & RESET_HAS_SRST)) { - ERROR("requested nSRST assertion, but the current configuration doesn't support this"); - return ERROR_JTAG_RESET_CANT_SRST; + LOG_ERROR("BUG: requested SRST assertion, but the current configuration doesn't support this"); + jtag_error=ERROR_FAIL; + return; } - if (req_trst && !(jtag_reset_config & RESET_HAS_TRST)) + if (req_tlr_or_trst) + { + if (!trst_with_tlr && (jtag_reset_config & RESET_HAS_TRST)) + { + jtag_trst = 1; + } else + { + trst_with_tlr = 1; + } + } else { - req_trst = 0; - trst_with_tms = 1; + jtag_trst = 0; } - - jtag_trst = req_trst; + jtag_srst = req_srst; - retval = interface_jtag_add_reset(req_trst, req_srst); + retval = interface_jtag_add_reset(jtag_trst, jtag_srst); if (retval!=ERROR_OK) { jtag_error=retval; - return retval; + return; } if (jtag_srst) { - DEBUG("SRST line asserted"); + LOG_DEBUG("SRST line asserted"); } else { - DEBUG("SRST line released"); + LOG_DEBUG("SRST line released"); if (jtag_nsrst_delay) jtag_add_sleep(jtag_nsrst_delay * 1000); } - if (trst_with_tms) + if (trst_with_tlr) { - DEBUG("JTAG reset with tms instead of TRST"); + LOG_DEBUG("JTAG reset with TLR instead of TRST"); jtag_add_end_state(TAP_TLR); - jtag_add_statemove(TAP_TLR); + jtag_add_tlr(); jtag_call_event_callbacks(JTAG_TRST_ASSERTED); - return ERROR_OK; + return; } if (jtag_trst) @@ -957,20 +1011,15 @@ int jtag_add_reset(int req_trst, int req_srst) /* we just asserted nTRST, so we're now in Test-Logic-Reset, * and inform possible listeners about this */ - DEBUG("TRST line asserted"); + LOG_DEBUG("TRST line asserted"); cmd_queue_cur_state = TAP_TLR; jtag_call_event_callbacks(JTAG_TRST_ASSERTED); } else { - /* the nTRST line got deasserted, so we're still in Test-Logic-Reset, - * but we might want to add a delay to give the TAP time to settle - */ - DEBUG("Now in TAP_TLR - Test-Logic-Reset(either due to TRST line asserted or tms reset)"); if (jtag_ntrst_delay) jtag_add_sleep(jtag_ntrst_delay * 1000); } - return ERROR_OK; } int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst) @@ -987,13 +1036,16 @@ int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst) (*last_cmd)->cmd.reset->trst = req_trst; (*last_cmd)->cmd.reset->srst = req_srst; - return ERROR_OK; } void jtag_add_end_state(enum tap_state state) { cmd_queue_end_state = state; + if ((cmd_queue_end_state == TAP_SD)||(cmd_queue_end_state == TAP_SD)) + { + LOG_ERROR("BUG: TAP_SD/SI can't be end state. Calling code should use a larger scan field"); + } } int MINIDRIVER(interface_jtag_add_sleep)(u32 us) @@ -1014,6 +1066,7 @@ int MINIDRIVER(interface_jtag_add_sleep)(u32 us) 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; @@ -1053,7 +1106,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) #endif buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); #ifdef _DEBUG_JTAG_IO_ - DEBUG("fields[%i].out_value: 0x%s", i, char_buf); + LOG_DEBUG("fields[%i].out_value: 0x%s", i, char_buf); free(char_buf); #endif } @@ -1062,7 +1115,6 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) } return bit_count; - } int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) @@ -1088,7 +1140,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) char *char_buf; char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); - DEBUG("fields[%i].in_value: 0x%s", i, char_buf); + LOG_DEBUG("fields[%i].in_value: 0x%s", i, char_buf); free(char_buf); #endif @@ -1100,7 +1152,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) { - WARNING("in_handler reported a failed check"); + LOG_WARNING("in_handler reported a failed check"); retval = ERROR_JTAG_QUEUE_FAILED; } } @@ -1114,7 +1166,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 */ - WARNING("in_handler reported a failed check"); + LOG_WARNING("in_handler reported a failed check"); retval = ERROR_JTAG_QUEUE_FAILED; } } @@ -1154,12 +1206,12 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) { char *in_check_mask_char; in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16); - WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char); + LOG_WARNING("value captured during scan didn't pass the requested check: 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 { - WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char); + 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); } free(captured_char); @@ -1182,7 +1234,7 @@ void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handle field->in_handler = jtag_check_value; else field->in_handler = NULL; /* No check, e.g. embeddedice uses value==NULL to indicate no check */ - field->in_handler_priv = NULL; /* this will be filled in at the invocation site to point to the field duplicate */ + field->in_handler_priv = NULL; field->in_check_value = value; field->in_check_mask = mask; } @@ -1206,7 +1258,13 @@ enum scan_type jtag_scan_type(scan_command_t *cmd) int MINIDRIVER(interface_jtag_execute_queue)(void) { int retval; - + + if (jtag==NULL) + { + LOG_ERROR("No JTAG interface configured yet. Issue 'init' command in startup scripts before communicating with targets."); + return ERROR_FAIL; + } + retval = jtag->execute_queue(); cmd_queue_free(); @@ -1232,7 +1290,7 @@ int jtag_reset_callback(enum jtag_event event, void *priv) { jtag_device_t *device = priv; - DEBUG("-"); + LOG_DEBUG("-"); if (event == JTAG_TRST_ASSERTED) { @@ -1288,7 +1346,7 @@ int jtag_examine_chain() /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */ if ((zero_check == 0x00) || (one_check == 0xff)) { - ERROR("JTAG communication failure, check connection, JTAG interface, target power etc."); + LOG_ERROR("JTAG communication failure, check connection, JTAG interface, target power etc."); return ERROR_JTAG_INIT_FAILED; } @@ -1325,7 +1383,7 @@ int jtag_examine_chain() part = (idcode & 0xffff000) >> 12; version = (idcode & 0xf0000000) >> 28; - INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", + LOG_INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", idcode, manufacturer, part, version); bit_count += 32; @@ -1335,9 +1393,9 @@ int jtag_examine_chain() /* see if number of discovered devices matches configuration */ if (device_count != jtag_num_devices) { - ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", + LOG_ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", device_count, jtag_num_devices); - ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)"); + LOG_ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)"); return ERROR_JTAG_INIT_FAILED; } @@ -1381,7 +1439,7 @@ int jtag_validate_chain() if (buf_get_u32(ir_test, chain_pos, 2) != 0x1) { char *cbuf = buf_to_str(ir_test, total_ir_length, 16); - ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + LOG_ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); free(cbuf); free(ir_test); return ERROR_JTAG_INIT_FAILED; @@ -1393,7 +1451,7 @@ int jtag_validate_chain() if (buf_get_u32(ir_test, chain_pos, 2) != 0x3) { char *cbuf = buf_to_str(ir_test, total_ir_length, 16); - ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); + LOG_ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf); free(cbuf); free(ir_test); return ERROR_JTAG_INIT_FAILED; @@ -1409,17 +1467,17 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "interface", handle_interface_command, COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command, - COMMAND_ANY, "set jtag speed (if supported) []"); + COMMAND_ANY, "set jtag speed (if supported)"); register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command, - COMMAND_ANY, "same as jtag_speed, except it takes khz as arguments"); + COMMAND_ANY, "same as jtag_speed, except it takes maximum khz as arguments. 0 KHz = RTCK."); 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); register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command, - COMMAND_CONFIG, NULL); + COMMAND_ANY, "jtag_nsrst_delay - delay after deasserting srst in ms"); register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command, - COMMAND_CONFIG, NULL); + COMMAND_ANY, "jtag_ntrst_delay - delay after deasserting trst in ms"); register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command, COMMAND_EXEC, "print current scan chain configuration"); @@ -1430,12 +1488,9 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) COMMAND_EXEC, "toggle reset lines "); register_command(cmd_ctx, NULL, "runtest", handle_runtest_command, COMMAND_EXEC, "move to Run-Test/Idle, and execute "); - register_command(cmd_ctx, NULL, "statemove", handle_statemove_command, - COMMAND_EXEC, "move to current endstate or [tap_state]"); register_command(cmd_ctx, NULL, "irscan", handle_irscan_command, COMMAND_EXEC, "execute IR scan [dev2] [instr2] ..."); - register_command(cmd_ctx, NULL, "drscan", handle_drscan_command, - COMMAND_EXEC, "execute DR scan [dev2] [var2] ..."); + register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan ..."); register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command, COMMAND_ANY, "verify value captured during Capture-IR "); @@ -1444,30 +1499,38 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) int jtag_interface_init(struct command_context_s *cmd_ctx) { + if (jtag) + return ERROR_OK; + if (!jtag_interface) { /* nothing was previously specified by "interface" command */ - ERROR("JTAG interface has to be specified, see \"interface\" command"); + LOG_ERROR("JTAG interface has to be specified, see \"interface\" command"); return ERROR_JTAG_INVALID_INTERFACE; } + if(hasKHz) + { + jtag_interface->khz(speed_khz, &jtag_speed); + hasKHz = 0; + } if (jtag_interface->init() != ERROR_OK) return ERROR_JTAG_INIT_FAILED; + + jtag = jtag_interface; return ERROR_OK; } -int jtag_init(struct command_context_s *cmd_ctx) +static int jtag_init_inner(struct command_context_s *cmd_ctx) { int validate_tries = 0; jtag_device_t *device; + int retval; - DEBUG("-"); + LOG_DEBUG("Init JTAG chain"); - if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - device = jtag_devices; jtag_ir_scan_size = 0; jtag_num_devices = 0; @@ -1478,36 +1541,99 @@ int jtag_init(struct command_context_s *cmd_ctx) device = device->next; } - jtag_add_statemove(TAP_TLR); - jtag_execute_queue(); + jtag_add_tlr(); + 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) { - ERROR("trying to validate configured JTAG chain anyway..."); + LOG_ERROR("trying to validate configured JTAG chain anyway..."); } while (jtag_validate_chain() != ERROR_OK) { validate_tries++; + if (validate_tries > 5) { - ERROR("Could not validate JTAG chain, exit"); + LOG_ERROR("Could not validate JTAG chain, exit"); return ERROR_JTAG_INVALID_INTERFACE; } usleep(10000); } - + return ERROR_OK; } +int jtag_init_reset(struct command_context_s *cmd_ctx) +{ + int retval; + + if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK) + return retval; + + LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR"); + + /* Reset can happen after a power cycle. + * + * Ideally we would only assert TRST or run TLR before the target reset. + * + * However w/srst_pulls_trst, trst is asserted together with the target + * reset whether we want it or not. + * + * NB! Some targets have JTAG circuitry disabled until a + * trst & srst has been asserted. + * + * NB! here we assume nsrst/ntrst delay are sufficient! + * + * NB! order matters!!!! srst *can* disconnect JTAG circuitry + * + */ + jtag_add_reset(1, 0); /* TLR or TRST */ + if (jtag_reset_config & RESET_HAS_SRST) + { + jtag_add_reset(1, 1); + if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0) + jtag_add_reset(0, 1); + } + jtag_add_reset(0, 0); + if ((retval = jtag_execute_queue()) != ERROR_OK) + return retval; + + /* Check that we can communication on the JTAG chain + eventually we want to + * be able to perform enumeration only after OpenOCD has started + * telnet and GDB server + * + * That would allow users to more easily perform any magic they need to before + * reset happens. + */ + return jtag_init_inner(cmd_ctx); +} + +int jtag_init(struct command_context_s *cmd_ctx) +{ + int retval; + if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK) + return retval; + if (jtag_init_inner(cmd_ctx)==ERROR_OK) + { + return ERROR_OK; + } + return jtag_init_reset(cmd_ctx); +} static int default_khz(int khz, int *jtag_speed) { - ERROR("Translation from khz to jtag_speed not implemented"); + LOG_ERROR("Translation from khz to jtag_speed not implemented"); return ERROR_FAIL; } +static int default_speed_div(int speed, int *khz) +{ + return ERROR_FAIL; +} + int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int i; @@ -1515,7 +1641,7 @@ int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char /* check whether the interface is already configured */ if (jtag_interface) { - WARNING("Interface already configured, ignoring"); + LOG_WARNING("Interface already configured, ignoring"); return ERROR_OK; } @@ -1538,6 +1664,10 @@ int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char { jtag_interface->khz = default_khz; } + if (jtag_interface->speed_div == NULL) + { + jtag_interface->speed_div = default_speed_div; + } return ERROR_OK; } } @@ -1545,11 +1675,11 @@ int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char /* no valid interface was found (i.e. the configuration option, * didn't match one of the compiled-in interfaces */ - ERROR("No valid jtag interface found (%s)", args[0]); - ERROR("compiled-in jtag interfaces:"); + LOG_ERROR("No valid jtag interface found (%s)", args[0]); + LOG_ERROR("compiled-in jtag interfaces:"); for (i = 0; jtag_interfaces[i]; i++) { - ERROR("%i: %s", i, jtag_interfaces[i]->name); + LOG_ERROR("%i: %s", i, jtag_interfaces[i]->name); } return ERROR_JTAG_INVALID_INTERFACE; @@ -1611,6 +1741,9 @@ int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + if (argc < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + if (argc >= 1) { if (strcmp(args[0], "none") == 0) @@ -1623,7 +1756,7 @@ int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, ch jtag_reset_config = RESET_TRST_AND_SRST; else { - ERROR("invalid reset_config argument, defaulting to none"); + LOG_ERROR("invalid reset_config argument, defaulting to none"); jtag_reset_config = RESET_NONE; return ERROR_INVALID_ARGUMENTS; } @@ -1631,19 +1764,23 @@ int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, ch if (argc >= 2) { - if (strcmp(args[1], "srst_pulls_trst") == 0) - jtag_reset_config |= RESET_SRST_PULLS_TRST; - else if (strcmp(args[1], "trst_pulls_srst") == 0) - jtag_reset_config |= RESET_TRST_PULLS_SRST; - else if (strcmp(args[1], "combined") == 0) - jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST; - else if (strcmp(args[1], "separate") == 0) - jtag_reset_config &= ~(RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST); - else + if (strcmp(args[1], "separate") == 0) { - ERROR("invalid reset_config argument, defaulting to none"); - jtag_reset_config = RESET_NONE; - return ERROR_INVALID_ARGUMENTS; + /* seperate reset lines - default */ + } else + { + if (strcmp(args[1], "srst_pulls_trst") == 0) + jtag_reset_config |= RESET_SRST_PULLS_TRST; + else if (strcmp(args[1], "trst_pulls_srst") == 0) + jtag_reset_config |= RESET_TRST_PULLS_SRST; + else if (strcmp(args[1], "combined") == 0) + jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST; + else + { + LOG_ERROR("invalid reset_config argument, defaulting to none"); + jtag_reset_config = RESET_NONE; + return ERROR_INVALID_ARGUMENTS; + } } } @@ -1655,7 +1792,7 @@ int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, ch jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN; else { - ERROR("invalid reset_config argument, defaulting to none"); + LOG_ERROR("invalid reset_config argument, defaulting to none"); jtag_reset_config = RESET_NONE; return ERROR_INVALID_ARGUMENTS; } @@ -1669,7 +1806,7 @@ int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, ch jtag_reset_config &= ~RESET_SRST_PUSH_PULL; else { - ERROR("invalid reset_config argument, defaulting to none"); + LOG_ERROR("invalid reset_config argument, defaulting to none"); jtag_reset_config = RESET_NONE; return ERROR_INVALID_ARGUMENTS; } @@ -1682,7 +1819,7 @@ int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd { if (argc < 1) { - ERROR("jtag_nsrst_delay command takes one required argument"); + LOG_ERROR("jtag_nsrst_delay command takes one required argument"); exit(-1); } else @@ -1697,7 +1834,7 @@ int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd { if (argc < 1) { - ERROR("jtag_ntrst_delay command takes one required argument"); + LOG_ERROR("jtag_ntrst_delay command takes one required argument"); exit(-1); } else @@ -1710,59 +1847,69 @@ int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - int cur_speed = 0; - if ((argc<1) || (argc>2)) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (argc >= 1) - cur_speed = jtag_speed = jtag_speed_post_reset = strtoul(args[0], NULL, 0); - if (argc == 2) - cur_speed = jtag_speed_post_reset = strtoul(args[1], NULL, 0); - - /* this command can be called during CONFIG, - * in which case jtag isn't initialized */ - if (jtag) - jtag->speed(cur_speed); + int retval=ERROR_OK; + + if (argc == 1) + { + LOG_DEBUG("handle jtag speed"); - return ERROR_OK; + int cur_speed = 0; + cur_speed = jtag_speed = strtoul(args[0], NULL, 0); + + /* this command can be called during CONFIG, + * in which case jtag isn't initialized */ + if (jtag) + { + retval=jtag->speed(cur_speed); + } + } else if (argc == 0) + { + } else + { + retval=ERROR_COMMAND_SYNTAX_ERROR; + } + command_print(cmd_ctx, "jtag_speed: %d", jtag_speed); + + return retval; } int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { - int cur_speed = 0; - int speed1, speed2; - if ((argc<1) || (argc>2)) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (jtag == NULL) - { - ERROR("Interface not selected yet"); - return ERROR_COMMAND_SYNTAX_ERROR; - } + int retval=ERROR_OK; + LOG_DEBUG("handle jtag khz"); - if (argc >= 1) - speed1 = strtoul(args[0], NULL, 0); - if (argc == 2) - speed2 = strtoul(args[1], NULL, 0); - - if (jtag->khz(speed1, &speed1)!=ERROR_OK) - return ERROR_OK; - - if (jtag->khz(speed2, &speed2)!=ERROR_OK) - return ERROR_OK; + if(argc == 1) + { + speed_khz = strtoul(args[0], NULL, 0); + if (jtag != NULL) + { + int cur_speed = 0; + LOG_DEBUG("have interface set up"); + int speed_div1; + if ((retval=jtag->khz(speed_khz, &speed_div1))!=ERROR_OK) + { + speed_khz = 0; + return retval; + } - if (argc >= 1) - cur_speed = jtag_speed = jtag_speed_post_reset = speed1; + cur_speed = jtag_speed = speed_div1; - if (argc == 2) - cur_speed = jtag_speed_post_reset = speed2; - - jtag->speed(cur_speed); + retval=jtag->speed(cur_speed); + } else + { + hasKHz = 1; + } + } else if (argc==0) + { + } else + { + retval=ERROR_COMMAND_SYNTAX_ERROR; + } + command_print(cmd_ctx, "jtag_khz: %d", speed_khz); + return retval; - return ERROR_OK; } - int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { enum tap_state state; @@ -1782,7 +1929,7 @@ int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char * } } } - command_print(cmd_ctx, "current endstate: %s", tap_state_strings[end_state]); + command_print(cmd_ctx, "current endstate: %s", tap_state_strings[cmd_queue_end_state]); return ERROR_OK; } @@ -1815,7 +1962,7 @@ int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_COMMAND_SYNTAX_ERROR; } - if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK) + if (jtag_interface_init(cmd_ctx) != ERROR_OK) return ERROR_JTAG_INIT_FAILED; jtag_add_reset(trst, srst); @@ -1838,29 +1985,6 @@ int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char ** } -int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - enum tap_state state; - - state = -1; - if (argc == 1) - { - for (state = 0; state < 16; state++) - { - if (strcmp(args[0], tap_state_strings[state]) == 0) - { - break; - } - } - } - - jtag_add_statemove(state); - jtag_execute_queue(); - - return ERROR_OK; - -} - int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int i; @@ -1898,63 +2022,92 @@ int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **a return ERROR_OK; } -int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args) { + int retval; scan_field_t *fields; - int num_fields = 0; + int num_fields; int field_count = 0; - var_t *var; - int i, j; - - if ((argc < 2) || (argc % 2)) + int i, e; + long device; + + /* args[1] = device + * args[2] = num_bits + * args[3] = hex string + * ... repeat num bits and hex string ... + */ + if ((argc < 4) || ((argc % 2)!=0)) { - return ERROR_COMMAND_SYNTAX_ERROR; + Jim_WrongNumArgs(interp, 1, args, "wrong arguments"); + return JIM_ERR; } - for (i = 0; i < argc; i+=2) + for (i = 2; i < argc; i+=2) { - var = get_var_by_namenum(args[i+1]); - if (var) - { - num_fields += var->num_fields; - } - else - { - command_print(cmd_ctx, "variable %s doesn't exist", args[i+1]); - return ERROR_OK; - } + long bits; + + e = Jim_GetLong(interp, args[i], &bits); + if (e != JIM_OK) + return e; } - fields = malloc(sizeof(scan_field_t) * num_fields); + e = Jim_GetLong(interp, args[1], &device); + if (e != JIM_OK) + return e; - for (i = 0; i < argc; i+=2) + num_fields=(argc-2)/2; + fields = malloc(sizeof(scan_field_t) * num_fields); + for (i = 2; i < argc; i+=2) { - var = get_var_by_namenum(args[i+1]); - - for (j = 0; j < var->num_fields; j++) - { - fields[field_count].device = strtol(args[i], NULL, 0); - fields[field_count].num_bits = var->fields[j].num_bits; - fields[field_count].out_value = malloc(CEIL(var->fields[j].num_bits, 8)); - buf_set_u32(fields[field_count].out_value, 0, var->fields[j].num_bits, var->fields[j].value); - fields[field_count].out_mask = NULL; - fields[field_count].in_value = fields[field_count].out_value; - fields[field_count].in_check_mask = NULL; - fields[field_count].in_check_value = NULL; - fields[field_count].in_handler = field_le_to_host; - fields[field_count++].in_handler_priv = &(var->fields[j]); - } + long bits; + int len; + const char *str; + + Jim_GetLong(interp, args[i], &bits); + str = Jim_GetString(args[i+1], &len); + + fields[field_count].device = device; + fields[field_count].num_bits = bits; + fields[field_count].out_value = malloc(CEIL(bits, 8)); + str_to_buf(str, len, fields[field_count].out_value, bits, 0); + fields[field_count].out_mask = NULL; + fields[field_count].in_value = fields[field_count].out_value; + fields[field_count].in_check_mask = NULL; + fields[field_count].in_check_value = NULL; + fields[field_count].in_handler = NULL; + fields[field_count++].in_handler_priv = NULL; } jtag_add_dr_scan(num_fields, fields, -1); - jtag_execute_queue(); - - for (i = 0; i < argc / 2; i++) - free(fields[i].out_value); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) + { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "drscan: jtag execute failed", NULL); + return JIM_ERR; + } + field_count=0; + Jim_Obj *list = Jim_NewListObj(interp, NULL, 0); + for (i = 2; i < argc; i+=2) + { + long bits; + char *str; + + Jim_GetLong(interp, args[i], &bits); + str = buf_to_str(fields[field_count].in_value, bits, 16); + free(fields[field_count].out_value); + + Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str))); + free(str); + field_count++; + } + + Jim_SetResult(interp, list); + free(fields); - return ERROR_OK; + return JIM_OK; } int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)