diff options
author | Øyvind Harboe <oyvind.harboe@zylin.com> | 2010-03-16 14:45:07 +0100 |
---|---|---|
committer | Øyvind Harboe <oyvind.harboe@zylin.com> | 2010-03-17 07:40:00 +0100 |
commit | 051e2c99ab8111f6bffdb412b40ceef333530ae6 (patch) | |
tree | 6fd42f5ea240924cc1f8f7939186e6435db145c9 /src/server | |
parent | 7e447043cd7967bd9b8976d829d5cb79bf359d3c (diff) | |
download | openocd+libswd-051e2c99ab8111f6bffdb412b40ceef333530ae6.tar.gz openocd+libswd-051e2c99ab8111f6bffdb412b40ceef333530ae6.tar.bz2 openocd+libswd-051e2c99ab8111f6bffdb412b40ceef333530ae6.tar.xz openocd+libswd-051e2c99ab8111f6bffdb412b40ceef333530ae6.zip |
gdb_server: improved gdb load performance
by ack'ing memory writes immediately and reporting either
at next memory write or stepi/continue time. GDB will then
send off a new packet that is ready by the time the previous
packet has been written to target memory.
On faster adapters this can be as much as 10% improvement.
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/gdb_server.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 17ca4398..f46980e1 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2,7 +2,7 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007-2009 Øyvind Harboe * + * Copyright (C) 2007-2010 Øyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2008 by Spencer Oliver * @@ -61,7 +61,12 @@ struct gdb_connection bool sync; /* set flag to true if you want the next stepi to return immediately. allowing GDB to pick up a fresh set of register values from the target without modifying the target state. */ - + /* We delay reporting memory write errors until next step/continue or memory + * write. This improves performance of gdb load significantly as the GDB packet + * can be replied immediately and a new GDB packet will be ready without delay + * (ca. 10% or so...). + */ + bool mem_write_error; }; @@ -821,6 +826,7 @@ static int gdb_new_connection(struct connection *connection) gdb_connection->busy = 0; gdb_connection->noack_mode = 0; gdb_connection->sync = true; + gdb_connection->mem_write_error = false; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); @@ -1361,7 +1367,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, uint32_t addr = 0; uint32_t len = 0; - int retval; + int retval = ERROR_OK; /* skip command character */ packet++; @@ -1382,14 +1388,18 @@ static int gdb_write_memory_binary_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - retval = ERROR_OK; - if (len) - { - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + struct gdb_connection *gdb_connection = connection->priv; - retval = target_write_buffer(target, addr, len, (uint8_t*)separator); + if (gdb_connection->mem_write_error) + { + retval = ERROR_FAIL; + /* now that we have reported the memory write error, we can clear the condition */ + gdb_connection->mem_write_error = false; } + /* By replying the packet *immediately* GDB will send us a new packet + * while we write the last one to the target. + */ if (retval == ERROR_OK) { gdb_put_packet(connection, "OK", 2); @@ -1400,6 +1410,17 @@ static int gdb_write_memory_binary_packet(struct connection *connection, return retval; } + if (len) + { + LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + + retval = target_write_buffer(target, addr, len, (uint8_t*)separator); + if (retval != ERROR_OK) + { + gdb_connection->mem_write_error = true; + } + } + return ERROR_OK; } @@ -2211,6 +2232,14 @@ static int gdb_input_inner(struct connection *connection) struct gdb_connection *gdb_con = connection->priv; log_add_callback(gdb_log_callback, connection); + if (gdb_con->mem_write_error) + { + LOG_ERROR("Memory write failure!"); + + /* now that we have reported the memory write error, we can clear the condition */ + gdb_con->mem_write_error = false; + } + bool nostep = false; bool already_running = false; if (target->state == TARGET_RUNNING) |