ESP8266: Offline Debugging with the Platformio Environment

Having tools is great but you also need to know how to use them. Being a native Java speaker using a debugger is a very natural and easy thing. With the ESP8266 on the other hand this looks a bit different. I struggled now for a half day to figure out how to use the debugger to resolve a nasty crash that was happening if I would use a NFC card reader several times in a row. Most of the time I tried to use life debugging as I was used from the Java world and it still doesn’t work. The debugger connects perfectly fine to the serial console (using the tcp_serial_redirect.py script) but then just waits after printing Remote debugging using localhost:9980. Please let me know if you have an idea what might be the problem.


But it turns out that life debugging wasn’t even necessary: you can use the crash information also offline to figure out what function was responsible for the crash!

Preparing the binary

These days I am using the platform.io environment with the Atom editor to do my ESP8266  development. In order to have enough information in the binary you have to add some flags to the platformio.ini. In the section for your target platform add:

 

build_flags = -Og -ggdb -DDEBUG_ESP_PORT=Serial



which will cause the compiler to create a binary containing the symbol information required for debugging. Save it and make sure that the whole workspace gets re-compiled.. Upload it, start the serial console and provoke the crash:

 

Fatal exception 0(IllegalInstructionCause):
epc1=0x4020188c, epc2=0x00000000

 

Related:  #ESP8266: Open-Source Designer Advice wanted for the weather station!

The interesting part here is the epc1 address, which is the program counter.

Finding the culprit

The next step was to figure out where the debugger was installed for the platformio environment.
On a Mac you can (currently) find it here:

~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-gdb

 Now you can start it by telling it where your binary is:

 

~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-gdb ./.pioenvs/nodemcuv2/firmware.elf

(assuming that you are in the root of your project folder). The debugger should great you with:

Reading symbols from .pioenvs/nodemcuv2/firmware.elf...done. (gdb)

Now you can enter the epc1 pointer from above and get a pretty clear picture where the problem occured:

(gdb) info line *0x4020188c Line 116 of ".pioenvs/nodemcuv2/FrameworkArduino/Tone.cpp" starts at address 0x4020188c and ends at 0x40201891 

Tone.cpp was the culprit! I quickly headed over to the Arduino/ESP8266 github repo and searched for problems with Tone and found the following issue:  https://github.com/esp8266/Arduino/issues/1761

Even better was that there was already a solution, even if not released yet: you just have to add ICACHE_RAM_ATTR  to a method in Tone.cpp. Since I cannot wait for the next release to fix this I did it myself and all the problems went away!

Summary

Even (or even more) on embedded devices debugging is a very powerful tool. But it might take some time to set it up properly. While I still did not succeed in doing operation on the open heart (life debugging) it wasn’t even necessary in this case. Having a program counter pointing me to the location of the crash helped already a lot. After debugging, don’t forget to remove the flags in platformio or you will miss compiler optimizations…

Related:  ESP8266: R.I.P. Long Term Data Logger after almost 3 months.
Now a beer! Did you like this post? It often takes me several hours of my free time to write one. If I was your neighbour would you offer me a beer for the hard work I did for you? The beauty is: beers can be teletransported with a painless donation using Paypal. A beer in a Swiss bar costs about USD $4.80. Or use this affiliate link if you order something on Banggood and I'll get a small kickback. Thank you!