aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/riscv/batch.c16
-rw-r--r--src/target/riscv/batch.h71
-rw-r--r--src/target/riscv/riscv-013.c190
3 files changed, 167 insertions, 110 deletions
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 4115a37..bb1070a 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -29,7 +29,7 @@ struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans)
out->allocated_scans = scans;
out->last_scan = RISCV_SCAN_TYPE_INVALID;
out->was_run = false;
- out->used_delay = 0;
+ out->last_scan_delay = 0;
out->data_out = NULL;
out->data_in = NULL;
@@ -109,7 +109,7 @@ static bool riscv_batch_was_scan_busy(const struct riscv_batch *batch,
}
static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_idx,
- struct riscv_scan_delays delays)
+ const struct riscv_scan_delays *delays)
{
if (!batch->was_run)
return;
@@ -121,9 +121,9 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_
? batch->delay_classes[start_idx - 1]
: RISCV_DELAY_BASE;
const unsigned int new_delay = riscv_scan_get_delay(delays, delay_class);
- if (new_delay <= batch->used_delay)
+ if (new_delay <= batch->last_scan_delay)
return;
- const unsigned int idle_change = new_delay - batch->used_delay;
+ const unsigned int idle_change = new_delay - batch->last_scan_delay;
LOG_TARGET_DEBUG(batch->target, "Adding %u idle cycles before the batch.",
idle_change);
assert(idle_change <= INT_MAX);
@@ -131,19 +131,19 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_
}
static int get_delay(const struct riscv_batch *batch, size_t scan_idx,
- struct riscv_scan_delays delays)
+ const struct riscv_scan_delays *delays)
{
assert(batch);
assert(scan_idx < batch->used_scans);
const enum riscv_scan_delay_class delay_class =
batch->delay_classes[scan_idx];
- const unsigned int delay = riscv_scan_get_delay(delays, delay_class);
+ const unsigned int delay = riscv_scan_get_delay(delays, delay_class);
assert(delay <= INT_MAX);
return delay;
}
int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
- struct riscv_scan_delays delays, bool resets_delays,
+ const struct riscv_scan_delays *delays, bool resets_delays,
size_t reset_delays_after)
{
assert(batch->used_scans);
@@ -195,7 +195,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
}
batch->was_run = true;
- batch->used_delay = get_delay(batch, batch->used_scans - 1, delays);
+ batch->last_scan_delay = get_delay(batch, batch->used_scans - 1, delays);
return ERROR_OK;
}
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 03947aa..327406c 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -25,40 +25,66 @@ enum riscv_scan_delay_class {
/* Delay for System Bus read operation: */
RISCV_DELAY_SYSBUS_READ,
/* Delay for System Bus write operation: */
- RISCV_DELAY_SYSBUS_WRITE,
+ RISCV_DELAY_SYSBUS_WRITE
};
+static inline const char *
+riscv_scan_delay_class_name(enum riscv_scan_delay_class delay_class)
+{
+ switch (delay_class) {
+ case RISCV_DELAY_BASE:
+ return "DM access";
+ case RISCV_DELAY_ABSTRACT_COMMAND:
+ return "Abstract Command";
+ case RISCV_DELAY_SYSBUS_READ:
+ return "System Bus read";
+ case RISCV_DELAY_SYSBUS_WRITE:
+ return "System Bus write";
+ }
+ assert(0);
+ return NULL;
+}
+
+/* The scan delay values are passed to "jtag_add_runtest()", which accepts an
+ * "int". Therefore, the passed value should be no greater than "INT_MAX".
+ *
+ * Since the resulting delay value can be a sum of two individual delays,
+ * individual delays are limited to "INT_MAX / 2" to prevent overflow of the
+ * final sum.
+ */
+#define RISCV_SCAN_DELAY_MAX (INT_MAX / 2)
+
struct riscv_scan_delays {
- /* The purpose of these delays is to be passed to "jtag_add_runtest()",
- * which accepts an "int".
- * Therefore, they should be no greater then "INT_MAX".
- */
unsigned int base_delay;
unsigned int ac_delay;
unsigned int sb_read_delay;
unsigned int sb_write_delay;
};
-static inline unsigned int riscv_scan_get_delay(struct riscv_scan_delays delays,
+static inline unsigned int
+riscv_scan_get_delay(const struct riscv_scan_delays *delays,
enum riscv_scan_delay_class delay_class)
{
switch (delay_class) {
case RISCV_DELAY_BASE:
- return delays.base_delay;
+ return delays->base_delay;
case RISCV_DELAY_ABSTRACT_COMMAND:
- return delays.ac_delay;
+ return delays->base_delay + delays->ac_delay;
case RISCV_DELAY_SYSBUS_READ:
- return delays.sb_read_delay;
+ return delays->base_delay + delays->sb_read_delay;
case RISCV_DELAY_SYSBUS_WRITE:
- return delays.sb_write_delay;
+ return delays->base_delay + delays->sb_write_delay;
}
+ assert(0);
return 0;
}
static inline void riscv_scan_set_delay(struct riscv_scan_delays *delays,
enum riscv_scan_delay_class delay_class, unsigned int delay)
{
- assert(delay <= INT_MAX);
+ assert(delay <= RISCV_SCAN_DELAY_MAX);
+ LOG_DEBUG("%s delay is set to %u.",
+ riscv_scan_delay_class_name(delay_class), delay);
switch (delay_class) {
case RISCV_DELAY_BASE:
delays->base_delay = delay;
@@ -73,6 +99,25 @@ static inline void riscv_scan_set_delay(struct riscv_scan_delays *delays,
delays->sb_write_delay = delay;
return;
}
+ assert(0);
+}
+
+static inline int riscv_scan_increase_delay(struct riscv_scan_delays *delays,
+ enum riscv_scan_delay_class delay_class)
+{
+ const unsigned int delay = riscv_scan_get_delay(delays, delay_class);
+ const unsigned int delay_step = delay / 10 + 1;
+ if (delay > RISCV_SCAN_DELAY_MAX - delay_step) {
+ /* It's not clear if this issue actually occurs in real
+ * use-cases, so stick with a simple solution until the
+ * first bug report.
+ */
+ LOG_ERROR("Delay for %s (%d) is not increased anymore (maximum was reached).",
+ riscv_scan_delay_class_name(delay_class), delay);
+ return ERROR_FAIL;
+ }
+ riscv_scan_set_delay(delays, delay_class, delay + delay_step);
+ return ERROR_OK;
}
/* A batch of multiple JTAG scans, which are grouped together to avoid the
@@ -113,7 +158,7 @@ struct riscv_batch {
/* Number of RTI cycles used by the last scan on the last run.
* Only valid when `was_run` is set.
*/
- unsigned int used_delay;
+ unsigned int last_scan_delay;
};
/* Allocates (or frees) a new scan set. "scans" is the maximum number of JTAG
@@ -138,7 +183,7 @@ bool riscv_batch_full(struct riscv_batch *batch);
* OpenOCD that are based on batches.
*/
int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
- struct riscv_scan_delays delays, bool resets_delays,
+ const struct riscv_scan_delays *delays, bool resets_delays,
size_t reset_delays_after);
/* Get the number of scans successfully executed form this batch. */
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 8d46a86..49c328e 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -169,21 +169,12 @@ typedef struct {
* access. */
unsigned int dtmcs_idle;
- /* This value is incremented every time a dbus access comes back as "busy".
- * It's used to determine how many run-test/idle cycles to feed the target
- * in between accesses. */
- unsigned int dmi_busy_delay;
-
- /* Number of run-test/idle cycles to add between consecutive bus master
- * reads/writes respectively. */
- unsigned int bus_master_write_delay, bus_master_read_delay;
-
- /* This value is increased every time we tried to execute two commands
- * consecutively, and the second one failed because the previous hadn't
- * completed yet. It's used to add extra run-test/idle cycles after
- * starting a command, so we don't have to waste time checking for busy to
- * go low. */
- unsigned int ac_busy_delay;
+ /* This structure is used to determine how many run-test/idle to use after
+ * an access of corresponding "riscv_scan_delay_class".
+ * Values are incremented every time an access results in a busy
+ * response.
+ */
+ struct riscv_scan_delays learned_delays;
bool abstract_read_csr_supported;
bool abstract_write_csr_supported;
@@ -478,15 +469,25 @@ static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr
return ERROR_OK;
}
-static void increase_dmi_busy_delay(struct target *target)
+static int increase_dmi_busy_delay(struct target *target)
{
- riscv013_info_t *info = get_info(target);
- info->dmi_busy_delay += info->dmi_busy_delay / 10 + 1;
- LOG_TARGET_DEBUG(target, "dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d",
- info->dtmcs_idle, info->dmi_busy_delay,
- info->ac_busy_delay);
+ RISCV013_INFO(info);
+
+ int res = dtmcontrol_scan(target, DTM_DTMCS_DMIRESET,
+ NULL /* discard result */);
+ if (res != ERROR_OK)
+ return res;
- dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
+ res = riscv_scan_increase_delay(&info->learned_delays,
+ RISCV_DELAY_BASE);
+ return res;
+}
+
+static void reset_learned_delays(struct target *target)
+{
+ RISCV013_INFO(info);
+ assert(info);
+ memset(&info->learned_delays, 0, sizeof(info->learned_delays));
}
static void decrement_reset_delays_counter(struct target *target, size_t finished_scans)
@@ -503,9 +504,7 @@ static void decrement_reset_delays_counter(struct target *target, size_t finishe
r->reset_delays_wait = -1;
LOG_TARGET_DEBUG(target,
"resetting learned delays (reset_delays_wait counter expired)");
- RISCV013_INFO(info);
- info->dmi_busy_delay = 0;
- info->ac_busy_delay = 0;
+ reset_learned_delays(target);
}
/**
* exec: If this is set, assume the scan results in an execution, so more
@@ -554,9 +553,9 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
}
- int idle_count = info->dmi_busy_delay;
- if (exec)
- idle_count += info->ac_busy_delay;
+ int idle_count = exec
+ ? riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_ABSTRACT_COMMAND)
+ : riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_BASE);
if (idle_count)
jtag_add_runtest(idle_count, TAP_IDLE);
@@ -635,7 +634,9 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
status = dmi_scan(target, NULL, NULL, op, address, data_out,
exec);
if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
+ int result = increase_dmi_busy_delay(target);
+ if (result != ERROR_OK)
+ return result;
if (dmi_busy_encountered)
*dmi_busy_encountered = true;
} else if (status == DMI_STATUS_SUCCESS) {
@@ -661,7 +662,9 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
status = dmi_scan(target, NULL, data_in, DMI_OP_NOP, address, 0,
false);
if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
+ int result = increase_dmi_busy_delay(target);
+ if (result != ERROR_OK)
+ return result;
if (dmi_busy_encountered)
*dmi_busy_encountered = true;
} else if (status == DMI_STATUS_SUCCESS) {
@@ -837,13 +840,11 @@ static int dmstatus_read(struct target *target, uint32_t *dmstatus,
return result;
}
-static void increase_ac_busy_delay(struct target *target)
+static int increase_ac_busy_delay(struct target *target)
{
riscv013_info_t *info = get_info(target);
- info->ac_busy_delay += info->ac_busy_delay / 10 + 1;
- LOG_TARGET_DEBUG(target, "dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d",
- info->dtmcs_idle, info->dmi_busy_delay,
- info->ac_busy_delay);
+ return riscv_scan_increase_delay(&info->learned_delays,
+ RISCV_DELAY_ABSTRACT_COMMAND);
}
static uint32_t __attribute__((unused)) abstract_register_size(unsigned width)
@@ -911,13 +912,13 @@ static int dm013_select_target(struct target *target)
return dm013_select_hart(target, info->index);
}
-#define EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE 2
+#define ABSTRACT_COMMAND_BATCH_SIZE 2
static size_t abstract_cmd_fill_batch(struct riscv_batch *batch,
uint32_t command)
{
assert(riscv_batch_available_scans(batch)
- >= EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE);
+ >= ABSTRACT_COMMAND_BATCH_SIZE);
riscv_batch_add_dm_write(batch, DM_COMMAND, command, /* read_back */ true,
RISCV_DELAY_ABSTRACT_COMMAND);
return riscv_batch_add_dm_read(batch, DM_ABSTRACTCS, RISCV_DELAY_BASE);
@@ -935,7 +936,9 @@ static int abstract_cmd_batch_check_and_clear_cmderr(struct target *target,
res = wait_for_idle(target, &abstractcs);
if (res != ERROR_OK)
goto clear_cmderr;
- increase_ac_busy_delay(target);
+ res = increase_ac_busy_delay(target);
+ if (res != ERROR_OK)
+ goto clear_cmderr;
}
*cmderr = get_field32(abstractcs, DM_ABSTRACTCS_CMDERR);
if (*cmderr == CMDERR_NONE)
@@ -975,7 +978,7 @@ static int execute_abstract_command(struct target *target, uint32_t command,
return ERROR_FAIL;
struct riscv_batch *batch = riscv_batch_alloc(target,
- EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE);
+ ABSTRACT_COMMAND_BATCH_SIZE);
const size_t abstractcs_read_key = abstract_cmd_fill_batch(batch, command);
/* Abstract commands are executed while running the batch. */
@@ -1203,7 +1206,7 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
assert(size_bits % 32 == 0);
const unsigned int size_in_words = size_bits / 32;
const unsigned int batch_size = size_in_words
- + EXECUTE_ABSTRACT_COMMAND_BATCH_SIZE;
+ + ABSTRACT_COMMAND_BATCH_SIZE;
struct riscv_batch * const batch = riscv_batch_alloc(target, batch_size);
abstract_data_write_fill_batch(batch, value, /*index*/ 0, size_bits);
@@ -2757,29 +2760,13 @@ static int sb_write_address(struct target *target, target_addr_t address,
(uint32_t)address, false, ensure_success);
}
-/* TODO: store delays in "struct riscv_scan_delays" and remove this function. */
-struct riscv_scan_delays get_scan_delays(struct target *target)
-{
- RISCV013_INFO(info);
- assert(info);
- struct riscv_scan_delays delays;
- riscv_scan_set_delay(&delays, RISCV_DELAY_BASE, info->dmi_busy_delay);
- riscv_scan_set_delay(&delays, RISCV_DELAY_ABSTRACT_COMMAND, info->dmi_busy_delay +
- info->ac_busy_delay);
- riscv_scan_set_delay(&delays, RISCV_DELAY_SYSBUS_READ, info->dmi_busy_delay +
- info->bus_master_read_delay);
- riscv_scan_set_delay(&delays, RISCV_DELAY_SYSBUS_WRITE, info->dmi_busy_delay +
- info->bus_master_write_delay);
- return delays;
-}
-
static int batch_run(struct target *target, struct riscv_batch *batch)
{
RISCV_INFO(r);
+ RISCV013_INFO(info);
select_dmi(target);
riscv_batch_add_nop(batch);
- const int result = riscv_batch_run_from(batch, 0,
- get_scan_delays(target),
+ const int result = riscv_batch_run_from(batch, 0, &info->learned_delays,
/*resets_delays*/ r->reset_delays_wait >= 0,
r->reset_delays_wait);
/* TODO: To use `riscv_batch_finished_scans()` here, it is needed for
@@ -2796,18 +2783,18 @@ static int batch_run(struct target *target, struct riscv_batch *batch)
static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
{
RISCV013_INFO(info);
-
select_dmi(target);
riscv_batch_add_nop(batch);
size_t finished_scans = 0;
const time_t start = time(NULL);
- const unsigned int old_dmi_busy_delay = info->dmi_busy_delay;
+ const unsigned int old_base_delay = riscv_scan_get_delay(&info->learned_delays,
+ RISCV_DELAY_BASE);
int result;
do {
RISCV_INFO(r);
result = riscv_batch_run_from(batch, finished_scans,
- get_scan_delays(target),
+ &info->learned_delays,
/*resets_delays*/ r->reset_delays_wait >= 0,
r->reset_delays_wait);
const size_t new_finished_scans = riscv_batch_finished_scans(batch);
@@ -2820,16 +2807,20 @@ static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
assert(finished_scans == batch->used_scans);
return ERROR_OK;
}
- increase_dmi_busy_delay(target);
+ result = increase_dmi_busy_delay(target);
+ if (result != ERROR_OK)
+ return result;
} while (time(NULL) - start < riscv_command_timeout_sec);
assert(result == ERROR_OK);
assert(riscv_batch_was_batch_busy(batch));
/* Reset dmi_busy_delay, so the value doesn't get too big. */
- LOG_TARGET_DEBUG(target, "dmi_busy_delay is restored to %u.",
- old_dmi_busy_delay);
- info->dmi_busy_delay = old_dmi_busy_delay;
+ LOG_TARGET_DEBUG(target, "%s delay is restored to %u.",
+ riscv_scan_delay_class_name(RISCV_DELAY_BASE),
+ old_base_delay);
+ riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE,
+ old_base_delay);
LOG_TARGET_ERROR(target, "DMI operation didn't complete in %d seconds. "
"The target is either really slow or broken. You could increase "
@@ -2968,7 +2959,11 @@ static int sample_memory_bus_v1(struct target *target,
* with a larger DMI delay. */
unsigned int sbcs_read_op = riscv_batch_get_dmi_read_op(batch, sbcs_read_index);
if (sbcs_read_op == DTM_DMI_OP_BUSY) {
- increase_dmi_busy_delay(target);
+ result = increase_dmi_busy_delay(target);
+ if (result != ERROR_OK) {
+ riscv_batch_free(batch);
+ return result;
+ }
continue;
}
@@ -2976,9 +2971,12 @@ static int sample_memory_bus_v1(struct target *target,
if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) {
/* Discard this batch when we encounter "busy error" state on the System Bus level.
* We'll try next time with a larger System Bus read delay. */
- info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
dm_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR);
+ int res = riscv_scan_increase_delay(&info->learned_delays,
+ RISCV_DELAY_SYSBUS_READ);
riscv_batch_free(batch);
+ if (res != ERROR_OK)
+ return res;
continue;
}
if (get_field(sbcs_read, DM_SBCS_SBERROR)) {
@@ -3135,11 +3133,7 @@ static int init_target(struct command_context *cmd_ctx,
riscv013_info_t *info = get_info(target);
info->progbufsize = -1;
-
- info->dmi_busy_delay = 0;
- info->bus_master_read_delay = 0;
- info->bus_master_write_delay = 0;
- info->ac_busy_delay = 0;
+ reset_learned_delays(target);
/* Assume all these abstract commands are supported until we learn
* otherwise.
@@ -3226,7 +3220,8 @@ static int deassert_reset(struct target *target)
return result;
uint32_t dmstatus;
- const int orig_dmi_busy_delay = info->dmi_busy_delay;
+ const unsigned int orig_base_delay = riscv_scan_get_delay(&info->learned_delays,
+ RISCV_DELAY_BASE);
time_t start = time(NULL);
LOG_TARGET_DEBUG(target, "Waiting for hart to come out of reset.");
do {
@@ -3259,7 +3254,8 @@ static int deassert_reset(struct target *target)
} while (get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL) &&
!get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET));
- info->dmi_busy_delay = orig_dmi_busy_delay;
+ riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE,
+ orig_base_delay);
if (target->reset_halt) {
target->state = TARGET_HALTED;
@@ -3588,10 +3584,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
if (sb_write_address(target, next_address, true) != ERROR_OK)
return ERROR_FAIL;
- if (info->bus_master_read_delay) {
+ unsigned int bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays,
+ RISCV_DELAY_SYSBUS_READ);
+ if (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);
+ bus_master_read_delay);
+ jtag_add_runtest(bus_master_read_delay, TAP_IDLE);
if (jtag_execute_queue() != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
return ERROR_FAIL;
@@ -3621,10 +3619,12 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
DMI_OP_READ, sbdata[j] + dm->base, 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) {
+ bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays,
+ RISCV_DELAY_SYSBUS_READ);
+ if (j == 0 && 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);
+ bus_master_read_delay);
+ jtag_add_runtest(bus_master_read_delay, TAP_IDLE);
if (jtag_execute_queue() != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
return ERROR_FAIL;
@@ -3711,9 +3711,10 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
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);
+ int res = riscv_scan_increase_delay(&info->learned_delays,
+ RISCV_DELAY_SYSBUS_READ);
+ if (res != ERROR_OK)
+ return res;
continue;
}
@@ -4129,8 +4130,12 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target,
uint32_t start_index, uint32_t *elements_read,
struct memory_access_info access)
{
- increase_ac_busy_delay(target);
- riscv013_clear_abstract_error(target);
+ int res = riscv013_clear_abstract_error(target);
+ if (res != ERROR_OK)
+ return res;
+ res = increase_ac_busy_delay(target);
+ if (res != ERROR_OK)
+ return res;
if (dm_write(target, DM_ABSTRACTAUTO, 0) != ERROR_OK)
return ERROR_FAIL;
@@ -4828,8 +4833,11 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address,
LOG_TARGET_DEBUG(target, "Sbbusyerror encountered during system bus write.");
/* Clear the sticky error flag. */
dm_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR);
- /* Slow down before trying again. */
- info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1;
+ /* Slow down before trying again.
+ * FIXME: Possible overflow is ignored here.
+ */
+ riscv_scan_increase_delay(&info->learned_delays,
+ RISCV_DELAY_SYSBUS_WRITE);
}
if (get_field(sbcs, DM_SBCS_SBBUSYERROR) || dmi_busy_encountered) {
@@ -4940,8 +4948,12 @@ static int write_memory_progbuf_teardown(struct target *target)
static int write_memory_progbuf_handle_busy(struct target *target,
target_addr_t *address_p, uint32_t size, const uint8_t *buffer)
{
- riscv013_clear_abstract_error(target);
- increase_ac_busy_delay(target);
+ int res = riscv013_clear_abstract_error(target);
+ if (res != ERROR_OK)
+ return res;
+ res = increase_ac_busy_delay(target);
+ if (res != ERROR_OK)
+ return res;
if (write_memory_progbuf_teardown(target) != ERROR_OK)
return ERROR_FAIL;