Debugging on ESP32 ================== Serial debugging ---------------- If an exception occurs in debug builds then a prompt will be printed to the serial terminal such as ``Entering gdb stub``. As with the ESP8266, if such an exception occurs you can stop the serial debug terminal and type ``make gdb``. See also :envvar:`ENABLE_GDB`. JTAG debugging -------------- More advanced debugging is available via JTAG if you have the appropriate tools. See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/index.html. A debugger and a JTAG hardware are required. The debugger is part of the provided toolchain. Make sure that you have the following executable in your PATH:: xtensa-esp32-elf-gdb Debugging with JTAG is explained in details in the `ESP-IDF documentation `__. Make sure to read it carefully. For the purposes of this documentation we will be using `ESP-Prog JTAG adapter `__ and ESP32-Cam microcontroller from AI-Thinker. Configure Hardware ------------------ The JTAG adapter has to be connected to your ESP32 microcontroller. The following pins from the JTAG adapter have to be connected to ESP32 for the communication to work. +---+---------------+-------------+-------------+-------------+ | | ESP32 Pin | nodeMCU Pin | USB Blaster | JTAG Signal | +===+===============+=============+=============+=============+ | 1 | VCC | 3V3 | 4 | VCC | +---+---------------+-------------+-------------+-------------+ | 2 | MTDO / GPIO15 | D15 | 3 | TDO | +---+---------------+-------------+-------------+-------------+ | 3 | MTDI / GPIO12 | D12 | 9 | TDI | +---+---------------+-------------+-------------+-------------+ | 4 | MTCK / GPIO13 | D13 | 1 | TCK | +---+---------------+-------------+-------------+-------------+ | 5 | MTMS / GPIO14 | D14 | 5 | TMS | +---+---------------+-------------+-------------+-------------+ | 6 | GND | GND | 2 | GND | +---+---------------+-------------+-------------+-------------+ Running OpenOCD --------------- Once the JTAG adapter is connected to the microcontroller and to a computer we have to start the OpenOCD server that will communicate with the JTAG adapter. For our specific hardware the following command has to be executed:: openocd -f interface/ftdi/esp32_devkitj_v1.cfg -f target/esp32.cfg If you have configured your JTAG adapter correctly the following messages should show up:: Open On-Chip Debugger v0.10.0-esp32-20190313 (2019-03-13-09:52) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html none separate adapter speed: 20000 kHz Info : Configured 2 cores esp32 interrupt mask on Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi_tdo_sample_edge falling" Info : clock speed 20000 kHz Info : JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1) Info : JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1) Info : esp32: Debug controller 0 was reset (pwrstat=0x5F, after clear 0x0F). Info : esp32: Core 0 was reset (pwrstat=0x5F, after clear 0x0F). Info : esp32: Debug controller 1 was reset (pwrstat=0x5F, after clear 0x0F). Info : esp32: Core 1 was reset (pwrstat=0x5F, after clear 0x0F). Info : Detected debug stubs @ 3ffb42ac on core0 of target 'esp32' Info : Listening on port 3333 for gdb connections Info : accepting 'gdb' connection on tcp/3333 Recompilation is required ------------------------- In order to debug applications based on Sming Framework make sure that you are using Sming version 3.8.0 or newer. Compilation directives ~~~~~~~~~~~~~~~~~~~~~~ If you want to debug your application and the Sming Framework code make sure to (re)compile it with :envvar:`ENABLE_GDB=1 ` directive:: cd $SMING_HOME/../samples/Basic_Blink make clean components-clean make ENABLE_GDB=1 The commands above will re-compile Sming with debug symbols and optimizations for debugging. Application ~~~~~~~~~~~ To use, (re)compile your application with the ENABLE_GDB option and flash it to the board. For this example we will use the :sample:`Basic_Blink` sample application:: cd $SMING_HOME/../samples/Basic_Blink make clean make ENABLE_GDB=1 # -- recompiles your application with debugging support make flashapp # flashes ONLY the (re)compiled application The device will restart then wait for a debugger to be connected. Before starting the debugger you must be sure that the OpenOCD server is running and listening for incoming connections on localhost port 3333. Now start the debugger:: make gdb This will start a new debugging session. The debugger will try to connect to OpenOCD server and in the OpenOCD logs you should see a message similar to the one below:: Info : accepting 'gdb' connection on tcp/3333 Info : Target halted. PRO_CPU: PC=0x4012F7EE (active) APP_CPU: PC=0x4012F7EE Info : Target halted. PRO_CPU: PC=0x4009171A (active) APP_CPU: PC=0x4012F7EE Info : Flash mapping 0: 0x10020 -> 0x3f400020, 89 KB Info : Flash mapping 1: 0x30018 -> 0x400d0018, 388 KB Info : Target halted. PRO_CPU: PC=0x4009171A (active) APP_CPU: PC=0x4012F7EE Info : Auto-detected flash size 4096 KB Info : Using flash size 4096 KB And in the GDB console you will see a message similar to this one:: Reading symbols from out/Esp32/debug/build/app.out...done. 0x4012f7ee in is_wifi_clk_peripheral (periph=PERIPH_LEDC_MODULE) at /x/esp-idf/components/driver/periph_ctrl.c:225 225 switch(periph) { JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1) JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1) esp32: Debug controller 0 was reset (pwrstat=0x5F, after clear 0x0F). esp32: Core 0 was reset (pwrstat=0x5F, after clear 0x0F). esp32: Debug controller 1 was reset (pwrstat=0x5F, after clear 0x5F). esp32: Core 1 was reset (pwrstat=0x5F, after clear 0x5F). Target halted. PRO_CPU: PC=0x5000004B (active) APP_CPU: PC=0x00000000 esp32: Core 0 was reset (pwrstat=0x1F, after clear 0x0F). Target halted. PRO_CPU: PC=0x40000400 (active) APP_CPU: PC=0x40000400 Hardware assisted breakpoint 1 at 0x400e1cd3: file /x/Sming/Sming/Arch/Esp32/Components/esp32/startup.cpp, line 21. (gdb) If the debugger is exited, the application will continue execution as normal. Re-connecting the debugger will pause execution. GDB commands ------------ There are multiple commands supported in GDB and we will mention only some of them. List current source code ~~~~~~~~~~~~~~~~~~~~~~~~ One possibility is to see the source code of the current line where the execution has stopped. To achieve this you should type ``list`` in the gdb console:: (gdb) list 220 221 static bool is_wifi_clk_peripheral(periph_module_t periph) 222 { 223 /* A small subset of peripherals use WIFI_CLK_EN_REG and 224 CORE_RST_EN_REG for their clock & reset registers */ 225 switch(periph) { 226 case PERIPH_SDMMC_MODULE: 227 case PERIPH_SDIO_SLAVE_MODULE: 228 case PERIPH_EMAC_MODULE: 229 case PERIPH_RNG_MODULE: (gdb) Break the execution ~~~~~~~~~~~~~~~~~~~ This command will pause the debugger once it reaches a specific function or line in the code. This is called ``breakpoint`` and can be set like this:: (gdb) break blink Breakpoint 2 at 0x400e1dc4: file app/application.cpp, line 9. Continue the execution ~~~~~~~~~~~~~~~~~~~~~~ To continue the execution of the application we can use the ``continue`` command:: (gdb) continue Continuing. Target halted. PRO_CPU: PC=0x400E1DC4 (active) APP_CPU: PC=0x4012F7EE [New Thread 1073483724] [New Thread 1073514968] [New Thread 1073494600] [New Thread 1073487892] [Switching to Thread 1073412944] Breakpoint 1, blink () at app/application.cpp:9 9 { (gdb) Because we have set already a breakpoint for the ``blink`` function the execution will be paused when the ``blink`` function is reached and from here you can go to the next line or see the current values of the variables. Go to the next line ~~~~~~~~~~~~~~~~~~~ This can be done using ``next``:: (gdb) next 10 digitalWrite(LED_PIN, state); See variable value ~~~~~~~~~~~~~~~~~~ The command to see a value is ``print`` followed by the name of the value. For example to see the value of the ``ledState`` variable inside the ``blink`` function we could type:: (gdb) print state $1 = true You can see more useful commands :ref:`here `. Or watch the following short video .. image:: https://img.youtube.com/vi/hVwSX_7Ey8c/3.jpg :target: https://www.youtube.com/watch?v=hVwSX_7Ey8c