aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/riscv/riscv-013.c86
1 files changed, 65 insertions, 21 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index dd3796e..ea5d7b9 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -287,6 +287,20 @@ static uint16_t dram_address(unsigned int index)
return 0x40 + index - 0x10;
}
+static void select_dmi(struct target *target)
+{
+ static uint8_t ir_dmi[1] = {DTM_DMI};
+ struct scan_field field = {
+ .num_bits = target->tap->ir_length,
+ .out_value = ir_dmi,
+ .in_value = NULL,
+ .check_value = NULL,
+ .check_mask = NULL
+ };
+
+ jtag_add_ir_scan(target->tap, &field, TAP_IDLE);
+}
+
static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
{
struct scan_field field;
@@ -302,8 +316,8 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
field.in_value = in_value;
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ /* Always return to dmi. */
+ select_dmi(target);
int retval = jtag_execute_queue();
if (retval != ERROR_OK) {
@@ -335,8 +349,8 @@ static uint32_t idcode_scan(struct target *target)
return retval;
}
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ /* Always return to dmi. */
+ select_dmi(target);
uint32_t in = buf_get_u32(field.in_value, 0, 32);
LOG_DEBUG("IDCODE: 0x0 -> 0x%x", in);
@@ -1546,7 +1560,7 @@ static struct reg_arch_type riscv_reg_arch_type = {
static int halt(struct target *target)
{
LOG_DEBUG("riscv_halt()");
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
cache_set32(target, 0, csrsi(CSR_DCSR, DCSR_HALT));
cache_set32(target, 1, csrr(S0, CSR_MHARTID));
@@ -1895,7 +1909,7 @@ static int step(struct target *target, int current, uint32_t address,
{
riscv013_info_t *info = get_info(target);
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
if (!current) {
if (xlen(target) > 32) {
@@ -1972,6 +1986,8 @@ static int examine(struct target *target)
LOG_DEBUG(" authtype=%d", get_field(dmcontrol, DMI_DMCONTROL_AUTHTYPE));
LOG_DEBUG(" version=%d", get_field(dmcontrol, DMI_DMCONTROL_VERSION));
+ unsigned hartstatus = DMI_DMCONTROL_HARTSTATUS;
+
if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
dmcontrol);
@@ -1984,6 +2000,16 @@ static int examine(struct target *target)
return ERROR_FAIL;
}
+ if (hartstatus == 2) {
+ LOG_ERROR("The hart is unavailable.");
+ return ERROR_FAIL;
+ }
+
+ if (hartstatus == 3) {
+ LOG_ERROR("The hart doesn't exist.");
+ return ERROR_FAIL;
+ }
+
// Check that abstract data registers are accessible.
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
@@ -2026,17 +2052,21 @@ static int examine(struct target *target)
value += 0x52534335;
}
- dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_HALTREQ | DMI_DMCONTROL_DMACTIVE);
- for (unsigned i = 0; i < 256; i++) {
- dmcontrol = dmi_read(target, DMI_DMCONTROL);
- if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) == 0)
- break;
- }
- if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) != 0) {
- LOG_ERROR("hart didn't halt; dmcontrol=0x%x", dmcontrol);
- return ERROR_FAIL;
+ if (hartstatus == 1) {
+ dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_HALTREQ | DMI_DMCONTROL_DMACTIVE);
+ for (unsigned i = 0; i < 256; i++) {
+ dmcontrol = dmi_read(target, DMI_DMCONTROL);
+ if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) == 0)
+ break;
+ }
+ if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) != 0) {
+ LOG_ERROR("hart didn't halt; dmcontrol=0x%x", dmcontrol);
+ return ERROR_FAIL;
+ }
}
+ // TODO: do this using Quick Access, if supported.
+
riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
if (abstract_read_register(target, 15, 128, NULL) == ERROR_OK) {
generic_info->xlen = 128;
@@ -2059,6 +2089,20 @@ static int examine(struct target *target)
return ERROR_FAIL;
}
+ if (hartstatus == 1) {
+ // Resume if the hart had been running.
+ dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
+ for (unsigned i = 0; i < 256; i++) {
+ dmcontrol = dmi_read(target, DMI_DMCONTROL);
+ if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) == 1)
+ break;
+ }
+ if (get_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS) != 1) {
+ LOG_ERROR("hart didn't resume; dmcontrol=0x%x", dmcontrol);
+ return ERROR_FAIL;
+ }
+ }
+
info->never_halted = true;
int result = riscv013_poll(target);
@@ -2317,7 +2361,7 @@ static int handle_halt(struct target *target, bool announce)
static int poll_target(struct target *target, bool announce)
{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
// Inhibit debug logging during poll(), which isn't usually interesting and
// just fills up the screen/logs with clutter.
@@ -2355,7 +2399,7 @@ static int riscv013_resume(struct target *target, int current, uint32_t address,
{
riscv013_info_t *info = get_info(target);
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
if (!current) {
if (xlen(target) > 32) {
@@ -2381,7 +2425,7 @@ static int assert_reset(struct target *target)
riscv013_info_t *info = get_info(target);
// TODO: Maybe what I implemented here is more like soft_reset_halt()?
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
// The only assumption we can make is that the TAP was reset.
if (wait_for_debugint_clear(target, true) != ERROR_OK) {
@@ -2412,7 +2456,7 @@ static int assert_reset(struct target *target)
static int deassert_reset(struct target *target)
{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
if (target->reset_halt) {
return wait_for_state(target, TARGET_HALTED);
} else {
@@ -2423,7 +2467,7 @@ static int deassert_reset(struct target *target)
static int read_memory(struct target *target, uint32_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
cache_set32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16));
switch (size) {
@@ -2589,7 +2633,7 @@ static int write_memory(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
riscv013_info_t *info = get_info(target);
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
+ select_dmi(target);
// Set up the address.
cache_set_store(target, 0, T0, SLOT1);