aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-02-16 14:16:18 -0800
committerTim Newsome <tim@sifive.com>2017-02-16 14:21:17 -0800
commit88f14f4d5eaa2eb7b5e74d4c30e1e201a294fe5d (patch)
tree62bf0271b6d0aaa7bf650ef53a1975f26622132d
parentef3875a320aeba3e7d1b678ce18633d07151ae0c (diff)
downloadriscv-openocd-88f14f4d5eaa2eb7b5e74d4c30e1e201a294fe5d.zip
riscv-openocd-88f14f4d5eaa2eb7b5e74d4c30e1e201a294fe5d.tar.gz
riscv-openocd-88f14f4d5eaa2eb7b5e74d4c30e1e201a294fe5d.tar.bz2
Check busy before triggering another command.
This version was able to download code, and run to a breakpoint. Change-Id: I0ead8350579263d8e55f8df35e2b7af6c374ef21
-rw-r--r--src/target/riscv/riscv-013.c96
1 files changed, 50 insertions, 46 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 2695682..2701f5d 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -131,6 +131,13 @@ typedef enum slot {
#define DMCONTROL_NDRESET (1<<1)
#define DMCONTROL_FULLRESET 1
+#define CMDERR_NONE 0
+#define CMDERR_BUSY 1
+#define CMDERR_NOT_SUPPORTED 2
+#define CMDERR_EXCEPTION 3
+#define CMDERR_HALT_RESUME 4
+#define CMDERR_OTHER 7
+
/*** Info about the core being debugged. ***/
#define DMI_ADDRESS_UNKNOWN 0xffff
@@ -235,8 +242,6 @@ static int register_get(struct reg *reg);
/*** Utility functions. ***/
-#define DEBUG_LENGTH 264
-
static riscv013_info_t *get_info(const struct target *target)
{
riscv_info_t *info = (riscv_info_t *) target->arch_info;
@@ -629,22 +634,31 @@ uint32_t abstract_register_size(unsigned width)
}
}
+static int wait_for_idle(struct target *target, uint32_t *abstractcs)
+{
+ time_t start = time(NULL);
+ while (1) {
+ *abstractcs = dmi_read(target, DMI_ABSTRACTCS);
+ if (get_field(*abstractcs, DMI_ABSTRACTCS_BUSY) == 0) {
+ return ERROR_OK;
+ }
+ if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
+ LOG_ERROR("Timed out waiting for busy to go low. (abstractcs=0x%x)",
+ *abstractcs);
+ return ERROR_FAIL;
+ }
+ }
+}
+
static int execute_abstract_command(struct target *target, uint32_t command)
{
dmi_write(target, DMI_COMMAND, command);
uint32_t abstractcs;
- for (unsigned i = 0; i < 256; i++) {
- abstractcs = dmi_read(target, DMI_ABSTRACTCS);
- if (get_field(abstractcs, DMI_ABSTRACTCS_BUSY) == 0)
- break;
- }
- if (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) {
- LOG_ERROR("Abstract command 0x%x never completed (abstractcs=0x%x)",
- command, abstractcs);
+ if (wait_for_idle(target, &abstractcs) != ERROR_OK)
return ERROR_FAIL;
- }
- if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
+
+ if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR) != CMDERR_NONE) {
const char *errors[8] = {
"none",
"busy",
@@ -775,22 +789,6 @@ static bits_t read_bits(struct target *target)
return result;
}
-static int wait_for_haltstatus(struct target *target, unsigned status)
-{
- time_t start = time(NULL);
- while (1) {
- uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
- unsigned s = get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS);
- if (s == status)
- return ERROR_OK;
- if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
- LOG_ERROR("Timed out waiting for hart status to be %d (dmcontrol=0x%x)",
- status, dmcontrol);
- return ERROR_FAIL;
- }
- }
-}
-
static int wait_for_debugint_clear(struct target *target, bool ignore_first)
{
time_t start = time(NULL);
@@ -1218,6 +1216,15 @@ static int maybe_write_tselect(struct target *target)
return ERROR_OK;
}
+static void reg_cache_set(struct target *target, unsigned int number,
+ uint64_t value)
+{
+ struct reg *r = &target->reg_cache->reg_list[number];
+ LOG_DEBUG("%s <= 0x%" PRIx64, r->name, value);
+ r->valid = true;
+ buf_set_u64(r->value, 0, r->size, value);
+}
+
static int execute_resume(struct target *target, bool step)
{
riscv013_info_t *info = get_info(target);
@@ -1266,12 +1273,9 @@ static int execute_resume(struct target *target, bool step)
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE |
DMI_DMCONTROL_RESUMEREQ);
- if (wait_for_haltstatus(target, 1) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
target->state = TARGET_RUNNING;
register_cache_invalidate(target->reg_cache);
+ reg_cache_set(target, ZERO, 0);
return ERROR_OK;
}
@@ -1307,15 +1311,6 @@ static int resume(struct target *target, int debug_execution, bool step)
return execute_resume(target, step);
}
-static void reg_cache_set(struct target *target, unsigned int number,
- uint64_t value)
-{
- struct reg *r = &target->reg_cache->reg_list[number];
- LOG_DEBUG("%s <= 0x%" PRIx64, r->name, value);
- r->valid = true;
- buf_set_u64(r->value, 0, r->size, value);
-}
-
/** Update register sizes based on xlen. */
static void update_reg_list(struct target *target)
{
@@ -1336,10 +1331,12 @@ static void update_reg_list(struct target *target)
} else {
r->size = xlen(target);
}
- r->valid = false;
+ if (i == ZERO) {
+ r->valid = true;
+ } else {
+ r->valid = false;
+ }
}
-
- reg_cache_set(target, ZERO, 0);
}
static uint64_t reg_cache_get(struct target *target, unsigned int number)
@@ -2331,7 +2328,7 @@ static int read_memory(struct target *target, uint32_t address,
execute_abstract_command(target,
AC_ACCESS_REGISTER_PREEXEC |
abstract_register_size(xlen(target)) | reg_number_to_no(S1));
- dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_AUTOEXEC0);
+ dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_AUTOEXEC0 | DMI_ABSTRACTCS_CMDERR);
for (uint32_t i = 0; i < count; i++) {
uint32_t value = dmi_read(target, DMI_DATA0);
@@ -2414,13 +2411,20 @@ static int write_memory(struct target *target, uint32_t address,
execute_abstract_command(target,
AC_ACCESS_REGISTER_WRITE | AC_ACCESS_REGISTER_POSTEXEC |
abstract_register_size(xlen(target)) | reg_number_to_no(S1));
- dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_AUTOEXEC0);
+ dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_AUTOEXEC0 | DMI_ABSTRACTCS_CMDERR);
+ } else {
+ uint32_t abstractcs;
+ if (wait_for_idle(target, &abstractcs) != ERROR_OK)
+ return ERROR_FAIL;
+ if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR) != CMDERR_NONE)
+ return ERROR_FAIL;
}
}
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
// TODO: retry with more delay?
+ LOG_ERROR("cmderr=%d", get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
return ERROR_FAIL;
}