Perform small writes before sending OK.
To speed up downloads, OpenOCD sends gdb OK when a write is received, even before the write has actually occurred. The failure is then returned for the next write. That leads to the following confusing behavior: ``` (gdb) p/x *((int*)0xdeadbeef)=8675309 $2 = 0x845fed (gdb) p/x *((int*)0x80000000)=6874742 Cannot access memory at address 0x80000000 ``` While it's actually the first write that failed. This change hacks around this problem by not sending OK for small writes (len<8) until the write has actually occurred. This does not impact download speed, since during downloads (almost) all writes will have much larger length. Change-Id: I1f8b9bb19b0707487f840df6871e372e4ba228dd Signed-off-by: Tim Newsome <tim@sifive.com> Reviewed-on: http://openocd.zylin.com/3803 Tested-by: jenkins Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
parent
4b50872ffe
commit
19df456a79
|
@ -1473,6 +1473,10 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
/* Packets larger than fast_limit bytes will be acknowledged instantly on
|
||||||
|
* the assumption that we're in a download and it's important to go as fast
|
||||||
|
* as possible. */
|
||||||
|
uint32_t fast_limit = 8;
|
||||||
|
|
||||||
/* skip command character */
|
/* skip command character */
|
||||||
packet++;
|
packet++;
|
||||||
|
@ -1493,19 +1497,23 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
|
||||||
|
|
||||||
struct gdb_connection *gdb_connection = connection->priv;
|
struct gdb_connection *gdb_connection = connection->priv;
|
||||||
|
|
||||||
if (gdb_connection->mem_write_error) {
|
if (gdb_connection->mem_write_error)
|
||||||
retval = ERROR_FAIL;
|
retval = ERROR_FAIL;
|
||||||
|
|
||||||
|
if (retval == ERROR_OK) {
|
||||||
|
if (len >= fast_limit) {
|
||||||
|
/* By replying the packet *immediately* GDB will send us a new packet
|
||||||
|
* while we write the last one to the target.
|
||||||
|
* We only do this for larger writes, so that users who do something like:
|
||||||
|
* p *((int*)0xdeadbeef)=8675309
|
||||||
|
* will get immediate feedback that that write failed.
|
||||||
|
*/
|
||||||
|
gdb_put_packet(connection, "OK", 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retval = gdb_error(connection, retval);
|
||||||
/* now that we have reported the memory write error, we can clear the condition */
|
/* now that we have reported the memory write error, we can clear the condition */
|
||||||
gdb_connection->mem_write_error = false;
|
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);
|
|
||||||
else {
|
|
||||||
retval = gdb_error(connection, retval);
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1518,6 +1526,15 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
|
||||||
gdb_connection->mem_write_error = true;
|
gdb_connection->mem_write_error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len < fast_limit) {
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
gdb_error(connection, retval);
|
||||||
|
gdb_connection->mem_write_error = false;
|
||||||
|
} else {
|
||||||
|
gdb_put_packet(connection, "OK", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue