Skip to content

Commit 2f224b4

Browse files
authored
Merge pull request #482 from espressif/debugging_with_vscode_setup
Sync Merge: debugging_with_vscode_setup
2 parents b632410 + 4ce63c6 commit 2f224b4

File tree

7 files changed

+276
-0
lines changed

7 files changed

+276
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: "Francesco Bez"
3+
---
251 KB
Loading
85.1 KB
Loading
16.9 KB
Loading
48.5 KB
Loading
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
---
2+
title: "Debugging with ESP-IDF VS Code extension: Part 1"
3+
date: 2025-05-20
4+
showAuthor: false
5+
authors:
6+
- francesco-bez
7+
tags:
8+
- Debugging
9+
- ESP-IDF
10+
- ESP32-C3
11+
- ESP32-S3
12+
summary: "This two-part guide shows how to set up VS Code with the ESP-IDF extension to debug Espressif boards using JTAG. This first part covers the debugging process, hardware setup and connections, and starting the openOCD server."
13+
---
14+
15+
## Introduction
16+
17+
Debugging is a critical part of the development process, especially when working with embedded systems. It allows developers to identify and fix errors, ensuring that the firmware interacts correctly with the peripherals and the external hardware. While there are several ways to debug code, the most powerful method is to use a _debugger_, which provides real-time insights into how the code runs on the hardware.
18+
19+
Many developers start with basic debugging, often using `printf` statements to track program flow and check variable values. While helpful, this method has major limits. Printf-based debugging forces you to change the code and recompile it each time you test something new. In contrast, debuggers let you step through code, inspect memory, and set breakpoints without touching the source.
20+
21+
In this guide, we'll walk through the steps necessary to set up debugging for Espressif devices using [Visual Studio Code](https://code.visualstudio.com/) (VS Code) and the [ESP-IDF Extension](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/). The ESP-IDF Extension manages the whole toolchain, but knowing the tools it uses, like `openOCD` and `gdb`, gives you more control and helps you fix problems that may arise along the way.
22+
23+
This guide will show you the two available hardware paths to debug Espressif devices (JTAG pins and USB pins) and the interacting tools which make debugging possible.
24+
25+
This article has two parts.
26+
In this first part, we will explain the debugging process, describe the tools, set up the hardware, and start the `openOCD` server.
27+
In the second part, we will run `gdb` and explore its options for debugging the code.
28+
29+
In the rest of the article, we’ll use “Espressif device" to refer to both the modules and SoCs, since the steps below apply to both.
30+
31+
__Prerequisites__
32+
33+
Before you begin, make sure you have the following:
34+
35+
- An Espressif development board based on one of the following series: **ESP32-C3**, **ESP32-C6**, or **ESP32-S3**
36+
37+
- Either an _expendable_ USB cable (that supports data transfer) or the [**ESP-PROG**](https://docs.espressif.com/projects/esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html#introduction-to-the-esp-prog-board) debug probe
38+
39+
- Visual Studio Code (VS Code)
40+
_If not installed, follow the [installation instructions](https://code.visualstudio.com/docs/setup/windows)_
41+
42+
- ESP-IDF Extension for VS Code
43+
_If not installed, follow the [setup instructions](https://github.com/espressif/vscode-esp-idf-extension?tab=readme-ov-file#esp-idf-extension-for-vs-code)_
44+
45+
- Ability to use ESP-IDF extension for VS Code to build, flash, and monitor a simple example project, such as `blink` or `hello_world`
46+
_If you're unsure, check [Create an ESP-IDF Project](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/startproject.html#create-an-esp-idf-project)_
47+
48+
49+
## Debugging process
50+
51+
The debugging process requires several tools working together. You interact with the IDE, which manages the compiler, the debugger and the flasher (software) tool. The flasher tool communicates to a (hardware) programmer which can upload the firmware to the flash memory of the microcontroller and manage JTAG interactions.
52+
53+
{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}}
54+
With USB enabled devices, the programmer/debugger is built into the SoC (but remains external to the workstation).
55+
{{< /alert >}}
56+
57+
You can find an overview of the debugging process in Fig. 1.
58+
59+
<!-- ![Debugging workflow](img/debuggingWorkflow.webp) -->
60+
{{< figure
61+
default=true
62+
src="img/debuggingWorkflow.webp"
63+
height=200
64+
caption="Fig.1 - Debugging Workflow"
65+
>}}
66+
67+
We will use VSCode IDE with `ESP-IDF Extension`, which manages the following tools for both flashing and debugging:
68+
69+
* __Compiling and flashing__: The extension uses [`idf.py`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-py.html#idf-frontend-idf-py), which is a CLI front-end tool which takes care of the compilation ([CMake/ninja](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#using-the-build-system)) and the flashing ([esptool.py](https://github.com/espressif/esptool?tab=readme-ov-file#esptoolpy)) processes.
70+
* __Debugging__: The extension connects seamlessly with `esp-gdb` which derives from the venerable [GNU Debugger](https://en.wikipedia.org/wiki/GNU_Debugger) (gdb). The `esp-gdb` interfaces with a forked version of `openOCD` called [`openocd-esp32`](https://github.com/espressif/openocd-esp32) which supports newly released SoC series sooner than the original `openOCD`. We will use the terms `openocd-esp32` and `openOCD` interchangeably. The same goes for `esp-gdb` and `gdb`.
71+
72+
{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}}
73+
With older ESP-IDF plugin versions, you needed to install openOCD separately. Now it comes directly with ESP-IDF plugin.
74+
{{< /alert >}}
75+
76+
__Testing openOCD availability__
77+
78+
Let's check if your version of VS Code extension comes with `openOCD` installed.
79+
80+
{{< alert iconColor="#df8e1d" cardColor="#edcea3">}}
81+
Most commands in VSCode are executed through the _Command Palette_, which you can open by pressing `CTRL+SHIFT+P` (or `CMD+SHIFT+P` if you're on mac-os). In this guide, commands to enter in the _Command Palette_ are marked with the symbol __`>`__ .
82+
{{< /alert >}}
83+
84+
* Lauch VS Code.
85+
* Open a new Terminal.
86+
&gt; `ESP-IDF: Open ESP-IDF-Terminal`
87+
* In the terminal type
88+
```bash
89+
openocd --version
90+
```
91+
92+
You should read something like
93+
```bash
94+
Open On-Chip Debugger v0.12.0-esp32-20241016 (2024-10-16-14:27)
95+
```
96+
97+
Now that we ensured we're using an updated IDE, let's set up the hardware.
98+
99+
## Hardware for debugging
100+
101+
Espressif devices usually require separate hardware for flashing and debugging via JTAG. By default, you flash Espressif devices using the serial port (UART0) which does not support JTAG.
102+
Note that most of Espressif development boards do __not__ include a JTAG probe. A notable exception is the [ESP32-WROVER-KIT](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp-wrover-kit/user_guide.html#functionality-overview). They only offer a USB-to-UART connection for flashing and monitoring.
103+
104+
To debug an development board—or any Espressif-based board—you have two options:
105+
106+
1. JTAG over JTAG pins (with a JTAG probe) -- briefly described below for completeness
107+
2. JTAG over USB pins -- used in the rest of the article
108+
109+
110+
All Espressif devices support the first option. The second option works only with USB-equipped devices, such as the ESP32-S3 or ESP32-C3. Although both options are shown, in the rest of the article, we will use the JTAG over USB pins option.
111+
112+
### JTAG over JTAG pins
113+
114+
To debug using the JTAG pins, you first need a JTAG probe. Espressif offers a probe called [ESP-PROG](https://docs.espressif.com/projects/esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html), whose JTAG connector is shown in Fig.2.
115+
116+
<!-- ![ESP-PROG JTAG](img/esp_prog_jtag.webp) -->
117+
118+
{{< figure
119+
default=true
120+
src="img/esp_prog_jtag.webp"
121+
width=350
122+
caption="Fig.2 - ESP-PROG JTAG connector"
123+
>}}
124+
125+
To enable JTAG programming, connect the four pins `TMS`, `TCK`, `TDO`, `TDI` of the JTAG probe to the corresponding Espressif module pins.
126+
127+
In the table below, you can find the pins for three common modules.
128+
129+
|JTAG|ESP-PROG|ESP32-C3-MINI-1|ESP32-S3-WROOM-1|ESP32-C6-WROOM-1
130+
|---|---|---|---|---|
131+
|__TMS__|ESP_TMS|GPIO 4|GPIO 42|GPIO 4|
132+
|__TCK__|ESP_TCK|GPIO 6|GPIO 39|GPIO 6|
133+
|__TDO__|ESP_TDO|GPIO 7|GPIO 40|GPIO 7|
134+
|__TDI__|ESP_TDI|GPIO 5|GPIO 41|GPIO 5|
135+
136+
For other modules, consult the _Pin Description_ section of the datasheet and look for `MTMS`, `MTCK`, `MTDO`, `MTDI` pins.
137+
138+
The JTAG peripheral is generally enabled by default and can be [disabled in production](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/security/security.html#debug-interfaces) and for security reasons using the appropriate eFuses (`EFUSE_DISABLE_JTAG` or `EFUSE_HARD_DIS_JTAG` depending on the SoC series).
139+
140+
While the ESP-PROG works with most Espressif devices, it requires additional hardware and uses up to four pins. In newer cores, you have a second option via USB, as shown Debugging workflow illustration in Fig.1.
141+
142+
### JTAG over USB
143+
144+
Most newer Espressif SoC series integrate the USB peripheral and it can be used for JTAG debugging.
145+
Take a thick usb cable (designed for both charging and data transmission) and strip it using a wire stripper or a pair of scissors. You should see the four wires inside, as shown in Fig.3.
146+
147+
<!--
148+
![ESP-PROG JTAG](img/usb_pins.webp) -->
149+
150+
{{< figure
151+
default=true
152+
src="img/usb_pins.webp"
153+
width=400
154+
caption="Fig.3 - USB cable pins"
155+
>}}
156+
157+
Now connect `GND` , `D+` and `D-` to the corresponding Espressif module pins.
158+
If you're using an development board you can connect `VCC` to the `+5V` of the pin (__not__ the `3v3` pin!).
159+
160+
{{< alert iconColor="#df8e1d" cardColor="#edcea3">}}
161+
USB supply pin is about 5V. To power your board with it, connect VCC to the input of an LDO regulator that outputs 3.3V for the Espressif module.
162+
{{< /alert >}}
163+
164+
In the table below, you can find the pins for three common modules.
165+
166+
||ESP32-C3-MINI-1|ESP32-S3-WROOM-1|ESP32-C6-WROOM-1|
167+
|---|---|---|---|
168+
|__D+__|GPIO 19|GPIO 19|GPIO 13|
169+
|__D-__|GPIO 18|GPIO 20|GPIO 12|
170+
171+
For other modules, consult the _Pin Description_ section of the datasheet and look for `USB_D+` and `USB_D-`.
172+
173+
Now that the hardware is ready, we can move back to the IDE. We will use the JTAG over USB pin option.
174+
175+
## OpenOCD connection
176+
177+
OpenOCD uses a server-client model to debug embedded systems. The OpenOCD server connects to the target hardware through a debug adapter (usually via JTAG). It exposes a _network interface_ that clients, such as `gdb` or `telnet`, can use to send commands or load code.
178+
179+
<!-- Now, we create a project and set the connection between `gdb` and `openOCD`. The steps below apply to every Espressif module and SoCs, but the specific detail is given for the ESP32-C3-Mini-1-N4 connected via USB pins. -->
180+
181+
Next, we'll start the openOCD server and test the connection with the hardware. The steps below are for an ESP32-C3 board, but you can easily adjust them for your module. We will use the JTAG over USB pins option. If you're using the ESP-PROG, modify steps 2 and 3 accordingly.
182+
183+
1. Create a project from the `hello_world` example.
184+
_If you're unsure, please check [the documentation](https://docs.espressif.com/projects/vscode-esp-idf-extension/en/latest/startproject.html#esp-idf-show-examples-projects)_
185+
2. &gt; `ESP-IDF: Select Port to Use (COM, tty, usbserial)` - Choose the port you're connected to. You may find the SoC name and package next to the correct option (e.g. ESP32-C3 (QFN32) (revision v0.3))
186+
3. &gt;`ESP-IDF: Set Espressif Device target` &rarr; `esp32c3` &rarr;`ESP32-C3 chip (via Built-in USB-JTAG)`
187+
("`esp32c3`" should now appear at the bottom left corner)
188+
4. &gt;`ESP-IDF: Select OpenOCD Board Configuration`&rarr;`ESP32-C3 chip (via Built-in USB-JTAG)`
189+
5. &gt;`ESP-IDF: OpenOCD Manager` &rarr; `Start OpenOCD`
190+
191+
{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}}
192+
The `Scan for kits` notification may appear. You can allow it to automatically set up the port and board, but be sure to check the result!
193+
{{< /alert >}}
194+
195+
After completing the steps, you should see:
196+
```bash
197+
Open On-Chip Debugger v0.12.0-esp32-20241016 (2024-10-16-14:27)
198+
Licensed under GNU GPL v2
199+
For bug reports, read
200+
http://openocd.org/doc/doxygen/bugs.html
201+
debug_level: 2
202+
203+
Info : only one transport option; autoselecting 'jtag'
204+
205+
Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001
206+
Info : esp_usb_jtag: capabilities descriptor set to 0x2000
207+
208+
Info : Listening on port 6666 for tcl connections
209+
Info : Listening on port 4444 for telnet connections
210+
211+
Info : esp_usb_jtag: serial (84:F7:03:42:8C:A8)
212+
213+
Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255
214+
215+
[...]
216+
217+
Info : [esp32c3] Examination succeed
218+
Info : [esp32c3] starting gdb server on 3333
219+
Info : Listening on port 3333 for gdb connections
220+
```
221+
222+
Congratulations, `openOCD` server is now waiting for a connection. In the second part, we'll start `gdb` and connect to it.
223+
224+
### Troubleshooting
225+
226+
Some issues may have logs that are hard for beginners to understand. Below are two common problems and how to fix them.
227+
228+
#### Address already in use
229+
230+
You could gets
231+
```bash
232+
❌ Error: couldn't bind tcl to socket on port 6666: Address already in use
233+
```
234+
it means that `openOCD` is already running. To close it, you have to:
235+
236+
* Open an ESP-IDF terminal: `≫ESP-IDF: Open ESP-IDF Terminal`
237+
* Find the process number: `ps aux | grep openocd` (e.g. 13819)
238+
* Kill the process: `kill <process-nr>` (e.g. `kill 13819`)
239+
240+
#### Could not find or open device
241+
242+
You could get
243+
`Error: esp_usb_jtag: could not find or open device (ESP32-S3-DevKitC-1) (OCD-631) #219`
244+
245+
it may mean that the firmware inside the board does not expect the connection.
246+
247+
You may need to
248+
* Build the project
249+
&gt; `ESP-IDF: Build your project`.
250+
* Flash the firmware
251+
&gt; `ESP-IDF: Flash (UART) your project`.
252+
253+
If you followed the steps above, the flashing is performed via the JTAG peripheral through the USB pins.
254+
255+
If it's still not working, connect your board via UART0 pins (which in an development board can be accessed using the development board USB port)
256+
* Choose the right port
257+
`ESP-IDF: Select Port to Use (COM, tty, usbserial)`
258+
* Flash it again
259+
&gt; `ESP-IDF: Flash (UART) your project`.
260+
261+
## Conclusion
262+
263+
In this tutorial, you learned how to connect your Espressif module via JTAG and start the openOCD server. In part two, we'll launch `gdb` and explore the code using various commands.
264+

data/authors/francesco-bez.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "Francesco Bez",
3+
"image" : "img/authors/francesco-bez.webp",
4+
"bio": "Developer Relations at Espressif",
5+
"social": [
6+
{ "github": "https://github.com/FBEZ" },
7+
{"linkedin":"https://www.linkedin.com/in/fbez/"}
8+
]
9+
}

0 commit comments

Comments
 (0)