Compare commits

...

3 Commits

Author SHA1 Message Date
Tim Newsome 06c596e19f Rename ERROR_BUSY to ERROR_TARGET_BUSY.
ERROR_BUSY is already defined somewhere in Windows land.

Change-Id: I91e6f5b6448ce38a2a38598b7261a40bd2488ec5
2019-12-18 14:19:18 -08:00
Tim Newsome 8a9df230ad Fix style.
Change-Id: I45a9397e512d074a7c33d90154ff2e1cbee16136
2019-12-18 14:11:20 -08:00
Tim Newsome 4fa9f61739 Deal with a case where DMI read returns busy.
This was exposed by the latest change, which modifies the number of
scans enough that this problem is now exposed by the testsuite.

This particular failure could happen in more cases, but I don't have the
time to address everything right now. In the real world they'll be very
rare. It only shows up in the test because it intentionally resets the
learned delays while a memory access is happening..

Change-Id: Ia865eb76ed630c3d836131a065ec2dad0657c9b4
2019-12-18 14:02:32 -08:00
2 changed files with 45 additions and 19 deletions

View File

@ -151,6 +151,7 @@ extern int debug_level;
#define ERROR_WAIT (-5)
/* ERROR_TIMEOUT is already taken by winerror.h. */
#define ERROR_TIMEOUT_REACHED (-6)
#define ERROR_TARGET_BUSY (-7)
#endif /* OPENOCD_HELPER_LOG_H */

View File

@ -606,6 +606,12 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
false);
if (status == DMI_STATUS_BUSY) {
increase_dmi_busy_delay(target);
if (dmi_op == DMI_OP_READ) {
/* The scan where we should have gotten the read value
* returned busy. It's anybody's guess whether the read
* actually happened or not. */
return ERROR_TARGET_BUSY;
}
} else if (status == DMI_STATUS_SUCCESS) {
break;
} else {
@ -2060,25 +2066,29 @@ static int read_memory_bus_word(struct target *target, target_addr_t address,
{
uint32_t value;
if (size > 12) {
if (dmi_read(target, &value, DMI_SBDATA3) != ERROR_OK)
return ERROR_FAIL;
int result = dmi_read(target, &value, DMI_SBDATA3);
if (result != ERROR_OK)
return result;
write_to_buf(buffer + 12, value, 4);
log_memory_access(address + 12, value, 4, true);
}
if (size > 8) {
if (dmi_read(target, &value, DMI_SBDATA2) != ERROR_OK)
return ERROR_FAIL;
int result = dmi_read(target, &value, DMI_SBDATA2);
if (result != ERROR_OK)
return result;
write_to_buf(buffer + 8, value, 4);
log_memory_access(address + 8, value, 4, true);
}
if (size > 4) {
if (dmi_read(target, &value, DMI_SBDATA1) != ERROR_OK)
return ERROR_FAIL;
int result = dmi_read(target, &value, DMI_SBDATA1);
if (result != ERROR_OK)
return result;
write_to_buf(buffer + 4, value, 4);
log_memory_access(address + 4, value, 4, true);
}
if (dmi_read(target, &value, DMI_SBDATA0) != ERROR_OK)
return ERROR_FAIL;
int result = dmi_read(target, &value, DMI_SBDATA0);
if (result != ERROR_OK)
return result;
write_to_buf(buffer, value, MIN(size, 4));
log_memory_access(address, value, MIN(size, 4), true);
return ERROR_OK;
@ -2296,10 +2306,19 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
}
}
for (uint32_t i = (next_address - address) / size; i < count - 1; i++) {
if (read_memory_bus_word(target, address + i * size, size,
buffer + i * size) != ERROR_OK)
return ERROR_FAIL;
bool busy = false;
for (uint32_t i = (next_address - address) / size;
i < (end_address - address) / size - 1;
i++) {
int result = read_memory_bus_word(target, address + i * size, size,
buffer + i * size);
if (result == ERROR_TARGET_BUSY) {
busy = true;
break;
} else if (result != ERROR_OK) {
return result;
}
next_address += size;
}
uint32_t sbcs_read = 0;
@ -2314,11 +2333,14 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_FAIL;
}
if (!get_field(sbcs_read, DMI_SBCS_SBERROR) &&
if (!busy && !get_field(sbcs_read, DMI_SBCS_SBERROR) &&
!get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
if (read_memory_bus_word(target, address + (count - 1) * size, size,
buffer + (count - 1) * size) != ERROR_OK)
return ERROR_FAIL;
int result = read_memory_bus_word(target, address + (count - 1) * size, size,
buffer + (count - 1) * size);
if (result == ERROR_TARGET_BUSY)
busy = true;
else if (result != ERROR_OK)
return result;
if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
return ERROR_FAIL;
@ -2326,15 +2348,18 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
if (get_field(sbcs_read, DMI_SBCS_SBBUSYERROR)) {
/* We read while the target was busy. Slow down and try again. */
if (dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR) != ERROR_OK)
return ERROR_FAIL;
if (get_field(sbcs_read, DMI_SBCS_SBBUSYERROR))
if (dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR) != ERROR_OK)
return ERROR_FAIL;
next_address = sb_read_address(target);
info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
continue;
}
unsigned error = get_field(sbcs_read, DMI_SBCS_SBERROR);
if (error == 0) {
if (busy) {
/* Nothing to do. next_address was already updated in the loop. */
} else if (error == 0) {
next_address = end_address;
} else {
/* Some error indicating the bus access failed, but not because of