diff options
author | Tim Newsome <tim@sifive.com> | 2018-02-19 13:42:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-19 13:42:50 -0800 |
commit | 352e6b82ed463bc8997d3fa5da268f7b08f14741 (patch) | |
tree | aad702c874233afcac08aee116a66b771c9e9ad2 | |
parent | 6cbb45f7f1eb04470f69472917cb986a238deee4 (diff) | |
parent | ace6b7e49ac0b54961fd363343c702b1c5172062 (diff) | |
download | riscv-openocd-352e6b82ed463bc8997d3fa5da268f7b08f14741.zip riscv-openocd-352e6b82ed463bc8997d3fa5da268f7b08f14741.tar.gz riscv-openocd-352e6b82ed463bc8997d3fa5da268f7b08f14741.tar.bz2 |
Merge pull request #208 from riscv/run_from_trigger
Handle resuming from a trigger...
-rw-r--r-- | src/rtos/riscv_debug.c | 2 | ||||
-rw-r--r-- | src/target/riscv/riscv-013.c | 3 | ||||
-rw-r--r-- | src/target/riscv/riscv.c | 63 | ||||
-rw-r--r-- | src/target/riscv/riscv.h | 6 |
4 files changed, 52 insertions, 22 deletions
diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c index b1a714d..90caf40 100644 --- a/src/rtos/riscv_debug.c +++ b/src/rtos/riscv_debug.c @@ -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); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6b03fd9..e136c98 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2039,8 +2039,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: diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index f8a2739..03fa46b 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -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); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 5d3a212..478731d 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -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); |