pyOCD
pyOCD copied to clipboard
Strange behavior while debugging application w/ interrupts
Hi all, I decided to open this issue while not having complete certainty that the problem I'm facing is directly related with pyocd and if so, forgive me for the possible error.
I have been using pyocd for quite some time. I mostly work with Arm's Musca A1/B1 platforms and until some weeks ago I was only working with pyocd 0.24.1 version (pyocd-gdbserver called by the eclipse plugin). When I decided to upgrade pyocd (v0.28.2) I started to experience unexpected behavior with the application that I'm developing. The secure code running in the secure state is periodically called by the secure systick timer. On the non-secure state, I have a simple timer interrupting the processor from time to time. While I was able to debug successfully both handlers, when I upgraded pyocd interrupts stopped triggering in debug mode. While trying to find a solution without having to downgrade pyocd, I notice the following argument option "-C" (VECTOR_CATCH). Since I started using this option ("pyocd gdb -C all"), the interrupt behavior of my application started working again normally during debugging sessions.
My question is if this behavior is expected since when I read what the option did, it didn't seem to be related to the problem I was having.
Hi @danielRep, thanks for asking about this. At first glance, I can't think of what would cause that change in behaviour. Or why vector catch would affect interrupt behaviour! Vector catch should only cause a debug event on exceptions, not interrupts.
Can you describe what you mean by "interrupts stopped triggering in debug mode" in more detail? A step by step description of what you (and your code) is doing, and where the behaviour diverges.
I'll review the changes since v0.24.1 and see if anything stands out.
Hi @flit , I will try to explain everything in detail.
I just simplified the example that I'm working now and I'm experiencing the same erratic behavior. As I told you, I'm working with a Musca-B1 platform. The program that I'm loading to the board is composed by the following pieces of code:
- standard boot routine (copy data to ram, zeroize bss section, init stack pointer)
- init routine which initializes some architectural features (init vtor, enable all fault handlers)
- init systick and enable it.
So, as you see my code is simply enabling the system timer and what I would expect is to get an exception from time to time related with the systick. During a debug session I simply add a hardware breakpoint (through Eclipse interface) into the systick exception handler and after resuming execution from the reset handler I would except that processor to be halted on that same breakpoint. The tricky part is that this happens only if I pass the "-C all" option to the gdbserver provided by pyocd, which is really strange. I can share the code with you if needed (privately if possible).
I hope I made my self clear.
PS: I don't know if it is relevant, but I am doing all of these tests in RAM memory to avoid having to flash my program which takes a lot of more cycles of productivity :) Ty! Tools info: pyocd v0.28.3 GNU gdb (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 8.3.0.20190709-git
Hi @flit ,
I'm getting back to this issue since I was dragged again to work with the musca boards (a1 and b1) and faced this problem again. However, I still didn't been able to deep dive in the problem I somehow managed to circumvent a workaround which I totally don't know for sure how is it working. Maybe you can have a better reasoning and help me solve and close this issue.
Basically, when I face this problem I try to perform a reset on the target with a specified type (sysresetreq or vectreset) and somehow I got the systick interrupt firing again.
EDIT1: After diving a little bit, in Arvm8M processors the VECTRESET bit was removed and only SYSRESETREQ is in place. I notice to in this code block in pyocd
# Fall back to emulated sw reset if the vectreset is specified and the core doesn't support it.
if (reset_type is Target.ResetType.SW_VECTRESET) and (not self._supports_vectreset):
reset_type = Target.ResetType.SW_EMULATED
As I understand, if the core doesn't support VECTRESET, pyocd performs a emulated reset. I tested, and somehow it works. So If I follow this procedure in GDB, all interrupts stop working:
target remote localhost:3333
monitor reset
load
monitor continue
On the other hand If I follow this procedure in GDB, all interrupts start working:
target remote localhost:3333
monitor reset emulated
load
monitor continue
I must notice that initiating pyocd as -C all
Do you have any hint what could be happening here?
H @danielRep. That is quite strange.
You are correct that v8-M dropped VECTRESET
. Kind of a pain, but there were good reasons for it as I understand (mostly around synchronisation of busses, potential outstanding requests, and similar concerns).
My guess is that the reset via SYSRESETREQ isn't actually performing a reset, while the emulated processor reset restores some register to a default value that fixes your problem. I've seen a lot of reset related issues on the Musca devices…
One thing you might try in order to verify this is to use a hardware reset (-Oreset_type=hw
). You'll probably need to use the latest pyocd version that automatically recovers from a lost DP connection after reset, since I think the Musca chips reset debug resources on a hardware reset.
Btw, is it possible for you to share your code (confidentially if you wish) so I can try to reproduce? I have all the Musca boards available for testing. You can send me an email if you'd like: see my profile @flit for the address. (I'm also curious in your research!)