Skip to content

12. Debugging

ronf-ucb edited this page Jan 23, 2021 · 20 revisions

Necessary menuconfig things to change:
CONFIG_ESP_COREDUMP_TO_FLASH_OR_UART (change to UART)
CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT or ESP_SYSTEM_PANIC_PRINT_HALT (change to print registers and halt)
CONFIG_ESP_COREDUMP_DATA_FORMAT (set to ELF)
Component config -> Core dump -> ELF format ELF format (Executable and Linkable Format file for core dump)

Compile with debugger (default option)

The esp-idf tools should be installed to be able to use espcoredump.py. These are installed when setting up platformio, located: .platformio/packages/framework-espidf/components/espcoredump/espcoredump.py

12.1 Core dump documentation

Documentation is at https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/core_dump.html
This gives a nice introduction ``ESP32 core dump tutorial’’ https://www.youtube.com/watch?v=MpD_3oVJAEs
Example use of gdb on dumped core file:
https://www.cse.unsw.edu.au/~learn/debugging/modules/gdb_coredumps/

12.2 Setting core dump

You may have coding errors that already generate a core dump (for example, memory access fault, or a timeout). The core dump can tell you what line of code caused the problem. Sometimes in debugging you would like to examine variables in a function without adding print statements. (This is like a software breakpoint). You can add an illegal memory access to trigger a core dump. Add this line of code where you want to trigger a core dump:
*((int *) 0) = 0; // cause panic by writing to nonexistent address
You should get an error and a core dump to UART.
Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled.

12.3 Using Core dump in Gnu Debugger

  1. Copy and paste base64 encoded core dump to a text file.

  2. Remove ================= CORE DUMP START =================
    and ================= CORE DUMP END ===================
    from text file

  3. From start menu, select ESP-IDF -> ESP-IDF command prompt. This sets up environment to give access to needed esp-idf tools.

  4. Run gdb startup on the dumped core, and also point to the compiled (.elf) project.
    espcoredump.py dbg_corefile -t b64 -c </path/to/saved/base64/text> </path/to/program/elf/file>
    Here is example with filenames:
    c:>python c:\Users\ronf\.platformio\packages\framework-espidf\components\ espcoredump\espcoredump.py dbg_corefile -t b64 -c coredump.txt .pio\build\featheresp32\firmware.elf

12.4 useful GDB commands for core dump

https://linuxconfig.org/gdb-debugging-tutorial-for-beginners

  • Help command
  • List shows 10 lines, list – shows 10 lines before current line
  • Print Variables accessible are those of the lexical environment of the selected stack frame, plus all those whose scope is global or an entire file.
  • Info locals (show local variables)
  • bt (backtrace- what function was called from)
  • frame # (print stack frame #)
  • info threads
  • thread # (navigate to specific thread, then can do list or backtrace)

12.5 Memory Usage

It is very easy to run out of memory, as the libraries are so huge. Beware that with updates, embedded code may no longer fit on your device, resulting in obsolescence.

To see how much memory is used by your program:

C:> python ~home\.platformio\packages\framework-espidf\components\esptool_py\esptool\esptool.py --chip esp32 image_info .pio\build\featheresp32\firmware.bin

To print usage inside C program: heap_caps_print_heap_info(uint32_t MALLOC_CAP_8BIT);

From inside your program the data RAM usage can be monitored with commands such as size_t heap_caps_get_largest_free_block(uint32_t caps)
see documentations here:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/mem_alloc.html?highlight=memory%20map

12.6 Error Codes

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_err.html
Convert error codes to text: esp_err_to_name() and esp_err_to_name_r()

12.7 Watchdog timers

Watchdogs are useful for detecting stuck code. Use RTC watchdog in start code: causes watchdog if startup fails

Task Watchdog Timer API Reference:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/wdts.html?highlight=task%20watchdog%20timer%20api%20reference
The Interrupt Watchdog Timer and the Task Watchdog Timer (TWDT). The Interrupt Watchdog Timer and the TWDT can both be enabled using Project Configuration Menu, however the TWDT can also be enabled during runtime.

CONFIG_ESP_INT_WDT Component config → Common ESP-related -> Interrupt Watchdog

Have to make sure idle can run, otherwise will get watchdog timeout. For example, if main() is waiting for keyboard input, then idle can be starved. Always use a vTaskDelay(1000 / portTICK_PERIOD_MS); to temporarily sleep process so IDLE has a chance to run.