Skip to content

Commit 3ab8614

Browse files
Fix USB JTAG Serial HardReset sequence in Windows (#594)
* feat: Reuse reset_after_flash * refactor: Avoid implementing ResetStrategy for hard_reset * refactor: Move reset_after_flash method to reset mod * docs: Update changelog
1 parent 7f41ad8 commit 3ab8614

File tree

5 files changed

+46
-48
lines changed

5 files changed

+46
-48
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
### Fixed
13+
- Change the `hard_reset` sequence to fix Windows issues (#594)
1314

1415
### Changed
15-
1616
- `FlashData::new` now returns `crate::Error` (#591)
17+
- Moved `reset_after_flash` method to `reset` module (#594)
1718

1819
### Removed
1920

espflash/src/cli/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -568,12 +568,13 @@ pub fn erase_flash(args: EraseFlashArgs, config: &Config) -> Result<()> {
568568
return Err(Error::StubRequired.into());
569569
}
570570

571-
let mut flash = connect(&args.connect_args, config, true, true)?;
572-
571+
let mut flasher = connect(&args.connect_args, config, true, true)?;
573572
info!("Erasing Flash...");
574573

575-
flash.erase_flash()?;
576-
flash.connection().reset_after(!args.connect_args.no_stub)?;
574+
flasher.erase_flash()?;
575+
flasher
576+
.connection()
577+
.reset_after(!args.connect_args.no_stub)?;
577578

578579
Ok(())
579580
}

espflash/src/cli/monitor/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use strum::{Display, EnumIter, EnumString, VariantNames};
2727

2828
use crate::{
2929
cli::monitor::parser::{InputParser, ResolvingPrinter},
30-
connection::{reset_after_flash, Port},
30+
connection::{reset::reset_after_flash, Port},
3131
};
3232

3333
pub mod parser;

espflash/src/connection/mod.rs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use self::reset::UnixTightReset;
2121
use self::{
2222
encoder::SlipEncoder,
2323
reset::{
24-
construct_reset_strategy_sequence, ClassicReset, HardReset, ResetAfterOperation,
25-
ResetBeforeOperation, ResetStrategy, UsbJtagSerialReset,
24+
construct_reset_strategy_sequence, hard_reset, reset_after_flash, ClassicReset,
25+
ResetAfterOperation, ResetBeforeOperation, ResetStrategy, UsbJtagSerialReset,
2626
},
2727
};
2828
use crate::{
@@ -256,8 +256,10 @@ impl Connection {
256256

257257
// Reset the device taking into account the reset after argument
258258
pub fn reset_after(&mut self, is_stub: bool) -> Result<(), Error> {
259+
let pid = self.get_usb_pid()?;
260+
259261
match self.after_operation {
260-
ResetAfterOperation::HardReset => HardReset.reset(&mut self.serial),
262+
ResetAfterOperation::HardReset => hard_reset(&mut self.serial, pid),
261263
ResetAfterOperation::NoReset => {
262264
info!("Staying in bootloader");
263265
soft_reset(self, true, is_stub)?;
@@ -486,33 +488,6 @@ impl Connection {
486488
}
487489
}
488490

489-
/// Reset the target device when flashing has completed
490-
pub fn reset_after_flash(serial: &mut Port, pid: u16) -> Result<(), serialport::Error> {
491-
sleep(Duration::from_millis(100));
492-
493-
if pid == USB_SERIAL_JTAG_PID {
494-
serial.write_data_terminal_ready(false)?;
495-
496-
sleep(Duration::from_millis(100));
497-
498-
serial.write_request_to_send(true)?;
499-
serial.write_data_terminal_ready(false)?;
500-
serial.write_request_to_send(true)?;
501-
502-
sleep(Duration::from_millis(100));
503-
504-
serial.write_request_to_send(false)?;
505-
} else {
506-
serial.write_request_to_send(true)?;
507-
508-
sleep(Duration::from_millis(100));
509-
510-
serial.write_request_to_send(false)?;
511-
}
512-
513-
Ok(())
514-
}
515-
516491
mod encoder {
517492
use std::io::Write;
518493

espflash/src/connection/reset.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! This entire module is copied from `esptool.py` (https://github.com/espressif/esptool/blob/a8586d02b1305ebc687d31783437a7f4d4dbb70f/esptool/reset.py)
1+
//! Most of this module is copied from `esptool.py` (https://github.com/espressif/esptool/blob/a8586d02b1305ebc687d31783437a7f4d4dbb70f/esptool/reset.py)
22
33
#[cfg(unix)]
44
use std::{io, os::fd::AsRawFd};
@@ -198,22 +198,43 @@ impl ResetStrategy for UsbJtagSerialReset {
198198
}
199199
}
200200

201-
/// Reset sequence for hard resetting the chip.
202-
///
203-
/// Can be used to reset out of the bootloader or to restart a running app.
204-
#[derive(Debug, Clone, Copy)]
205-
pub struct HardReset;
201+
/// Reset the target device
202+
pub fn reset_after_flash(serial: &mut Port, pid: u16) -> Result<(), serialport::Error> {
203+
sleep(Duration::from_millis(100));
206204

207-
impl ResetStrategy for HardReset {
208-
fn reset(&self, serial_port: &mut Port) -> Result<(), Error> {
209-
debug!("Using HardReset reset strategy");
205+
if pid == USB_SERIAL_JTAG_PID {
206+
serial.write_data_terminal_ready(false)?;
210207

211-
self.set_rts(serial_port, true)?;
212208
sleep(Duration::from_millis(100));
213-
self.set_rts(serial_port, false)?;
214209

215-
Ok(())
210+
serial.write_request_to_send(true)?;
211+
serial.write_data_terminal_ready(false)?;
212+
serial.write_request_to_send(true)?;
213+
214+
sleep(Duration::from_millis(100));
215+
216+
serial.write_request_to_send(false)?;
217+
} else {
218+
serial.write_request_to_send(true)?;
219+
220+
sleep(Duration::from_millis(100));
221+
222+
serial.write_request_to_send(false)?;
216223
}
224+
225+
Ok(())
226+
}
227+
228+
/// Reset sequence for hard resetting the chip.
229+
pub fn hard_reset(serial_port: &mut Port, pid: u16) -> Result<(), Error> {
230+
debug!("Using HardReset reset strategy");
231+
232+
// Using esptool HardReset strategy (https://github.com/espressif/esptool/blob/3301d0ff4638d4db1760a22540dbd9d07c55ec37/esptool/reset.py#L132-L153)
233+
// leads to https://github.com/esp-rs/espflash/issues/592 in Windows, using `reset_after_flash` instead works fine for all platforms.
234+
// We had similar issues in the past: https://github.com/esp-rs/espflash/pull/157
235+
reset_after_flash(serial_port, pid)?;
236+
237+
Ok(())
217238
}
218239

219240
/// Perform a soft reset of the device.

0 commit comments

Comments
 (0)