X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fjtag.c;h=6199ed29cdb3381387d2b7e9f2047f25e6802431;hp=c73e0c9aa879663b1056e796215d2b2591c44a78;hb=dfbb9f3e89ae6a3769d0df2167208c7c07e22e3c;hpb=eabb49b570290f2bcda80a0c591431b7ef240d43 diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index c73e0c9aa8..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,7 +104,7 @@ 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 @@ -142,7 +140,7 @@ int jtag_ntrst_delay = 0; /* default to no nTRST delay */ jtag_event_callback_t *jtag_event_callbacks; /* speed in kHz*/ -static int speed1 = 0, speed2 = 0; +static int speed_khz = 0; /* flag if the kHz speed was defined */ static int hasKHz = 0; @@ -156,7 +154,11 @@ static int hasKHz = 0; #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 @@ -189,6 +191,10 @@ static int hasKHz = 0; 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, @@ -196,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 @@ -219,6 +228,9 @@ jtag_interface_t *jtag_interfaces[] = { #endif #if BUILD_USBPROG == 1 &usbprog_interface, +#endif +#if BUILD_JLINK == 1 + &jlink_interface, #endif NULL, }; @@ -228,7 +240,7 @@ jtag_interface_t *jtag = NULL; /* configuration */ jtag_interface_t *jtag_interface = NULL; int jtag_speed = 0; -int jtag_speed_post_reset = 0; + /* forward declarations */ @@ -254,7 +266,7 @@ int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char * 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_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); @@ -361,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) { @@ -381,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; } @@ -425,9 +438,11 @@ static void jtag_prelude(enum tap_state 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; } @@ -511,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; } @@ -557,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; } @@ -581,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)); @@ -653,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; @@ -737,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; } @@ -815,6 +838,10 @@ int MINIDRIVER(interface_jtag_add_tlr)() 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) { @@ -822,8 +849,6 @@ void jtag_add_pathmove(int num_states, enum tap_state *path) exit(-1); } - enum tap_state cur_state=cmd_queue_cur_state; - int i; for (i=0; i 0,0 transition.... */ + //LOG_ERROR("BUG: transition of req_tlr_or_trst and req_srst in the same jtag_add_reset() call is undefined"); + } + } + /* Make sure that jtag_reset_config allows the requested reset */ /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */ if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst)) @@ -956,7 +999,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) if (trst_with_tlr) { - LOG_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_tlr(); jtag_call_event_callbacks(JTAG_TRST_ASSERTED); @@ -993,7 +1036,6 @@ 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; } @@ -1024,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; @@ -1072,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) @@ -1192,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; } @@ -1216,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(); @@ -1419,7 +1467,7 @@ 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 maximum khz as arguments. 0 KHz = RTCK."); register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command, @@ -1442,8 +1490,7 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) COMMAND_EXEC, "move to Run-Test/Idle, and execute "); 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 "); @@ -1452,6 +1499,9 @@ 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 */ @@ -1460,11 +1510,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) } if(hasKHz) { - /*stay on "reset speed"*/ - if (jtag_interface->khz(speed1, &speed1) == ERROR_OK) - jtag_speed = speed1; - if (jtag_interface->khz(speed2, &speed2) == ERROR_OK) - jtag_speed_post_reset = speed2; + jtag_interface->khz(speed_khz, &jtag_speed); hasKHz = 0; } @@ -1477,16 +1523,14 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) 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; - LOG_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; @@ -1498,7 +1542,8 @@ int jtag_init(struct command_context_s *cmd_ctx) } jtag_add_tlr(); - jtag_execute_queue(); + 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) @@ -1521,6 +1566,62 @@ int jtag_init(struct command_context_s *cmd_ctx) 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) { @@ -1528,6 +1629,11 @@ static int default_khz(int khz, int *jtag_speed) 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; @@ -1558,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; } } @@ -1737,66 +1847,68 @@ 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; + int retval=ERROR_OK; - if (argc != 0) + if (argc == 1) { - if ((argc<1) || (argc>2)) - return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("handle jtag speed"); - - 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); + + 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) - jtag->speed(cur_speed); - } - command_print(cmd_ctx, "jtag_speed: %d, %d", jtag_speed, jtag_speed_post_reset); + { + 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 ERROR_OK; + return retval; } int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + int retval=ERROR_OK; LOG_DEBUG("handle jtag khz"); - if ((argc<1) || (argc>2)) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (argc >= 1) - speed1 = speed2 = strtoul(args[0], NULL, 0); - if (argc == 2) - speed2 = strtoul(args[1], NULL, 0); - - if (jtag != NULL) + 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; + } + + cur_speed = jtag_speed = speed_div1; + + retval=jtag->speed(cur_speed); + } else + { + hasKHz = 1; + } + } else if (argc==0) { - int cur_speed = 0; - LOG_DEBUG("have interface set up"); - int speed_div1, speed_div2; - if (jtag->khz(speed1, &speed_div1)!=ERROR_OK) - return ERROR_OK; - if (jtag->khz(speed2, &speed_div2)!=ERROR_OK) - return ERROR_OK; - - if (argc >= 1) - cur_speed = jtag_speed = jtag_speed_post_reset = speed_div1; - if (argc == 2) - cur_speed = jtag_speed_post_reset = speed_div2; - - jtag->speed(cur_speed); } else { - hasKHz = 1; + retval=ERROR_COMMAND_SYNTAX_ERROR; } - - return ERROR_OK; -} + command_print(cmd_ctx, "jtag_khz: %d", speed_khz); + return retval; +} int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { @@ -1850,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); @@ -1873,7 +1985,6 @@ int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char ** } - int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int i; @@ -1911,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)