Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

target/riscv: Handle sbbusyerror in read_memory_bus_v1 #957

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -3168,15 +3168,17 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_FAIL;

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);
if (jtag_execute_queue() != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
return ERROR_FAIL;
}
}

/* First value has been read, and is waiting for us to issue a DMI read
* to get it. */
/* First read has been started. Optimistically assume that it has
* completed. */

static int sbdata[4] = {DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3};
uint32_t sbvalue[4] = {0};
Expand All @@ -3195,7 +3197,19 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
}
keep_alive();
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) {
JanMatCodasip marked this conversation as resolved.
Show resolved Hide resolved
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)
increase_dmi_busy_delay(target);
else if (status == DMI_STATUS_SUCCESS)
Expand Down Expand Up @@ -3258,16 +3272,32 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
}

if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) {
/* 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)
/* We read while the target was busy. Slow down and try again.
* Clear sbbusyerror, as well as readondata or readonaddr. */
if (dm_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR) != ERROR_OK)
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;
LOG_TARGET_DEBUG(target, "Increasing bus_master_read_delay to %d.",
info->bus_master_read_delay);
continue;
}

unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR);
if (error == 0) {
if (error == DM_SBCS_SBERROR_NONE) {
next_address = end_address;
} else {
/* Some error indicating the bus access failed, but not because of
Expand Down
Loading