pyOCD icon indicating copy to clipboard operation
pyOCD copied to clipboard

Strange behavior while debugging application w/ interrupts

Open danielRep opened this issue 3 years ago • 4 comments

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.

danielRep avatar Nov 10 '20 12:11 danielRep

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.

flit avatar Nov 14 '20 21:11 flit

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:

  1. standard boot routine (copy data to ram, zeroize bss section, init stack pointer)
  2. init routine which initializes some architectural features (init vtor, enable all fault handlers)
  3. 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

danielRep avatar Nov 16 '20 11:11 danielRep

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?

danielRep avatar Nov 24 '21 16:11 danielRep

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!)

flit avatar Nov 24 '21 19:11 flit