Skip to content

Instantly share code, notes, and snippets.

@motla
Last active January 16, 2023 14:36
Show Gist options
  • Select an option

  • Save motla/ab7fdcf14303208996c40ca7fefe6f11 to your computer and use it in GitHub Desktop.

Select an option

Save motla/ab7fdcf14303208996c40ca7fefe6f11 to your computer and use it in GitHub Desktop.
ESP-IDF 4 in VSCode : How to setup tasks and debug

Setup ESP-IDF v4 in VSCode

I post here my best attempt to run ESP-IDF v4 (idf.py, CMake, Ninja...) in VSCode.

From scratch:

  1. Follow the new ESP-IDF Get Started Guide (latest)
  2. Download and install VSCode
  3. Install 3 VSCode extensions: C/C++, Native Debug, Task Explorer

Inside your VSCode project folder, add these files:

.vscode/tasks.json (click to expand)

// ======================== tasks.json ========================
{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [{
      "label": "Configure",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py menuconfig",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py menuconfig" }
    },
    {
      "label": "Build",
      "group": "build",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py build",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py build" },
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}/build"],
        "pattern": {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      }
    },
    {
      "label": "Get size",
      "group": "build",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py size",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py size" },
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}/build"],
        "pattern": {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      }
    },
    {
      "label": "Clean",
      "group": "build",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py clean",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py clean" }
    },
    {
      "label": "Clean (full)",
      "group": "build",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py fullclean",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py fullclean" }
    },
    {
      "label": "Flash",
      "group": "test",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py flash",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py flash" },
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}/build"],
        "pattern": {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      }
    },
    {
      "label": "Erase flash",
      "group": "build",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py erase_flash",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py erase_flash" }
    },
    {
      "label": "Monitor",
      "group": "test",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && idf.py monitor",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && idf.py monitor" },
      "isBackground": true,
      //"dependsOn": ["Flash"]
    },
    {
      "label": "OpenOCD",
      "type": "shell",
      "command": ". $HOME/esp/esp-idf/export.sh && openocd -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp32-wrover.cfg",
      "windows": { "command": "%userprofile%\\esp\\esp-idf\\export.bat && openocd -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp32-wrover.cfg" },
      "isBackground": true,
      "problemMatcher": {
        "pattern": {
          "regexp": "^(Info |Warn ):(.*)$", // Ignore errors
          "severity": 1,
          "message": 2
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": ".",
          "endsPattern": "Info : Listening on port \\d+ for gdb connections"
        }
      }
    }
  ]
}

.vscode/launch.json (click to expand)

// ======================== launch.json ========================
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "gdb",
      "request": "launch",
      "name": "Debug ESP32",
      "target": "build/${workspaceFolderBasename}.elf",
      "cwd": "${workspaceFolder}",
      "gdbpath": "${env:HOME}/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb", // Path of the toolchain
      "autorun": [
        "target remote :3333", // Connect to OpenOCD
        "mon reset halt", // Reset the chip and keep the CPUs halted
        "set remote hardware-watchpoint-limit 2", // Restrict GDB to using two hardware watchpoints supported by ESP32
        "flushregs", // Force GDB to get new state from the target
        "thb app_main", // Insert a temporary hardware breakpoint at the main function
        "c" // Resume the program. It will then stop at breakpoint inserted at app_main
      ],
      "preLaunchTask": "OpenOCD"
    }
  ]
}

.vscode/c_cpp_properties.json (click to expand)

{
    "configurations": [
        {
            "name": "Generic",
            "includePath": [
                "${workspaceFolder}/main/**",
                "${env.HOME}/esp/esp-idf/components/**"
            ],
            "browse": {
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            },
            "intelliSenseMode": "gcc-x64",
            "compileCommands": "${workspaceFolder}/build/compile_commands.json"
        }
    ],
    "version": 4
}

.vscode/settings.json (click to expand)

// ======================== settings.json ========================
{
  "taskExplorer.enableMake": false,
  "search.exclude": {
    "**/build": true
  }
}

You should now see the different tasks in the Explorer:

image

And you should be able to start a debug session:

image

Some quirks:

  • You should adapt the OpenOCD script in tasks.json to your match your ESP32 module (if not ESP-WROVER), and set the gdbpath in launch.json manually.
  • The correct firmware must be flashed before starting a debug session (OpenOCD is not configured to flash the ESP32).
  • OpenOCD is started automatically before a debug session, but is not terminated after the debug session. You must terminate it manually in the Task Explorer in order to flash a new firmware (just like the ESP Monitor)...
  • I tested on macOS only, but it should work on Linux and Windows as well. Please give some feedback.
  • You can use ESP Monitor while debugging only if it was launched before the debug session. So the correct order is Flash CPU, Start Monitor, Start Debug.
  • If you're using FT2232HL based board for JTAG debug (ESP-PROG, ESP-WROVER-KIT, ...), specially on macOS, you may have to unplug and replug your device after a debug session in order to access the UART functions again (this guide didn't work for me). Still looking for a workaround...
@emildeev
Copy link

emildeev commented Jun 1, 2021

Hi, I setting json files like on your tutorial, but I get error:

CMake Error at /Users/emilislamov/esp32/esp-idf/tools/cmake/project.cmake:269 (__project):The CMAKE_ASM_COMPILER:

xtensa-esp32-elf-gcc

is not a full path and was not found in the PATH.

Tell CMake where to find the compiler by setting either the environment
variable "ASM" or the CMake cache entry CMAKE_ASM_COMPILER to the full path
to the compiler, or to the compiler name if it is in the PATH.

Can you help me with this problem?

@motla
Copy link
Author

motla commented Jun 1, 2021

@emilmircod I'm on macOS so I can't test it sorry. This guide is outdated now that Espressif made an official plugin for VSCode. Better check out their official guide instead: https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/tutorial/install.md

@emildeev
Copy link

emildeev commented Jun 1, 2021

I use macOS, and official plugin for VSCode

@motla
Copy link
Author

motla commented Jun 1, 2021

@emilmircod what did you set as "gdbpath" in the launch.json file? can you reach this folder and make sure the toolchain is installed there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment