This is an automated email from Gerrit. "Antonio Borneo <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9563
-- gerrit commit 61469cf5439fd03b472c844bca0c1d85aafc39fa Author: Antonio Borneo <[email protected]> Date: Fri Apr 3 15:59:41 2026 +0200 cortex_a: allow resume over synchronous watchpoint The ARMv7-A/R specification reports that watchpoints hit can be handled either synchronous or asynchronously. Synchronous watchpoints halt at the instruction that accessing the memory triggers it, without executing the instruction nor the associated memory access. A command resume or step will then execute again that instruction and will trigger the watchpoint again, which is annoying. Asynchronous watchpoints halt few instructions after the one that triggered the watchpoint, when the memory access is already done. A command resume or step will correctly execute the following instructions. Modify the resume code to detect the synchronous watchpoints case and run a preliminarily single step across the instruction that hits the watchpoint. The code for single-step is already able to disable the watchpoint. Change-Id: I78593371624a9c799eb838f2590e86e314fa6c7f Signed-off-by: Antonio Borneo <[email protected]> diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 27fafe3d82..e215753402 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -71,6 +71,8 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint); static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint); +static int cortex_a_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints); static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask, uint32_t value, uint32_t *dscr); static int cortex_a_mmu(struct target *target, bool *enabled); @@ -897,11 +899,25 @@ static int cortex_a_halt(struct target *target) static int cortex_a_internal_restore(struct target *target, bool current, target_addr_t address, bool handle_breakpoints, bool debug_execution) { + struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; int retval; uint32_t resume_pc; + /* + * if halted on precise watchpoint, run a single step to skip the current + * instruction, then continue + */ + if (current && target->debug_reason == DBG_REASON_WATCHPOINT && + DSCR_ENTRY(cortex_a->cpudbg_dscr) == DSCR_ENTRY_PRECISE_WATCHPT) { + retval = cortex_a_step(target, true, 0, handle_breakpoints); + if (retval != ERROR_OK) + return retval; + + LOG_INFO("Now PC is 0x%08" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); + } + if (!debug_execution) target_free_all_working_areas(target); --
