Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do not assume DTM version unless dtmcontrol is read successfully #929

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/target/riscv/riscv-011.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ static uint16_t dram_address(unsigned int index)
return 0x40 + index - 0x10;
}

static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
struct scan_field field;
uint8_t in_value[4];
Expand All @@ -300,7 +300,9 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
uint32_t in = buf_get_u32(field.in_value, 0, 32);
LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);

return in;
if (in_ptr)
*in_ptr = in;
return ERROR_OK;
}

static uint32_t idcode_scan(struct target *target)
Expand Down Expand Up @@ -338,7 +340,7 @@ static void increase_dbus_busy_delay(struct target *target)
info->dtmcontrol_idle, info->dbus_busy_delay,
info->interrupt_high_delay);

dtmcontrol_scan(target, DTMCONTROL_DBUS_RESET);
dtmcontrol_scan(target, DTMCONTROL_DBUS_RESET, NULL /* discard value */);
}

static void increase_interrupt_high_delay(struct target *target)
Expand Down Expand Up @@ -1459,16 +1461,17 @@ static int step(struct target *target, int current, target_addr_t address,
static int examine(struct target *target)
{
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
uint32_t dtmcontrol;
if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) {
LOG_ERROR("Could not scan dtmcontrol. Check JTAG connectivity/board power.");
return ERROR_FAIL;
}

uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
LOG_DEBUG(" addrbits=%d", get_field(dtmcontrol, DTMCONTROL_ADDRBITS));
LOG_DEBUG(" version=%d", get_field(dtmcontrol, DTMCONTROL_VERSION));
LOG_DEBUG(" idle=%d", get_field(dtmcontrol, DTMCONTROL_IDLE));
if (dtmcontrol == 0) {
LOG_ERROR("dtmcontrol is 0. Check JTAG connectivity/board power.");
return ERROR_FAIL;
}

if (get_field(dtmcontrol, DTMCONTROL_VERSION) != 0) {
LOG_ERROR("Unsupported DTM version %d. (dtmcontrol=0x%x)",
get_field(dtmcontrol, DTMCONTROL_VERSION), dtmcontrol);
Expand Down
26 changes: 15 additions & 11 deletions src/target/riscv/riscv-013.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,14 @@ static void select_dmi(struct target *target)
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
}

static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
struct scan_field field;
uint8_t in_value[4];
uint8_t out_value[4] = { 0 };

if (bscan_tunnel_ir_width != 0)
return dtmcontrol_scan_via_bscan(target, out);
return dtmcontrol_scan_via_bscan(target, out, in_ptr);

buf_set_u32(out_value, 0, 32, out);

Expand All @@ -441,7 +441,9 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
uint32_t in = buf_get_u32(field.in_value, 0, 32);
LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in);

return in;
if (in_ptr)
*in_ptr = in;
return ERROR_OK;
}

static void increase_dmi_busy_delay(struct target *target)
Expand All @@ -452,7 +454,7 @@ static void increase_dmi_busy_delay(struct target *target)
info->dtmcs_idle, info->dmi_busy_delay,
info->ac_busy_delay);

dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
}

/**
Expand Down Expand Up @@ -597,7 +599,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
} else if (status == DMI_STATUS_SUCCESS) {
break;
} else {
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
break;
}
if (time(NULL) - start > timeout_sec)
Expand Down Expand Up @@ -632,7 +634,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
"Failed DMI %s (NOP) at 0x%x; status=%d", op_name, address,
status);
}
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
return ERROR_FAIL;
}
if (time(NULL) - start > timeout_sec)
Expand Down Expand Up @@ -1845,17 +1847,19 @@ static int examine(struct target *target)
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
LOG_TARGET_DEBUG(target, "dbgbase=0x%x", target->dbgbase);

uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
uint32_t dtmcontrol;
if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) {
LOG_TARGET_ERROR(target, "Could not scan dtmcontrol. Check JTAG connectivity/board power.");
return ERROR_FAIL;
}

LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
LOG_TARGET_DEBUG(target, " dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
LOG_TARGET_DEBUG(target, " idle=%d", get_field(dtmcontrol, DTM_DTMCS_IDLE));
LOG_TARGET_DEBUG(target, " dmistat=%d", get_field(dtmcontrol, DTM_DTMCS_DMISTAT));
LOG_TARGET_DEBUG(target, " abits=%d", get_field(dtmcontrol, DTM_DTMCS_ABITS));
LOG_TARGET_DEBUG(target, " version=%d", get_field(dtmcontrol, DTM_DTMCS_VERSION));
if (dtmcontrol == 0) {
LOG_TARGET_ERROR(target, "dtmcontrol is 0. Check JTAG connectivity/board power.");
return ERROR_FAIL;
}

if (get_field(dtmcontrol, DTM_DTMCS_VERSION) != 1) {
LOG_TARGET_ERROR(target, "Unsupported DTM version %d. (dtmcontrol=0x%x)",
get_field(dtmcontrol, DTM_DTMCS_VERSION), dtmcontrol);
Expand Down
75 changes: 58 additions & 17 deletions src/target/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ void select_dmi_via_bscan(struct target *target)
bscan_tunnel_nested_tap_select_dmi, TAP_IDLE);
}

uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out)
int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
/* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN TAP's DR */
uint8_t tunneled_ir_width[4] = {bscan_tunnel_ir_width};
Expand Down Expand Up @@ -362,18 +362,19 @@ uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out)
uint32_t in = buf_get_u32(in_value, 1, 32);
LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in);

return in;
if (in_ptr)
*in_ptr = in;
return ERROR_OK;
}

static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
struct scan_field field;
uint8_t in_value[4];
uint8_t out_value[4] = { 0 };

if (bscan_tunnel_ir_width != 0)
return dtmcontrol_scan_via_bscan(target, out);

return dtmcontrol_scan_via_bscan(target, out, in_ptr);

buf_set_u32(out_value, 0, 32, out);

Expand All @@ -389,14 +390,16 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)

int retval = jtag_execute_queue();
if (retval != ERROR_OK) {
LOG_ERROR("failed jtag scan: %d", retval);
LOG_TARGET_ERROR(target, "dtmcontrol scan failed, error code = %d", retval);
return retval;
}

uint32_t in = buf_get_u32(field.in_value, 0, 32);
LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);

return in;
if (in_ptr)
*in_ptr = in;
return ERROR_OK;
}

static struct target_type *get_target_type(struct target *target)
Expand All @@ -408,11 +411,13 @@ static struct target_type *get_target_type(struct target *target)

RISCV_INFO(info);
switch (info->dtm_version) {
case 0:
case DTM_DTMCS_VERSION_0_11:
return &riscv011_target;
case 1:
case DTM_DTMCS_VERSION_1_0:
return &riscv013_target;
default:
/* TODO: once we have proper support for non-examined targets
* we should have an assert here */
LOG_TARGET_ERROR(target, "Unsupported DTM version: %d",
info->dtm_version);
return NULL;
Expand Down Expand Up @@ -479,6 +484,7 @@ static void riscv_free_registers(struct target *target)
free(target->reg_cache->reg_list);
}
free(target->reg_cache);
target->reg_cache = NULL;
}
}

Expand All @@ -488,6 +494,8 @@ static void riscv_deinit_target(struct target *target)

struct riscv_info *info = target->arch_info;
struct target_type *tt = get_target_type(target);
if (!tt)
LOG_TARGET_ERROR(target, "Could not identify target type.");

if (riscv_flush_registers(target) != ERROR_OK)
LOG_TARGET_ERROR(target, "Failed to flush registers. Ignoring this error.");
Expand Down Expand Up @@ -1517,6 +1525,8 @@ static int oldriscv_step(struct target *target, int current, uint32_t address,
int handle_breakpoints)
{
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->step(target, current, address, handle_breakpoints);
}

Expand All @@ -1542,25 +1552,40 @@ static int riscv_examine(struct target *target)
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */

RISCV_INFO(info);
uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
uint32_t dtmcontrol;
if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) {
LOG_TARGET_ERROR(target, "Could not read dtmcontrol. Check JTAG connectivity/board power.");
return ERROR_FAIL;
}
LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
info->dtm_version = get_field(dtmcontrol, DTMCONTROL_VERSION);
LOG_TARGET_DEBUG(target, "version=0x%x", info->dtm_version);

int examine_status = ERROR_FAIL;
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
goto examine_fail;

int result = tt->init_target(info->cmd_ctx, target);
if (result != ERROR_OK)
return result;
examine_status = tt->init_target(info->cmd_ctx, target);
if (examine_status != ERROR_OK)
goto examine_fail;

examine_status = tt->examine(target);
if (examine_status != ERROR_OK)
goto examine_fail;

return ERROR_OK;

return tt->examine(target);
examine_fail:
info->dtm_version = DTM_DTMCS_VERSION_UNKNOWN;
JanMatCodasip marked this conversation as resolved.
Show resolved Hide resolved
return examine_status;
}

static int oldriscv_poll(struct target *target)
{
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->poll(target);
}

Expand Down Expand Up @@ -1694,6 +1719,8 @@ static int halt_go(struct target *target)
int result;
if (!r->get_hart_state) {
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
result = tt->halt(target);
} else {
result = riscv_halt_go_all_harts(target);
Expand All @@ -1715,6 +1742,8 @@ int riscv_halt(struct target *target)

if (!r->get_hart_state) {
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->halt(target);
}

Expand Down Expand Up @@ -1760,6 +1789,8 @@ static int riscv_assert_reset(struct target *target)
{
LOG_TARGET_DEBUG(target, "coreid: [%d]", target->coreid);
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
riscv_invalidate_register_cache(target);
return tt->assert_reset(target);
}
Expand All @@ -1768,6 +1799,8 @@ static int riscv_deassert_reset(struct target *target)
{
LOG_TARGET_DEBUG(target, "coreid: [%d]", target->coreid);
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->deassert_reset(target);
}

Expand Down Expand Up @@ -1900,6 +1933,8 @@ static int resume_go(struct target *target, int current,
int result;
if (!r->get_hart_state) {
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
result = tt->resume(target, current, address, handle_breakpoints,
debug_execution);
} else {
Expand Down Expand Up @@ -2400,6 +2435,8 @@ static int riscv_write_phys_memory(struct target *target, target_addr_t phys_add
uint32_t size, uint32_t count, const uint8_t *buffer)
{
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->write_memory(target, phys_address, size, count, buffer);
}

Expand All @@ -2416,6 +2453,8 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
address = physical_addr;

struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->write_memory(target, address, size, count, buffer);
}

Expand Down Expand Up @@ -2493,6 +2532,8 @@ static int riscv_get_gdb_reg_list(struct target *target,
static int riscv_arch_state(struct target *target)
{
struct target_type *tt = get_target_type(target);
if (!tt)
return ERROR_FAIL;
return tt->arch_state(target);
}

Expand Down Expand Up @@ -4230,7 +4271,7 @@ COMMAND_HANDLER(riscv_exec_progbuf)
struct target *target = get_current_target(CMD_CTX);

RISCV_INFO(r);
if (r->dtm_version != 1) {
if (r->dtm_version != DTM_DTMCS_VERSION_1_0) {
LOG_TARGET_ERROR(target, "exec_progbuf: Program buffer is "
"only supported on v0.13 or v1.0 targets.");
return ERROR_FAIL;
Expand Down Expand Up @@ -4628,7 +4669,7 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)

r->common_magic = RISCV_COMMON_MAGIC;

r->dtm_version = 1;
r->dtm_version = DTM_DTMCS_VERSION_UNKNOWN;
r->version_specific = NULL;

memset(r->trigger_unique_id, 0xff, sizeof(r->trigger_unique_id));
Expand Down
6 changes: 4 additions & 2 deletions src/target/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ typedef struct {
char *name;
} range_list_t;

#define DTM_DTMCS_VERSION_UNKNOWN ((unsigned int)-1)

struct riscv_info {
unsigned int common_magic;

unsigned dtm_version;
unsigned int dtm_version;

struct command_context *cmd_ctx;
void *version_specific;
Expand Down Expand Up @@ -357,7 +359,7 @@ extern uint32_t bscan_tunneled_select_dmi_num_fields;
typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER } bscan_tunnel_type_t;
extern int bscan_tunnel_ir_width;

uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out);
int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr);
void select_dmi_via_bscan(struct target *target);

/*** OpenOCD Interface */
Expand Down
Loading