0

Is there a way to put a breakpoint in trace32, when a particular core executes a statement.

I have a quad-core cortex-a7 board (raspberry pi 2). I am able to connect to it, put breakpoints (only for core 0 right now), but i want trace32 to hit the breakpoint only when a particular core executes the breakpoint code. Say for e.g. core 3 executes it.

Presently breakpoint is hit only with core-0. I have written a simple program, that outputs 0-9 to the UART. Also when i run any program inside trace32, by loading it directly to RAM, only core 0 seems to be executing, and it repeatedly goes into "stopped by vector catch", but when i try it by loading the program in sdcard/flash memory, all four cores seem to be executing.

I have checked the uart output, by both activating other cores and deactivating them, and it seems the cores do get activated and deactivated accordingly.

The uart output when the core is deactivated is proper/in order (printing a series from 0 to 9), when the cores are active, its mixed (print of 0-9 are not in order), proving my assumption.

Also when it stops at a breakpoint for core 0, if i select other cores from the drop down menu in trace32 status bar, the other cores are executing different statements. i.e. The pc is different for different cores.

I tried using conditional breakpoints, something like

break.set myfunc\7   /COND core()==3

but that seems to be not working.

Any help appreciated. Thanks in advance

tarkshya
  • 1
  • 2

3 Answers3

0

Actually there is something weird, so far I remember, each time you place a breakpoint it is enabled for all the debug resources of the cores, that is, for all the cores. So, seems like if you are not enabling all the cores when debugging your application. How do you start the cores? Are you using any operating system? Or is just a bare metal application?

juansolsona
  • 186
  • 7
  • its bare metal, uses the UART (on the raspi 2), and prints 0-9. my config file activates all the cores (as per raspi forum) on boot --- kernel_old=1 kernel_address=0x0 disable_commandline_tags=1 ----- The uart output confirms this, when i use the above config file, the uart output is mixed, i.e. 0-9 is not in order, as different cores are executing and each one trying to print its series. Without config file, it prints 0-9 in order, confirming only core 0 executes. In trace32, i can see different cores are at different statements, when i manually break and use the above config. – tarkshya May 27 '16 at 17:48
0

You could check that your command for setting breakpoints is correct by calling the function containing the breakpoint directly from different cores:

Break.set encode\7  /COND Core()==3.   // Breakpoint command we want
                                       // to check

Break.set sYmbol.EXIT(encode)  // Set a breakpoint to the end of 
                               // the function  

Var.Call encode(&string)   // Call “encode” with parameter &string
                           // and halt at first instruction

Go   // Restart all cores

The command Frame.Swap is useful in this context. It is described here.

 Frame.SWAP  // Restore initial state of registers

You could also switch to a logging-based approach as described here.

To check if the core-selective command is working:

  1. Execute for core 0 ---> Core should stop at the end of the function
  2. Execute for core 3 ---> Core should stop at the first breakpoint

If you see this behaviour, you have a pretty good confirmation that the core-selective breakpoint is working correctly. If you get a positive outcome, the next step would be to find out why only core 0 is entering this function.

If you want to get an idea what the other cores are doing you could give sample-based profiling a try. Beware that it is not highly accurate. Please check the documentation for the command PERF.

Another option is the command Snooper to track the program counter periodically.

xasc
  • 181
  • 5
  • when i do var.set myfunc (from another core), whether i call frame.swap or not, i get - "target function call failed, pc not at expected location" the first time & breakpoint is hit from a another core too (after the info msg). Subsequent calls to var.set works, without the msg. With the logging method, functions is called, Brk pt is hit and it prints core 0. I am pretty sure, other cores are executing, as when the Bkpt is hit & i switch cores, the cores have different PC. UART too proves that. But the original problem still remains, unable to set breakpoint for cores others than 0. – tarkshya May 28 '16 at 04:36
  • The error message is just an effect of the breakpoint that is hit. Usually TRACE32 would restore the initial context after completion of the function call. The breakpoint prevents this from happening. Your application could be put into an unstable state. Most likely the command `Var.call` is a better choice here. Afterwards simply use `Frame.Swap`. – xasc May 28 '16 at 11:25
  • i tried your suggestions, i am individually able to call the methods per core, but when i do "GO", it breaks only on core 0. Sometimes it breaks only for core 1. At any point only one core is hit. The core()==3 condition is never satisfied during runtime. Am just selecting the core from the status bar context menu and executing the commands, or is there any other way to do it? – tarkshya May 31 '16 at 15:27
0

You are obviously using TRACE32 in SMP configuration (one GUI for all cores) and not AMP configuration (one GUI per core). In SMP configuration a program breakpoints is always set for all cores.

By setting your breakpoint with /CONDition <expr> the breakpoints will still stop any core. However, the debugger will restart any core immediately which does not meet the condition. So Break.Set myfunc\7 /CONDition CORE()==3 will stop any core in line 7 of myfunc(), but TRACE32 restarts any core which is not your 4th core.

Please consider: If you set a breakpoint to a writeable program address (in SRAM/DRAM) the debugger will use software breakpoints: A breakpoint instruction gets patched in your application code. So as long as all your cores execute the same code from the same memory location they must stop.

So maybe some cores do not stop, because they do not execute the same code from the same memory location: Either you have the same code multiple times in memory for different cores. Or you have a caching issue.

If you assume a caching issue try to set the breakpoint as an onchip-breakpoint: Break.Set myfunc\7 /CONDition CORE()==3 /Onchip


In general, if you cores works find from SD card but not in debugger, it is very likely that you are missing some configuration, which is done by a bootloader or so when you start from SD card. Consider that TRACE32 normally starts from your reset vector, while processors normally execute some bootloader code to get an application from and SD card.

If you assume that your problem is caused by the debugger, you should contact the Lauterbach support, I guess.

Holger
  • 3,920
  • 1
  • 13
  • 35
  • i tried using onchip breakpoints, the result is the same, conditional breakpoints are not hit for any core. Breakpoint (both onchip/soft) is hit for core 0 (strangely sometimes its core 1) only. I am booting my Raspberry Pi 2 from an SD card, that activates the JTAG, then use trace32 to load my bare metal app. I have tried this successfully with the single core raspi-1, but this cortex version it doesnt work as expected. If somebody is willing to try it on his system, i can mail my program. People have reported that such a setup works with openocd, then why not trace32? – tarkshya May 31 '16 at 17:59
  • When you connect to your board, do you use SYStem.Up or SYStem.Attach? If you've executed bootcode from SD card it should be "attach", to avoid any core reset. – Holger May 31 '16 at 18:47
  • How do you load your bare-metal program to the target memory? If you do a simple `Data.LOAD.Elf myprog.elf` you will download the code to memory, load the debug symbols to the debugger and set the program counter *of the active core* to the entry point of your application. I think you should load the code via the SD card, let the bootloader handle the program counter initialization and just load the symbols to the debugger with `Data.LOAD.Elf myprog.elf /NoCODE` – Holger May 31 '16 at 18:59
  • System.attach doesnt work, goes into a "vector catch" for core 0 (I tried your suggested method loading the code via SD card, then a System.attach + "Data.LOAD.Elf myprog.elf /NoCODE"). The standard way with Raspberry Pi 2 is to load a separate program to activate the JTAG pins (on GPIO) and use a script to load the main program. lauterbach's own example script for raspberry pi 1( single core) gives this method. Would it be possible for you to try at your end? i can mail you the program and the trace32 script. – tarkshya May 31 '16 at 19:56
  • I'd love to test this on my end. Unfortunately I have no access to a Raspberry during the next 6 days. Maybe you should contact Lauterbach in between. They usually respond rather quick. – Holger May 31 '16 at 21:10
  • I've also heard that you need a special bootloader on the SD card to enable JTAG. But I understood that you have that on your card. So two ideas you can try. Idea 1: Put you application on the card. Then do a SYStem.Up, load you symbols with NoCODE, set you breakpoint as an onchip breakpoint and then hit GO to start the CPUs. Idea 2: Just load you application as normal via the debugger and then set the Program Counter of all cores manually to your applications entry point. E.g: `Register.Set PC _start /CORE 3` – Holger May 31 '16 at 21:25
  • Tried both ideas, idea 1, as mentioned in my previous comment, didnt yield anything, was going into a vector catch (using system.up was not working at all, had to use system.attach). I didnt understand what to do with idea 2, if it was to check that others cores are executing, i have mentioned that they are, or probably i didnt understand your 2nd idea, forgive me for my ignorance. – tarkshya Jun 01 '16 at 03:48
  • I've just seen that there is a tiny multicore example for Rasberry Pi 2 on the Lauterbach Website (at Downloads > Scripts). Have you already tried that one? – Holger Jun 01 '16 at 17:50
  • Yes, tried it without any success. That script doesnt specify any method of setting per core breakpoints. Though i have also sent a mail to their support. – tarkshya Jun 01 '16 at 23:54