Handle resuming from a trigger...
... by disabling all triggers, single stepping, enabling them, and then resuming as usual. Without this change, you'd just be stuck on an address trigger and would have to manually disable it. Change-Id: I5834984671baa6b64f72e533c4aa94555c64617e
This commit is contained in:
parent
6e278cded6
commit
ace6b7e49a
|
@ -248,7 +248,7 @@ static int riscv_gdb_v_packet(struct connection *connection, const char *packet,
|
|||
if (strcmp(packet_stttrr, "vCont;c") == 0) {
|
||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
|
||||
target_call_event_callbacks(target, TARGET_EVENT_RESUME_START);
|
||||
riscv_resume_all_harts(target);
|
||||
riscv_openocd_resume(target, 1, 0, 0, 0);
|
||||
target->state = TARGET_RUNNING;
|
||||
gdb_set_frontend_state_running(connection);
|
||||
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||
|
|
|
@ -2037,8 +2037,9 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
|
|||
|
||||
switch (get_field(dcsr, CSR_DCSR_CAUSE)) {
|
||||
case CSR_DCSR_CAUSE_SWBP:
|
||||
case CSR_DCSR_CAUSE_TRIGGER:
|
||||
return RISCV_HALT_BREAKPOINT;
|
||||
case CSR_DCSR_CAUSE_TRIGGER:
|
||||
return RISCV_HALT_TRIGGER;
|
||||
case CSR_DCSR_CAUSE_STEP:
|
||||
return RISCV_HALT_SINGLESTEP;
|
||||
case CSR_DCSR_CAUSE_DEBUGINT:
|
||||
|
|
|
@ -640,6 +640,7 @@ static int old_or_new_riscv_step(
|
|||
int handle_breakpoints
|
||||
){
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
|
||||
if (r->is_halted == NULL)
|
||||
return oldriscv_step(target, current, address, handle_breakpoints);
|
||||
else
|
||||
|
@ -728,6 +729,7 @@ static int old_or_new_riscv_resume(
|
|||
int debug_execution
|
||||
){
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
|
||||
if (r->is_halted == NULL)
|
||||
return oldriscv_resume(target, current, address, handle_breakpoints, debug_execution);
|
||||
else
|
||||
|
@ -1027,6 +1029,9 @@ int riscv_openocd_poll(struct target *target)
|
|||
case RISCV_HALT_BREAKPOINT:
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
break;
|
||||
case RISCV_HALT_TRIGGER:
|
||||
target->debug_reason = DBG_REASON_WATCHPOINT;
|
||||
break;
|
||||
case RISCV_HALT_INTERRUPT:
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
break;
|
||||
|
@ -1077,13 +1082,53 @@ int riscv_openocd_resume(
|
|||
int current,
|
||||
target_addr_t address,
|
||||
int handle_breakpoints,
|
||||
int debug_execution
|
||||
) {
|
||||
LOG_DEBUG("resuming all harts");
|
||||
int debug_execution)
|
||||
{
|
||||
LOG_DEBUG("debug_reason=%d", target->debug_reason);
|
||||
|
||||
if (!current)
|
||||
riscv_set_register(target, GDB_REGNO_PC, address);
|
||||
|
||||
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
|
||||
/* To be able to run off a trigger, disable all the triggers, step, and
|
||||
* then resume as usual. */
|
||||
struct watchpoint *watchpoint = target->watchpoints;
|
||||
bool trigger_temporarily_cleared[RISCV_MAX_HWBPS] = {0};
|
||||
|
||||
int i = 0;
|
||||
int result = ERROR_OK;
|
||||
while (watchpoint && result == ERROR_OK) {
|
||||
LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set);
|
||||
trigger_temporarily_cleared[i] = watchpoint->set;
|
||||
if (watchpoint->set) {
|
||||
result = riscv_remove_watchpoint(target, watchpoint);
|
||||
}
|
||||
watchpoint = watchpoint->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (result == ERROR_OK) {
|
||||
result = riscv_step_rtos_hart(target);
|
||||
}
|
||||
|
||||
watchpoint = target->watchpoints;
|
||||
i = 0;
|
||||
while (watchpoint) {
|
||||
LOG_DEBUG("watchpoint %d: cleared=%d", i, trigger_temporarily_cleared[i]);
|
||||
if (trigger_temporarily_cleared[i]) {
|
||||
if (result == ERROR_OK)
|
||||
result = riscv_add_watchpoint(target, watchpoint);
|
||||
else
|
||||
riscv_add_watchpoint(target, watchpoint);
|
||||
}
|
||||
watchpoint = watchpoint->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
int out = riscv_resume_all_harts(target);
|
||||
if (out != ERROR_OK) {
|
||||
LOG_ERROR("unable to resume all harts");
|
||||
|
@ -1601,18 +1646,6 @@ enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
|
|||
return r->halt_reason(target);
|
||||
}
|
||||
|
||||
int riscv_count_triggers(struct target *target)
|
||||
{
|
||||
return riscv_count_triggers_of_hart(target, riscv_current_hartid(target));
|
||||
}
|
||||
|
||||
int riscv_count_triggers_of_hart(struct target *target, int hartid)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
assert(hartid < riscv_count_harts(target));
|
||||
return r->trigger_count[hartid];
|
||||
}
|
||||
|
||||
size_t riscv_debug_buffer_size(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
|
|
@ -30,6 +30,7 @@ enum riscv_halt_reason {
|
|||
RISCV_HALT_INTERRUPT,
|
||||
RISCV_HALT_BREAKPOINT,
|
||||
RISCV_HALT_SINGLESTEP,
|
||||
RISCV_HALT_TRIGGER,
|
||||
RISCV_HALT_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -216,11 +217,6 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
|
|||
bool riscv_is_halted(struct target *target);
|
||||
enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid);
|
||||
|
||||
/* Returns the number of triggers availiable to either the current hart or to
|
||||
* the given hart. */
|
||||
int riscv_count_triggers(struct target *target);
|
||||
int riscv_count_triggers_of_hart(struct target *target, int hartid);
|
||||
|
||||
/* These helper functions let the generic program interface get target-specific
|
||||
* information. */
|
||||
size_t riscv_debug_buffer_size(struct target *target);
|
||||
|
|
Loading…
Reference in New Issue