Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkg/espflasher/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,13 @@ func hardReset(port serial.Port, usesUSB bool) error {
}
set(port.SetRTS(true)) // EN=LOW (chip in reset)
if usesUSB {
// The chip resets on this edge. An app that moves the USB PHY to
// USB-OTG removes the port before the release, so ignore that error.
reset := firstErr == nil
time.Sleep(200 * time.Millisecond)
set(port.SetRTS(false))
if err := port.SetRTS(false); !reset {
set(err)
}
time.Sleep(200 * time.Millisecond)
} else {
time.Sleep(100 * time.Millisecond)
Expand Down
32 changes: 32 additions & 0 deletions pkg/espflasher/reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,38 @@ func TestHardResetReportsError(t *testing.T) {
}
}

// goneAfterResetPort fails every write after the first SetRTS(true), like a
// USB-JTAG port that disappears when the new app moves the PHY to USB-OTG.
type goneAfterResetPort struct {
recordingPort
gone bool
}

func (g *goneAfterResetPort) SetDTR(dtr bool) error {
g.recordingPort.SetDTR(dtr) //nolint:errcheck
if g.gone {
return errors.New("broken pipe")
}
return nil
}

func (g *goneAfterResetPort) SetRTS(rts bool) error {
g.recordingPort.SetRTS(rts) //nolint:errcheck
if g.gone {
return errors.New("broken pipe")
}
g.gone = rts
return nil
}

// TestHardResetUSBPortGoneAfterReset verifies the USB path reports success
// when only the release write fails, since the reset already happened.
func TestHardResetUSBPortGoneAfterReset(t *testing.T) {
assert.NoError(t, hardReset(&goneAfterResetPort{}, true))
assert.Error(t, hardReset(&goneAfterResetPort{}, false),
"UART bridges keep the port, so a failed release still matters")
}

// TestFlasherResetReportsFailedReset verifies Reset() doesn't claim
// "Device reset." when the DTR/RTS writes never reached the device.
func TestFlasherResetReportsFailedReset(t *testing.T) {
Expand Down
Loading