diff --git a/src/helper/log.c b/src/helper/log.c
index e9c1fa205d2a5aa5273a3b2fa445593aa6d5ee88..0a416244829452571c60fbf5cfbd96484717dd28 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 37490a8603d2af47bd4bc0cdbda785d785cb8e00..7a7c90cbc462678afe690aa3188074bac4f133f1 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 2d910a1ab0ee9bc5d794253046dca642f6ad29cb..ce0ee6cd231863a41fbbe973042d608a2860f4a3 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 589f626f0902f61a6f551cca298eeada31614b03..ea130ce3a52e42c06cfa4b69a937d0198a41b188 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)