aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2018-12-04 12:38:51 -0800
committerTim Newsome <tim@sifive.com>2018-12-04 12:38:51 -0800
commit41e5272adc21e6479ad89f3cc43127bca145c29c (patch)
tree8d566b3d5ad5c47d6aa2eabad20a6102b2bf5732 /src
parentd650ef6089e293f7fd6cce4a0dac2e63e2098b52 (diff)
downloadriscv-openocd-41e5272adc21e6479ad89f3cc43127bca145c29c.zip
riscv-openocd-41e5272adc21e6479ad89f3cc43127bca145c29c.tar.gz
riscv-openocd-41e5272adc21e6479ad89f3cc43127bca145c29c.tar.bz2
Add `riscv reset_delays` for testing.
This allows me to test corner cases in block read/write errors. Change-Id: I3ccfe707851dbc578277ea0d5e278eab81a3c7ef
Diffstat (limited to 'src')
-rw-r--r--src/target/riscv/riscv-011.c18
-rw-r--r--src/target/riscv/riscv-013.c36
-rw-r--r--src/target/riscv/riscv.c27
-rw-r--r--src/target/riscv/riscv.h4
4 files changed, 83 insertions, 2 deletions
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index 4ddc0e9..1de72b1 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -206,6 +206,8 @@ typedef struct {
bool need_strict_step;
bool never_halted;
+
+ int reset_delays_wait;
} riscv011_info_t;
typedef struct {
@@ -359,6 +361,14 @@ static void add_dbus_scan(const struct target *target, struct scan_field *field,
{
riscv011_info_t *info = get_info(target);
+ if (info->reset_delays_wait >= 0) {
+ info->reset_delays_wait--;
+ if (info->reset_delays_wait < 0) {
+ info->dbus_busy_delay = 0;
+ info->interrupt_high_delay = 0;
+ }
+ }
+
field->num_bits = info->addrbits + DBUS_OP_SIZE + DBUS_DATA_SIZE;
field->in_value = in_value;
field->out_value = out_value;
@@ -1375,6 +1385,13 @@ static int halt(struct target *target)
return ERROR_OK;
}
+static int reset_delays(struct target *target, int wait)
+{
+ riscv011_info_t *info = get_info(target);
+ info->reset_delays_wait = wait;
+ return ERROR_OK;
+}
+
static int init_target(struct command_context *cmd_ctx,
struct target *target)
{
@@ -1382,6 +1399,7 @@ static int init_target(struct command_context *cmd_ctx,
riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
generic_info->get_register = get_register;
generic_info->set_register = set_register;
+ generic_info->reset_delays = &reset_delays;
generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
if (!generic_info->version_specific)
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index f0f007f..0660de4 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -215,6 +215,8 @@ typedef struct {
/* DM that provides access to this target. */
dm013_info_t *dm;
+
+ int reset_delays_wait;
} riscv013_info_t;
LIST_HEAD(dm_list);
@@ -468,6 +470,14 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
.in_value = in
};
+ if (info->reset_delays_wait >= 0) {
+ info->reset_delays_wait--;
+ if (info->reset_delays_wait < 0) {
+ info->dmi_busy_delay = 0;
+ info->ac_busy_delay = 0;
+ }
+ }
+
memset(in, 0, num_bytes);
assert(info->abits != 0);
@@ -1595,6 +1605,13 @@ int riscv013_authdata_write(struct target *target, uint32_t value)
return ERROR_OK;
}
+static int reset_delays(struct target *target, int wait)
+{
+ riscv013_info_t *info = get_info(target);
+ info->reset_delays_wait = wait;
+ return ERROR_OK;
+}
+
static int init_target(struct command_context *cmd_ctx,
struct target *target)
{
@@ -1625,6 +1642,7 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->dmi_write = &dmi_write;
generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg;
generic_info->test_compliance = &riscv013_test_compliance;
+ generic_info->reset_delays = &reset_delays;
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
if (!generic_info->version_specific)
return ERROR_FAIL;
@@ -2086,6 +2104,20 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_OK;
}
+static int batch_run(const struct target *target, struct riscv_batch *batch)
+{
+ RISCV013_INFO(info);
+ if (info->reset_delays_wait >= 0) {
+ info->reset_delays_wait -= batch->used_scans;
+ if (info->reset_delays_wait <= 0) {
+ batch->idle_count = 0;
+ info->dmi_busy_delay = 0;
+ info->ac_busy_delay = 0;
+ }
+ }
+ return riscv_batch_run(batch);
+}
+
/**
* Read the requested memory, taking care to execute every read exactly once,
* even if cmderr=busy is encountered.
@@ -2157,7 +2189,7 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres
break;
}
- riscv_batch_run(batch);
+ batch_run(target, batch);
/* Wait for the target to finish performing the last abstract command,
* and update our copy of cmderr. If we see that DMI is busy here,
@@ -2715,7 +2747,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
}
}
- result = riscv_batch_run(batch);
+ result = batch_run(target, batch);
riscv_batch_free(batch);
if (result != ERROR_OK)
goto error;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 1c89e6d..fc7f777 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -1608,6 +1608,23 @@ COMMAND_HANDLER(riscv_test_sba_config_reg)
}
}
+COMMAND_HANDLER(riscv_reset_delays)
+{
+ int wait = 0;
+
+ if (CMD_ARGC > 1) {
+ LOG_ERROR("Command takes at most one argument");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ if (CMD_ARGC == 1)
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], wait);
+
+ struct target *target = get_current_target(CMD_CTX);
+ RISCV_INFO(r);
+ return r->reset_delays(target, wait);
+}
+
static const struct command_registration riscv_exec_command_handlers[] = {
{
.name = "test_compliance",
@@ -1697,6 +1714,16 @@ static const struct command_registration riscv_exec_command_handlers[] = {
", an illegal, 128-byte aligned address for error flag/handling cases,"
"and whether sbbusyerror test should be run."
},
+ {
+ .name = "reset_delays",
+ .handler = riscv_reset_delays,
+ .mode = COMMAND_ANY,
+ .usage = "reset_delays [wait]",
+ .help = "OpenOCD learns how many Run-Test/Idle cycles are required "
+ "between scans to avoid encountering the target being busy. This "
+ "command resets those learned values after `wait` scans. It's only "
+ "useful for testing OpenOCD itself."
+ },
COMMAND_REGISTRATION_DONE
};
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index deca21e..82c1916 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -130,6 +130,10 @@ typedef struct {
uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
int (*test_compliance)(struct target *target);
+
+ /* After wait scans, reset the number of Run-Test/Idle cycles we've learned
+ * are required. */
+ int (*reset_delays)(struct target *target, int wait);
} riscv_info_t;
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/