More dbus->dmi.

Change-Id: Ia691f1e7ce909da4d9c16e6d691c4f2cf768a7fb
__archive__
Tim Newsome 2017-02-14 09:38:09 -08:00
parent 24033b53d8
commit 00925574d5
1 changed files with 65 additions and 21 deletions

View File

@ -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);