242 lines
9.3 KiB
ReStructuredText
242 lines
9.3 KiB
ReStructuredText
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 <https://docs.espressif.com/projects/esp-idf/en/v4.1/api-guides/jtag-debugging/index.html>`__.
|
|
Make sure to read it carefully.
|
|
|
|
For the purposes of this documentation we will be using `ESP-Prog JTAG adapter <https://github.com/espressif/esp-iot-solution/blob/master/documents/evaluation_boards/ESP-Prog_guide_en.md>`__
|
|
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 <ENABLE_GDB>` 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 <useful-gdb-commands>`.
|
|
|
|
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
|