Properly detect errors in SBA reads. (#392)

Also don't set/clear sbreadondata when only reading one word.

Change-Id: Ia81834014895f1f4b552312ad0b60b3d3967a2c7
debug-log-reg-failure
Tim Newsome 2019-07-26 11:08:35 -07:00 committed by GitHub
parent 239a515a9c
commit 7eaf60f1b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 19 deletions

View File

@ -2211,11 +2211,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
target_addr_t end_address = address + count * size; target_addr_t end_address = address + count * size;
while (next_address < end_address) { while (next_address < end_address) {
uint32_t sbcs = set_field(0, DMI_SBCS_SBREADONADDR, 1); uint32_t sbcs_write = set_field(0, DMI_SBCS_SBREADONADDR, 1);
sbcs |= sb_sbaccess(size); sbcs_write |= sb_sbaccess(size);
sbcs = set_field(sbcs, DMI_SBCS_SBAUTOINCREMENT, 1); sbcs_write = set_field(sbcs_write, DMI_SBCS_SBAUTOINCREMENT, 1);
sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, count > 1); if (count > 1)
if (dmi_write(target, DMI_SBCS, sbcs) != ERROR_OK) sbcs_write = set_field(sbcs_write, DMI_SBCS_SBREADONDATA, count > 1);
if (dmi_write(target, DMI_SBCS, sbcs_write) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
/* This address write will trigger the first read. */ /* This address write will trigger the first read. */
@ -2236,23 +2237,29 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_FAIL; return ERROR_FAIL;
} }
/* "Writes to sbcs while sbbusy is high result in undefined behavior. uint32_t sbcs_read = 0;
* A debugger must not write to sbcs until it reads sbbusy as 0." */ if (count > 1) {
if (read_sbcs_nonbusy(target, &sbcs) != ERROR_OK) /* "Writes to sbcs while sbbusy is high result in undefined behavior.
return ERROR_FAIL; * A debugger must not write to sbcs until it reads sbbusy as 0." */
if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
return ERROR_FAIL;
sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, 0); sbcs_write = set_field(sbcs_write, DMI_SBCS_SBREADONDATA, 0);
if (dmi_write(target, DMI_SBCS, sbcs) != ERROR_OK) if (dmi_write(target, DMI_SBCS, sbcs_write) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
if (read_memory_bus_word(target, address + (count - 1) * size, size, if (!get_field(sbcs_read, DMI_SBCS_SBERROR) &&
buffer + (count - 1) * size) != ERROR_OK) !get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
return ERROR_FAIL; if (read_memory_bus_word(target, address + (count - 1) * size, size,
buffer + (count - 1) * size) != ERROR_OK)
return ERROR_FAIL;
if (read_sbcs_nonbusy(target, &sbcs) != ERROR_OK) if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
if (get_field(sbcs, DMI_SBCS_SBBUSYERROR)) { if (get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
/* We read while the target was busy. Slow down and try again. */ /* We read while the target was busy. Slow down and try again. */
if (dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR) != ERROR_OK) if (dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -2261,7 +2268,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
continue; continue;
} }
unsigned error = get_field(sbcs, DMI_SBCS_SBERROR); unsigned error = get_field(sbcs_read, DMI_SBCS_SBERROR);
if (error == 0) { if (error == 0) {
next_address = end_address; next_address = end_address;
} else { } else {