Notice when a hart has reset.
Attempt to notify the user. Deal correctly with a halted target that is suddenly running. Change-Id: Ib0e0aa843d1da22df673713687ec884f6af14949
This commit is contained in:
parent
fd2759a63d
commit
4d2d1f7324
|
@ -1107,10 +1107,9 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
||||||
int result = register_read_abstract(target, value, number,
|
int result = register_read_abstract(target, value, number,
|
||||||
register_size(target, number));
|
register_size(target, number));
|
||||||
|
|
||||||
if (result != ERROR_OK && info->progbufsize + r->impebreak >= 2 &&
|
if (result != ERROR_OK &&
|
||||||
riscv_is_halted(target)) {
|
info->progbufsize + r->impebreak >= 2 &&
|
||||||
assert(number != GDB_REGNO_S0);
|
number > GDB_REGNO_XPR31) {
|
||||||
|
|
||||||
struct riscv_program program;
|
struct riscv_program program;
|
||||||
riscv_program_init(&program, target);
|
riscv_program_init(&program, target);
|
||||||
|
|
||||||
|
@ -2567,6 +2566,14 @@ static bool riscv013_is_halted(struct target *target)
|
||||||
LOG_ERROR("hart %d is unavailable", riscv_current_hartid(target));
|
LOG_ERROR("hart %d is unavailable", riscv_current_hartid(target));
|
||||||
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT))
|
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT))
|
||||||
LOG_ERROR("hart %d doesn't exist", riscv_current_hartid(target));
|
LOG_ERROR("hart %d doesn't exist", riscv_current_hartid(target));
|
||||||
|
if (get_field(dmstatus, DMI_DMSTATUS_ANYHAVERESET)) {
|
||||||
|
int hartid = riscv_current_hartid(target);
|
||||||
|
LOG_INFO("hart %d unexpectedly reset!", hartid);
|
||||||
|
/* TODO: Can we make this more obvious to eg. a gdb user? */
|
||||||
|
dmi_write(target, DMI_DMCONTROL,
|
||||||
|
set_field(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET,
|
||||||
|
hartsel_mask(target), hartid));
|
||||||
|
}
|
||||||
return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED);
|
return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -969,7 +969,8 @@ int riscv_blank_check_memory(struct target *target,
|
||||||
|
|
||||||
enum riscv_poll_hart {
|
enum riscv_poll_hart {
|
||||||
RPH_NO_CHANGE,
|
RPH_NO_CHANGE,
|
||||||
RPH_CHANGE,
|
RPH_DISCOVERED_HALTED,
|
||||||
|
RPH_DISCOVERED_RUNNING,
|
||||||
RPH_ERROR
|
RPH_ERROR
|
||||||
};
|
};
|
||||||
static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
|
static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
|
||||||
|
@ -978,15 +979,19 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
|
||||||
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
|
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
|
||||||
return RPH_ERROR;
|
return RPH_ERROR;
|
||||||
|
|
||||||
LOG_DEBUG("polling hart %d, target->state=%d (TARGET_HALTED=%d)", hartid,
|
LOG_DEBUG("polling hart %d, target->state=%d", hartid, target->state);
|
||||||
target->state, TARGET_HALTED);
|
|
||||||
|
|
||||||
/* If OpenOCD thinks we're running but this hart is halted then it's time
|
/* If OpenOCD thinks we're running but this hart is halted then it's time
|
||||||
* to raise an event. */
|
* to raise an event. */
|
||||||
if (target->state != TARGET_HALTED && riscv_is_halted(target)) {
|
bool halted = riscv_is_halted(target);
|
||||||
|
if (target->state != TARGET_HALTED && halted) {
|
||||||
LOG_DEBUG(" triggered a halt");
|
LOG_DEBUG(" triggered a halt");
|
||||||
r->on_halt(target);
|
r->on_halt(target);
|
||||||
return RPH_CHANGE;
|
return RPH_DISCOVERED_HALTED;
|
||||||
|
} else if (target->state != TARGET_RUNNING && !halted) {
|
||||||
|
LOG_DEBUG(" triggered running");
|
||||||
|
target->state = TARGET_RUNNING;
|
||||||
|
return RPH_DISCOVERED_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RPH_NO_CHANGE;
|
return RPH_NO_CHANGE;
|
||||||
|
@ -996,26 +1001,27 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
|
||||||
int riscv_openocd_poll(struct target *target)
|
int riscv_openocd_poll(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("polling all harts");
|
LOG_DEBUG("polling all harts");
|
||||||
int triggered_hart = -1;
|
int halted_hart = -1;
|
||||||
if (riscv_rtos_enabled(target)) {
|
if (riscv_rtos_enabled(target)) {
|
||||||
/* Check every hart for an event. */
|
/* Check every hart for an event. */
|
||||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||||
enum riscv_poll_hart out = riscv_poll_hart(target, i);
|
enum riscv_poll_hart out = riscv_poll_hart(target, i);
|
||||||
switch (out) {
|
switch (out) {
|
||||||
case RPH_NO_CHANGE:
|
case RPH_NO_CHANGE:
|
||||||
|
case RPH_DISCOVERED_RUNNING:
|
||||||
continue;
|
continue;
|
||||||
case RPH_CHANGE:
|
case RPH_DISCOVERED_HALTED:
|
||||||
triggered_hart = i;
|
halted_hart = i;
|
||||||
break;
|
break;
|
||||||
case RPH_ERROR:
|
case RPH_ERROR:
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (triggered_hart == -1) {
|
if (halted_hart == -1) {
|
||||||
LOG_DEBUG(" no harts just halted, target->state=%d", target->state);
|
LOG_DEBUG(" no harts just halted, target->state=%d", target->state);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(" hart %d halted", triggered_hart);
|
LOG_DEBUG(" hart %d halted", halted_hart);
|
||||||
|
|
||||||
/* If we're here then at least one hart triggered. That means
|
/* If we're here then at least one hart triggered. That means
|
||||||
* we want to go and halt _every_ hart in the system, as that's
|
* we want to go and halt _every_ hart in the system, as that's
|
||||||
|
@ -1028,17 +1034,17 @@ int riscv_openocd_poll(struct target *target)
|
||||||
} else {
|
} else {
|
||||||
enum riscv_poll_hart out = riscv_poll_hart(target,
|
enum riscv_poll_hart out = riscv_poll_hart(target,
|
||||||
riscv_current_hartid(target));
|
riscv_current_hartid(target));
|
||||||
if (out == RPH_NO_CHANGE)
|
if (out == RPH_NO_CHANGE || out == RPH_DISCOVERED_RUNNING)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
else if (out == RPH_ERROR)
|
else if (out == RPH_ERROR)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
triggered_hart = riscv_current_hartid(target);
|
halted_hart = riscv_current_hartid(target);
|
||||||
LOG_DEBUG(" hart %d halted", triggered_hart);
|
LOG_DEBUG(" hart %d halted", halted_hart);
|
||||||
}
|
}
|
||||||
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
switch (riscv_halt_reason(target, triggered_hart)) {
|
switch (riscv_halt_reason(target, halted_hart)) {
|
||||||
case RISCV_HALT_BREAKPOINT:
|
case RISCV_HALT_BREAKPOINT:
|
||||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||||
break;
|
break;
|
||||||
|
@ -1059,8 +1065,8 @@ int riscv_openocd_poll(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riscv_rtos_enabled(target)) {
|
if (riscv_rtos_enabled(target)) {
|
||||||
target->rtos->current_threadid = triggered_hart + 1;
|
target->rtos->current_threadid = halted_hart + 1;
|
||||||
target->rtos->current_thread = triggered_hart + 1;
|
target->rtos->current_thread = halted_hart + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
Loading…
Reference in New Issue