From: David B. <dbr...@us...> - 2009-12-05 03:58:01
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via f67f6fe5bb8a466cc4d49f83608f026c4b233949 (commit) via a0edb8a328ceea23186ab74c941454fb146c9a48 (commit) via f4651c869fb0bbe00495a09470af0a934814c92a (commit) from 87a0119fa24fe0fc904dcf2e6569cc0b9cb580ed (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f67f6fe5bb8a466cc4d49f83608f026c4b233949 Author: David Brownell <dbr...@us...> Date: Fri Dec 4 18:57:31 2009 -0800 ARM11: report watchpoint trigger insn As with Cortex-A8, the WFAR register holds useful information that should be recorded and, where relevant, displayed. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm11.c b/src/target/arm11.c index 943ab8a..0486b04 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -217,6 +217,19 @@ static int arm11_debug_entry(struct arm11_common *arm11) } + if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) { + uint32_t wfar; + + /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */ + retval = arm11_run_instr_data_from_core_via_r0(arm11, + ARMV4_5_MRC(15, 0, 0, 6, 0, 1), + &wfar); + if (retval != ERROR_OK) + return retval; + arm_dpm_report_wfar(arm11->arm.dpm, wfar); + } + + retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; @@ -356,12 +369,17 @@ static int arm11_poll(struct target *target) /* architecture specific status reply */ static int arm11_arch_state(struct target *target) { + struct arm11_common *arm11 = target_to_arm11(target); int retval; retval = armv4_5_arch_state(target); /* REVISIT also display ARM11-specific MMU and cache status ... */ + if (target->debug_reason == DBG_REASON_WATCHPOINT) + LOG_USER("Watchpoint triggered at PC %#08x", + (unsigned) arm11->dpm.wp_pc); + return retval; } commit a0edb8a328ceea23186ab74c941454fb146c9a48 Author: David Brownell <dbr...@us...> Date: Fri Dec 4 18:57:31 2009 -0800 ARM11: basic watchpoint support Use the DPM watchpoint support; remove old incomplete stubs. Signed-off-by: David Brownell <dbr...@us...> diff --git a/NEWS b/NEWS index 38ae4da..498797b 100644 --- a/NEWS +++ b/NEWS @@ -24,10 +24,12 @@ Target Layer: - accelerated GDB memory checksum - support "arm regs" command - can access all core modes and registers + - watchpoint support Cortex-A8 - support "arm regs" command - can access all core modes and registers - supports "reset-assert" event (used on OMAP3530) + - watchpoint support Cortex-M3 - Exposed DWT registers like cycle counter diff --git a/src/target/arm11.c b/src/target/arm11.c index b05ef30..943ab8a 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -286,6 +286,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp) */ retval = arm_dpm_write_dirty_registers(&arm11->dpm, bpwp); + retval = arm11_bpwp_flush(arm11); + register_cache_invalidate(arm11->arm.core_cache); /* restore DSCR */ @@ -1212,7 +1214,6 @@ static int arm11_examine(struct target *target) } arm11->brp = ((didr >> 24) & 0x0F) + 1; - arm11->wrp = ((didr >> 28) & 0x0F) + 1; /** \todo TODO: reserve one brp slot if we allow breakpoints during step */ arm11->free_brps = arm11->brp; diff --git a/src/target/arm11.h b/src/target/arm11.h index f3f0644..421f8d1 100644 --- a/src/target/arm11.h +++ b/src/target/arm11.h @@ -53,9 +53,10 @@ struct arm11_common /** Debug module state. */ struct arm_dpm dpm; + struct arm11_sc7_action *bpwp_actions; + unsigned bpwp_n; size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */ - size_t wrp; /**< Number of Watchpoint Register Pairs from DIDR */ size_t free_brps; /**< Number of breakpoints allocated */ uint32_t dscr; /**< Last retrieved DSCR value. */ diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index e37ad56..9ad5662 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -892,7 +892,7 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions */ void arm11_sc7_clear_vbw(struct arm11_common * arm11) { - size_t clear_bw_size = arm11->brp + arm11->wrp + 1; + size_t clear_bw_size = arm11->brp + 1; struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size); struct arm11_sc7_action * pos = clear_bw; @@ -905,11 +905,6 @@ void arm11_sc7_clear_vbw(struct arm11_common * arm11) for (size_t i = 0; i < arm11->brp; i++) (pos++)->address = ARM11_SC7_BCR0 + i; - - for (size_t i = 0; i < arm11->wrp; i++) - (pos++)->address = ARM11_SC7_WCR0 + i; - - (pos++)->address = ARM11_SC7_VCR; arm11_sc7_run(arm11, clear_bw, clear_bw_size); @@ -1013,6 +1008,88 @@ static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm, opcode, data); } +/* Because arm11_sc7_run() takes a vector of actions, we batch breakpoint + * and watchpoint operations instead of running them right away. Since we + * pre-allocated our vector, we don't need to worry about space. + */ +static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index, + uint32_t addr, uint32_t control) +{ + struct arm11_common *arm11 = dpm_to_arm11(dpm); + struct arm11_sc7_action *action; + + action = arm11->bpwp_actions + arm11->bpwp_n; + + /* Invariant: this bp/wp is disabled. + * It also happens that the core is halted here, but for + * DPM-based cores we don't actually care about that. + */ + + action[0].write = action[1].write = true; + + action[0].value = addr; + action[1].value = control; + + switch (index) { + case 0 ... 15: + action[0].address = ARM11_SC7_BVR0 + index; + action[1].address = ARM11_SC7_BCR0 + index; + break; + case 16 ... 32: + index -= 16; + action[0].address = ARM11_SC7_WVR0 + index; + action[1].address = ARM11_SC7_WCR0 + index; + break; + default: + return ERROR_FAIL; + } + + arm11->bpwp_n += 2; + + return ERROR_OK; +} + +static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index) +{ + struct arm11_common *arm11 = dpm_to_arm11(dpm); + struct arm11_sc7_action *action; + + action = arm11->bpwp_actions + arm11->bpwp_n; + + action[0].write = true; + action[0].value = 0; + + switch (index) { + case 0 ... 15: + action[0].address = ARM11_SC7_BCR0 + index; + break; + case 16 ... 32: + index -= 16; + action[0].address = ARM11_SC7_WCR0 + index; + break; + default: + return ERROR_FAIL; + } + + arm11->bpwp_n += 1; + + return ERROR_OK; +} + +/** Flush any pending breakpoint and watchpoint updates. */ +int arm11_bpwp_flush(struct arm11_common *arm11) +{ + int retval; + + if (!arm11->bpwp_n) + return ERROR_OK; + + retval = arm11_sc7_run(arm11, arm11->bpwp_actions, arm11->bpwp_n); + arm11->bpwp_n = 0; + + return retval; +} + /** Set up high-level debug module utilities */ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr) { @@ -1032,11 +1109,22 @@ int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr) dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc; dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0; + dpm->bpwp_enable = arm11_bpwp_enable; + dpm->bpwp_disable = arm11_bpwp_disable; + retval = arm_dpm_setup(dpm); if (retval != ERROR_OK) return retval; + /* alloc enough to enable all breakpoints and watchpoints at once */ + arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp), + sizeof *arm11->bpwp_actions); + if (!arm11->bpwp_actions) + return ERROR_FAIL; + retval = arm_dpm_initialize(dpm); + if (retval != ERROR_OK) + return retval; - return retval; + return arm11_bpwp_flush(arm11); } diff --git a/src/target/arm11_dbgtap.h b/src/target/arm11_dbgtap.h index 2c586cc..3139a09 100644 --- a/src/target/arm11_dbgtap.h +++ b/src/target/arm11_dbgtap.h @@ -59,5 +59,6 @@ int arm11_read_memory_word(struct arm11_common *arm11, uint32_t address, uint32_t *result); int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr); +int arm11_bpwp_flush(struct arm11_common *arm11); #endif // ARM11_DBGTAP_H commit f4651c869fb0bbe00495a09470af0a934814c92a Author: David Brownell <dbr...@us...> Date: Fri Dec 4 18:57:30 2009 -0800 ARM11: tweak TAP ops and debugging Tweak scanchain 7 debug messaging: - show register addresses in decimal, matching ARM docs; - remove some pointless noise Avoid some needless roundtrips: - skip SCAN_N when SCREG already holds that number (speeds up polling and other common operations) - avoid zeroing vcr twice on resume Show the IR opcode as a label ("RESTART") too; and in decimal, matching ARM docs. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm11.c b/src/target/arm11.c index 20ad22d..b05ef30 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -513,7 +513,8 @@ static int arm11_resume(struct target *target, int current, brp_num++; } - arm11_sc7_set_vcr(arm11, arm11_vcr); + if (arm11_vcr) + arm11_sc7_set_vcr(arm11, arm11_vcr); } arm11_leave_debug_state(arm11, handle_breakpoints); @@ -1133,7 +1134,7 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp) arm11->jtag_info.tap = target->tap; arm11->jtag_info.scann_size = 5; arm11->jtag_info.scann_instr = ARM11_SCAN_N; - /* cur_scan_chain == 0 */ + arm11->jtag_info.cur_scan_chain = ~0; /* invalid/unknown */ arm11->jtag_info.intest_instr = ARM11_INTEST; return ERROR_OK; diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index e5d3f80..e37ad56 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -91,6 +91,38 @@ void arm11_setup_field(struct arm11_common * arm11, int num_bits, void * out_dat field->in_value = in_data; } +static const char *arm11_ir_to_string(uint8_t ir) +{ + const char *s = "unknown"; + + switch (ir) { + case ARM11_EXTEST: + s = "EXTEST"; + break; + case ARM11_SCAN_N: + s = "SCAN_N"; + break; + case ARM11_RESTART: + s = "RESTART"; + break; + case ARM11_HALT: + s = "HALT"; + break; + case ARM11_INTEST: + s = "INTEST"; + break; + case ARM11_ITRSEL: + s = "ITRSEL"; + break; + case ARM11_IDCODE: + s = "IDCODE"; + break; + case ARM11_BYPASS: + s = "BYPASS"; + break; + } + return s; +} /** Write JTAG instruction register * @@ -110,7 +142,7 @@ void arm11_add_IR(struct arm11_common * arm11, uint8_t instr, tap_state_t state) return; } - JTAG_DEBUG("IR <= 0x%02x", instr); + JTAG_DEBUG("IR <= %s (0x%02x)", arm11_ir_to_string(instr), instr); struct scan_field field; @@ -135,7 +167,8 @@ static void arm11_in_handler_SCAN_N(uint8_t *in_value) jtag_set_error(ERROR_FAIL); } - JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v); + if (v != 0x10) + JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v); } /** Select and write to Scan Chain Register (SCREG) @@ -150,6 +183,9 @@ static void arm11_in_handler_SCAN_N(uint8_t *in_value) * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default * value (Pause-DR). * + * Changes the current scan chain if needed, transitions to the specified + * TAP state, and leaves the IR undefined. + * * The chain takes effect when Update-DR is passed (usually when subsequently * the INTEXT/EXTEST instructions are written). * @@ -162,9 +198,19 @@ static void arm11_in_handler_SCAN_N(uint8_t *in_value) * \remarks This adds to the JTAG command queue but does \em not execute it. */ -int arm11_add_debug_SCAN_N(struct arm11_common * arm11, uint8_t chain, tap_state_t state) +int arm11_add_debug_SCAN_N(struct arm11_common *arm11, + uint8_t chain, tap_state_t state) { - JTAG_DEBUG("SCREG <= 0x%02x", chain); + /* Don't needlessly switch the scan chain. + * NOTE: the ITRSEL instruction fakes SCREG changing; + * but leaves its actual value unchanged. + */ + if (arm11->jtag_info.cur_scan_chain == chain) { + JTAG_DEBUG("SCREG <= %d SKIPPED", chain); + return jtag_add_statemove((state == ARM11_TAP_DEFAULT) + ? TAP_DRPAUSE : state); + } + JTAG_DEBUG("SCREG <= %d", chain); arm11_add_IR(arm11, ARM11_SCAN_N, ARM11_TAP_DEFAULT); @@ -791,30 +837,31 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions } else { - nRW = 0; + nRW = 1; DataOut = 0; AddressOut = 0; } do { - JTAG_DEBUG("SC7 <= Address %02x Data %08x nRW %d", + JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", (unsigned) AddressOut, (unsigned) DataOut, - nRW); + nRW ? "write" : "read"); arm11_add_dr_scan_vc(ARRAY_SIZE(chain7_fields), chain7_fields, TAP_DRPAUSE); CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("SC7 => Address %02x Data %08x Ready %d", - (unsigned) AddressIn, - (unsigned) DataIn, - Ready); + if (!Ready) + JTAG_DEBUG("SC7 => !ready"); } while (!Ready); /* 'nRW' is 'Ready' on read out */ + if (!nRW) + JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn); + if (i > 0) { if (actions[i - 1].address != AddressIn) @@ -835,15 +882,6 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions } } } - - for (size_t i = 0; i < count; i++) - { - JTAG_DEBUG("SC7 %02d: %02x %s %08x", - (unsigned) i, actions[i].address, - actions[i].write ? "<=" : "=>", - (unsigned) actions[i].value); - } - return ERROR_OK; } @@ -892,7 +930,6 @@ void arm11_sc7_set_vcr(struct arm11_common * arm11, uint32_t value) set_vcr.address = ARM11_SC7_VCR; set_vcr.value = value; - arm11_sc7_run(arm11, &set_vcr, 1); } ----------------------------------------------------------------------- Summary of changes: NEWS | 2 + src/target/arm11.c | 26 ++++++- src/target/arm11.h | 3 +- src/target/arm11_dbgtap.c | 181 ++++++++++++++++++++++++++++++++++++++------- src/target/arm11_dbgtap.h | 1 + 5 files changed, 181 insertions(+), 32 deletions(-) hooks/post-receive -- Main OpenOCD repository |