diff options
-rw-r--r-- | src/helper/startup.tcl | 9 | ||||
-rw-r--r-- | src/jtag/core.c | 117 | ||||
-rw-r--r-- | src/jtag/jtag.h | 9 | ||||
-rw-r--r-- | src/jtag/tcl.c | 35 |
4 files changed, 131 insertions, 39 deletions
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl index 9fb537d..14b2092 100644 --- a/src/helper/startup.tcl +++ b/src/helper/startup.tcl @@ -134,15 +134,6 @@ proc ocd_gdb_restart {target_num} { reset halt } -# If RCLK is not supported, use fallback_speed_khz -proc jtag_rclk {fallback_speed_khz} { - if {[catch {jtag_khz 0}]!=0} { - jtag_khz $fallback_speed_khz - } -} - -add_help_text jtag_rclk "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed" - proc ocd_process_reset { MODE } { # If this target must be halted... diff --git a/src/jtag/core.c b/src/jtag/core.c index 4e6e5b5..222bff1 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -101,8 +101,9 @@ static jtag_event_callback_t *jtag_event_callbacks; /* speed in kHz*/ static int speed_khz = 0; -/* flag if the kHz speed was defined */ -static bool hasKHz = false; +/* 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 int jtag_speed = 0; static struct jtag_interface_s *jtag = NULL; @@ -1140,16 +1141,34 @@ int jtag_interface_init(struct command_context_s *cmd_ctx) LOG_ERROR("JTAG interface has to be specified, see \"interface\" command"); return ERROR_JTAG_INVALID_INTERFACE; } - if (hasKHz) - { - jtag_interface->khz(jtag_get_speed_khz(), &jtag_speed); - hasKHz = false; - } + jtag = jtag_interface; if (jtag_interface->init() != ERROR_OK) + { + jtag = NULL; 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); + if (ERROR_OK != retval) + return retval; + + if (actual_khz) + { + if ((CLOCK_MODE_RCLK == clock_mode) + || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz)) + { + LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz" + , actual_khz); + } + else + LOG_INFO("clock speed %d kHz", actual_khz); + } + else + LOG_INFO("RCLK (adaptive clock speed)"); - jtag = jtag_interface; return ERROR_OK; } @@ -1255,20 +1274,15 @@ int jtag_init(struct command_context_s *cmd_ctx) return jtag_init_reset(cmd_ctx); } -void jtag_set_speed_khz(unsigned khz) -{ - speed_khz = khz; -} unsigned jtag_get_speed_khz(void) { return speed_khz; } -int jtag_config_khz(unsigned khz) -{ - LOG_DEBUG("handle jtag khz"); - jtag_set_speed_khz(khz); - int cur_speed = 0; +static int jtag_khz_to_speed(unsigned khz, int* speed) +{ + LOG_DEBUG("convert khz to interface specific speed value"); + speed_khz = khz; if (jtag != NULL) { LOG_DEBUG("have interface set up"); @@ -1276,33 +1290,84 @@ int jtag_config_khz(unsigned khz) int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1); if (ERROR_OK != retval) { - jtag_set_speed_khz(0); return retval; } - cur_speed = speed_div1; + *speed = speed_div1; } - return jtag_set_speed(cur_speed); + return ERROR_OK; } -int jtag_get_speed(void) +static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int* speed) { - return jtag_speed; + int retval = jtag_khz_to_speed(0, speed); + if ((ERROR_OK != retval) && fallback_speed_khz) + { + LOG_DEBUG("trying fallback speed..."); + retval = jtag_khz_to_speed(fallback_speed_khz, speed); + } + return retval; } -int jtag_set_speed(int speed) +static int jtag_set_speed(int speed) { jtag_speed = speed; /* this command can be called during CONFIG, * in which case jtag isn't initialized */ - hasKHz = !jtag; return jtag ? jtag->speed(speed) : ERROR_OK; } -int jtag_get_speed_readable(int *speed) +int jtag_config_speed(int speed) +{ + LOG_DEBUG("handle jtag speed"); + clock_mode = CLOCK_MODE_SPEED; + return jtag_set_speed(speed); +} + +int jtag_config_khz(unsigned khz) +{ + LOG_DEBUG("handle jtag khz"); + clock_mode = CLOCK_MODE_KHZ; + int speed = 0; + int retval = jtag_khz_to_speed(khz, &speed); + return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); +} + +int jtag_config_rclk(unsigned fallback_speed_khz) { - return jtag ? jtag->speed_div(jtag_get_speed(), speed) : ERROR_OK; + LOG_DEBUG("handle jtag rclk"); + clock_mode = CLOCK_MODE_RCLK; + rclk_fallback_speed_khz = fallback_speed_khz; + int speed = 0; + int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed); + return (ERROR_OK != retval) ? retval : jtag_set_speed(speed); } +int jtag_get_speed(void) +{ + int speed; + switch(clock_mode) + { + case CLOCK_MODE_SPEED: + speed = jtag_speed; + break; + case CLOCK_MODE_KHZ: + jtag_khz_to_speed(jtag_get_speed_khz(), &speed); + break; + case CLOCK_MODE_RCLK: + jtag_rclk_to_speed(rclk_fallback_speed_khz, &speed); + break; + default: + LOG_ERROR("BUG: unknown jtag clock mode"); + speed = 0; + break; + } + return speed; +} + +int jtag_get_speed_readable(int *khz) +{ + return jtag ? jtag->speed_div(jtag_get_speed(), khz) : ERROR_OK; +} void jtag_set_verify(bool enable) { diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 3c6c5ce..37a90b1 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -252,13 +252,16 @@ int jtag_get_speed_readable(int *speed); * @returns ERROR_OK during configuration or on success, or an error * code returned from the interface @c speed callback. */ -int jtag_set_speed(int speed); +int jtag_config_speed(int speed); /// Attempt to configure the interface for the specified KHz. int jtag_config_khz(unsigned khz); -/// Set the clock speed of the JTAG interface in KHz. -void jtag_set_speed_khz(unsigned speed); +/** + * Attempt to enable RTCK/RCLK. If that fails, fallback to the + * specified frequency. + */ +int jtag_config_rclk(unsigned fallback_speed_khz); /// Retreives the clock speed of the JTAG interface in KHz. unsigned jtag_get_speed_khz(void); diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index c81f161..ff16a56 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -55,6 +55,7 @@ static int handle_interface_list_command(struct command_context_s *cmd_ctx, static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -577,6 +578,8 @@ int jtag_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command, COMMAND_ANY, "set maximum jtag speed (if supported); " "parameter is maximum khz, or 0 for adaptive clocking (RTCK)."); + register_command(cmd_ctx, NULL, "jtag_rclk", handle_jtag_rclk_command, + COMMAND_ANY, "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed"); register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command, COMMAND_CONFIG, "(DEPRECATED) jtag_device <ir_length> <ir_expected> <ir_mask>"); register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command, @@ -955,7 +958,7 @@ static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cm int retval = parse_uint(args[0], &cur_speed); if (ERROR_OK != retval) return retval; - retval = jtag_set_speed(cur_speed); + retval = jtag_config_speed(cur_speed); } command_print(cmd_ctx, "jtag_speed: %d", jtag_get_speed()); @@ -993,6 +996,36 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, return retval; } +static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + int retval = ERROR_OK; + if (argc == 1) + { + unsigned khz = 0; + int retval = parse_uint(args[0], &khz); + if (ERROR_OK != retval) + return retval; + retval = jtag_config_rclk(khz); + if (ERROR_OK != retval) + return retval; + } + + int cur_khz = jtag_get_speed_khz(); + retval = jtag_get_speed_readable(&cur_khz); + if (ERROR_OK != retval) + return retval; + + if (cur_khz) + command_print(cmd_ctx, "RCLK not supported - fallback to %d kHz", cur_khz); + else + command_print(cmd_ctx, "RCLK - adaptive"); + + return retval; +} + static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { |