X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fcore.c;h=b26701e3c01b83476b8cfb90ba9b04ff8a2afaa7;hp=1068681964ee379a858078f434c31174cd4f1f82;hb=6446dbaacbf7c0607ea571ed7f5a4f32745544eb;hpb=803351ec59cb57c63129c77d95b5edf2fc65c302 diff --git a/src/jtag/core.c b/src/jtag/core.c index 1068681964..b26701e3c0 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -33,7 +33,7 @@ #include "jtag.h" #include "interface.h" -#include "transport.h" +#include #ifdef HAVE_STRINGS_H #include @@ -124,11 +124,14 @@ static struct jtag_event_callback *jtag_event_callbacks; static int speed_khz = 0; /* speed to fallback to when RCLK is requested but not supported */ static int rclk_fallback_speed_khz = 0; -static enum {CLOCK_MODE_SPEED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; +static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode; static int jtag_speed = 0; static struct jtag_interface *jtag = NULL; + +const struct swd_driver *swd = NULL; + /* configuration */ struct jtag_interface *jtag_interface = NULL; @@ -213,7 +216,7 @@ void jtag_tap_add(struct jtag_tap *t) } /* returns a pointer to the n-th device in the scan chain */ -static inline struct jtag_tap *jtag_tap_by_position(unsigned n) +struct jtag_tap *jtag_tap_by_position(unsigned n) { struct jtag_tap *t = jtag_all_taps(); @@ -296,28 +299,24 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv) int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv) { - struct jtag_event_callback **callbacks_p; - struct jtag_event_callback **next; + struct jtag_event_callback **p = &jtag_event_callbacks, *temp; if (callback == NULL) { return ERROR_INVALID_ARGUMENTS; } - for (callbacks_p = &jtag_event_callbacks; - *callbacks_p != NULL; - callbacks_p = next) + while (*p) { - next = &((*callbacks_p)->next); - - if ((*callbacks_p)->priv != priv) - continue; - - if ((*callbacks_p)->callback == callback) + if (((*p)->priv != priv) || ((*p)->callback != callback)) { - free(*callbacks_p); - *callbacks_p = *next; + p = &(*p)->next; + continue; } + + temp = *p; + *p = (*p)->next; + free(temp); } return ERROR_OK; @@ -696,7 +695,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst) retval = jtag_execute_queue(); if (retval != ERROR_OK) { - LOG_ERROR("TRST/SRST error %d", retval); + LOG_ERROR("TRST/SRST error"); return; } } @@ -872,9 +871,16 @@ static int jtag_reset_callback(enum jtag_event event, void *priv) return ERROR_OK; } +/* sleep at least us microseconds. When we sleep more than 1000ms we + * do an alive sleep, i.e. keep GDB alive. Note that we could starve + * GDB if we slept for <1000ms many times. + */ void jtag_sleep(uint32_t us) { - alive_sleep(us/1000); + if (us < 1000) + usleep(us); + else + alive_sleep((us+999)/1000); } /* Maximum number of enabled JTAG devices we expect in the scan chain, @@ -1362,12 +1368,13 @@ int adapter_init(struct command_context *cmd_ctx) return ERROR_JTAG_INVALID_INTERFACE; } - jtag = jtag_interface; - if (jtag_interface->init() != ERROR_OK) + int retval; + retval = jtag_interface->init(); + if (retval != ERROR_OK) { - jtag = NULL; - return ERROR_JTAG_INIT_FAILED; + return retval; } + jtag = jtag_interface; /* LEGACY SUPPORT ... adapter drivers must declare what * transports they allow. Until they all do so, assume @@ -1377,16 +1384,30 @@ int adapter_init(struct command_context *cmd_ctx) LOG_ERROR("Adapter driver '%s' did not declare " "which transports it allows; assuming " "JTAG-only", jtag->name); - int retval = allow_transports(cmd_ctx, jtag_only); + retval = allow_transports(cmd_ctx, jtag_only); if (retval != ERROR_OK) return retval; } + if (CLOCK_MODE_UNSELECTED == clock_mode) + { + LOG_ERROR("An adapter speed is not selected in the init script." + " Insert a call to adapter_khz or jtag_rclk to proceed."); + return ERROR_JTAG_INIT_FAILED; + } + int requested_khz = jtag_get_speed_khz(); int actual_khz = requested_khz; - int retval = jtag_get_speed_readable(&actual_khz); + int jtag_speed_var; + retval = jtag_get_speed(&jtag_speed_var); + if (retval != ERROR_OK) + return retval; + retval = jtag->speed(jtag_speed_var); + if (retval != ERROR_OK) + return retval; + retval = jtag_get_speed_readable(&actual_khz); if (ERROR_OK != retval) - LOG_INFO("adapter-specific clock speed value %d", jtag_get_speed()); + LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var); else if (actual_khz) { /* Adaptive clocking -- JTAG-specific */ @@ -1445,17 +1466,19 @@ int jtag_init_inner(struct command_context *cmd_ctx) case ERROR_OK: /* complete success */ break; - case ERROR_JTAG_INIT_SOFT_FAIL: + default: /* For backward compatibility reasons, try coping with * configuration errors involving only ID mismatches. * We might be able to talk to the devices. + * + * Also the device might be powered down during startup. + * + * After OpenOCD starts, we can try to power on the device + * and run a reset. */ LOG_ERROR("Trying to use configured scan chain anyway..."); issue_setup = false; break; - default: - /* some hard error; already issued diagnostics */ - return retval; } /* Now look at IR values. Problems here will prevent real @@ -1466,7 +1489,13 @@ int jtag_init_inner(struct command_context *cmd_ctx) */ retval = jtag_validate_ircapture(); if (retval != ERROR_OK) - return retval; + { + /* The target might be powered down. The user + * can power it up and reset it after firing + * up OpenOCD. + */ + issue_setup = false; + } if (issue_setup) jtag_notify_event(JTAG_TAP_EVENT_SETUP); @@ -1624,31 +1653,30 @@ int jtag_config_rclk(unsigned fallback_speed_khz) return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); } -int jtag_get_speed(void) +int jtag_get_speed(int *speed) { - int speed; switch(clock_mode) { - case CLOCK_MODE_SPEED: - speed = jtag_speed; - break; case CLOCK_MODE_KHZ: - adapter_khz_to_speed(jtag_get_speed_khz(), &speed); + adapter_khz_to_speed(jtag_get_speed_khz(), speed); break; case CLOCK_MODE_RCLK: - jtag_rclk_to_speed(rclk_fallback_speed_khz, &speed); + jtag_rclk_to_speed(rclk_fallback_speed_khz, speed); break; default: LOG_ERROR("BUG: unknown jtag clock mode"); - speed = 0; - break; + return ERROR_FAIL; } - return speed; + return ERROR_OK; } int jtag_get_speed_readable(int *khz) { - return jtag ? jtag->speed_div(jtag_get_speed(), khz) : ERROR_OK; + int jtag_speed_var = 0; + int retval = jtag_get_speed(&jtag_speed_var); + if (retval != ERROR_OK) + return retval; + return jtag ? jtag->speed_div(jtag_speed_var, khz) : ERROR_OK; } void jtag_set_verify(bool enable)