---
title: Debugging on STM32 and ESP32 with VS Code and PlatformIO
description: Get started debugging on STM32 and ESP32 microcontrollers with these simple instructions.
source_url: https://dev.blues.io/blog/debugging-stm32-esp32-vscode-platformio/
canonical_url: https://dev.blues.io/blog/debugging-stm32-esp32-vscode-platformio/
markdown_url: https://dev.blues.io/blog/debugging-stm32-esp32-vscode-platformio.md
---

# Debugging on STM32 and ESP32 with VS Code and PlatformIO

![Debugging on STM32 and ESP32 with VS Code and PlatformIO banner](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/banner.jpg?v=fca25d7d)

March 19, 2024

## Get started debugging on STM32 and ESP32 microcontrollers with these simple instructions.

- [Debug](https://dev.blues.io/blog/tag/debug)
- [ESP32](https://dev.blues.io/blog/tag/esp32)
- [STM32](https://dev.blues.io/blog/tag/stm32)

[![Rob Lauer](https://dev.blues.io/images/blog/authors/rob-lauer.jpg?v=57fb21a7)](https://dev.blues.io/blog/author/rob-lauer/)

[Rob LauerSenior Director of Developer Relations](https://dev.blues.io/blog/author/rob-lauer/)

I don't know about you, but the code I write is always perfect. It's bug-free. I understand exactly what's happening in every 3rd party library I use and there is never a situation where I need to see what's going on under the covers.

It Just Works™.

Back in reality, it's a minor miracle if I write more than a couple lines of code without some flaw. Maybe it's a simple syntax mistake or maybe the logic I'm coding fundamentally alters the functional intent of my product. Either way, **I need a decent debugger to make me even remotely efficient**.

As someone who grew up in the web/mobile/cloud world, I'm used to using robust debuggers in tools like Visual Studio alongside Postman and the inspectors available in virtually every web browser today. Unfortunately the embedded space still lags behind when it comes to ease of both iterative development and on-device debugging of code in realtime.

This article aims to provide a little bit of guidance for those of you who, like me, certainly *try* to write bug-free code, but need a little help. Specifically, we are going to look at getting started debugging code on both the **STM32 and ESP32 architectures** using [Visual Studio Code](https://code.visualstudio.com/) and [PlatformIO](https://platformio.org/).

Let's dig in and squash some bugs on the [STM32](#debugging-on-stm32) and [ESP32](#debugging-on-esp32).

## Debugging on STM32

Step 0: You'll need an in-circuit debugger and programmer for the STM32.

Using a debugger/programmer is not just a means to properly debug and inspect code while it's running on a device, it also helps you deploy updated firmware without contorting your fingers to press tiny buttons, forcing the board into its bootloader.

The [STLINK](https://www.st.com/en/development-tools/stlink-v3minie.html) line from STMicroelectronics and [J-Link](https://www.segger.com/products/debug-probes/j-link/) from Segger are two popular types of debuggers that work with STM32-based boards.

In this section I'm going to document how to debug with the **STLINK-V3MINI**, but your experience with other similar programmer/debuggers shouldn't differ.

### Connecting an STLINK

Depending on the host board you are using, you can either connect the STLINK via a 14-pin STDC14 header or manually wire it via GPIO pins.

> **Note:**
>
> If you're using a [Nucleo board](https://www.st.com/en/evaluation-tools/stm32-nucleo-boards.html) or [Discovery kit](https://www.st.com/en/evaluation-tools/stm32-discovery-kits.html), these come with an on-board STLINK debugger, so using an external STLINK is not necessary!

For example, the [Blues Swan](https://shop.blues.com/collections/swan/products/swan?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link) includes a 14-pin male STDC14 header, so the STLINK-V3MINI slots easily onto the board:

![blues swan and stlink](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/swan-stlink.jpg?v=edfedde8)

However, if you have to directly wire the GPIO pins from the STLINK, be sure to follow this wiring guide:

| Pin function | Debugger pin     | Target pin    |
| ------------ | ---------------- | ------------- |
| Ground pin   | GND              | Any GND pin   |
| +3.3V pin    | VCC / VDD / 3.3V | Any +3.3V pin |
| Clock pin    | SWCLK / SWCK     | PA14          |
| Data pin     | SWDIO            | PA13          |

> **Warning:**
>
> Do not connect the +3.3V pin if you are powering your board externally.

> **Note:**
>
> A full set of guides for connecting your STLINK is [available here](https://stm32-base.org/guides/connecting-your-debugger.html).

### Powering STLINK and Host

The STLINK requires a direct serial connection to your PC, often using a Micro USB or USB-C cable. However, since the STLINK cannot power your host STM32 host directly, you'll also need to provide power to the board. This can be accomplished either via an external LiPo battery or by connecting another USB cable from the host to your PC.

![blues swan and stlink full setup](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/swan-stlink-full.jpg?v=093c65ef)

### Debugging with STLINK-V3MINI

Let's look more closely at how to set breakpoints and use the "step out", "step over", and "step into" commands to debug firmware running on an STM32 host.

> New to PlatformIO? Get started with [What is PlatformIO?](https://docs.platformio.org/en/latest/what-is-platformio.html).

1. Update your `platformio.ini` file to add the specific debugging tool you're using.

   ```unknown
   debug_tool = stlink
   ```

2. While you're at it, update that same file to include the proper `upload_protocol`, which dictates how firmware is uploaded to the device:

   ```unknown
   upload_protocol = stlink
   ```

3. And...that's actually all you have to do to enable debugging in PlatformIO!

4. Next, you can set one or more breakpoints on any line of code by clicking in the small column to the left of any line number. This will add a little red dot (the breakpoint) which will halt execution of the program and allow you to manually debug and inspect relevant variables and properties.

   ![add breakpoint to vs code](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/add-breakpoint.png?v=33c2fd0a)

5. With your breakpoint(s) set, it's time to build and deploy to your STM32 device. Navigate to the "Run and Debug" tab in VS Code and press `F5` (or hit the "Start Debugging" button) to build and deploy to your device:

   ![start debugging](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/start-debugging.png?v=4e8c10a8)

6. Code will be executed and advance line-by-line until a breakpoint is hit. At that time, you'll be allowed to inspect variables, memory allocations, and either step over, into, or out of the current state.

   ![step over](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/step-over.png?v=21437df2)

7. One of the more useful features of debugging in VS Code is adding a variable to "watch". This lets you watch the value of any specified variable when a breakpoint is hit, and follow as it changes.

   You can even manually edit the variable value and see how it impacts your device in realtime!

   ![watch variables](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/watch-variables.png?v=1c74c315)

## Debugging on ESP32

Just like when debugging on an STM32, when working with an ESP32-based board your journey begins with a debugger/programmer. The most commonly used debugger is the [ESP-Prog](https://docs.espressif.com/projects/espressif-esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html).

![esp-prog board](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/esp-prog.png?v=444044d5)

You can also use FT2232HL- and FT232H-based debuggers or the aforementioned Segger J-Link. Certain ESP32-based dev boards like the [ESP-WROVER-KIT](https://www.espressif.com/en/products/hardware/esp-wrover-kit/overview) ship with an integrated debugger.

### Connecting an ESP-PROG

Most ESP-Prog boards ship with multiple ribbon cables that let you connect directly to your board, provided the appropriate JTAG port is exposed. Unfortunately in ESP32 land, that's not the norm.

In my case, I'm using Adafruit's HUZZAH32 Feather and therefore have to manually wire my host to the ESP-Prog. No worries though, as the wiring required is relatively minimal:

| JTAG | ESP32  |
| ---- | ------ |
| GND  | GND    |
| TDO  | GPIO15 |
| TDI  | GPIO12 |
| TCK  | GPIO13 |
| TMS  | GPIO14 |

*For reference, here is the pinout for the ESP-Prog:*

![esp-prog pinout](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/esp-prog-pinout.png?v=00fe0946)

### Powering ESP-Prog and Host

When all is said and done, the ESP-Prog is connected via a Micro USB cable, properly wired to my Feather, and the Feather is also connected to my computer via Micro USB (but could also be powered via a LiPo battery).

A bit messy, but it works!

![huzzah32 esp-prog wiring](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/huzzah-wiring.jpg?v=e43165fa)

### Debugging with ESP-Prog

Like we did above with STM32, let's see what changes we need to make to our PlatformIO project to enable debugging on the ESP32.

1. Add the following lines to your `platformio.ini` file to specify the debugging tool you're using. Use of `tbreak setup` is optional, but useful if you need the debugger to halt anywhere in the `setup()` method.

   ```unknown
   debug_tool = esp-prog
   debug_init_break = tbreak setup
   ```

2. And that's the only configuration required in PlatformIO!

3. **Using Windows?** You may also have to install Zadig to add the "WinUSB" driver. See [this Hackster tutorial](https://www.hackster.io/brian-lough/use-the-platformio-debugger-on-the-esp32-using-an-esp-prog-f633b6) for more information. Don't worry, it's not as bad as it sounds!

4. Next, just like with STM32, you can set one or more breakpoints on any line of code by clicking in the column to the left of a line number.

   ![add breakpoint to vs code](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/add-breakpoint.png?v=33c2fd0a)

5. With your breakpoints(s) set, build and deploy to your ESP32 device by navigating to the "Run and Debug" tab in VS Code and pressing `F5` (or use the "Start Debugging" button).

   Again, just like with STM32, your code execution will halt when it reaches a breakpoint, allowing you to watch variables and inspect other properties.

   ![watch variable esp32](https://dev.blues.io/images/blog/posts/debugging-stm32-esp32/esp32-watch-variable.png?v=86e3420c)

> **Warning:**
>
> Since the ESP32 uses GPIO `13` to manage its onboard LED and ESP-Prog *also* uses GPIO `13` for `TCK` (test clock), you won't be able to use the onboard LED while debugging.
>
> Hopefully this will save you the hours it took me to figure that out!

## Wrapping Up

I'm hoping this article helped you take those first steps to properly debug on STM32 and ESP32 boards with PlatformIO and VS Code. While your mileage may vary when using other ST and Espressif configurations, I had luck with the following hardware pairs:

### STM32

- [Blues Swan (STM32L4)](https://shop.blues.com/collections/swan/products/swan?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link)
- [STLINKV3-MINI](https://shop.blues.com/collections/accessories/products/stlink-v3mini?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link)

### ESP32

- [Adafruit HUZZAH32 Feather](https://learn.adafruit.com/adafruit-huzzah32-esp32-feather)
- [ESP-Prog](https://www.sparkfun.com/products/19099)

Happy debugging! 🐛
