Properly detect errors in SBA reads. (#392)
Also don't set/clear sbreadondata when only reading one word. Change-Id: Ia81834014895f1f4b552312ad0b60b3d3967a2c7debug-log-reg-failure
parent
239a515a9c
commit
7eaf60f1b5
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue