From 94e75e0c06c4d683b33a03aee17b80c8a59bbd47 Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 18 Jul 2008 10:20:10 +0000 Subject: [PATCH] 1. GDB will print cryptic error messages if it is not fed keep-alive packets within the last 2000ms. To fix this, add keep_alive() if you are spending >1000ms in an algorithm thus holding up the server loop. target_call_timer_callbacks() invokes keep_alive(). 2. post_reset script is now executed at normal JTAG speed and not reset speed. 3. Resume is now synchronous again. Hopefully it will work this time. git-svn-id: svn://svn.berlios.de/openocd/trunk@826 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/helper/log.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/helper/log.h | 2 ++ src/server/server.c | 1 + src/target/target.c | 26 +++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/helper/log.c b/src/helper/log.c index e9c1fa205d..0a41624482 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -40,6 +40,9 @@ int debug_level = -1; static FILE* log_output; static log_callback_t *log_callbacks = NULL; +static long long last_time; +static long long current_time; + static long long start; static char *log_strings[5] = @@ -229,6 +232,8 @@ int log_init(struct command_context_s *cmd_ctx) log_output = stderr; } + start=last_time=timeval_ms(); + return ERROR_OK; } @@ -327,3 +332,43 @@ char *alloc_printf(const char *format, ...) va_end(ap); return string; } + +/* Code must return to the server loop before 1000ms has returned or invoke + * this function. + * + * The GDB connection will time out if it spends >2000ms and you'll get nasty + * error messages from GDB: + * + * Ignoring packet error, continuing... + * Reply contains invalid hex digit 116 + * + * While it is possible use "set remotetimeout" to more than the default 2000ms + * in GDB, OpenOCD guarantees that it sends keep-alive packages on the + * GDB protocol and it is a bug in OpenOCD not to either return to the server + * loop or invoke keep_alive() every 1000ms. + * + * This function will send a keep alive packet if >500ms has passed since last time + * it was invoked. + * + */ +void keep_alive() +{ + current_time=timeval_ms(); + if (current_time-last_time>1000) + { + LOG_WARNING("keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (%d)", current_time-last_time); + last_time=current_time; + } else if (current_time-last_time>500) + { + /* this will keep the GDB connection alive */ + LOG_USER_N("%s", ""); + last_time=current_time; + } +} + +/* reset keep alive timer without sending message */ +void kept_alive() +{ + current_time=timeval_ms(); + last_time=current_time; +} diff --git a/src/helper/log.h b/src/helper/log.h index 37490a8603..7a7c90cbc4 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -56,6 +56,8 @@ __attribute__ ((format (printf, 5, 6))); extern int log_register_commands(struct command_context_s *cmd_ctx); extern int log_init(struct command_context_s *cmd_ctx); extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output); +extern void keep_alive(); +extern void kept_alive(); typedef void (*log_callback_fn)(void *priv, const char *file, int line, const char *function, const char *string); diff --git a/src/server/server.c b/src/server/server.c index 2d910a1ab0..ce0ee6cd23 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -310,6 +310,7 @@ int server_loop(command_context_t *command_context) #endif openocd_sleep_prelude(); + kept_alive(); // Only while we're sleeping we'll let others run retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv); openocd_sleep_postlude(); diff --git a/src/target/target.c b/src/target/target.c index 589f626f09..ea130ce3a5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -266,6 +266,9 @@ int target_halt(struct target_s *target) int target_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution) { int retval; + int timeout_ms = 5000; + + enum target_state resume_state = debug_execution ? TARGET_DEBUG_RUNNING : TARGET_RUNNING; /* We can't poll until after examine */ if (!target->type->examined) @@ -277,6 +280,21 @@ int target_resume(struct target_s *target, int current, u32 address, int handle_ if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK) return retval; + /* wait for target to exit halted mode */ + target_poll(target); + + while (target->state != resume_state) + { + target_call_timer_callbacks(); + usleep(10000); + target_poll(target); + if ((timeout_ms -= 10) <= 0) + { + LOG_ERROR("timeout waiting for target resume"); + return ERROR_TARGET_TIMEOUT; + } + } + return retval; } @@ -407,6 +425,11 @@ int target_process_reset(struct command_context_s *cmd_ctx) return retval; } + /* post reset scripts can be quite long, increase speed now. If post + * reset scripts needs a different speed, they can set the speed to + * whatever they need. + */ + jtag->speed(jtag_speed_post_reset); LOG_DEBUG("Waiting for halted stated as approperiate"); @@ -464,7 +487,6 @@ int target_process_reset(struct command_context_s *cmd_ctx) } target_unregister_event_callback(target_init_handler, cmd_ctx); - jtag->speed(jtag_speed_post_reset); return retval; } @@ -738,6 +760,8 @@ static int target_call_timer_callbacks_check_time(int checktime) target_timer_callback_t *next_callback; struct timeval now; + keep_alive(); + gettimeofday(&now, NULL); while (callback) -- 2.30.2