ESP8266 SDK: how to debug with gdb

by kacang bawang

Not long ago, to little fanfare, Espressif (the makers of ESP8266) released gdbstub – a library that allows use of gdb on ESP8266. It works with both non-OS and RTOS SDKs, and works over UART, not JTAG. You get 1 breakpoint for RAM and 1 breakpoint for FLASH. Is this awesome, or what!? Authorship is unattributed, but is believed to have been written by Sprite_tm.

In this post, I will show you how to add gdb support to your project. This example will use the RTOS SDK, but applies just the same to the non-OS SDK.

First, let’s talk a little bit about project organization. We will use esp-open-sdk on Linux. See previous articles about setting up non-os and rtos sdks.

I will skip over parts of the setup that have been discussed in the previous articles. You can find the exact copy of this project here, to use as a reference.

First, clone the git repository for the gdbstub somewhere locally. Then, set up the following folder structure.

Each directory inside src is compiled into its own .a. Then, the outer makefile rolls them into flash.bin and irom0text.bin.

Thus, gdbstub is added as a module, inside its own directory. Now, we need to connect it to the rest of the project.

First, we need a “module makefile” inside the directory. As a base, we will use the one found inside src/user/. I realize that there is already a Makefile inside the gdbstub, but it gives errors with the latest RTOS SDK.

Take src/user/Makefile copy (and overwrite) into src/gdbstub/, and within, change the GEN_LIBS line to look like:

Then, edit the “inner makefile” in src/Makefile to look like:

Now let’s take a look at some small tweaks to the source of gdbstub. The only file we need to modify is gdbstub.c

Lastly, let’s add an instruction to wait for debugger to attach into user_main.c.

Now we can compile by running make on the “outer makefile” and flash the resulting output from ./bin.

Ok, but how to we launch into a debug session? Use gdbcmds file from gdbstub like this:

Make sure that /dev/ttyUSBx specified in gdbcmds matches what is found /dev. Now we find ourselves at a gdb prompt:

We can either just continue (c) or set a breakpoint in RAM or FLASH. Breakpoints in RAM are set with br, while breakpoints in FLASH are set with hbr. Remember, we only have 1 of each.

Stepping is possible only in RAM. So, if you need to step through a function, make sure to place it into ram like this:

By default (without any *_ATTR) code is placed into FLASH. If you try to step through a function located in FLASH you will see an error message like this:

Happy debugging!