Error: couldn't open {.pio/build/seeed_xiao/firmware.bin}

I’m trying to get esp-builtin working for debugging and uploading to a Seeed XAIO ESP32-C3. But I’m getting the above error. When I look at that path the firmware.bin file is there. I have v3.3.1 of platformio.

Here is my platformio.ini

[env:seeed_xiao]
platform = espressif32
board = seeed_xiao_esp32c3
framework = arduino
debug_tool = esp-builtin
upload_protocol = esp-builtin
monitor_speed = 115200

The build output:

Linking .pio/build/seeed_xiao/firmware.elf
Retrieving maximum program size .pio/build/seeed_xiao/firmware.elf
Checking size .pio/build/seeed_xiao/firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   2.0% (used 6440 bytes from 327680 bytes)
Flash: [=         ]   8.5% (used 111978 bytes from 1310720 bytes)
Building .pio/build/seeed_xiao/firmware.bin
esptool.py v4.6-dev
Creating esp32c3 image...
Merged 2 ELF sections
Successfully created esp32c3 image.
Configuring upload protocol...
AVAILABLE: cmsis-dap, esp-bridge, esp-builtin, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esp-builtin
Uploading .pio/build/seeed_xiao/firmware.bin
Open On-Chip Debugger v0.12.0-esp32-20230921 (2023-09-21-13:27)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1
adapter speed: 40000 kHz
** program_esp input args <0x10000 verify> **
** Programming Started **
Error: couldn't open {.pio/build/seeed_xiao/firmware.bin}
embedded:startup.tcl:1524: Error: ** Programming Failed **
in procedure 'program_esp' 
in procedure 'program_error' called at file "/Users/cgriffin/.platformio/packages/tool-openocd-esp32/share/openocd/scripts/target/esp_common.cfg", line 434
at file "embedded:startup.tcl", line 1524
*** [upload] Error 1

Is this perhaps a case where the error message is not telling what really happened?

I was able to upload the program with this command line:

openocd -f board/esp32c3-builtin.cfg -c "program_esp .pio/build/seeed_xiao/firmware.bin 0x10000 verify exit"

And here is the output from that command:

Open On-Chip Debugger v0.12.0-esp32-20230419 (2023-04-18-22:02)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselecting 'jtag'
Info : esp_usb_jtag: VID set to 0x303a and PID to 0x1001
Info : esp_usb_jtag: capabilities descriptor set to 0x2000
Warn : Transport "jtag" was already selected
** program_esp input args <0x10000 verify exit> **
Info : esp_usb_jtag: serial (64:E8:33:12:8A:E4)
Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255
Info : clock speed 40000 kHz
Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)
Info : datacount=2 progbufsize=16
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=32, misa=0x40101104
Info : starting gdb server for esp32c3 on 3333
Info : Listening on port 3333 for gdb connections
Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)
Info : Reset cause (3) - (Software core reset)
Info : [esp32c3] Found 8 triggers
Info : Flash mapping 0: 0x10020 -> 0x3c030020, 54 KB
Info : Flash mapping 1: 0x20020 -> 0x42000020, 143 KB
Info : Auto-detected flash bank 'esp32c3.flash' size 4096 KB
Info : Using flash bank 'esp32c3.flash' size 4096 KB
** Programming Started **
Info : PROF: Erased 139264 bytes in 1110.04 ms
Info : PROF: Data transferred in 1984.49 ms @ 68.5316 KB/s
Info : PROF: Wrote 139264 bytes in 2486.48 ms (data transfer time included)
** Programming Finished in 4448 ms **
** Verify Started **
Info : PROF: Flash verified in 307.883 ms 
** Verify OK **
shutdown command invoked

I encountered the same issue and, after thorough investigation, identified an issue with the logic in openocd\scripts\target\espcommon.cfg. The critical execution line in this file is: if {[catch {eval flash writeimage erase $flash_args}] == 0}

Prior to this, the {} around the $flash_args variable needed to be removed; my modified code is:

set flashargs [string map {“{” " “}” “”} $flashargs]
if {[catch {eval flash write-image erase $flash_args}] == 0}

Before executing, I added a line to modify the flash_args string. This allowed the code to run flawlessly. I’d like to express my gratitude to GPT4o for assisting me in understanding the TCL language.

Did you file a bug report with https://github.com/espressif/openocd-esp32? This is their code.

I believe it’s unlikely a bug in OpenOCD. I haven’t explored how Pio executes the debugging function. The problem likely lies in the data pio passed to espcommon.cfg (line: 340) during the debugging execution. Ideally, I shouldn’t alter espcommon.cfg, but should trace the source of the parameters passed by pio and address the issue at its root.

Okay, then better file a bug with https://github.com/platformio/platform-espressif32/ if you think the OpenOCD invocation command is wrong. (if not already filed).