JTAG Debugging - revamping of Debugging documentation

This commit is contained in:
krzychb 2017-06-11 21:12:30 +02:00 committed by Ivan Grokhotkov
parent 002f38fa8f
commit 1fb85b494c
40 changed files with 1717 additions and 223 deletions

View file

@ -138,7 +138,7 @@ endchoice
config FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
bool "Stop program on scheduler start when JTAG/OCD is detected"
depends on ESP32_DEBUG_OCDAWARE
default y
default n
help
If JTAG/OCD is connected, stop execution when the scheduler is started and the first
task is executed.

@ -1 +1 @@
Subproject commit 3bcc416e13cc790e2fb45fcfe9111d38609c5032
Subproject commit 2f146e4d4cfe895d65599b87df7d847435f0e1b4

BIN
docs/_static/debug-perspective.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
docs/_static/debugging-step-into.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
docs/_static/debugging-step-over.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
docs/_static/debugging-target-halted.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
docs/_static/hw-debugging-main-tab.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
docs/_static/jtag-debugging-overview.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View file

@ -37,7 +37,7 @@ Config Options and Dependencies
Using of this feature depends on two components:
1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions how to set it up, please, see :doc:`Debugging <../api-guides/openocd>` for details.
1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions how to set it up, please, see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>` for details.
2. **Target side:** Application tracing functionality can be enabled by ``CONFIG_ESP32_APPTRACE_ENABLE`` macro via menuconfig. This option enables the module and makes tracing API available for users. Actually there is menu which allows selecting destination for the trace data (HW interface for transport). So choosing one of the destinations automatically enables ``CONFIG_ESP32_APPTRACE_ENABLE`` option.
.. note::
@ -113,7 +113,7 @@ Also according to his needs user may want to receive data from the host. Piece o
}
2. The next step is to build the program image and download it to the target as described in :doc:`Build and Flash <../get-started/make-project>`.
3. Run OpenOCD (see :doc:`Debugging <../api-guides/openocd>`).
3. Run OpenOCD (see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>`).
4. Connect to OpenOCD telnet server. On Linux it can be done using the following command in terminal ``telnet <oocd_host> 4444``. If telnet session is opened on the same machine which runs OpenOCD you can use ``localhost`` as ``<oocd_host>`` in the command above.
5. Start trace data collection using special OpenOCD command. This command will transfer tracing data and redirect them to specified file or socket (currently only files are supported as trace data destination). For description of the corresponding commands see `OpenOCD Application Level Tracing Commands`_.
6. The final step is to process received data. Since format of data is defined by user the processing stage is out of the scope of this document. Good starting points for data processor are python scripts in ``$IDF_PATH/tools/esp_app_trace``: ``apptrace_proc.py`` (used for feature tests) and ``logtrace_proc.py`` (see more details in section `Logging to Host`_).

View file

@ -1,51 +0,0 @@
#
# Example configuration file to hook up an ESP32 module or board to a JTAG
# adapter. Please modify this file to your local setup.
#
#
# Include the configuration for the JTAG adapter. We use the Tian TUMPA here.
# If you have a different interface, please edit this to include the
# configuration file of yours.
source [find interface/ftdi/tumpa.cfg]
# The ESP32 only supports JTAG.
transport select jtag
# The speed of the JTAG interface, in KHz. If you get DSR/DIR errors (and they
# do not relate to OpenOCD trying to read from a memory range without physical
# memory being present there), you can try lowering this.
adapter_khz 200
# With no variables set, openocd will configure JTAG for the two cores of the ESP32 and
# will do automatic RTOS detection. This can be be adjusted by uncommenting any of the
# following lines:
# Only configure the PRO CPU
#set ESP32_ONLYCPU 1
# Only configure the APP CPU
#set ESP32_ONLYCPU 2
# Disable RTOS support
#set ESP32_RTOS none
# Force RTOS to be FreeRTOS
#set ESP32_RTOS FreeRTOS
#Source the ESP32 configuration file
source [find target/esp32.cfg]
# The TDI pin of ESP32 is also a bootstrap pin that selects the voltage the SPI flash
# chip runs at. When a hard reset happens (e.g. because someone switches the board off
# and on) the ESP32 will use the current TDI value as the bootstrap value because the
# JTAG adapter overrides the pull-up or pull-down resistor that is supposed to do the
# bootstrapping. These lines basically set the idle value of the TDO line to a
# specified value, therefore reducing the chance of a bad bootup due to a bad flash
# voltage greatly.
# Enable this for 1.8V SPI flash
esp108 flashbootstrap 1.8
# Enable this for 3.3V SPI flash
#esp108 flashbootstrap 3.3

View file

@ -6,13 +6,13 @@ API Guides
General Notes <general-notes>
Build System <build-system>
Debugging <openocd>
Deep Sleep Wake Stubs <deep-sleep-stub>
ESP32 Core Dump <core_dump>
Partition Tables <partition-tables>
Flash Encryption <../security/flash-encryption>
High Level Interrupts <hlinterrupts>
JTAG Debugging <jtag-debugging/index>
Partition Tables <partition-tables>
Secure Boot <../security/secure-boot>
Deep Sleep Wake Stubs <deep-sleep-stub>
ULP Coprocessor <ulp>
Unit Testing <unit-tests>
Application Level Tracing <app_trace>

View file

@ -0,0 +1,83 @@
***************************************
Building OpenOCD from Sources for Linux
***************************************
The following instructions are alternative to downloading binary OpenOCD from Espressif website. To quickly setup the binary OpenOCD, instead of compiling it yourself, backup and proceed to section :doc:`setup-openocd-linux`.
.. highlight:: bash
Install Git
===========
To be able to download OpenOCD sources from GitHub, install ``git`` package::
sudo apt-get install git
Download Sources of OpenOCD
===========================
The sources for the ESP32-enabled variant of OpenOCD are available from Espressif GitHub under https://github.com/espressif/openocd-esp32. To download the sources, use the following commands::
cd ~/esp
git clone recursive https://github.com/espressif/openocd-esp32.git
The clone of sources should be now saved in ``~/esp/openocd-esp32`` directory.
Install Dependencies
====================
Install packages that are required to compile OpenOCD.
.. note::
Install the following packages one by one, check if installation was successful and then proceed to the next package. Resolve reported problems before moving to the next step.
::
sudo apt-get install make
sudo apt-get install libtool
sudo apt-get install pkg-config
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install texinfo
sudo apt-get install libusb-1.0
.. note::
* Version of pkg-config should be 0.2.3 or above.
* Version of autoconf should be 2.6.4 or above.
* Version of automake should be 1.9 or above.
* When using USB-Blaster, ASIX Presto, OpenJTAG and FT2232 as adapters, drivers libFTDI and FTD2XX need to be downloaded and installed.
* When using CMSIS-DAP, HIDAPI is needed.
Build OpenOCD
=============
Proceed with configuring and building OpenOCD::
cd ~/esp/openocd-esp32
./bootstrap
./configure
make
Optionally you can add ``sudo make install`` step at the end. Skip it, if you have an existing OpenOCD (from e.g. another development platform), as it may get overwritten.
.. note::
* Should an error occur, resolve it and try again until the command ``make`` works.
* If there is a submodule problem from OpenOCD, please ``cd`` to the ``openocd-esp32`` directory and input ``git submodule update --init``.
* If the ``./configure`` is successfully run, information of enabled JTAG will be printed under ``OpenOCD configuration summary``.
* If the information of your device is not shown in the log, use ``./configure`` to enable it as described in ``../openocd-esp32/doc/INSTALL.txt``.
* For details concerning compiling OpenOCD, please refer to ``openocd-esp32/README``.
Once ``make`` process is successfully completed, the executable of OpenOCD will be saved in ``~/openocd-esp32/bin`` directory.
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.

View file

@ -0,0 +1,20 @@
***************************************
Building OpenOCD from Sources for MacOS
***************************************
The following instructions are alternative to downloading binary OpenOCD from Espressif website. To quickly setup the binary OpenOCD, instead of compiling it yourself, backup and proceed to section :doc:`setup-openocd-macos`.
Build OpenOCD
=============
Refer to build process described in ``README.OSX`` file, that is provided with
OpenOCD source code in https://github.com/espressif/openocd-esp32 repository.
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.

View file

@ -0,0 +1,18 @@
*****************************************
Building OpenOCD from Sources for Windows
*****************************************
The following instructions are alternative to downloading binary OpenOCD from Espressif website. To quickly setup the binary OpenOCD, instead of compiling it yourself, backup and proceed to section :doc:`setup-openocd-windows`.
Build OpenOCD
=============
Refer to build process described in ``README.Windows`` file, that is provided with
OpenOCD source code in https://github.com/espressif/openocd-esp32 repository.
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.

View file

@ -0,0 +1,45 @@
Configure Other JTAG Interface
==============================
Refer to section :ref:`jtag-debugging-selecting-jtag-adapter` for guidance what JTAG interface to select, so it is able to operate with OpenOCD and ESP32. Then follow three configuration steps below to get it working.
Configure Hardware
^^^^^^^^^^^^^^^^^^
1. Identify all pins / signals on JTAG interface and ESP32 board, that should be connected to establish communication.
+---+---------------+-------------+
| | ESP32 Pin | JTAG Signal |
+===+===============+=============+
| 1 | CHIP_PU | TRST_N |
+---+---------------+-------------+
| 2 | MTDO / GPIO15 | TDO |
+---+---------------+-------------+
| 3 | MTDI / GPIO12 | TDI |
+---+---------------+-------------+
| 4 | MTCK / GPIO13 | TCK |
+---+---------------+-------------+
| 5 | MTMS / GPIO14 | TMS |
+---+---------------+-------------+
| 6 | GND | GND |
+---+---------------+-------------+
2. Verify if ESP32 pins used for JTAG communication are not connected to some other h/w that may disturb JTAG operation.
3. Connect identified pin / signals of ESP32 and JTAG interface.
Configure Drivers
^^^^^^^^^^^^^^^^^
You may need to install driver s/w to make JTAG work with computer. Refer to documentation of JTAG adapter, that should provide related details.
Connect
^^^^^^^
Connect JTAG interface to the computer. Power on ESP32 and JTAG interface boards. Check if JTAG interface is visible by computer.
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-run-openocd`.

View file

@ -0,0 +1,102 @@
Configure WROVER JTAG Interface
===============================
All versions of ESP32 WROVER KIT boards have JTAG functionality build in. Putting it to work requires setting jumpers to enable JTAG functionality, setting SPI flash voltage and configuring USB drivers. Please refer to step by step instructions below.
Configure Hardware
^^^^^^^^^^^^^^^^^^
1. Enable on-board JTAG functionality by setting JP8 according to :doc:`../../get-started/get-started-wrover-kit`, section :ref:`esp-wrover-setup-options`.
2. Verify if ESP32 pins used for JTAG communication are not connected to some other h/w that may disturb JTAG operation:
+---+---------------+-------------+
| | ESP32 Pin | JTAG Signal |
+===+===============+=============+
| 1 | CHIP_PU | TRST_N |
+---+---------------+-------------+
| 2 | MTDO / GPIO15 | TDO |
+---+---------------+-------------+
| 3 | MTDI / GPIO12 | TDI |
+---+---------------+-------------+
| 4 | MTCK / GPIO13 | TCK |
+---+---------------+-------------+
| 5 | MTMS / GPIO14 | TMS |
+---+---------------+-------------+
Configure USB Drivers
^^^^^^^^^^^^^^^^^^^^^
Install and configure USB drivers, so OpenOCD is able to communicate with JTAG interface on ESP32 WROVER KIT board as well as with UART interface used to upload application for flash. Follow steps below specific to your operating system.
Windows
"""""""
1. Using standard USB A / mini USB B cable connect ESP32 WROVER KIT to the computer. Switch the WROVER KIT on.
2. Wait until USB ports of WROVER KIT are recognized by Windows and drives are installed. If they do not install automatically, then then download them from http://www.ftdichip.com/Drivers/D2XX.htm and install manually.
3. Download Zadig tool (Zadig_X.X.exe) from http://zadig.akeo.ie/ and run it.
4. In Zadig tool go to "Options" and check "List All Devices".
5. Check the list of devices that should contain two WROVER specific USB entries: "Dual RS232-HS (Interface 0)" and "Dual RS232-HS (Interface 1)". The driver name would be "FTDIBUS (vxxxx)" and USB ID: 0403 6010.
.. figure:: ../../_static/jtag-usb-configuration-zadig.jpg
:align: center
:alt: Configuration of JTAG USB driver in Zadig tool
:figclass: align-center
Configuration of JTAG USB driver in Zadig tool
6. The first device (Dual RS232-HS (Interface 0)) is connected to the JTAG port of the ESP32. Original "FTDIBUS (vxxxx)" driver of this device should be replaced with "WinUSB (v6xxxxx)". To do so, select "Dual RS232-HS (Interface 0) and reinstall attached driver to the "WinUSB (v6xxxxx)", see picture above.
.. note::
Do not change the second device "Dual RS232-HS (Interface 1)". It is routed to ESP32's serial port (UART) used for upload of application to ESP32's flash.
Now ESP32 WROVER KIT's JTAG interface should be available to the OpenOCD. To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-run-openocd`.
Linux
"""""
1. Using standard USB A / mini USB B cable connect ESP32 WROVER KIT board to the computer. Power on the board.
.. highlight:: none
2. Open a terminal, enter ``ls -l /dev/ttyUSB*`` command and check, if board's USB ports are recognized by the O/S. You are looking for similar result:
::
user-name@computer-name:~/esp$ ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 Jul 10 19:04 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Jul 10 19:04 /dev/ttyUSB1
3. Following section "Permissions delegation" in OpenOCD's README, set up the access permissions to both USB ports.
4. Log off and login, then cycle the power to the board to make the changes effective. In terminal enter again ``ls -l /dev/ttyUSB*`` command to verify, if group-owner has changed from ``dialout`` to ``plugdev``:
::
user-name@computer-name:~/esp$ ls -l /dev/ttyUSB*
crw-rw-r-- 1 root plugdev 188, 0 Jul 10 19:07 /dev/ttyUSB0
crw-rw-r-- 1 root plugdev 188, 1 Jul 10 19:07 /dev/ttyUSB1
If you see similar result and you are a member of ``plugdev`` group, then the set up is complete.
The ``/dev/ttyUSBn`` interface with lower number is used for JTAG communication. The other interface is routed to ESP32's serial port (UART) used for upload of application to ESP32's flash.
Now ESP32 WROVER KIT's JTAG interface should be available to the OpenOCD. To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-run-openocd`.
MacOS
"""""
[TBD]
Now ESP32 WROVER KIT's JTAG interface should be available to the OpenOCD. To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-run-openocd`.

View file

@ -0,0 +1,655 @@
Debugging Examples
==================
This section describes debugging with GDB from :ref:`jtag-debugging-examples-eclipse` as well as from :ref:`jtag-debugging-examples-command-line`.
.. highlight:: none
.. _jtag-debugging-examples-eclipse:
Eclipse
-------
Verify if your target is ready and loaded with :example:`get-started/blink` example. Configure and start debugger following steps in section :ref:`jtag-debugging-using-debugger-eclipse`. Pick up where target was left by debugger, i.e. having the application halted at breakpoint established at ``app_main()``.
.. figure:: ../../_static/debug-perspective.jpg
:align: center
:alt: Debug Perspective in Eclipse
:figclass: align-center
Debug Perspective in Eclipse
Examples in this section
^^^^^^^^^^^^^^^^^^^^^^^^
1. :ref:`jtag-debugging-examples-eclipse-01`
2. :ref:`jtag-debugging-examples-eclipse-02`
3. :ref:`jtag-debugging-examples-eclipse-03`
4. :ref:`jtag-debugging-examples-eclipse-04`
5. :ref:`jtag-debugging-examples-eclipse-05`
6. :ref:`jtag-debugging-examples-eclipse-06`
7. :ref:`jtag-debugging-examples-eclipse-07`
.. _jtag-debugging-examples-eclipse-01:
Navigating though the code, call stack and threads
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the target is halted, debugger shows the list of threads in "Debug" window. The line of code where program halted is highlighted in another window below, as shown on the following picture. The LED stops blinking.
.. figure:: ../../_static/debugging-target-halted.jpg
:align: center
:alt: Target halted during debugging
:figclass: align-center
Target halted during debugging
Specific thread where the program halted is expanded showing the call stack. It represents function calls that lead up to the highlighted line of code, where the target halted. The first line of call stack under Thread #1 contains the last called function ``app_main()``, that in turn was called from function ``main_task()`` shown in a line below. Each line of the stack also contains the file name and line number where the function was called. By clicking / highlighting the stack entries, in window below, you will see contents of this file.
By expanding threads you can navigate throughout the application. Expand Thread #5 that contains much longer call stack. You will see there, besides function calls, numbers like ``0x4000000c``. They represent addresses of binary code not provided in source form.
.. figure:: ../../_static/debugging-navigate-through-the-stack.jpg
:align: center
:alt: Navigate through the call stack
:figclass: align-center
Navigate through the call stack
In another window on right, you can see the disassembled machine code no matter if your project provides it in source or only the binary form.
Go back to the ``app_main()`` in Thread #1 to familiar code of ``blink.c`` file that will be examined in more details in the following examples. Debugger makes it easy to navigate through the code of entire application. This comes handy when stepping though the code and working with breakpoints and will be discussed below.
.. _jtag-debugging-examples-eclipse-02:
Setting and clearing breakpoints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers / peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
Let's establish two breakpoints when the state of LED changes. Basing on code listing above, this happens at lines 33 and 36. To do so, hold the "Control" on the keyboard and double clink on number ``33`` in file ``blink.c`` file. A dialog will open where you can confirm your selection by pressing "OK" button. If you do not like to see the dialog just double click the line number. Set another breakpoint in line 36.
.. figure:: ../../_static/debugging-setting-breakpoint.jpg
:align: center
:alt: Setting a breakpoint
:figclass: align-center
Setting a breakpoint
Information how many breakpoints are set and where is shown in window "Breakpoints" on top right. Click "Show Breakpoints Supported by Selected Target" to refresh this list. Besides the two just set breakpoints the list may contain temporary breakpoint at function ``app_main()`` established at debugger start. As maximum two breakpoints are allowed (see :ref:`jtag-debugging-tip-breakpoints`), you need to delete it, or debugging will fail.
.. figure:: ../../_static/debugging-three-breakpoints-set.jpg
:align: center
:alt: Three breakpoints are set / maximum two are allowed
:figclass: align-center
Three breakpoints are set / maximum two are allowed
If you now click "Resume" (click ``blink_task()`` under "Tread #8", if "Resume" button is grayed out), the processor will run and halt at a breakpoint. Clicking "Resume" another time will make it run again, halt on second breakpoint, and so on.
You will be also able to see that LED is changing the state after each click to "Resume" program execution.
Read more about breakpoints under :ref:`jtag-debugging-tip-breakpoints` and :ref:`jtag-debugging-tip-where-breakpoints`
.. _jtag-debugging-examples-eclipse-03:
Halting the target manually
^^^^^^^^^^^^^^^^^^^^^^^^^^^
When debugging, you may resume application and enter code waiting for some event or staying in infinite loop without any break points defined. In such case, to go back to debugging mode, you can break program execution manually by pressing "Suspend" button.
To check it, delete all breakpoints and click "Resume". Then click "Suspend". Application will be halted at some random point and LED will stop blinking. Debugger will expand tread and highlight the line of code where application halted.
.. figure:: ../../_static/debugging-target-halted-manually.jpg
:align: center
:alt: Target halted manually
:figclass: align-center
Target halted manually
In particular case above, the application has been halted in line 52 of code in file ``freertos_hooks.c`` Now you can resume it again by pressing "Resume" button or do some debugging as discussed below.
.. _jtag-debugging-examples-eclipse-04:
Stepping through the code
^^^^^^^^^^^^^^^^^^^^^^^^^
It is also possible to step through the code using "Step Into (F5)" and "Step Over (F6)" commands. The difference is that "Step Into (F5)" is entering inside subroutines calls, while "Step Over (F6)" steps over the call, treating it as a single source line.
Before being able to demonstrate this functionality, using information discussed in previous paragraph, make sure that you have only one breakpoint defined at line ``36`` of ``blink.c``.
Resume program by entering pressing F8 and let it halt. Now press "Step Over (F6)", one by one couple of times, to see how debugger is stepping one program line at a time.
.. figure:: ../../_static/debugging-step-over.jpg
:align: center
:alt: Stepping through the code with "Step Over (F6)"
:figclass: align-center
Stepping through the code with "Step Over (F6)"
If you press "Step Into (F5)" instead, then debugger will step inside subroutine calls.
.. figure:: ../../_static/debugging-step-into.jpg
:align: center
:alt: Stepping through the code with "Step Into (F5)"
:figclass: align-center
Stepping through the code with "Step Into (F5)"
In this particular case debugger stepped inside ``gpio_set_level(BLINK_GPIO, 0)`` and effectively moved to ``gpio.c`` driver code.
See :ref:`jtag-debugging-tip-why-next-works-as-step` for potential limitation of using ``next`` command.
.. _jtag-debugging-examples-eclipse-05:
Checking and setting memory
^^^^^^^^^^^^^^^^^^^^^^^^^^^
To display or set contents of memory use "Memory" tab at the bottom of "Debug" perspective.
With the "Memory" tab, we will read from and write to the memory location ``0x3FF44004`` labeled as ``GPIO_OUT_REG`` used to set and clear individual GPIO's. For more information please refer to `ESP32 Technical Reference Manual <http://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>`__, chapter IO_MUX and GPIO Matrix.
Being in the same ``blink.c`` project as before, set two breakpoints right after ``gpio_set_level`` instruction. Click "Memory" tab and then "Add Memory Monitor" button. Enter ``0x3FF44004`` in provided dialog.
Now resume program by pressing F8 and observe "Monitor" tab.
.. figure:: ../../_static/debugging-memory-location-on.jpg
:align: center
:alt: Observing memory location 0x3FF44004 changing one bit to ON"
:figclass: align-center
Observing memory location 0x3FF44004 changing one bit to ON"
You should see one bit being flipped over at memory location ``0x3FF44004`` (and LED changing the state) each time F8 is pressed.
.. figure:: ../../_static/debugging-memory-location-off.jpg
:align: center
:alt: Observing memory location 0x3FF44004 changing one bit to ON"
:figclass: align-center
Observing memory location 0x3FF44004 changing one bit to ON"
To set memory use the same "Monitor" tab and the same memory location. Type in alternate bit pattern as previously observed. Immediately after pressing enter you will see LED changing the state.
.. _jtag-debugging-examples-eclipse-06:
Watching and setting program variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A common debugging tasks is checking the value of a program variable as the program runs. To be able to demonstrate this functionality, update file ``blink.c`` by adding a declaration of a global variable ``int i`` above definition of function ``blink_task``. Then add ``i++`` inside ``loop(1)`` of this function to get ``i`` incremented on each blink.
Exit debugger, so it is not confused with new code, build and flash the code to the ESP and restart debugger. There is no need to restart OpenOCD.
Once application is halted, enter a breakpoint in the line where you put ``i++``.
In next step, in the window with "Breakpoints", click the "Expressions" tab. If this tab is not visible, then add it by going to the top menu Window > Show View > Expressions. Then click "Add new expression" and enter ``i``.
Resume program execution by pressing F8. Each time the program is halted you will see ``i`` value being incremented.
.. figure:: ../../_static/debugging-watch-variable.jpg
:align: center
:alt: Watching program variable "i"
:figclass: align-center
Watching program variable "i"
To modify ``i`` enter a new number in "Value" column. After pressing "Resume (F8)" the program will keep incrementing ``i`` starting from the new entered number.
.. _jtag-debugging-examples-eclipse-07:
Setting conditional breakpoints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here comes more interesting part. You may set a breakpoint to halt the program execution, if certain condition is satisfied. Right click on the breakpoint to open a context menu and select "Breakpoint Properties". Change the selection under "Type:" to "Hardware" and enter a "Condition:" like ``i == 2``.
.. figure:: ../../_static/debugging-setting-conditional-breakpoint.jpg
:align: center
:alt: Setting a conditional breakpoint
:figclass: align-center
Setting a conditional breakpoint
If current value of ``i`` is less than ``2`` (change it if required) and program is resumed, it will blink LED in a loop until condition ``i == 2`` gets true and then finally halt.
.. _jtag-debugging-examples-command-line:
Command Line
------------
Verify if your target is ready and loaded with :example:`get-started/blink` example. Configure and start debugger following steps in section :ref:`jtag-debugging-using-debugger-command-line`. Pick up where target was left by debugger, i.e. having the application halted at breakpoint established at ``app_main()``::
Temporary breakpoint 1, app_main () at /home/user-name/esp/blink/main/./blink.c:43
43 xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
(gdb)
Examples in this section
^^^^^^^^^^^^^^^^^^^^^^^^
1. :ref:`jtag-debugging-examples-command-line-01`
2. :ref:`jtag-debugging-examples-command-line-02`
3. :ref:`jtag-debugging-examples-command-line-03`
4. :ref:`jtag-debugging-examples-command-line-04`
5. :ref:`jtag-debugging-examples-command-line-05`
6. :ref:`jtag-debugging-examples-command-line-06`
7. :ref:`jtag-debugging-examples-command-line-07`
.. _jtag-debugging-examples-command-line-01:
Navigating though the code, call stack and threads
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When you see the ``(gdb)`` prompt, the application is halted. LED should not be blinking.
To find out where exactly the code is halted, enter ``l`` or ``list``, and debugger will show couple of lines of code around the halt point (line 43 of code in file ``blink.c``) ::
(gdb) l
38 }
39 }
40
41 void app_main()
42 {
43 xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
44 }
(gdb)
Check how code listing works by entering, e.g. ``l 30, 40`` to see particular range of lines of code.
You can use ``bt`` or ``backtrace`` to see what function calls lead up to this code::
(gdb) bt
#0 app_main () at /home/user-name/esp/blink/main/./blink.c:43
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/esp32/./cpu_start.c:339
(gdb)
Line #0 of output provides the last function call before the application halted, i.e. ``app_main ()`` we have listed previously. The ``app_main ()`` was in turn called by function ``main_task`` from line 339 of code located in file ``cpu_start.c``.
To get to the context of ``main_task`` in file ``cpu_start.c``, enter ``frame N``, where N = 1, because the ``main_task`` is listed under #1)::
(gdb) frame 1
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/esp32/./cpu_start.c:339
339 app_main();
(gdb)
Enter ``l`` and this will reveal the piece of code that called ``app_main()`` (in line 339)::
(gdb) l
334 ;
335 }
336 #endif
337 //Enable allocation in region where the startup stacks were located.
338 heap_caps_enable_nonos_stack_heaps();
339 app_main();
340 vTaskDelete(NULL);
341 }
342
(gdb)
By listing some lines before, you will see the function name ``main_task`` we have been looking for::
(gdb) l 326, 341
326 static void main_task(void* args)
327 {
328 // Now that the application is about to start, disable boot watchdogs
329 REG_CLR_BIT(TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN_S);
330 REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
331 #if !CONFIG_FREERTOS_UNICORE
332 // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
333 while (port_xSchedulerRunning[1] == 0) {
334 ;
335 }
336 #endif
337 //Enable allocation in region where the startup stacks were located.
338 heap_caps_enable_nonos_stack_heaps();
339 app_main();
340 vTaskDelete(NULL);
341 }
(gdb)
To see the other code, enter ``i threads``. This will show the list of threads running on target::
(gdb) i threads
Id Target Id Frame
8 Thread 1073411336 (dport) 0x400d0848 in dport_access_init_core (arg=<optimized out>)
at /home/user-name/esp/esp-idf/components/esp32/./dport_access.c:170
7 Thread 1073408744 (ipc0) xQueueGenericReceive (xQueue=0x3ffae694, pvBuffer=0x0, xTicksToWait=1644638200,
xJustPeeking=0) at /home/user-name/esp/esp-idf/components/freertos/./queue.c:1452
6 Thread 1073431096 (Tmr Svc) prvTimerTask (pvParameters=0x0)
at /home/user-name/esp/esp-idf/components/freertos/./timers.c:445
5 Thread 1073410208 (ipc1 : Running) 0x4000bfea in ?? ()
4 Thread 1073432224 (dport) dport_access_init_core (arg=0x0)
at /home/user-name/esp/esp-idf/components/esp32/./dport_access.c:150
3 Thread 1073413156 (IDLE) prvIdleTask (pvParameters=0x0)
at /home/user-name/esp/esp-idf/components/freertos/./tasks.c:3282
2 Thread 1073413512 (IDLE) prvIdleTask (pvParameters=0x0)
at /home/user-name/esp/esp-idf/components/freertos/./tasks.c:3282
* 1 Thread 1073411772 (main : Running) app_main () at /home/user-name/esp/blink/main/./blink.c:43
(gdb)
The thread list shows the last function calls per each thread together with the name of C source file if available.
You can navigate to specific thread by entering ``thread N``, where ``N`` is the thread Id. To see how it works go to thread thread 5::
(gdb) thread 5
[Switching to thread 5 (Thread 1073410208)]
#0 0x4000bfea in ?? ()
(gdb)
Then check the backtrace::
(gdb) bt
#0 0x4000bfea in ?? ()
#1 0x40083a85 in vPortCPUReleaseMutex (mux=<optimized out>) at /home/user-name/esp/esp-idf/components/freertos/./port.c:415
#2 0x40083fc8 in vTaskSwitchContext () at /home/user-name/esp/esp-idf/components/freertos/./tasks.c:2846
#3 0x4008532b in _frxt_dispatch ()
#4 0x4008395c in xPortStartScheduler () at /home/user-name/esp/esp-idf/components/freertos/./port.c:222
#5 0x4000000c in ?? ()
#6 0x4000000c in ?? ()
#7 0x4000000c in ?? ()
#8 0x4000000c in ?? ()
(gdb)
As you see, the backtrace may contain several entries. This will let you check what exact sequence of function calls lead to the code where the target halted. Question marks ``??`` instead of a function name indicate that application is available only in binary format, without any source file in C language. The value like ``0x4000bfea`` is the memory address of the function call.
Using ``bt``, ``i threads``, ``thread N`` and ``list`` commands we are now able to navigate through the code of entire application. This comes handy when stepping though the code and working with breakpoints and will be discussed below.
.. _jtag-debugging-examples-command-line-02:
Setting and clearing breakpoints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers / peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
Let's establish two breakpoints when the state of LED changes. Basing on code listing above this happens at lines 33 and 36. Breakpoints may be established using command ``break M`` where M is the code line number::
(gdb) break 33
Breakpoint 2 at 0x400db6f6: file /home/user-name/esp/blink/main/./blink.c, line 33.
(gdb) break 36
Breakpoint 3 at 0x400db704: file /home/user-name/esp/blink/main/./blink.c, line 36.
If you new enter ``c``, the processor will run and halt at a breakpoint. Entering ``c`` another time will make it run again, halt on second breakpoint, and so on::
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB6F6 (active) APP_CPU: PC=0x400D10D8
Breakpoint 2, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:33
33 gpio_set_level(BLINK_GPIO, 0);
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB6F8 (active) APP_CPU: PC=0x400D10D8
Target halted. PRO_CPU: PC=0x400DB704 (active) APP_CPU: PC=0x400D10D8
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:36
36 gpio_set_level(BLINK_GPIO, 1);
(gdb)
You will be also able to see that LED is changing the state only if you resume program execution by entering ``c``.
To examine how many breakpoints are set and where, use command ``info break``::
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y 0x400db6f6 in blink_task at /home/user-name/esp/blink/main/./blink.c:33
breakpoint already hit 1 time
3 breakpoint keep y 0x400db704 in blink_task at /home/user-name/esp/blink/main/./blink.c:36
breakpoint already hit 1 time
(gdb)
Please note that breakpoint numbers (listed under ``Num``) start with ``2``. This is because first breakpoint has been already established at function ``app_main()`` by running command ``thb app_main`` on debugger launch. As it was a temporary breakpoint, it has been automatically deleted and now is not listed anymore.
To remove breakpoints enter ``delete N`` command (in short ``d N``), where ``N`` is the breakpoint number::
(gdb) delete 1
No breakpoint number 1.
(gdb) delete 2
(gdb)
Read more about breakpoints under :ref:`jtag-debugging-tip-breakpoints` and :ref:`jtag-debugging-tip-where-breakpoints`
.. _jtag-debugging-examples-command-line-03:
Halting and resuming the application
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When debugging, you may resume application and enter code waiting for some event or staying in infinite loop without any break points defined. In such case, to go back to debugging mode, you can break program execution manually by entering Ctrl+C.
To check it delete all breakpoints and enter ``c`` to resume application. Then enter Ctrl+C. Application will be halted at some random point and LED will stop blinking. Debugger will print the following::
(gdb) c
Continuing.
^CTarget halted. PRO_CPU: PC=0x400D0C00 APP_CPU: PC=0x400D0C00 (active)
[New Thread 1073433352]
Program received signal SIGINT, Interrupt.
[Switching to Thread 1073413512]
0x400d0c00 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/esp32/./freertos_hooks.c:52
52 asm("waiti 0");
(gdb)
In particular case above, the application has been halted in line 52 of code in file ``freertos_hooks.c``. Now you can resume it again by enter ``c`` or do some debugging as discussed below.
.. note::
In MSYS2 shell Ctrl+C does not halt the target but exists debugger. To resolve this issue consider debugging with :ref:`jtag-debugging-examples-eclipse` or check a workaround under http://www.mingw.org/wiki/Workaround_for_GDB_Ctrl_C_Interrupt.
.. _jtag-debugging-examples-command-line-04:
Stepping through the code
^^^^^^^^^^^^^^^^^^^^^^^^^
It is also possible to step through the code using ``step`` and ``next`` commands (in short ``s`` and ``n``). The difference is that ``step`` is entering inside subroutines calls, while ``next`` steps over the call, treating it as a single source line.
To demonstrate this functionality, using command ``break`` and ``delete`` discussed in previous paragraph, make sure that you have only one breakpoint defined at line ``36`` of ``blink.c``::
(gdb) info break
Num Type Disp Enb Address What
3 breakpoint keep y 0x400db704 in blink_task at /home/user-name/esp/blink/main/./blink.c:36
breakpoint already hit 1 time
(gdb)
Resume program by entering ``c`` and let it halt::
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB754 (active) APP_CPU: PC=0x400D1128
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:36
36 gpio_set_level(BLINK_GPIO, 1);
(gdb)
Then enter ``n`` couple of times to see how debugger is stepping one program line at a time::
(gdb) n
Target halted. PRO_CPU: PC=0x400DB756 (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB758 (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
37 vTaskDelay(1000 / portTICK_PERIOD_MS);
(gdb) n
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400846FC (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB761 (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB746 (active) APP_CPU: PC=0x400D1128
33 gpio_set_level(BLINK_GPIO, 0);
(gdb)
If you enter ``s`` instead, then debugger will step inside subroutine calls::
(gdb) s
Target halted. PRO_CPU: PC=0x400DB748 (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB74B (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DC04C (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DC04F (active) APP_CPU: PC=0x400D1128
gpio_set_level (gpio_num=GPIO_NUM_4, level=0) at /home/user-name/esp/esp-idf/components/driver/./gpio.c:183
183 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
(gdb)
In this particular case debugger stepped inside ``gpio_set_level(BLINK_GPIO, 0)`` and effectively moved to ``gpio.c`` driver code.
See :ref:`jtag-debugging-tip-why-next-works-as-step` for potential limitation of using ``next`` command.
.. _jtag-debugging-examples-command-line-05:
Checking and setting memory
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Displaying the contents of memory is done with command ``x``. With additional parameters you may vary the format and count of memory locations displayed. Run ``help x`` to see more details. Companion command to ``x`` is ``set`` that let you write values to the memory.
We will demonstrate how ``x`` and ``set`` work by reading from and writing to the memory location ``0x3FF44004`` labeled as ``GPIO_OUT_REG`` used to set and clear individual GPIO's. For more information please refer to `ESP32 Technical Reference Manual <http://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>`__, chapter IO_MUX and GPIO Matrix.
Being in the same ``blink.c`` project as before, set two breakpoints right after ``gpio_set_level`` instruction. Enter two times ``c`` to get to the break point followed by ``x /1wx 0x3FF44004`` to display contents of ``GPIO_OUT_REG`` memory location::
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB75E (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB74E (active) APP_CPU: PC=0x400D1128
Breakpoint 2, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:34
34 vTaskDelay(1000 / portTICK_PERIOD_MS);
(gdb) x /1wx 0x3FF44004
0x3ff44004: 0x00000000
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D1128
Target halted. PRO_CPU: PC=0x400DB75B (active) APP_CPU: PC=0x400D1128
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:37
37 vTaskDelay(1000 / portTICK_PERIOD_MS);
(gdb) x /1wx 0x3FF44004
0x3ff44004: 0x00000010
(gdb)
If your are blinking LED connected to GPIO4, then you should see fourth bit being flipped each time the LED changes the state::
0x3ff44004: 0x00000000
...
0x3ff44004: 0x00000010
Now, when the LED is off, that corresponds to ``0x3ff44004: 0x00000000`` being displayed, try using ``set`` command to set this bit by writting ``0x00000010`` to the same memory location::
(gdb) x /1wx 0x3FF44004
0x3ff44004: 0x00000000
(gdb) set {unsigned int}0x3FF44004=0x000010
You should see the LED to turn on immediately after entering ``set {unsigned int}0x3FF44004=0x000010`` command.
.. _jtag-debugging-examples-command-line-06:
Watching and setting program variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A common debugging tasks is checking the value of a program variable as the program runs. To be able to demonstrate this functionality, update file ``blink.c`` by adding a declaration of a global variable ``int i`` above definition of function ``blink_task``. Then add ``i++`` inside ``loop(1)`` of this function to get ``i`` incremented on each blink.
Exit debugger, so it is not confused with new code, build and flash the code to the ESP and restart debugger. There is no need to restart OpenOCD.
Once application is halted, enter the command ``watch i``::
(gdb) watch i
Hardware watchpoint 2: i
(gdb)
This will insert so called "watchpoint" in each place of code where variable ``i`` is being modified. Now enter ``continue`` to resume the application and observe it being halted::
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB751 (active) APP_CPU: PC=0x400D0811
[New Thread 1073432196]
Program received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 1073432196]
0x400db751 in blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:33
33 i++;
(gdb)
Resume application couple more times so ``i`` gets incremented. Now you can enter ``print i`` (in short ``p i``) to check the current value of ``i``::
(gdb) p i
$1 = 3
(gdb)
To modify the value of ``i`` use ``set`` command as below (you can then print it out to check if it has been indeed changed)::
(gdb) set var i = 0
(gdb) p i
$3 = 0
(gdb)
You may have up to two watchpoints, see :ref:`jtag-debugging-tip-breakpoints`.
.. _jtag-debugging-examples-command-line-07:
Setting conditional breakpoints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here comes more interesting part. You may set a breakpoint to halt the program execution, if certain condition is satisfied. Delete existing breakpoints and try this::
(gdb) break blink.c:34 if (i == 2)
Breakpoint 3 at 0x400db753: file /home/user-name/esp/blink/main/./blink.c, line 34.
(gdb)
Above command sets conditional breakpoint to halt program execution in line ``34`` of ``blink.c`` if ``i == 2``.
If current value of ``i`` is less than ``2`` and program is resumed, it will blink LED in a loop until condition ``i == 2`` gets true and then finally halt::
(gdb) set var i = 0
(gdb) c
Continuing.
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
Target halted. PRO_CPU: PC=0x400DB755 (active) APP_CPU: PC=0x400D112C
Target halted. PRO_CPU: PC=0x400DB753 (active) APP_CPU: PC=0x400D112C
Breakpoint 3, blink_task (pvParameter=0x0) at /home/user-name/esp/blink/main/./blink.c:34
34 gpio_set_level(BLINK_GPIO, 0);
(gdb)
Obtaining help on commands
^^^^^^^^^^^^^^^^^^^^^^^^^^
Commands presented so for should provide are very basis and intended to let you quickly get started with JTAG debugging. Check help what are the other commands at you disposal. To obtain help on syntax and functionality of particular command, being at ``(gdb)`` prompt type ``help`` and command name::
(gdb) help next
Step program, proceeding through subroutine calls.
Usage: next [N]
Unlike "step", if the current source line calls a subroutine,
this command does not enter the subroutine, but instead steps over
the call, in effect treating it as a single source line.
(gdb)
By typing just ``help``, you will get top level list of command classes, to aid you drilling down to more details. Optionally refer to available GDB cheat sheets, for instance http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf. Good to have as a reference (even if not all commands are applicable in an embedded environment).
Ending debugger session
^^^^^^^^^^^^^^^^^^^^^^^
To quit debugger enter ``q``::
(gdb) q
A debugging session is active.
Inferior 1 [Remote target] will be detached.
Quit anyway? (y or n) y
Detaching from program: /home/user-name/esp/blink/build/blink.elf, Remote target
Ending remote debugging.
user-name@computer-name:~/esp/blink$

View file

@ -0,0 +1,289 @@
JTAG Debugging
==============
This document provides a guide to installing OpenOCD for ESP32 and debugging using
GDB. The document is structured as follows:
:ref:`jtag-debugging-introduction`
Introduction to the purpose of this guide.
:ref:`jtag-debugging-how-it-works`
Description how ESP32, JTAG interface, OpenOCD and GDB are interconnected and working together to enable debugging of ESP32.
:ref:`jtag-debugging-selecting-jtag-adapter`
What are the criteria and options to select JTAG adapter hardware.
:ref:`jtag-debugging-setup-openocd`
Procedure to install OpenOCD using prebuild software packages for :doc:`Windows <setup-openocd-windows>`, :doc:`Linux <setup-openocd-linux>` and :doc:`MacOS <setup-openocd-macos>` operating systems.
:ref:`jtag-debugging-configuring-esp32-target`
Configuration of OpenOCD software and set up JTAG adapter hardware that will make together a debugging target.
:ref:`jtag-debugging-launching-debugger`
Steps to start up a debug session with GDB from :ref:`jtag-debugging-using-debugger-eclipse` and from :ref:`jtag-debugging-using-debugger-command-line`.
:ref:`jtag-debugging-examples`
If you are not familiar with GDB, check this section for debugging examples provided from from :ref:`jtag-debugging-examples-eclipse` as well as from :ref:`jtag-debugging-examples-command-line`.
:ref:`jtag-debugging-building-openocd`
Procedure to build OpenOCD from sources for :doc:`Windows <building-openocd-windows>`, :doc:`Linux <building-openocd-linux>` and :doc:`MacOS <building-openocd-macos>` operating systems.
:ref:`jtag-debugging-tips-and-quirks`
This section provides collection of tips and quirks related JTAG debugging of ESP32 with OpenOCD and GDB.
.. _jtag-debugging-introduction:
Introduction
------------
The ESP32 has two powerful Xtensa cores, allowing for a great deal of variety of program architectures. The FreeRTOS OS that comes with ESP-IDF is capable of multi-core preemptive multithreading, allowing for an intuitive way of writing software.
The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are printf statements. A better and in many cases quicker way to debug such problems is by using a debugger, connected to the processors over a debug port.
Espressif has ported OpenOCD to support the ESP32 processor and the multicore FreeRTOS, which will be the foundation of most ESP32 apps, and has written some tools to help with features OpenOCD does not support natively.
This document provides a guide to installing OpenOCD for ESP32 and debugging using GDB under Linux, Windows and MacOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems.
.. note::
Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTE. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, MacOS or Linux and / or a different release of Eclipse.
.. _jtag-debugging-how-it-works:
How it Works?
-------------
The key software and hardware to perform debugging of ESP32 with OpenOCD over JTAG (Joint Test Action Group) interface is presented below and includes **xtensa-esp32-elf-gdb debugger**, **OpenOCD** on chip debugger and **JTAG adapter** connected to **ESP32** target.
.. figure:: ../../_static/jtag-debugging-overview.jpg
:align: center
:alt: JTAG debugging - overview diagram
:figclass: align-center
JTAG debugging - overview diagram
Under "Application Loading and Monitoring" there is another software and hardware to compile, build and flash application to ESP32, as well as to provide means to monitor diagnostic messages from ESP32.
Debugging using JTAG and application loading / monitoring is integrated under the `Eclipse <http://www.eclipse.org/>`_ environment, to provide quick and easy transition from writing, compiling and loading the code to debugging, back to writing the code, and so on. All the software is available for Windows, Linux and MacOS platforms.
If the :doc:`ESP32 WROVER KIT <../../hw-reference/modules-and-boards>` is used, then connection from PC to ESP32 is done effectively with a single USB cable thanks to FT2232H chip installed on WROVER, which provides two USB channels, one for JTAG and the second for JTAG connection.
Loading of application over JTAG connection is not yet implemented.
Depending on user preferences, both `debugger` and `make` can be operated directly from terminal / command line, instead from Eclipse.
.. _jtag-debugging-selecting-jtag-adapter:
Selecting JTAG Adapter
----------------------
The quickest and most convenient way to start with JTAG debugging is by using :doc:`ESP32 WROVER KIT <../../hw-reference/modules-and-boards>`. Each version of this development board has JTAG interface already build in. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to ESP32. WROVER KIT is using FT2232H JTAG interface operating at 20 MHz clock speed, which is difficult to achieve with an external adapter.
If you decide to use separate JTAG adapter, look for one that is compatible with both the voltage levels on the ESP32 as well as with the OpenOCD software. The JTAG port on the ESP32 is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3V rail) so the JTAG adapter needs to be able to work with JTAG pins in that voltage range.
On the software side, OpenOCD supports a fair amount of JTAG adapters. See http://openocd.org/doc/html/Debug-Adapter-Hardware.html for an (unfortunately slightly incomplete) list of the adapters OpenOCD works with. This page lists SWD-compatible adapters as well; take note that the ESP32 does not support SWD. JTAG adapters that are hardcoded to a specific product line, e.g. STM32 debugging adapters, will not work.
The minimal signalling to get a working JTAG connection are TDI, TDO, TCK, TMS and GND. Some JTAG debuggers also need a connection from the ESP32 power line to a line called e.g. Vtar to set the working voltage. SRST can optionally be connected to the CH_PD of the ESP32, although for now, support in OpenOCD for that line is pretty minimal.
.. _jtag-debugging-setup-openocd:
Setup of OpenOCD
----------------
This step covers installation of OpenOCD binaries. If you like to build OpenOCS from sources then refer to section :ref:`jtag-debugging-building-openocd`. All OpenOCD files will be placed in ``~/esp/openocd-esp32`` directory. You may choose any other directory, but need to adjust respective paths used in examples.
.. toctree::
:hidden:
Windows <setup-openocd-windows>
Linux <setup-openocd-linux>
MacOS <setup-openocd-macos>
Pick up your OS below and follow provided instructions to setup OpenOCD.
+-------------------+-------------------+-------------------+
| |windows-logo| | |linux-logo| | |macos-logo| |
+-------------------+-------------------+-------------------+
| `Windows`_ | `Linux`_ | `Mac OS`_ |
+-------------------+-------------------+-------------------+
.. |windows-logo| image:: ../../_static/windows-logo.png
:target: ../jtag-debugging/setup-openocd-windows.html
.. |linux-logo| image:: ../../_static/linux-logo.png
:target: ../jtag-debugging/setup-openocd-linux.html
.. |macos-logo| image:: ../../_static/macos-logo.png
:target: ../jtag-debugging/setup-openocd-macos.html
.. _Windows: ../jtag-debugging/setup-openocd-windows.html
.. _Linux: ../jtag-debugging/setup-openocd-linux.html
.. _Mac OS: ../jtag-debugging/setup-openocd-macos.html
After installation is complete, get familiar with two key directories inside ``openocd-esp32`` installation folder:
* ``bin`` containing OpenOCD executable
* ``share\openocd\scripts`` containing configuration files invoked together with OpenOCD as command line parameters
.. note::
Directory names and structure above are specific to binary distribution of OpenOCD. They are used in examples of invoking OpenOCD throughout this guide. Directories for OpenOCD build from sources are different, so the way to invoke OpenOCD. For details see :ref:`jtag-debugging-building-openocd`.
.. _jtag-debugging-configuring-esp32-target:
Configuring ESP32 Target
------------------------
Once OpenOCD is installed, move to configuring ESP32 target (i.e ESP32 board with JTAG interface). You will do it in the following three steps:
* Configure and connect JTAG interface
* Run OpenOCD
* Upload application for debugging
Configure and connect JTAG interface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This step depends on JTAG and ESP32 board you are using - see the two cases described below.
.. toctree::
:maxdepth: 1
configure-wrover
configure-other-jtag
.. _jtag-debugging-run-openocd:
Run OpenOCD
^^^^^^^^^^^
Once target is configured and connected to computer, you are ready to launch OpenOCD.
.. highlight:: bash
Open terminal, go to directory where OpenOCD is installed and start it up::
cd ~/esp/openocd-esp32
bin/openocd -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg
.. note::
The files provided after ``-f`` above, are specific for ESP-WROVER-KIT with ESP-WROOM-32 module. You may need to provide different files depending on used hardware, For guidance see :ref:`jtag-debugging-tip-openocd-configure-target`.
.. highlight:: none
You should now see similar output (this log is for ESP32 WROVER KIT)::
user-name@computer-name:~/esp/openocd-esp32$ bin/openocd -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg
Open On-Chip Debugger 0.10.0-dev-ged7b1a9 (2017-07-10-07:16)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
none separate
adapter speed: 20000 kHz
force hard breakpoints
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 was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32: Core was reset (pwrstat=0x5F, after clear 0x0F).
* If there is an error indicating permission problems, please see the "Permissions delegation" bit in the OpenOCD README file in ``~/esp/openocd-esp32`` directory.
* In case there is an error finding configuration files, e.g. ``Can't find interface/ftdi/esp32_devkitj_v1.cfg``, check the path after ``-s``. This path is used by OpenOCD to look for the files specified after ``-f``. Also check if the file is indeed under provided path.
* If you see JTAG errors (...all ones/...all zeroes) please check your connections, whether no other signals are connected to JTAG besides ESP32's pins, and see if everything is powered on.
Upload application for debugging
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Build and upload your application to ESP32 as usual, see :ref:`get-started-build-flash`.
You are now ready to start application debugging. Follow steps described in section below.
.. _jtag-debugging-launching-debugger:
Launching Debugger
------------------
The toolchain for ESP32 features GNU Debugger, in short GDB. It is available with other toolchain programs under filename ``xtensa-esp32-elf-gdb``. GDB can be called and operated directly from command line in a terminal. Another option is to call it from within IDE (like Eclipse, Visual Studio Code, etc.) and operate indirectly with help of GUI instead of typing commands in a terminal.
Both options of using debugger are discussed under links below.
* :ref:`jtag-debugging-using-debugger-eclipse`
* :ref:`jtag-debugging-using-debugger-command-line`
It is recommended to first check if debugger works from :ref:`jtag-debugging-using-debugger-command-line` and then move to using :ref:`jtag-debugging-using-debugger-eclipse`.
.. _jtag-debugging-examples:
Debugging Examples
------------------
This section is intended for users not familiar with GDB. It presents example debugging session from :ref:`jtag-debugging-examples-eclipse` using simple application available under :example:`get-started/blink` and covers the following debugging actions:
1. :ref:`jtag-debugging-examples-eclipse-01`
2. :ref:`jtag-debugging-examples-eclipse-02`
3. :ref:`jtag-debugging-examples-eclipse-03`
4. :ref:`jtag-debugging-examples-eclipse-04`
5. :ref:`jtag-debugging-examples-eclipse-05`
6. :ref:`jtag-debugging-examples-eclipse-06`
7. :ref:`jtag-debugging-examples-eclipse-07`
Similar debugging actions are provided using GDB from :ref:`jtag-debugging-examples-command-line`.
Before proceeding to examples, set up your ESP32 target and load it with :example:`get-started/blink`.
.. _jtag-debugging-building-openocd:
Building OpenOCD from Sources
-----------------------------
Please refer to separate documents listed below, that describe build process.
.. toctree::
:maxdepth: 1
Windows <building-openocd-windows>
Linux <building-openocd-linux>
MacOS <building-openocd-macos>
.. note::
Examples of invoking OpenOCD in this document assume using pre-built binary distribution described in section :ref:`jtag-debugging-setup-openocd`. To use binaries build locally from sources, change the path to OpenOCD executable to ``src/openocd`` and the path to configuration files to ``-s tcl``.
Example of invoking OpenOCD build locally from sources::
src/openocd -s tcl -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg
.. _jtag-debugging-tips-and-quirks:
Tips and Quirks
---------------
This section provides collection of links to all tips and quirks referred to from various parts of this guide.
* :ref:`jtag-debugging-tip-breakpoints`
* :ref:`jtag-debugging-tip-where-breakpoints`
* :ref:`jtag-debugging-tip-why-next-works-as-step`
* :ref:`jtag-debugging-tip-code-options`
* :ref:`jtag-debugging-tip-freertos-support`
* :ref:`jtag-debugging-tip-code-flash-voltage`
* :ref:`jtag-debugging-tip-debugger-startup-commands`
* :ref:`jtag-debugging-tip-openocd-configure-target`
* :ref:`jtag-debugging-tip-reset-by-debugger`
* :ref:`jtag-debugging-tip-jtag-pins-reconfigured`
* :ref:`jtag-debugging-tip-reporting-issues`
Related Documents
-----------------
.. toctree::
:maxdepth: 1
using-debugger
debugging-examples
tips-and-quirks
../app_trace

View file

@ -0,0 +1,32 @@
***********************
Setup OpenOCD for Linux
***********************
Setup OpenOCD
=============
OpenOCD for 64-bit Linux is available for download from Espressif website:
https://dl.espressif.com/dl/openocd-esp32-linux64-ed7b1a9.tar.gz
Download this file, then extract it in ``~/esp/`` directory::
cd ~/esp
tar -xzf ~/Downloads/openocd-esp32-linux64-ed7b1a9.tar.gz
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.
Related Documents
=================
.. toctree::
:maxdepth: 1
building-openocd-linux

View file

@ -0,0 +1,32 @@
***********************
Setup OpenOCD for MacOS
***********************
Setup OpenOCD
=============
OpenOCD for MacOS is available for download from Espressif website:
https://dl.espressif.com/dl/openocd-esp32-macos-ed7b1a9.tar.gz
Download this file, then extract it in ``~/esp`` directory::
cd ~/esp
tar -xzf ~/Downloads/openocd-esp32-macos-ed7b1a9.tar.gz
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.
Related Documents
=================
.. toctree::
:maxdepth: 1
building-openocd-macos

View file

@ -0,0 +1,28 @@
*************************
Setup OpenOCD for Windows
*************************
Setup OpenOCD
=============
OpenOCD for Windows / MSYS2 is available for download from Espressif website:
https://dl.espressif.com/dl/openocd-esp32-win32-ed7b1a9.zip
Download this file and extract ``openocd-esp32`` folder inside to ``~/esp/`` directory.
Next Steps
==========
To carry on with debugging environment setup, proceed to section :ref:`jtag-debugging-configuring-esp32-target`.
Related Documents
=================
.. toctree::
:maxdepth: 1
building-openocd-windows

View file

@ -0,0 +1,224 @@
Tips and Quirks
---------------
This section provides collection of all tips and quirks referred to from various parts of this guide.
.. _jtag-debugging-tip-breakpoints:
Breakpoints and watchpoints available
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ESP32 supports 2 hardware breakpoints. It also supports two watchpoints, so two variables can be watched for change or read by the GDB command ``watch myVariable``. Note that menuconfig option "Component config > FreeRTOS > Set a debug watchpoint as a stack overflow check" use the 2nd watchpoint and will not provide expected results, if you also try to use it within OpenOCD / GDB. See menuconfig's help for detailed description.
.. _jtag-debugging-tip-where-breakpoints:
What else should I know about breakpoints?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Normal GDB breakpoints (``b myFunction``) can only be set in IRAM, because that memory is writable. Setting these types of breakpoints in code in flash will not work. Instead, use a hardware breakpoint (``hb myFunction``).
.. _jtag-debugging-tip-why-next-works-as-step:
Why stepping with "next" does not bypass subroutine calls?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When stepping through the code with ``next`` command, GDB is internally setting a breakpoint (one out of two available) ahead in the code to bypass the subroutine calls. This functionality will not work, if the two available breakpoints are already set elsewhere in the code. If this is the case, delete breakpoints to have one "spare". With both breakpoints already used, stepping through the code with ``next`` command will work as like with ``step`` command and debugger will step inside subroutine calls.
.. _jtag-debugging-tip-code-options:
Support options for OpenOCD at compile time
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ESP-IDF code has various support options for OpenOCD set at compile time: it can stop execution when the first thread is started and break the system if a panic or unhandled exception is thrown. First option is disabled and second enabled by default and both can be changed using the esp-idf configuration menu. Please see the :ref:`make menuconfig <get-started-configure>` menu for more details.
.. _jtag-debugging-tip-freertos-support:
FreeRTOS support
^^^^^^^^^^^^^^^^
OpenOCD has explicit support for the ESP-IDF FreeRTOS. GDB can see FreeRTOS tasks as threads. Viewing them all can be done using the GDB ``i threads`` command, changing to a certain task is done with ``thread n``, with ``n`` being the number of the thread. FreeRTOS detection can be disabled in target's configuration. For more details see :ref:`jtag-debugging-tip-openocd-configure-target`.
.. _jtag-debugging-tip-code-flash-voltage:
Why to set SPI flash voltage in OpenOCD configuration?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The MTDI pin of ESP32, being among four pins used for JTAG communication, is also one of ESP32's bootstrapping pins. On power up ESP32 is sampling binary level on MTDI to set it's internal voltage regulator used to supply power to external SPI flash chip. If binary level on MDTI pin on power up is low, the voltage regulator is set to deliver 3.3V, if it is high, then the voltage is set to 1.8V. The MTDI pin should have a pull-up or may rely on internal weak pull down resistor (see ESP32 Datasheet for details), depending on the type of SPI chip used. Once JTAG is connected, it overrides the pull-up or pull-down resistor that is supposed to do the bootstrapping.
To handle this issue OpenOCD's board configuration file (e.g. ``boards\esp-wroom-32.cfg`` for ESP-WROOM-32 module) provides ``ESP32_FLASH_VOLTAGE`` parameter to set the idle state of the ``TDO`` line to a specified binary level, therefore reducing the chance of a bad bootup of application due to incorrect flash voltage.
Check specification of ESP32 module connected to JTAG, what is the power supply voltage of SPI flash chip. Then set ``ESP32_FLASH_VOLTAGE`` accordingly. Most WROOM modules use 3.3V flash, while WROVER modules use 1.8V flash.
.. _jtag-debugging-tip-debugger-startup-commands:
What is the meaning of debugger's startup commands?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On startup, debugger is issuing sequence of commands to reset the chip and halt it at specific line of code. This sequence (shown below) is user defined to pick up at most convenient / appropriate line and start debugging.
* ``mon reset halt`` — reset the chip and keep the CPUs halted
* ``hb app_main`` — insert a hardware breakpoint at app_main, put here another function name if required
* ``x $a1=0`` — this is the tricky part. As far as we can tell, there is no way for a ``mon`` command to tell GDB that the target state has changed. GDB will assume that whatever stack the target had before ``mon reset halt`` will still be valid. In fact, after reset the target state will change and executing ``x $a1=0`` is a way to force GDB to get new state from the target.
* ``c`` — resume the program. It will then stop at breakpoint inserted at ``app_main``.
.. _jtag-debugging-tip-openocd-configure-target:
Configuration of OpenOCD for specific target
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OpenOCD needs to be told what JTAG adapter **interface** to use, as well as what type of **board** and processor the JTAG adapter is connected to. To do so, use existing configuration files located in OpenOCD's ``/share/openocd/scripts/interface`` and ``/share/openocd/scripts/board`` folders.
For example, if you connect to ESP-WROVER-KIT with ESP-WROOM-32 module installed (see section :doc:`ESP32 WROVER KIT <../../hw-reference/modules-and-boards>`), use the following configuration files:
* ``interface/ftdi/esp32_devkitj_v1.cfg``
* ``board/esp-wroom-32.cfg``
Optionally prepare configuration by yourself. To do so, you can check existing files and modify them to match you specific hardware. Below is the summary of available configuration parameters for **board** configuration.
.. highlight:: none
Adapter's clock speed
""""""""""""""""""""""
::
adapter_khz 20000
Single core debugging
"""""""""""""""""""""
::
set ESP32_ONLYCPU 1
Comment out this line for dual core debugging.
Disable RTOS support
""""""""""""""""""""
::
set ESP32_RTOS none
Comment out this line to have RTOS support.
Power supply voltage of ESP32's SPI flash chip
""""""""""""""""""""""""""""""""""""""""""""""
::
set ESP32_FLASH_VOLTAGE 1.8
Comment out this line to set 3.3V, ref: :ref:`jtag-debugging-tip-code-flash-voltage`.
Configuration file for ESP32 targets
""""""""""""""""""""""""""""""""""""
::
source [find target/esp32.cfg]
.. note::
Do not change ``source [find target/esp32.cfg]`` line unless you are familiar with OpenOCD internals.
Currently ``target/esp32.cfg`` remains the only configuration file for ESP32 targets (esp108 and esp32). The matrix of supported configurations is as follows:
+---------------+---------------+---------------+
| Dual/single | RTOS | Target used |
+===============+===============+===============+
| dual | FreeRTOS | esp32 |
+---------------+---------------+---------------+
| single | FreeRTOS | esp108 (*) |
+---------------+---------------+---------------+
| dual | none | esp108 |
+---------------+---------------+---------------+
| single | none | esp108 |
+---------------+---------------+---------------+
(*) — we plan to fix this and add support for single core debugging with esp32 target in a subsequent commits.
Look inside ``board/esp-wroom-32.cfg`` for additional information provided in comments besides each configuration parameter.
.. _jtag-debugging-tip-reset-by-debugger:
How debugger resets ESP32?
^^^^^^^^^^^^^^^^^^^^^^^^^^
The board can be reset by entering ``mon reset`` or ``mon reset halt`` into GDB.
.. _jtag-debugging-tip-jtag-pins-reconfigured:
Do not use JTAG pins for something else
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Operation of JTAG may be disturbed, if some other h/w is connected to JTAG pins besides ESP32 module and JTAG adapter.
JTAG communication will likely fail, if configuration of JTAG pins is changed by user application. If OpenOCD initializes correctly (detects the two Tensilica cores), but loses sync and spews out a lot of DTR/DIR errors when the program is ran, it is likely that the application reconfigures the JTAG pins to something else, or the user forgot to connect Vtar to a JTAG adapter that needed it.
.. highlight:: none
Below is an excerpt from series of errors reported by GDB after the application stepped into the code that reconfigured MTDO / GPIO15 to be an input::
cpu0: xtensa_resume (line 431): DSR (FFFFFFFF) indicates target still busy!
cpu0: xtensa_resume (line 431): DSR (FFFFFFFF) indicates DIR instruction generated an exception!
cpu0: xtensa_resume (line 431): DSR (FFFFFFFF) indicates DIR instruction generated an overrun!
cpu1: xtensa_resume (line 431): DSR (FFFFFFFF) indicates target still busy!
cpu1: xtensa_resume (line 431): DSR (FFFFFFFF) indicates DIR instruction generated an exception!
cpu1: xtensa_resume (line 431): DSR (FFFFFFFF) indicates DIR instruction generated an overrun!
.. _jtag-debugging-tip-reporting-issues:
Reporting issues with OpenOCD / GDB
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In case you encounter a problem with OpenOCD or GDB programs itself, open an issue in the OpenOCD issue tracker under https://github.com/espressif/openocd-esp32/issues.
Create a simple example that is representative to observed issue. Describe steps how to reproduce it. In such an example debugging should not be affected by non-deterministic behaviour introduced by the Wi-Fi stack, so problems will likely be easier to reproduce, if encountered once.
Prepare logs from debugging session by adding additional parameters to start up commands.
.. highlight:: bash
OpenOCD:
::
bin/openocd -l openocd_log.txt -d 3 -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg
Logging to a file this way will prevent information displayed on the terminal. This may be a good thing taken amount of information provided, when increased debug level ``-d 3`` is set. If you still like to see the log on the screen, then use another command instead:
::
bin/openocd -d 3 -s share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg 2>&1 | tee openocd.log
.. note::
See :ref:`jtag-debugging-building-openocd` for slightly different command format, when running OpenOCD built from sources.
Debugger:
::
xtensa-esp32-elf-gdb -ex "set remotelogfile gdb_log.txt" <all other options>
Optionally add command ``remotelogfile gdb_log.txt`` to the ``gdbinit`` file.
Attach both ``openocd_log.txt`` and ``gdb_log.txt`` files to your issue report.

View file

@ -0,0 +1,174 @@
Using Debugger
--------------
This section covers configuration and running debugger either from :ref:`jtag-debugging-using-debugger-eclipse`
or :ref:`jtag-debugging-using-debugger-command-line`. It is recommended to first check if debugger works from :ref:`jtag-debugging-using-debugger-command-line` and then move to using Eclipse.
.. _jtag-debugging-using-debugger-eclipse:
Eclipse
^^^^^^^
Debugging functionality is provided out of box in standard Eclipse installation. Another option is to use pluggins like "GDB Hardware Debugging" plugin. We have found this plugin quite convenient and decided to use throughout this guide.
To begin with, install "GDB Hardware Debugging" plugin by opening Eclipse and going to `Help` > `Install` New Software.
Once installation is complete, configure debugging session following steps below. Please note that some of configuration parameters are generic and some are project specific. This will be shown below by configuring debugging for "blink" example project. If not done already, add this project to Eclipse workspace following guidance in section :doc:`Build and Flash with Eclipse IDE <../../get-started/eclipse-setup>`. The source of :example:`get-started/blink` application is available in :idf:`examples` directory of ESP-IDF repository.
1. In Eclipse go to `Run` > `Debug Configuration`. A new window will open. In the window's left pane double click "GDB Hardware Debugging" (or select "GDB Hardware Debugging" and press the "New" button) to create a new configuration.
2. In a form that will show up on the right, enter the "Name:" of this configuration, e.g. "Blink checking".
3. On the "Main" tab below, under "Project:", press "Browse" button and select the "blink" project.
4. In next line "C/C++ Application:" press "Browse" button and select "blink.elf" file. If "blink.elf" is not there, then likely this project has not been build yet. See :doc:`Build and Flash with Eclipse IDE <../../get-started/eclipse-setup>` how to do it.
5. Finally, under "Build (if required) before launching" click "Disable auto build".
A sample window with settings entered in points 1 - 5 is shown below.
.. figure:: ../../_static/hw-debugging-main-tab.jpg
:align: center
:alt: Configuration of GDB Hardware Debugging - Main tab
:figclass: align-center
Configuration of GDB Hardware Debugging - Main tab
6. Click "Debugger" tab. In field "GDB Command" enter ``xtensa-esp32-elf-gdb`` to invoke debugger.
7. Change default configuration of "Remote host" by entering ``3333`` under the "Port number".
Configuration entered in points 6 and 7 is shown on the following picture.
.. figure:: ../../_static/hw-debugging-debugger-tab.jpg
:align: center
:alt: Configuration of GDB Hardware Debugging - Debugger tab
:figclass: align-center
Configuration of GDB Hardware Debugging - Debugger tab
8. The last tab to that requires changing of default configuration is "Startup". Under "Initialization Commands" uncheck "Reset and Delay (seconds)" and "Halt"". Then, in entry field below, type ``mon reset halt`` and ``x $a1=0`` (in two separate lines).
9. Under "Load Image and Symbols" uncheck "Load image" option.
10. Further down on the same tab, establish an initial breakpoint to halt CPUs after they are reset by debugger. The plugin will set this breakpoint at the beginning of the function entered under "Set break point at:". Checkout this option and enter ``app_main`` in provided field.
11. Checkout "Resume" option. This will make the program to resume after ``mon reset halt`` is invoked per point 8. The program will then stop at breakpoint inserted at ``app_main``.
Configuration described in points 8 - 11 is shown below.
.. figure:: ../../_static/hw-debugging-startup-tab.jpg
:align: center
:alt: Configuration of GDB Hardware Debugging - Startup tab
:figclass: align-center
Configuration of GDB Hardware Debugging - Startup tab
If the "Startup" sequence looks convoluted and respective "Initialization Commands" are not clear to you, check :ref:`jtag-debugging-tip-debugger-startup-commands` for additional explanation.
12. If you previously completed :ref:`jtag-debugging-configuring-esp32-target` steps described above, so the target is running and ready to talk to debugger, go right to debugging by pressing "Debug" button. Otherwise press "Apply" to save changes, go back to :ref:`jtag-debugging-configuring-esp32-target` and return here to start debugging.
Once all 1 - 12 configuration steps are satisfied, the new Eclipse perspective called "Debug" will open as shown on example picture below.
.. figure:: ../../_static/debug-perspective.jpg
:align: center
:alt: Debug Perspective in Eclipse
:figclass: align-center
Debug Perspective in Eclipse
If you are not quite sure how to use GDB, check :ref:`jtag-debugging-examples-eclipse` example debugging session in section :ref:`jtag-debugging-examples`.
.. _jtag-debugging-using-debugger-command-line:
Command Line
^^^^^^^^^^^^
1. To be able start debugging session, the target should be up and running. If not done already, complete steps described under :ref:`jtag-debugging-configuring-esp32-target`.
.. highlight:: bash
2. Open a new terminal session and go to directory that contains project for debugging, e.g.
::
cd ~/esp/blink
.. highlight:: none
3. When launching a debugger, you will need to provide couple of configuration parameters and commands. Instead of entering them one by one in command line, create a configuration file and name it ``gdbinit``:
::
target remote :3333
mon reset halt
thb app_main
x $a1=0
c
Save this file in current directory.
For more details what's inside ``gdbinit`` file, see :ref:`jtag-debugging-tip-debugger-startup-commands`
.. highlight:: bash
4. Now you are ready to launch GDB. Type the following in terminal:
::
xtensa-esp32-elf-gdb -x gdbinit build/blink.elf
.. highlight:: none
5. If previous steps have been done correctly, you will see a similar log concluded with ``(gdb)`` prompt:
::
user-name@computer-name:~/esp/blink$ xtensa-esp32-elf-gdb -x gdbinit build/blink.elf
GNU gdb (crosstool-NG crosstool-ng-1.22.0-61-gab8375a) 7.10
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=xtensa-esp32-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from build/blink.elf...done.
0x400d10d8 in esp_vApplicationIdleHook () at /home/user-name/esp/esp-idf/components/esp32/./freertos_hooks.c:52
52 asm("waiti 0");
JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
JTAG tap: esp32.slave tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
esp32: Debug controller was reset (pwrstat=0x5F, after clear 0x0F).
esp32: Core was reset (pwrstat=0x5F, after clear 0x0F).
Target halted. PRO_CPU: PC=0x5000004B (active) APP_CPU: PC=0x00000000
esp32: target state: halted
esp32: Core was reset (pwrstat=0x1F, after clear 0x0F).
Target halted. PRO_CPU: PC=0x40000400 (active) APP_CPU: PC=0x40000400
esp32: target state: halted
Hardware assisted breakpoint 1 at 0x400db717: file /home/user-name/esp/blink/main/./blink.c, line 43.
0x0: 0x00000000
Target halted. PRO_CPU: PC=0x400DB717 (active) APP_CPU: PC=0x400D10D8
[New Thread 1073428656]
[New Thread 1073413708]
[New Thread 1073431316]
[New Thread 1073410672]
[New Thread 1073408876]
[New Thread 1073432196]
[New Thread 1073411552]
[Switching to Thread 1073411996]
Temporary breakpoint 1, app_main () at /home/user-name/esp/blink/main/./blink.c:43
43 xTaskCreate(&blink_task, "blink_task", 512, NULL, 5, NULL);
(gdb)
Note the third line from bottom that shows debugger halting at breakpoint established in ``gdbinit`` file at function ``app_main()``. Since the processor is halted, the LED should not be blinking. If this is what you see as well, you are ready to start debugging.
If you are not quite sure how to use GDB, check :ref:`jtag-debugging-examples-command-line` example debugging session in section :ref:`jtag-debugging-examples`.

View file

@ -1,131 +0,0 @@
Debugging
=========
OpenOCD setup for ESP32
-----------------------
The ESP31 and ESP32 have two powerful Xtensa cores, allowing for a great variety of program architectures. The FreeRTOS
OS that comes with ESP-IDF is capable of multi-core pre-emptive multithreading, allowing for an intuitive way of writing software.
The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused
by two threads, maybe even running simultaneously on two different CPU cores, can take a long time when all you have are printf
statements. A better and in many cases quicker way to debug such problems is by using a debugger, connected to the processors over
a debug port.
Espressif has ported OpenOCD to support the ESP32 processor and the multicore FreeRTOS that will be the foundation of most ESP32
apps, and has written some tools to help with features OpenOCD does not support natively. These are all available for free, and
this document describes how to install and use them.
JTAG adapter hardware
---------------------
You will need a JTAG adapter that is compatible with both the voltage levels on the ESP32 as well as with the OpenOCD software.
The JTAG port on the ESP32 is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins
all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3V rail) so the JTAG adapter needs to be
able to work with JTAG pins in that voltage range. On the software side, OpenOCD supports a fair amount of JTAG adapters.
See http://openocd.org/doc/html/Debug-Adapter-Hardware.html for an (unfortunately slightly incomplete) list of the adapters
OpenOCD works with. This page lists SWD-compatible adapters as well; take note that the ESP32 does not support SWD.
At Espressif, we have tested the TIAO USB Multi-protocol Adapter board as well as the Flyswatter2, which are both USB2.0 high-speed
devices and give a good throughput. We also tested a J-link-compatible and an EasyOpenJTAG adapter; both worked as well but are
somewhat slower.
The minimal signalling to get a working JTAG connection are TDI, TDO, TCK, TMS and Gnd. Some JTAG debuggers also need a connection
from the ESP32 power line to a line called e.g. Vtar to set the working voltage. SRST can optionally be connected to the CH_PD of
the ESP32, although for now, support in OpenOCD for that line is pretty minimal.
Installing OpenOCD
------------------
The sources for the ESP32-enabled variant of OpenOCD are available from `Espressifs Github <https://github.com/espressif/openocd-esp32>`_.
To download the source, use the following commands::
git clone --recursive https://github.com/espressif/openocd-esp32.git
cd openocd-esp32
For compilation of OpenOCD, please refer to the README, README.OSX and README.Windows file in the openocd-esp32 directory. You can skip
the ``make install`` step if you want.
Configuring the ESP32 target in OpenOCD
---------------------------------------
After OpenOCD is compiled (and optionally installed) and the JTAG adapter is connected to the ESP32 board, everything is ready to
invoke OpenOCD for the first time. To do this, OpenOCD needs to be told what JTAG adapter to use as well as what type of board
and processor the JTAG adapter is connected to. It is the easiest to do both using a configuration file. A template configuration
file (esp32.cfg) is included in the same directory as this file. A way to use this would be:
- Copy esp32.cfg to the openocd-esp32 directory
- Edit the copied esp32.cfg file. Most importantly, change the ``source [find interface/ftdi/tumpa.cfg]`` line to reflect the
physical JTAG adapter connected.
- Open a terminal and ``cd`` to the openocd-esp32 directory.
- Run ``./src/openocd -s ./tcl -f ./esp32.cfg`` to start OpenOCD
You should now see something like this::
user@machine:~/esp32/openocd-esp32$ ./src/openocd -s ./tcl/ -f ../openocd-esp32-tools/esp32.cfg
Open On-Chip Debugger 0.10.0-dev-00446-g6e13a97-dirty (2016-08-23-16:36)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
none separate
adapter speed: 200 kHz
Info : clock speed 200 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.cpu0: Debug controller was reset (pwrstat=0x5F, after clear 0x0F).
Info : esp32.cpu0: Core was reset (pwrstat=0x5F, after clear 0x0F).
- If you see an error indicating permission problems, please see the 'Permissions delegation' bit in the OpenOCD README
- If you see JTAG errors (...all ones/...all zeroes) please check your connections and see if everything is powered on.
Connecting a debugger to OpenOCD
--------------------------------
OpenOCD should now be ready to accept gdb connections. If you have compiled the ESP32 toolchain using Crosstool-NG, or
if you have downloaded a precompiled toolchain from the Espressif website, you should already have xtensa-esp32-elf-gdb,
a version of gdb that can be used for this. First, make sure the project you want to debug is compiled and flashed
into the ESP32's SPI flash. Then, in a different console than OpenOCD is running in, invoke gdb. For example, for the
template app, you would do this like such::
cd esp-idf-template
xtensa-esp32-elf-gdb -ex 'target remote localhost:3333' ./build/app-template.elf
This should give you a gdb prompt.
FreeRTOS support
----------------
OpenOCD has explicit support for the ESP-IDF FreeRTOS; FreeRTOS detection can be disabled in esp32.conf. When enabled,
gdb can see FreeRTOS tasks as threads. Viewing them all can be done using the gdb ``i threads`` command, changing
to a certain task is done with ``thread x``, with x being the number of the thread. All threads can be switched to
except for a thread actually running on the other CPU, please see ``ESP32 quirks`` for more information.
ESP32 quirks
------------
Normal gdb breakpoints (``b myFunction``) can only be set in IRAM, because that memory is writable. Setting these types of
breakpoints in code in flash will not work. Instead, use a hardware breakpoint (``hb myFunction``). The esp32 supports
2 hardware breakpoints. It also supports two watchpoint, so two variables can be watched for change or read by the gdb
command ``watch myVariable``.
Connecting gdb to the APP or PRO cpu happens by changing the port gdb connects to. ``target remote localhost:3333`` connects
to the PRO CPU, ``target remote localhost:3334`` to the APP CPU. Hardware-wise, when one CPU is halted because of debugging
reasons, the other one will be halted as well; resuming also happens simultaneously.
Because gdb only sees the system from the point of view of the selected CPU, only the FreeRTOS tasks that are suspended
and the task running on the CPU gdb is connected to, will be shown correctly. The task that was active on the other
cpu can be inspected, but its state may be wildly inconsistent.
The ESP-IDF code has the option of compiling in various support options for OpenOCD: it can stop execution when the first
thread is started and break the system if a panic or unhandled exception is thrown. Both options are enabled by default
but can be disabled using the esp-idf configuration menu. Please see the ``make menuconfig`` menu for more details.
Normally, under OpenOCD, a board can be reset by entering 'mon reset' or 'mon reset halt' into gdb. For
the ESP32, these commands work more or less, but have side effects. First of all, an OpenOCD reset only
resets the CPU cores, not the peripherals, which may lead to undefined behaviour if software assumes the
after-reset state of peripherals. Secondly, 'mon reset halt' stops before FreeRTOS is initialized.
OpenOCD assumes (in the default configuration, you can change this by editing esp32.cfg) a running
FreeRTOS and may get confused.

View file

@ -1,5 +1,6 @@
*****************
ESP32 ROM console
=================
*****************
When an ESP32 is unable to boot from flash ROM (and the fuse disabling it hasn't been blown), it boots into a rom console. The console
is based on TinyBasic, and statements entered should be in the form of BASIC statements. As is common in the BASIC language, without a

View file

@ -14,31 +14,5 @@ Developers can use this library to send application specific state of execution
API Reference
-------------
Header Files
^^^^^^^^^^^^
.. include:: /_build/inc/esp_app_trace.inc
* :component_file:`app_trace/include/esp_app_trace.h`
Macros
^^^^^^
.. doxygendefine:: ESP_APPTRACE_TMO_INFINITE
Enumerations
^^^^^^^^^^^^
.. doxygenenum:: esp_apptrace_dest_t
Functions
^^^^^^^^^
.. doxygenfunction:: esp_apptrace_init
.. doxygenfunction:: esp_apptrace_buffer_get
.. doxygenfunction:: esp_apptrace_buffer_put
.. doxygenfunction:: esp_apptrace_write
.. doxygenfunction:: esp_apptrace_vprintf_to
.. doxygenfunction:: esp_apptrace_vprintf
.. doxygenfunction:: esp_apptrace_read
.. doxygenfunction:: esp_apptrace_flush
.. doxygenfunction:: esp_apptrace_flush_nolock

View file

@ -29,9 +29,9 @@ which it can't do for a normal malloc() call. This can help to use all the avail
API Reference - Heap Allocation
-------------------------------
.. include:: /_build/inc/esp_heap_alloc_caps.inc
.. include:: /_build/inc/esp_heap_caps.inc
API Reference - Heap Regions
----------------------------
.. include:: /_build/inc/heap_regions.inc
.. include:: /_build/inc/multi_heap.inc

View file

@ -61,7 +61,7 @@ Development board that has dual port USB to serial converter for programming and
:alt: ESP32 WROVER KIT V1 / ESP32 DevKitJ V1 board
* `Schematic <http://dl.espressif.com/dl/schematics/ESP32-DevKitJ-v1_sch.pdf>`__ (PDF)
* `JTAG Debugging for ESP32`_ (PDF)
* :doc:`../api-guides/jtag-debugging/index`
* `FTDI Virtual COM Port Drivers`_
@ -78,7 +78,7 @@ This is updated version of ESP32 DevKitJ V1 described above with design improvem
Comparing to previous version, this board has a shiny black finish and a male camera header.
* `Schematic V2 <http://dl.espressif.com/dl/schematics/ESP-WROVER-KIT_SCH-2.pdf>`__ (PDF)
* `JTAG Debugging for ESP32`_ (PDF)
* :doc:`../api-guides/jtag-debugging/index`
* `FTDI Virtual COM Port Drivers`_
@ -98,10 +98,9 @@ All versions of ESP32 WROVER KIT are ready to accommodate an ESP-WROOM-32 or ESP
* `Schematic V3 <http://dl.espressif.com/dl/schematics/ESP-WROVER-KIT_SCH-3.pdf>`__ (PDF)
* :doc:`../get-started/get-started-wrover-kit`
* `JTAG Debugging for ESP32`_ (PDF)
* :doc:`../api-guides/jtag-debugging/index`
* `FTDI Virtual COM Port Drivers`_
.. _JTAG Debugging for ESP32: http://espressif.com/sites/default/files/documentation/jtag_debugging_for_esp32_en.pdf
.. _FTDI Virtual COM Port Drivers: http://www.ftdichip.com/Drivers/D2XX.htm