Discuss here different C compiler set ups, and compiling executables for the ESP8266

User avatar
By projectgus
#18016
cal wrote:Can you do me a favor?
As far as I understand the OCD/JTAG/whatever stuff the gdb communitates with some JTAG speaking
gdbserver.
Do you have access to the logs of such a communication between gdb and gdb server from the startup to
some single stepping and continue?
I would like to clarify how some gdb stuff is used on a bare metal target.


Your understanding is right, the gdbserver (here it would be openocd or xt-ocd) talks via JTAG to the esp8266 and via the gdb remote protocol to gdb.

You can produce gdb remote protocol logs with gdb itself:

Code: Select allset debug remote 1


Setting this in gdb should cause it to print every gdb protocol packet to/from the gdbserver. There's a detailed description of the remote protocol in the gdb manual.

If you're using openocd then running with the '-d' command line argument will produce a fairly detailed log of the JTAG operations at the OCD TAP level. This is a different view to the gdb commands, but you can usually infer what gdb asked for (ie if it's reading memory then gdb just asked for a memory read, or if it's reading registers then gdb is refreshing register state after a halt, etc.)

Where things can get complex from a "debugging the debugger" point of view is that openocd (or xt-ocd, although I don't know anything about it) will also cache the status of the target in various ways, because it can't query much while the target is running - only when halted. Also the ocd tool manipulates the state of registers itself in order to do things like read/write memory, but it restores the registers to the program values whenever it resumes execution. The OCD tool hides those low-level debug manipulations from gdb.

One other command worth mentioning is:

Code: Select allset debug xtensa X


where X is a level 0-4 I think (check the help). This enables printing of the debug lines from the XTensa gdb support, which is handy if you're trying to figure out processes like stack unwinding! My debugging of openocd so far has used this feature and the '-d' output of openocd.

Angus
User avatar
By cal
#18023 Moin Angus,

thanks for the information!
I don't have a jtag hardware so I can't create a remote log myself.
The remote debug log is exactly what i need.
It would be great if you can provide one for me!
I am studying the gdb rsp and need some details about some command results
when used on a bare metal target. I can test against a linux gdbserver to see a running
"big" target but need a "tiny" example.

Thanks,
Cal
User avatar
By cal
#18024 Hello again!

i have some more questios, i hope you don't mind ...

How to you typically start a ocd debugging session?
Setting breakpoints upfront and then starting the hardware?
Calling into the debugger using a break op code?
Using some ctrl-c or break signal to interrupt the cpu?
What ways to continue after break?
Do you have to manipulate the cpu state before continue?
E.g. set $pc += 3 or the like?
I struggle with "c" (continue) vs. "Cxx" (continue with signal).
What happens with interrupts when single stepping?
int 1 level interrupts execute callbacks on intlevel 0 and so single stepping may be suddenly applied to that code
if not taken care of. I wonder, how?

So many questions, so little time. :?

Thanks for your time,
Cal
User avatar
By projectgus
#18343
cal wrote:How to you typically start a ocd debugging session?
Setting breakpoints upfront and then starting the hardware?
Calling into the debugger using a break op code?
Using some ctrl-c or break signal to interrupt the cpu?


If I'm debugging on a different platform, like ARM Cortex-M, I'll often run a 'reset halt' in openocd which resets the CPU and then halts it immediately after reset, PC still set to the reset vector address, before any instructions are executed. Once it halts you can set the breakpoints you want in gdb, and run 'continue' from gdb to get it to run.

Once the breakpoints are set, gdb will keep them set through future 'reset halt' cycles.

Sometimes I'll press ctrl-c to randomly halt a running CPU 'now', if I don't understand what's happening (usually it's gotten stuck in an infinite loop somewhere).

On esp8266, there's not a proper 'reset halt' yet (at least on openocd) so it's a bit more haphazard. My technique so far has been to halt as soon as possible after reset and set up the debugger state then. Which works OK as long as you're not debugging early startup code.

Also, as you've mentiond, with esp8266 you only have one hardware breakpoint so you have to keep deleting the current breakpoint after you add a new one (the breakpoints don't get written to the hardware until you 'continue'). On a "normal" platform openocd will tell gdb where the flash regions vs the RAM regions of the address space are, so gdb will automatically choose soft vs hard breakpoints depending on the target address. This isn't supported yet for openocd, it might work for xt-ocd!

I have once or twice used:

Code: Select allasm("break 0, 0");


... to compile in a software breakpoint.

cal wrote:What ways to continue after break?


Usually I just type 'c' in gdb.

cal wrote:Do you have to manipulate the cpu state before continue?
E.g. set $pc += 3 or the like?
I struggle with "c" (continue) vs. "Cxx" (continue with signal).


You can do this, but you don't need to for normal execution if you just want to continue from the next instruction.

There's also 'step', si/stepi, finish. All worth looking at (see 'help xxx' for a quick summary.

cal wrote:What happens with interrupts when single stepping?
int 1 level interrupts execute callbacks on intlevel 0 and so single stepping may be suddenly applied to that code
if not taken care of. I wonder, how?


Openocd should step into an int1 interrupt handler if you're stepping and an interrupt comes. I don't know about xt-ocd.

The single higher level interrupt (NMI) is currently ignored by the debugger due to the debug level set by openocd. I want to change eventually so it's an openocd parameter, so you can into the NMI handler if you want (or alternatively you could set it so that you don't step into interrupt handlers). The NMI seems to be called a lot (it's related to the radio layer), so it can be quite confusing to constantly step into it!

Remember that the debug (interrupt) level is a CPU state not something in the code, so if level 1 interrupt calls a callback in your code then the CPU debug level stays at level 1, until the callback returns and the interrupt handler ends. (Unless I'm misunderstanding the question.)