aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Gosvig <40368726+cgsfv@users.noreply.github.com>2018-10-19 23:07:22 +0200
committerGitHub <noreply@github.com>2018-10-19 23:07:22 +0200
commit983a07be643cbceb5a83672fa62f5ed1c9026797 (patch)
treeb5c3f2b01dd190a7f9b7ac02817076e4672a6249
parent60c37e1679615428577fe1b0b785327e1d48b4fa (diff)
parent9703c00b2510b12cc1fa195218ba2a0800d28084 (diff)
downloadriscv-openocd-983a07be643cbceb5a83672fa62f5ed1c9026797.zip
riscv-openocd-983a07be643cbceb5a83672fa62f5ed1c9026797.tar.gz
riscv-openocd-983a07be643cbceb5a83672fa62f5ed1c9026797.tar.bz2
Merge pull request #308 from riscv/eclipse_memory_read
Fixing Eclipse block memory read
-rw-r--r--src/server/gdb_server.c2
-rw-r--r--src/target/riscv/riscv-013.c125
2 files changed, 82 insertions, 45 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 58df51a..3ea3242 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -390,7 +390,7 @@ static int gdb_put_packet_inner(struct connection *connection,
break;
}
- LOG_WARNING("Discard unexpected char %c", reply);
+ LOG_DEBUG("Discard unexpected char %c", reply);
}
#endif
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 11a7c3c..8919d4a 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -2040,53 +2040,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
* Read the requested memory, taking care to execute every read exactly once,
* even if cmderr=busy is encountered.
*/
-static int read_memory_progbuf(struct target *target, target_addr_t address,
+static int read_memory_progbuf_inner(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
RISCV013_INFO(info);
int result = ERROR_OK;
- LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
- size, address);
-
- select_dmi(target);
-
- /* s0 holds the next address to write to
- * s1 holds the next data value to write
- */
- uint64_t s0, s1;
- if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
- return ERROR_FAIL;
- if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
- return ERROR_FAIL;
-
- if (execute_fence(target) != ERROR_OK)
- return ERROR_FAIL;
-
- /* Write the program (load, increment) */
- struct riscv_program program;
- riscv_program_init(&program, target);
- switch (size) {
- case 1:
- riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
- break;
- case 2:
- riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
- break;
- case 4:
- riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
-
- if (riscv_program_ebreak(&program) != ERROR_OK)
- return ERROR_FAIL;
- riscv_program_write(&program);
-
/* Write address to S0, and execute buffer. */
result = register_write_direct(target, GDB_REGNO_S0, address);
if (result != ERROR_OK)
@@ -2214,7 +2174,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
break;
default:
- LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
+ LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
riscv013_clear_abstract_error(target);
riscv_batch_free(batch);
result = ERROR_FAIL;
@@ -2272,13 +2232,90 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
write_to_buf(buffer + receive_addr - address, value, size);
log_memory_access(receive_addr, value, size, true);
- riscv_set_register(target, GDB_REGNO_S0, s0);
- riscv_set_register(target, GDB_REGNO_S1, s1);
return ERROR_OK;
error:
dmi_write(target, DMI_ABSTRACTAUTO, 0);
+ return result;
+}
+
+/**
+ * Read the requested memory, silently handling memory access errors.
+ */
+static int read_memory_progbuf(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer)
+{
+ int result = ERROR_OK;
+
+ LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
+ size, address);
+
+ select_dmi(target);
+
+ memset(buffer, 0, count*size);
+
+ /* s0 holds the next address to write to
+ * s1 holds the next data value to write
+ */
+ uint64_t s0, s1;
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ return ERROR_FAIL;
+ if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (execute_fence(target) != ERROR_OK)
+ return ERROR_FAIL;
+
+ /* Write the program (load, increment) */
+ struct riscv_program program;
+ riscv_program_init(&program, target);
+ switch (size) {
+ case 1:
+ riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
+ break;
+ case 2:
+ riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
+ break;
+ case 4:
+ riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
+ break;
+ default:
+ LOG_ERROR("Unsupported size: %d", size);
+ return ERROR_FAIL;
+ }
+ riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
+
+ if (riscv_program_ebreak(&program) != ERROR_OK)
+ return ERROR_FAIL;
+ riscv_program_write(&program);
+
+ result = read_memory_progbuf_inner(target, address, size, count, buffer);
+
+ if (result != ERROR_OK) {
+ /* The full read did not succeed, so we will try to read each word individually. */
+ /* This will not be fast, but reading outside actual memory is a special case anyway. */
+ /* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */
+ target_addr_t address_i = address;
+ uint32_t size_i = size;
+ uint32_t count_i = 1;
+ uint8_t *buffer_i = buffer;
+
+ for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) {
+ result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i);
+
+ /* The read of a single word failed, so we will just return 0 for that instead */
+ if (result != ERROR_OK) {
+ LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR,
+ size_i, address_i);
+
+ uint64_t value_i = 0;
+ write_to_buf(buffer_i, value_i, size_i);
+ }
+ }
+ result = ERROR_OK;
+ }
+
riscv_set_register(target, GDB_REGNO_S0, s0);
riscv_set_register(target, GDB_REGNO_S1, s1);
return result;