This is an automated email from Gerrit. Felipe Balbi ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4016
-- gerrit commit 067e549ed16e1291bfe7258b5294fc1859c33e09 Author: Felipe Balbi <[email protected]> Date: Fri Feb 24 15:26:39 2017 +0200 target: lakemon: implement reset break support Because our adapters don't have support for PREQ#/PRDY# signals, we don't have means to reset the SoC. The only way of doing so is by using reset break via probemode which will cause the TAP to drive PREQ#/PRDY# accordingly inside the SoC. This patch implements that and also assumes that we rely on it. It makes not sense to implement support for PREQ#/PRDY# on the adapter until we have adapters supporting those. Tested with Intel Galileo GEN2. Change-Id: Ia406e31c156f8001717d5b6a08bd03f71de790d3 Signed-off-by: Felipe Balbi <[email protected]> diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 5f92f0d..3ca548c 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -1115,15 +1115,124 @@ int lakemont_step(struct target *t, int current, return retval; } -/* TODO - implement resetbreak fully through CLTAP registers */ -int lakemont_reset_assert(struct target *t) +static int lakemont_reset_break(struct target *t) { - LOG_DEBUG("-"); + struct x86_32_common *x86_32 = target_to_x86_32(t); + struct jtag_tap *saved_tap = x86_32->curr_tap; + struct scan_field *fields = &scan.field; + + /* write 0x6 to I/O port 0xcf9 to cause the reset */ + const uint8_t cf9_reset_val[] = { 0x6 }; + + int retval = ERROR_OK; + + LOG_DEBUG("issuing port 0xcf9 reset"); + + /* we can't be running when issuing an I/O port write */ + if (t->state == TARGET_RUNNING) { + retval = lakemont_halt(t); + if (retval != ERROR_OK) { + LOG_ERROR("%s could not halt target", __func__); + return retval; + } + } + + /* prepare resetbreak setting the proper bits in CLTAPC_CPU_VPREQ */ + x86_32->curr_tap = jtag_tap_by_position(1); + if (x86_32->curr_tap == NULL) { + x86_32->curr_tap = saved_tap; + LOG_ERROR("%s could not select quark_x10xx.cltap", __func__); + return ERROR_FAIL; + } + + fields->in_value = NULL; + fields->num_bits = 8; + + /* select CLTAPC_CPU_VPREQ instruction*/ + scan.out[0] = 0x51; + fields->out_value = ((uint8_t *)scan.out); + jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + x86_32->curr_tap = saved_tap; + LOG_ERROR("%s irscan failed to execute queue", __func__); + return retval; + } + + /* set enable_preq_on_reset & enable_preq_on_reset2 bits*/ + scan.out[0] = 0x06; + fields->out_value = ((uint8_t *)scan.out); + jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE); + retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + LOG_ERROR("%s drscan failed to execute queue", __func__); + x86_32->curr_tap = saved_tap; + return retval; + } + + /* restore current tap */ + x86_32->curr_tap = saved_tap; + + retval = x86_32_common_write_io(t, (uint32_t)0xcf9, BYTE, cf9_reset_val); + if (retval != ERROR_OK) { + LOG_ERROR("%s could not write to port 0xcf9", __func__); + return retval; + } + + /* entered PM after reset, update the state */ + retval = lakemont_update_after_probemode_entry(t); + if (retval != ERROR_OK) { + LOG_ERROR("%s could not update state after probemode entry", __func__); + return retval; + } + + /* remove breakpoints and watchpoints */ + x86_32_common_reset_breakpoints_watchpoints(t); + return ERROR_OK; } +int lakemont_reset_assert(struct target *t) +{ + LOG_DEBUG(" "); + + /* + * If we ever get an adapter with support for PREQ# and PRDY#, we should + * update this function to add support for using those two signals. + * + * Meanwhile, we're assuming that we only support reset break. + */ + + return lakemont_reset_break(t); +} + int lakemont_reset_deassert(struct target *t) { - LOG_DEBUG("-"); + int retval; + + LOG_DEBUG(" "); + + if (target_was_examined(t)) { + retval = lakemont_poll(t); + if (retval != ERROR_OK) + return retval; + } + + if (t->reset_halt) { + if (t->state != TARGET_HALTED) { + LOG_WARNING("%s: ran after reset and before halt ...", + target_name(t)); + if (target_was_examined(t)) { + retval = target_halt(t); + if (retval != ERROR_OK) + return retval; + } else { + t->state = TARGET_UNKNOWN; + } + } + } else { + return target_resume(t, true, 0x00, false, true); + } + return ERROR_OK; } diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index 34f92ea..0d87ba5 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -1260,6 +1260,38 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) return ERROR_OK; } +/* after reset breakpoints and watchpoints in memory are not valid anymore and + * debug registers are cleared. + * we can't afford to remove sw breakpoints using the default methods as the + * memory doesn't have the same layout yet and an access might crash the target, + * so we just clear the openocd breakpoints structures. + */ +void x86_32_common_reset_breakpoints_watchpoints(struct target *t) +{ + struct x86_32_common *x86_32 = target_to_x86_32(t); + struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; + struct breakpoint *next_b; + struct watchpoint *next_w; + + while (t->breakpoints) { + next_b = t->breakpoints->next; + free(t->breakpoints->orig_instr); + free(t->breakpoints); + t->breakpoints = next_b; + } + + while (t->watchpoints) { + next_w = t->watchpoints->next; + free(t->watchpoints); + t->watchpoints = next_w; + } + + for (int i = 0; i < x86_32->num_hw_bpoints; i++) { + debug_reg_list[i].used = 0; + debug_reg_list[i].bp_value = 0; + } +} + static int read_hw_reg_to_cache(struct target *t, int num) { uint32_t reg_value; diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index 0aaa963..fe100ea 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -326,5 +326,6 @@ int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp); int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp); int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp); int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp); +void x86_32_common_reset_breakpoints_watchpoints(struct target *t); #endif /* OPENOCD_TARGET_X86_32_COMMON_H */ -- ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
