aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegan Wachs <megan@sifive.com>2017-03-22 17:51:46 -0700
committerMegan Wachs <megan@sifive.com>2017-03-22 17:51:46 -0700
commitc61b3efe9a3eafadce256706fde826f55d6abcd6 (patch)
treeb68a54d18cf1158d5f35bf64cc3f6fcc9623710c
parent98420e377a946c825960a6d6104c209caa1faf6c (diff)
downloadriscv-openocd-c61b3efe9a3eafadce256706fde826f55d6abcd6.zip
riscv-openocd-c61b3efe9a3eafadce256706fde826f55d6abcd6.tar.gz
riscv-openocd-c61b3efe9a3eafadce256706fde826f55d6abcd6.tar.bz2
riscv: Retry failed memory reads
-rw-r--r--src/target/riscv/riscv-013.c140
1 files changed, 75 insertions, 65 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index e67d69a..1bd31f9 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1830,72 +1830,82 @@ static int read_memory(struct target *target, uint32_t address,
{
select_dmi(target);
- abstract_write_register(target, S0, xlen(target), address);
-
- program_t *program = program_new();
- switch (size) {
- case 1:
- program_add32(program, lb(S1, S0, 0));
- break;
- case 2:
- program_add32(program, lh(S1, S0, 0));
- break;
- case 4:
- program_add32(program, lw(S1, S0, 0));
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- program_add32(program, addi(S0, S0, size));
- program_add32(program, ebreak());
- write_program(target, program);
- program_delete(program);
-
- if (execute_abstract_command(target,
- AC_ACCESS_REGISTER_PREEXEC |
- abstract_register_size(xlen(target)) | reg_number_to_no(S1)) != ERROR_OK) {
- return ERROR_FAIL;
- }
- dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
- dmi_write(target, DMI_ABSTRACTAUTO, 0x1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
-
- uint32_t abstractcs;
- for (uint32_t i = 0; i < count; i++) {
- uint32_t value = dmi_read(target, DMI_DATA0);
- switch (size) {
- case 1:
- buffer[i] = value;
- break;
- case 2:
- buffer[2*i] = value;
- buffer[2*i+1] = value >> 8;
- break;
- case 4:
- buffer[4*i] = value;
- buffer[4*i+1] = value >> 8;
- buffer[4*i+2] = value >> 16;
- buffer[4*i+3] = value >> 24;
- break;
- default:
- return ERROR_FAIL;
- }
- // The above dmi_read started an abstract command. If we just
- // immediately read here, we'll probably get a busy error. Wait for idle first,
- // or otherwise take ac_command_busy into account (this defeats the purpose
- // of autoexec, this whole code needs optimization).
- if (wait_for_idle(target, &abstractcs) != ERROR_OK) {
- return ERROR_FAIL;
- }
+ while (1) {
+ abstract_write_register(target, S0, xlen(target), address);
+
+ program_t *program = program_new();
+ switch (size) {
+ case 1:
+ program_add32(program, lb(S1, S0, 0));
+ break;
+ case 2:
+ program_add32(program, lh(S1, S0, 0));
+ break;
+ case 4:
+ program_add32(program, lw(S1, S0, 0));
+ break;
+ default:
+ LOG_ERROR("Unsupported size: %d", size);
+ return ERROR_FAIL;
+ }
+ program_add32(program, addi(S0, S0, size));
+ program_add32(program, ebreak());
+ write_program(target, program);
+ program_delete(program);
+
+ if (execute_abstract_command(target,
+ AC_ACCESS_REGISTER_PREEXEC |
+ abstract_register_size(xlen(target)) | reg_number_to_no(S1)) != ERROR_OK) {
+ return ERROR_FAIL;
+ }
+ dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
+ dmi_write(target, DMI_ABSTRACTAUTO, 0x1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
+
+ uint32_t abstractcs;
+ for (uint32_t i = 0; i < count; i++) {
+ uint32_t value = dmi_read(target, DMI_DATA0);
+ switch (size) {
+ case 1:
+ buffer[i] = value;
+ break;
+ case 2:
+ buffer[2*i] = value;
+ buffer[2*i+1] = value >> 8;
+ break;
+ case 4:
+ buffer[4*i] = value;
+ buffer[4*i+1] = value >> 8;
+ buffer[4*i+2] = value >> 16;
+ buffer[4*i+3] = value >> 24;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ // The above dmi_read started an abstract command. If we just
+ // immediately read here, we'll probably get a busy error. Wait for idle first,
+ // or otherwise take ac_command_busy into account (this defeats the purpose
+ // of autoexec, this whole code needs optimization).
+ if (wait_for_idle(target, &abstractcs) != ERROR_OK) {
+ return ERROR_FAIL;
+ }
+ }
+ dmi_write(target, DMI_ABSTRACTAUTO, 0);
+ dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
+ abstractcs = dmi_read(target, DMI_ABSTRACTCS);
+ unsigned cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
+ if (cmderr == CMDERR_BUSY) {
+ dmi_write(target, DMI_ABSTRACTCS, 0);
+ increase_ac_busy_delay(target);
+ } else if (cmderr) {
+ LOG_ERROR("cmderr=%d", get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
+ return ERROR_FAIL;
+ } else {
+ return ERROR_OK;
+ }
}
- dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
- abstractcs = dmi_read(target, DMI_ABSTRACTCS);
- if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
- // TODO: retry with more delay?
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
+ // Should not get here.
+ assert(0);
+ return ERROR_OK;
}
/**