commit
a854089fd1
|
@ -63,7 +63,6 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a,
|
|||
static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a);
|
||||
static int riscv013_dmi_write_u64_bits(struct target *target);
|
||||
static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
|
||||
static void riscv013_reset_current_hart(struct target *target);
|
||||
|
||||
/**
|
||||
* Since almost everything can be accomplish by scanning the dbus register, all
|
||||
|
@ -904,7 +903,6 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
generic_info->fill_dmi_read_u64 = &riscv013_fill_dmi_read_u64;
|
||||
generic_info->fill_dmi_nop_u64 = &riscv013_fill_dmi_nop_u64;
|
||||
generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits;
|
||||
generic_info->reset_current_hart = &riscv013_reset_current_hart;
|
||||
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
|
||||
if (!generic_info->version_specific)
|
||||
return ERROR_FAIL;
|
||||
|
@ -1187,23 +1185,54 @@ static int examine(struct target *target)
|
|||
|
||||
static int assert_reset(struct target *target)
|
||||
{
|
||||
/*FIXME -- this only works for single-hart.*/
|
||||
RISCV_INFO(r);
|
||||
assert(r->current_hartid == 0);
|
||||
|
||||
select_dmi(target);
|
||||
LOG_DEBUG("ASSERTING NDRESET");
|
||||
uint32_t control = dmi_read(target, DMI_DMCONTROL);
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
if (target->reset_halt) {
|
||||
LOG_DEBUG("TARGET RESET HALT SET, ensuring halt is set during reset.");
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 1);
|
||||
|
||||
uint32_t control_base = set_field(0, DMI_DMCONTROL_DMACTIVE, 1);
|
||||
|
||||
if (target->rtos) {
|
||||
// There's only one target, and OpenOCD thinks each hart is a thread.
|
||||
// We must reset them all.
|
||||
|
||||
// TODO: Try to use hasel in dmcontrol
|
||||
|
||||
// Set haltreq/resumereq for each hart.
|
||||
uint32_t control = control_base;
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
continue;
|
||||
|
||||
control = set_field(control_base, DMI_DMCONTROL_HARTSEL, i);
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
||||
target->reset_halt ? 1 : 0);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
}
|
||||
// Assert ndmreset
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("TARGET RESET HALT NOT SET");
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 0);
|
||||
// Reset just this hart.
|
||||
uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL,
|
||||
r->current_hartid);
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
||||
target->reset_halt ? 1 : 0);
|
||||
control = set_field(control, DMI_DMCONTROL_HARTRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
// Read back to check if hartreset is supported.
|
||||
uint32_t rb = dmi_read(target, DMI_DMCONTROL);
|
||||
if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) {
|
||||
// Use ndmreset instead. That will reset the entire device, but
|
||||
// that's probably what OpenOCD wants anyway.
|
||||
control = set_field(control, DMI_DMCONTROL_HARTRESET, 0);
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
}
|
||||
}
|
||||
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
target->state = TARGET_RESET;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -1214,38 +1243,55 @@ static int deassert_reset(struct target *target)
|
|||
RISCV013_INFO(info);
|
||||
select_dmi(target);
|
||||
|
||||
/*FIXME -- this only works for Single Hart*/
|
||||
assert(r->current_hartid == 0);
|
||||
|
||||
/*FIXME -- is there bookkeeping we need to do here*/
|
||||
|
||||
uint32_t control = dmi_read(target, DMI_DMCONTROL);
|
||||
LOG_DEBUG("%d", r->current_hartid);
|
||||
|
||||
// Clear the reset, but make sure haltreq is still set
|
||||
if (target->reset_halt) {
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 1);
|
||||
}
|
||||
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 0);
|
||||
uint32_t control = 0;
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
|
||||
control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid);
|
||||
control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
uint32_t status;
|
||||
uint32_t dmstatus;
|
||||
int dmi_busy_delay = info->dmi_busy_delay;
|
||||
time_t start = time(NULL);
|
||||
|
||||
if (target->reset_halt) {
|
||||
LOG_DEBUG("DEASSERTING RESET, waiting for hart to be halted.");
|
||||
LOG_DEBUG("Waiting for hart to be halted.");
|
||||
do {
|
||||
status = dmi_read(target, DMI_DMSTATUS);
|
||||
} while (get_field(status, DMI_DMSTATUS_ALLHALTED) == 0);
|
||||
} else {
|
||||
LOG_DEBUG("DEASSERTING RESET, waiting for hart to be running.");
|
||||
do {
|
||||
status = dmi_read(target, DMI_DMSTATUS);
|
||||
if (get_field(status, DMI_DMSTATUS_ANYHALTED) ||
|
||||
get_field(status, DMI_DMSTATUS_ANYUNAVAIL)) {
|
||||
LOG_ERROR("Unexpected hart status during reset.");
|
||||
abort();
|
||||
dmstatus = dmi_read(target, DMI_DMSTATUS);
|
||||
if (time(NULL) - start > riscv_reset_timeout_sec) {
|
||||
LOG_ERROR("Hart didn't halt coming out of reset in %ds; "
|
||||
"dmstatus=0x%x; "
|
||||
"Increase the timeout with riscv set_reset_timeout_sec.",
|
||||
riscv_reset_timeout_sec, dmstatus);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
} while (get_field(status, DMI_DMSTATUS_ALLRUNNING) == 0);
|
||||
target->state = TARGET_HALTED;
|
||||
} while (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0);
|
||||
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("Waiting for hart to be running.");
|
||||
do {
|
||||
dmstatus = dmi_read(target, DMI_DMSTATUS);
|
||||
if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) ||
|
||||
get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) {
|
||||
LOG_ERROR("Unexpected hart status during reset. dmstatus=0x%x",
|
||||
dmstatus);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (time(NULL) - start > riscv_reset_timeout_sec) {
|
||||
LOG_ERROR("Hart didn't run coming out of reset in %ds; "
|
||||
"dmstatus=0x%x; "
|
||||
"Increase the timeout with riscv set_reset_timeout_sec.",
|
||||
riscv_reset_timeout_sec, dmstatus);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
} while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0);
|
||||
target->state = TARGET_RUNNING;
|
||||
}
|
||||
info->dmi_busy_delay = dmi_busy_delay;
|
||||
return ERROR_OK;
|
||||
|
@ -1880,37 +1926,6 @@ int riscv013_dmi_write_u64_bits(struct target *target)
|
|||
return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
|
||||
}
|
||||
|
||||
void riscv013_reset_current_hart(struct target *target)
|
||||
{
|
||||
select_dmi(target);
|
||||
uint32_t control = dmi_read(target, DMI_DMCONTROL);
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
time_t start = time(NULL);
|
||||
|
||||
while (1) {
|
||||
uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS);
|
||||
if (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED)) {
|
||||
break;
|
||||
}
|
||||
if (time(NULL) - start > riscv_reset_timeout_sec) {
|
||||
LOG_ERROR("Hart didn't halt coming out of reset in %ds; "
|
||||
"dmstatus=0x%x; "
|
||||
"Increase the timeout with riscv set_reset_timeout_sec.",
|
||||
riscv_reset_timeout_sec, dmstatus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
}
|
||||
|
||||
/* Helper Functions. */
|
||||
static void riscv013_on_step_or_resume(struct target *target, bool step)
|
||||
{
|
||||
|
|
|
@ -676,14 +676,13 @@ static int old_or_new_riscv_halt(struct target *target)
|
|||
return riscv_openocd_halt(target);
|
||||
}
|
||||
|
||||
static int oldriscv_assert_reset(struct target *target)
|
||||
static int riscv_assert_reset(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("RISCV ASSERT RESET");
|
||||
struct target_type *tt = get_target_type(target);
|
||||
return tt->assert_reset(target);
|
||||
}
|
||||
|
||||
static int oldriscv_deassert_reset(struct target *target)
|
||||
static int riscv_deassert_reset(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("RISCV DEASSERT RESET");
|
||||
struct target_type *tt = get_target_type(target);
|
||||
|
@ -691,24 +690,6 @@ static int oldriscv_deassert_reset(struct target *target)
|
|||
}
|
||||
|
||||
|
||||
static int old_or_new_riscv_assert_reset(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
if (r->is_halted == NULL)
|
||||
return oldriscv_assert_reset(target);
|
||||
else
|
||||
return riscv_openocd_assert_reset(target);
|
||||
}
|
||||
|
||||
static int old_or_new_riscv_deassert_reset(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
if (r->is_halted == NULL)
|
||||
return oldriscv_deassert_reset(target);
|
||||
else
|
||||
return riscv_openocd_deassert_reset(target);
|
||||
}
|
||||
|
||||
static int oldriscv_resume(struct target *target, int current, uint32_t address,
|
||||
int handle_breakpoints, int debug_execution)
|
||||
{
|
||||
|
@ -1115,29 +1096,6 @@ int riscv_openocd_step(
|
|||
return out;
|
||||
}
|
||||
|
||||
int riscv_openocd_assert_reset(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("asserting reset for all harts");
|
||||
int out = riscv_reset_all_harts(target);
|
||||
if (out != ERROR_OK) {
|
||||
LOG_ERROR("unable to reset all harts");
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int riscv_openocd_deassert_reset(struct target *target)
|
||||
{
|
||||
LOG_DEBUG("deasserting reset for all harts");
|
||||
if (target->reset_halt)
|
||||
riscv_halt_all_harts(target);
|
||||
else
|
||||
riscv_resume_all_harts(target);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Command Handlers */
|
||||
COMMAND_HANDLER(riscv_set_command_timeout_sec) {
|
||||
|
||||
|
@ -1217,8 +1175,8 @@ struct target_type riscv_target =
|
|||
.resume = old_or_new_riscv_resume,
|
||||
.step = old_or_new_riscv_step,
|
||||
|
||||
.assert_reset = old_or_new_riscv_assert_reset,
|
||||
.deassert_reset = old_or_new_riscv_deassert_reset,
|
||||
.assert_reset = riscv_assert_reset,
|
||||
.deassert_reset = riscv_deassert_reset,
|
||||
|
||||
.read_memory = riscv_read_memory,
|
||||
.write_memory = riscv_write_memory,
|
||||
|
@ -1315,33 +1273,6 @@ int riscv_resume_one_hart(struct target *target, int hartid)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_reset_all_harts(struct target *target)
|
||||
{
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
continue;
|
||||
|
||||
riscv_reset_one_hart(target, i);
|
||||
}
|
||||
|
||||
riscv_invalidate_register_cache(target);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_reset_one_hart(struct target *target, int hartid)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("resetting hart %d", hartid);
|
||||
riscv_halt_one_hart(target, hartid);
|
||||
riscv_set_current_hartid(target, hartid);
|
||||
r->reset_current_hart(target);
|
||||
/* At this point the hart must be halted. On platforms that support
|
||||
* "reset halt" exactly we expect the hart to have been halted before
|
||||
* executing any instructions, while on older cores it'll just have
|
||||
* halted quickly. */
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_step_rtos_hart(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
|
|
@ -103,7 +103,6 @@ typedef struct {
|
|||
void (*fill_dmi_write_u64)(struct target *target, char *buf, int a, uint64_t d);
|
||||
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
|
||||
void (*fill_dmi_nop_u64)(struct target *target, char *buf);
|
||||
void (*reset_current_hart)(struct target *target);
|
||||
} riscv_info_t;
|
||||
|
||||
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
|
||||
|
@ -161,8 +160,6 @@ int riscv_halt_all_harts(struct target *target);
|
|||
int riscv_halt_one_hart(struct target *target, int hartid);
|
||||
int riscv_resume_all_harts(struct target *target);
|
||||
int riscv_resume_one_hart(struct target *target, int hartid);
|
||||
int riscv_reset_all_harts(struct target *target);
|
||||
int riscv_reset_one_hart(struct target *target, int hartid);
|
||||
|
||||
/* Steps the hart that's currently selected in the RTOS, or if there is no RTOS
|
||||
* then the only hart. */
|
||||
|
|
Loading…
Reference in New Issue