Skip to content

Commit 23d8831

Browse files
committed
target: avoid polling during 'resumed' event handler
OpenOCD is based on a single main loop that schedules all the activities. At the execution of a TCL command, the timestamp is checked to eventually trigger the polling of the targets. This means that by executing a TCL command the polling can be triggered and detect a change of target's state. When openocd 'resumes' a target, the target can halt again by hitting a breakpoint. The 'resumed' event handler is started just after the target has been resumed, but it triggers a polling before the execution of its very first instruction. If the polling finds the target halted, it will run the 'halted' event handler, that will then be executed 'before' the pending 'resumed' handler. In case of gdb, a 'continue' command will restart the target but, polling (and halt detection) executed before the end of the resume process will hide the halt. As a consequence, the gdb will not be informed of the halt and will remains waiting as if the target is still running without showing the prompt. This can be verified by running on the target a firmware with a loop, run openocd with a dummy 'resumed' event, and let gdb to set a breakpoint in the loop. A 'continue' command will cause the target to halt again by hitting the breakpoint at the next loop iteration, but gdb will loose it and will not return the prompt. openocd -f board/st_nucleo_f4.cfg -c \ 'stm32f4x.cpu configure -event resumed {echo hello}' arm-none-eabi-gdb -ex 'target remote :3333' -ex 'b *$pc' -ex c Disable the polling while executing target's resume(). Document it and provide hints to developers to cope with future implementation. Change-Id: I3be830a8e7c2ef6278617cb4547a4d676b0ddeb5 Signed-off-by: Antonio Borneo <[email protected]> Reported-by: Габитов Александр Фаритович <[email protected]> Reviewed-on: http://openocd.zylin.com/6074 Reviewed-by: Tomas Vanek <[email protected]> Tested-by: jenkins
1 parent ba0f382 commit 23d8831

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

doc/openocd.texi

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5035,6 +5035,19 @@ when reset disables PLLs needed to use a fast clock.
50355035
@* After target hardware trace configuration was changed
50365036
@end itemize
50375037

5038+
@quotation Note
5039+
OpenOCD events are not supposed to be preempt by another event, but this
5040+
is not enforced in current code. Only the target event @b{resumed} is
5041+
executed with polling disabled; this avoids polling to trigger the event
5042+
@b{halted}, reversing the logical order of execution of their handlers.
5043+
Future versions of OpenOCD will prevent the event preemption and will
5044+
disable the schedule of polling during the event execution. Do not rely
5045+
on polling in any event handler; this means, don't expect the status of
5046+
a core to change during the execution of the handler. The event handler
5047+
will have to enable polling or use @command{$target_name arp_poll} to
5048+
check if the core has changed status.
5049+
@end quotation
5050+
50385051
@node Flash Commands
50395052
@chapter Flash Commands
50405053

src/target/target.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,18 @@ int target_resume(struct target *target, int current, target_addr_t address,
637637
* we poll. The CPU can even halt at the current PC as a result of
638638
* a software breakpoint being inserted by (a bug?) the application.
639639
*/
640+
/*
641+
* resume() triggers the event 'resumed'. The execution of TCL commands
642+
* in the event handler causes the polling of targets. If the target has
643+
* already halted for a breakpoint, polling will run the 'halted' event
644+
* handler before the pending 'resumed' handler.
645+
* Disable polling during resume() to guarantee the execution of handlers
646+
* in the correct order.
647+
*/
648+
bool save_poll = jtag_poll_get_enabled();
649+
jtag_poll_set_enabled(false);
640650
retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution);
651+
jtag_poll_set_enabled(save_poll);
641652
if (retval != ERROR_OK)
642653
return retval;
643654

0 commit comments

Comments
 (0)