Debugging ESP32-S3 over JTAG

There are different ways of debugging embedded software. Less powerful but easier one is printing statements when your code reaches certain line, for example:

ESP_LOGI(TAG, "Create RMT TX channel");

Using JTAG provides more insight because it allows you to set breakepoints, stop code execution and look at all variables and registers. Setting up JTAG on ESP32 wasn’t straightforward to me so I’d like to collect some hints here. I used ESP-PROG and ESP32-S3-WROOM-1 based module.

ESP32-S3 is not ESP32

I followed great tutorial https://youtu.be/uq93H7T7cOQ?si=oWbgDsFn5zGZvezt which is focused on ESP32. There are two important differences when using ESP32-S3:

  • By default, ESP32-S3 JTAG interface is connected to the built-in USB_SERIAL_JTAG and you can’t use JTAG pins (TDI, TCK, TDO, TMS)
  • JTAG pinout differs between ESP32 and ESP32-S3

Burning efuse DIS_USB_JTAG to enable JTAG pins

To debug over JTAG pins I burnt the DIS_USB_JTAG efuse:

espefuse.py --port COM10 burn_efuse DIS_USB_JTAG

to confirm I read all the efuses with:

espefuse.py summary --port COM10

in the ESP-IDF Terminal. The result should now contain following line:

DIS_USB_JTAG (BLOCK0)                              Set this bit to disable function of usb switch to  = True R/W (0b1)

which means, that the ESP32-S3 can be debugged over JTAG pins. This means also, that debugging over built-in USB JTAG is not possible anymore. Burning efuses can’t be reversed so be warned.

ESP32 vs ESP32-S3 JTAG pinout

Here comes minimal pinout for JTAG debugging with ESP32 and ESP32-S3

ESP-PROGESP32ESP32-S3
TDIIO12IO41
TCKIO13IO39
TDOIO15IO40
TMSIO14IO42
GNDGNDGND
3V33V33V3

Here is my connection diagram:

tasks.json

task labeled “preRun” should start openocd. In my case this file contains:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "preRun",
            "type": "shell",
            "windows":{
                "command": "start C:/Users/Arek/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/bin/openocd.exe -c \"set ESP_RTOS none\" -f board/esp32s3-ftdi.cfg & exit",
            }
        }
    ]
}

I had to provide full path to openocd. I observed that openocd is recognized in ESP-IDF Terminal but not in windows command line. In the ESP-IDF Terminal I used where command to get the full path which openocd is used by my VS Code ESP-IDF plug-in configuration:

C:\Users\Arek\p9_led_strip_simple>where openocd
C:\Users\Arek.espressif\tools\openocd-esp32\v0.12.0-esp32-20241016\openocd-esp32\bin\openocd.exe

You have to provide correct configuration file for the openocd. If you see something like:

C:\Users\Arek\p9_led_strip_simple>openocd -f board/esp32-wrover-kit-3.3v.cfg
Open On-Chip Debugger v0.12.0-esp32-20241016 (2024-10-16-14:17)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi tdo_sample_edge falling"
Info : clock speed 20000 kHz
Info : JTAG tap: esp32.tap0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32.tap1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : [esp32.cpu0] Examination succeed
Info : [esp32.cpu1] Examination succeed
Info : [esp32.cpu0] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
Info : [esp32.cpu0] Debug controller was reset.
Info : [esp32.cpu0] Core was reset.
Info : [esp32.cpu1] Debug controller was reset.
Info : [esp32.cpu1] Core was reset.
Error: [esp32.cpu0] DSR (8020CC13) indicates DIR instruction generated an exception!
Error: Exception reading expstate!
Info : [esp32.cpu0] Target halted, PC=0x00000000, debug_reason=00000000
Error: [esp32.cpu1] DSR (8020CC13) indicates DIR instruction generated an exception!
Error: Exception reading expstate!

It might mean, you have selected incorrect configuration file -f board/esp32-wrover-kit-3.3v.cfg Misled by the error description I tried:

openocd -f board/esp32-wrover-kit-3.3v.cfg -c "ftdi tdo_sample_edge falling" -c "adapter_speed 1000"

but it wasn’t matter of sampling point and clock speed.

settings.json

Visual studio can run tasks either in Windows PowerShell or in the command line. I had to modify settings.json to use command line cmd.exe instead of the WIndows PowerShell:

{
    "C_Cpp.intelliSenseEngine": "default",
    "idf.espIdfPathWin": "C:\\Users\\Arek\\esp\\v5.3.2\\esp-idf",
    "idf.openOcdConfigs": [
        "interface/ftdi/esp32_devkitj_v1.cfg",
        "target/esp32s3.cfg"
    ],
    "idf.toolsPathWin": "C:\\Users\\Arek\\.espressif",
    "idf.flashType": "UART",
    "idf.portWin": "COM10",
    "terminal.integrated.defaultProfile.windows": "Command Prompt",
    "terminal.integrated.profiles.windows": {
        "PowerShell": {
            "source": "PowerShell",
            "icon": "terminal-powershell"
        },
        "Command Prompt": {
            "path": [
                "${env:windir}\\Sysnative\\cmd.exe",
                "${env:windir}\\System32\\cmd.exe"
            ],
            "args": [],
            "icon": "terminal-cmd"
        },
        "Git Bash": {
            "source": "Git Bash"
        }
    }   
}

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "preLaunchTask": "preRun",
      "type": "cppdbg",
      "name": "ESP32_OpenOCD",
      "request": "launch",
      "cwd": "${workspaceFolder}/build",
      "program": "${workspaceFolder}/build/p9_led_strip_simple.elf",
      "miDebuggerPath": "C:/Users/Arek/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin/xtensa-esp32s3-elf-gdb.exe",
      "setupCommands": [
        { "text": "target remote 127.0.0.1:3333"},
        { "text": "set remote hardware-watchpoint-limit 2"},
        { "text": "monitor reset halt"},
        { "text": "flushregs"},
        { "text": "mon program_esp build/bootloader/bootloader.bin 0x0 verify"},
        { "text": "mon program_esp build/partition_table/partition-table.bin 0x8000 verify"},
        { "text": "mon program_esp build/p9_led_strip_simple.bin 0x10000 verify"}
      ]
    }
  ]
}

launch.json starts the gdb debugger and flashes bootloader, partition table and the code into the ESP32-S3

What is ESP-IDF Terminal?

Clicking this button in the Visual Studio code:

open “ESP-IDF terminal” This is a normal windows command line but it runs the export.bat file first:

this allows you to enter just esptool.py in the terminal instead of providing complete path.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top