Merge pull request #957 from riscv/sbbusyerror
target/riscv: Handle sbbusyerror in read_memory_bus_v1
This commit is contained in:
commit
d5ea55cfca
|
@ -3171,6 +3171,8 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (info->bus_master_read_delay) {
|
if (info->bus_master_read_delay) {
|
||||||
|
LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay",
|
||||||
|
info->bus_master_read_delay);
|
||||||
jtag_add_runtest(info->bus_master_read_delay, TAP_IDLE);
|
jtag_add_runtest(info->bus_master_read_delay, TAP_IDLE);
|
||||||
if (jtag_execute_queue() != ERROR_OK) {
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
|
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
|
||||||
|
@ -3178,8 +3180,8 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First value has been read, and is waiting for us to issue a DMI read
|
/* First read has been started. Optimistically assume that it has
|
||||||
* to get it. */
|
* completed. */
|
||||||
|
|
||||||
static int sbdata[4] = {DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3};
|
static int sbdata[4] = {DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3};
|
||||||
uint32_t sbvalue[4] = {0};
|
uint32_t sbvalue[4] = {0};
|
||||||
|
@ -3198,7 +3200,19 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
}
|
}
|
||||||
keep_alive();
|
keep_alive();
|
||||||
dmi_status_t status = dmi_scan(target, NULL, &sbvalue[next_read_j],
|
dmi_status_t status = dmi_scan(target, NULL, &sbvalue[next_read_j],
|
||||||
DMI_OP_READ, sbdata[j], 0, false);
|
DMI_OP_READ, sbdata[j], 0, false);
|
||||||
|
/* By reading from sbdata0, we have just initiated another system bus read.
|
||||||
|
* If necessary add a delay so the read can finish. */
|
||||||
|
if (j == 0 && info->bus_master_read_delay) {
|
||||||
|
LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay",
|
||||||
|
info->bus_master_read_delay);
|
||||||
|
jtag_add_runtest(info->bus_master_read_delay, TAP_IDLE);
|
||||||
|
if (jtag_execute_queue() != ERROR_OK) {
|
||||||
|
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (status == DMI_STATUS_BUSY)
|
if (status == DMI_STATUS_BUSY)
|
||||||
increase_dmi_busy_delay(target);
|
increase_dmi_busy_delay(target);
|
||||||
else if (status == DMI_STATUS_SUCCESS)
|
else if (status == DMI_STATUS_SUCCESS)
|
||||||
|
@ -3261,16 +3275,32 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) {
|
if (get_field(sbcs_read, DM_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 (dm_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR) != ERROR_OK)
|
* Clear sbbusyerror, as well as readondata or readonaddr. */
|
||||||
|
if (dm_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
next_address = sb_read_address(target);
|
|
||||||
|
if (get_field(sbcs_read, DM_SBCS_SBERROR) == DM_SBCS_SBERROR_NONE) {
|
||||||
|
/* Read the address whose read was last completed. */
|
||||||
|
next_address = sb_read_address(target);
|
||||||
|
|
||||||
|
/* Read the value for the last address. It's
|
||||||
|
* sitting in the register for us, but we read it
|
||||||
|
* too early (sbbusyerror became set). */
|
||||||
|
target_addr_t current_address = next_address - (increment ? size : 0);
|
||||||
|
if (read_memory_bus_word(target, current_address, size,
|
||||||
|
buffer + current_address - address) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
|
info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
|
||||||
|
LOG_TARGET_DEBUG(target, "Increasing bus_master_read_delay to %d.",
|
||||||
|
info->bus_master_read_delay);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR);
|
unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR);
|
||||||
if (error == 0) {
|
if (error == DM_SBCS_SBERROR_NONE) {
|
||||||
next_address = end_address;
|
next_address = end_address;
|
||||||
} else {
|
} else {
|
||||||
/* Some error indicating the bus access failed, but not because of
|
/* Some error indicating the bus access failed, but not because of
|
||||||
|
|
Loading…
Reference in New Issue