In “Eclipse JTAG Debugging the ESP32 with a SEGGER J-Link” I used a SEGGER J-Link to debug an ESP32 device with JTAG. I looked at using one of the FTDI FT2232HL development boards which are supported by OpenOCD. The FT2232HL is dual high-speed USB to UART/FIFO device, and similar FTDI devices are used on many boards as UART to USB converters. With OpenOCD these devices can be turned into inexpensive JTAG debug probes. This article shows how to use a $10 FTDI board as JTAG interface to program and debug the Espressif ESP32.
We are using the TTGO ESP32 module (Espressif Pico D4) Wi-Fi module on the lab robot. On that robot the NXP K22FX512 is using the ESP32 as Wi-Fi gateway (see “Programming the ESP32 with an ARM Cortex-M USB CDC Gateway“).
The FT2232HL is available around $10 from different webstores or from AliExpress:
I’m using an Adafruit adapter board (Adafruit #2094) to make the connection between the FTDI and the JTAG pins. I’m using the FTDI signals from the ADBUS:
Below are the signals on the 2×10 pin JTAG header:
On the ESP32 (TTGO Pico-D4 Module) the following pins are used:
- TMS: IO14
- TDI: IO12
- TCKL: IO13
- TDO: IO15
The FT2232 shows up with two USB serial ports in the Windows device manager:
For OpenOCD, use the SysProgs USB Driver Tool on Windows to load the WinUSB Driver for the FT2232HL chip. Notice that it shows up here as ‘USB Serial Converter A’ and ‘USB Serial Converter B’. As I’m using the ADBUS, I’m configuration the A converter:
OpenOCD needs a configuration file. I’m using the one below:
# # OpenOCD configuration file for the FTDI FT2232HL # evaluation board used as JTAG adapter # Please modify this file to your local setup. # # Include the configuration for the JTAG adapter. # If you have a different interface, please edit this to include the # configuration file of yours. #source [find interface/ftdi/mbftdi.cfg] interface ftdi ftdi_vid_pid 0x0403 0x6010 ftdi_channel 0 ftdi_layout_init 0x0038 0x003b # 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 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
Install that FT2232HL.cfg file into the following folder of your OpenOCD installation:
Then OpenOCD can be launched as below:
c:\esp\openocd-esp32\bin\openocd.exe -f interface/ftdi/FT2232HL.cfg -f board/esp-wroom-32.cfg
With this, it shall connect:
To program or flash the application, use something like this:
c:\esp\openocd-esp32\bin\openocd.exe -f interface/ftdi/FT2232HL.cfg -f board/esp-wroom-32.cfg -c "program_esp32 build/hello-world.bin 0x10000 verify exit"
Below is an example output for reference:
Open On-Chip Debugger v0.10.0-esp32-20190708 (2019-07-08-11:04) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html adapter speed: 200 kHz Warn : Transport "jtag" was already selected adapter speed: 1000 kHz Info : Configured 2 cores esp32 interrupt mask on Error: libusb_open() failed with LIBUSB_ERROR_NOT_SUPPORTED Info : clock speed 1000 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 : Detected debug stubs @ 3ffb39c0 on core0 of target 'esp32' Info : Listening on port 3333 for gdb connections 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 : Target halted. PRO_CPU: PC=0x4013843A (active) APP_CPU: PC=0x4013843A Info : esp32: Debug controller 0 was reset (pwrstat=0x5F, after clear 0x0F). Info : esp32: Core 0 was reset (pwrstat=0x5F, after clear 0x0F). Info : esp32: Debug controller 1 was reset (pwrstat=0x5F, after clear 0x5F). Info : esp32: Core 1 was reset (pwrstat=0x5F, after clear 0x5F). Info : Target halted. PRO_CPU: PC=0x5000004B (active) APP_CPU: PC=0x00000000 Info : esp32: Core 0 was reset (pwrstat=0x1F, after clear 0x0F). Info : Target halted. PRO_CPU: PC=0x40000400 (active) APP_CPU: PC=0x40000400 ** Programming Started ** auto erase enabled Info : Target halted. PRO_CPU: PC=0x400916EE (active) APP_CPU: PC=0x40000400 Info : Flash mapping 0: 0x10020 -> 0x3f400020, 84 KB Info : Flash mapping 1: 0x30018 -> 0x400d0018, 422 KB Info : Target halted. PRO_CPU: PC=0x400916EE (active) APP_CPU: PC=0x40000400 Info : Auto-detected flash size 4096 KB Info : Using flash size 4096 KB Info : Target halted. PRO_CPU: PC=0x400916EE (active) APP_CPU: PC=0x40000400 Info : Target halted. PRO_CPU: PC=0x400916EE (active) APP_CPU: PC=0x40000400 wrote 602112 bytes from file build/hello-world.bin in 19.480507s (30.184 KiB/s) ** Programming Finished ** ** Verify Started ** Info : Target halted. PRO_CPU: PC=0x400916EE (active) APP_CPU: PC=0x40000400 read 599632 bytes from file build/hello-world.bin and flash bank 0 at offset 0x00010000 in 13.326755s (43.940 KiB/s) contents match ** Verified OK ** shutdown command invoked Warn : Flash driver of esp32.flash does not support free_driver_priv() Warn : Flash driver of irom does not support free_driver_priv() Warn : Flash driver of drom does not support free_driver_priv()
To use the setup with Eclipse, have a read at my previous article: “Building and Flashing ESP32 with Eclipse“. With this I can program and debug the ESP32 in one step.
FTDI FT2232 Serial Port
The FT2232 board has two USB-2-Serial ports. While using one for JTAG debugging, the second one can be still used as an extra serial port which is a cool extra feature.
For this, connect pin 0 and 1 of the CDBUS plus GND:
With this I have both a debug connection plus a serial connection available.
It is possible to use an inexpensive FTDI evaluation board as JTAG debug interface to debug ESP32 based devices. For a more convenient connection between the FTDI board and the ESP32 JTAG signals I’m considering building an adapter board on top of the FTDI eval board with a mini 10-pin JTAG connector. If there is any interest on this, post a comment and I make that design available.
Happy FTDI’ing 🙂
- ESP32 JTAG debugging: https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/
- Future Technology Devices International FT2232H Datasheet: https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf
- Building your own bootloader gateway to ESP: https://mcuoneclipse.com/2019/09/01/programming-the-esp32-with-an-arm-cortex-m-usb-cdc-gateway/
- Using Eclipse with ESP32: https://mcuoneclipse.com/2019/08/18/building-and-flashing-esp32-applications-with-eclipse/
- Debugging ESP32 with SEGGER J-Link: https://mcuoneclipse.com/2019/09/22/eclipse-jtag-debugging-the-esp32-with-a-segger-j-link/