Skip to content

espflasher: add USB-JTAG/Serial reset support for ESP32-S3/C3/C6/H2#29

Merged
deadprogram merged 1 commit intomainfrom
fix-jtag-flashing
Apr 13, 2026
Merged

espflasher: add USB-JTAG/Serial reset support for ESP32-S3/C3/C6/H2#29
deadprogram merged 1 commit intomainfrom
fix-jtag-flashing

Conversation

@deadprogram
Copy link
Copy Markdown
Member

Add proper handling for chips connected via the built-in USB-JTAG/Serial peripheral (ttyACM/usbmodem ports), where DTR/RTS ioctls on a disconnected cdc_acm fd block for ~5s each on Linux.

Key changes:

  • Add connectViaUSBJTAG() which runs usbJTAGSerialReset in a goroutine with a 500ms timeout, then closes the stale port and reopens after USB re-enumeration. Used by ResetUSBJTAG and ResetAuto modes.

  • Fix usbJTAGSerialReset to match esptool's full USBJTAGSerialReset sequence: idle → set IO0 → trigger reset through (1,1) → release EN.

  • Fix hardReset to deassert DTR before toggling RTS on USB connections, so GPIO0=HIGH at reset and the chip boots into user code instead of bootloader mode.

  • Fix Reset() to use flashEnd(reboot=false) to keep the stub running and USB alive for the subsequent hardReset, and run hardReset in a goroutine to avoid blocking on the dead fd after the chip resets.

  • Make 64-byte USB CDC write chunking conditional on usesUSB flag to avoid unnecessary syscall overhead on UART bridge connections.

  • Optimize sync() to drain extra ROM responses via direct frame reads instead of sending dummy commands.

  • After failed sync, try reopening the port and syncing again before looping back to issue another reset.

Add proper handling for chips connected via the built-in USB-JTAG/Serial
peripheral (ttyACM/usbmodem ports), where DTR/RTS ioctls on a
disconnected cdc_acm fd block for ~5s each on Linux.

Key changes:

- Add connectViaUSBJTAG() which runs usbJTAGSerialReset in a goroutine
  with a 500ms timeout, then closes the stale port and reopens after
  USB re-enumeration. Used by ResetUSBJTAG and ResetAuto modes.

- Fix usbJTAGSerialReset to match esptool's full USBJTAGSerialReset
  sequence: idle → set IO0 → trigger reset through (1,1) → release EN.

- Fix hardReset to deassert DTR before toggling RTS on USB connections,
  so GPIO0=HIGH at reset and the chip boots into user code instead of
  bootloader mode.

- Fix Reset() to use flashEnd(reboot=false) to keep the stub running
  and USB alive for the subsequent hardReset, and run hardReset in a
  goroutine to avoid blocking on the dead fd after the chip resets.

- Make 64-byte USB CDC write chunking conditional on usesUSB flag to
  avoid unnecessary syscall overhead on UART bridge connections.

- Optimize sync() to drain extra ROM responses via direct frame reads
  instead of sending dummy commands.

- After failed sync, try reopening the port and syncing again before
  looping back to issue another reset.

Signed-off-by: deadprogram <ron@hybridgroup.com>
@deadprogram deadprogram merged commit 16cf133 into main Apr 13, 2026
3 checks passed
@deadprogram deadprogram deleted the fix-jtag-flashing branch April 13, 2026 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant