From 3ee4b008fd5c8dd77f6f27ecf5899ee9ff3595b1 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 5 Oct 2023 15:29:17 +0200 Subject: [PATCH 1/5] feat: Implement reset strategies --- Cargo.lock | 1 + cargo-espflash/Cargo.toml | 20 +- espflash/Cargo.toml | 27 +- .../src/{connection.rs => connection/mod.rs} | 98 +++----- espflash/src/connection/reset.rs | 237 ++++++++++++++++++ espflash/src/interface.rs | 26 +- 6 files changed, 315 insertions(+), 94 deletions(-) rename espflash/src/{connection.rs => connection/mod.rs} (81%) create mode 100644 espflash/src/connection/reset.rs diff --git a/Cargo.lock b/Cargo.lock index 2aa10ea8..f763cb51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1118,6 +1118,7 @@ dependencies = [ "lazy_static", "log", "miette", + "nix 0.27.1", "parse_int", "regex", "rppal", diff --git a/cargo-espflash/Cargo.toml b/cargo-espflash/Cargo.toml index 506ece05..42f9ec62 100644 --- a/cargo-espflash/Cargo.toml +++ b/cargo-espflash/Cargo.toml @@ -3,21 +3,11 @@ name = "cargo-espflash" version = "3.0.0-dev" edition = "2021" rust-version = "1.70" -description = "Cargo subcommand for flashing Espressif devices" -repository = "https://github.com/esp-rs/espflash" -license = "MIT OR Apache-2.0" -keywords = [ - "cargo", - "cli", - "embedded", - "esp", -] -categories = [ - "command-line-utilities", - "development-tools", - "development-tools::cargo-plugins", - "embedded", -] +description = "Cargo subcommand for flashing Espressif devices" +repository = "https://github.com/esp-rs/espflash" +license = "MIT OR Apache-2.0" +keywords = ["cargo", "cli", "embedded", "esp"] +categories = ["command-line-utilities", "development-tools", "development-tools::cargo-plugins", "embedded"] [package.metadata.binstall] pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ target }.{ archive-format }" diff --git a/espflash/Cargo.toml b/espflash/Cargo.toml index cf7e4a82..e67b1a5d 100644 --- a/espflash/Cargo.toml +++ b/espflash/Cargo.toml @@ -3,19 +3,11 @@ name = "espflash" version = "3.0.0-dev" edition = "2021" rust-version = "1.70" -description = "A command-line tool for flashing Espressif devices" -repository = "https://github.com/esp-rs/espflash" -license = "MIT OR Apache-2.0" -keywords = [ - "cli", - "embedded", - "esp", -] -categories = [ - "command-line-utilities", - "development-tools", - "embedded", -] +description = "A command-line tool for flashing Espressif devices" +repository = "https://github.com/esp-rs/espflash" +license = "MIT OR Apache-2.0" +keywords = ["cli", "embedded", "esp"] +categories = ["command-line-utilities", "development-tools", "embedded"] [package.metadata.binstall] pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ target }.{ archive-format }" @@ -26,8 +18,8 @@ pkg-fmt = "zip" rustdoc-args = ["--cfg", "docsrs"] [[bin]] -name = "espflash" -path = "./src/bin/espflash.rs" +name = "espflash" +path = "./src/bin/espflash.rs" required-features = ["cli"] [dependencies] @@ -63,7 +55,10 @@ strum = { version = "0.25.0", features = ["derive"] } thiserror = "1.0.49" toml = "0.8.2" update-informer = { version = "1.1.0", optional = true } -xmas-elf = "0.9.0" +xmas-elf = "0.9.0" + +[target.'cfg(unix)'.dependencies] +nix = { version = "0.27.1", default-features = false, features = ["ioctl"] } [features] default = ["cli"] diff --git a/espflash/src/connection.rs b/espflash/src/connection/mod.rs similarity index 81% rename from espflash/src/connection.rs rename to espflash/src/connection/mod.rs index 1835dcdf..a06b58ef 100644 --- a/espflash/src/connection.rs +++ b/espflash/src/connection/mod.rs @@ -4,21 +4,29 @@ //! sending/decoding of commands, and provides higher-level operations with the //! device. -use std::{io::BufWriter, thread::sleep, time::Duration}; +use std::{io::BufWriter, iter::zip, thread::sleep, time::Duration}; use binrw::{io::Cursor, BinRead, BinReaderExt}; use log::{debug, info}; use serialport::UsbPortInfo; use slip_codec::SlipDecoder; -use self::encoder::SlipEncoder; +#[cfg(unix)] +use self::reset::UnixTightReset; +use self::{ + encoder::SlipEncoder, + reset::{construct_reset_strategy_sequence, ClassicReset, ResetStrategy, UsbJtagSerialReset}, +}; use crate::{ command::{Command, CommandType}, error::{ConnectionError, Error, ResultExt, RomError, RomErrorKind}, interface::Interface, }; -const DEFAULT_CONNECT_ATTEMPTS: usize = 7; +mod reset; + +const MAX_CONNECT_ATTEMPTS: usize = 7; +const MAX_SYNC_ATTEMPTS: usize = 5; pub(crate) const USB_SERIAL_JTAG_PID: u16 = 0x1001; /// A response from a target device following a command @@ -50,16 +58,11 @@ impl Connection { /// Initialize a connection with a device pub fn begin(&mut self) -> Result<(), Error> { - let mut extra_delay = false; - for _ in 0..DEFAULT_CONNECT_ATTEMPTS { - if self.connect_attempt(extra_delay).is_err() { - extra_delay = !extra_delay; - - info!( - "Unable to connect, retrying with {} delay...", - if extra_delay { "extra" } else { "default" } - ); - } else { + let port_name = self.serial.serial_port().name().unwrap_or_default(); + let reset_sequence = construct_reset_strategy_sequence(&port_name, self.port_info.pid); + + for (_, reset_strategy) in zip(0..MAX_CONNECT_ATTEMPTS, reset_sequence.iter().cycle()) { + if self.connect_attempt(reset_strategy).is_ok() { return Ok(()); } } @@ -68,11 +71,12 @@ impl Connection { } /// Try to connect to a device - fn connect_attempt(&mut self, extra_delay: bool) -> Result<(), Error> { - self.reset_to_flash(extra_delay)?; - - for _ in 0..5 { + #[allow(clippy::borrowed_box)] + fn connect_attempt(&mut self, reset_strategy: &Box) -> Result<(), Error> { + reset_strategy.reset(&mut self.serial)?; + for _ in 0..MAX_SYNC_ATTEMPTS { self.flush()?; + if self.sync().is_ok() { return Ok(()); } @@ -86,12 +90,14 @@ impl Connection { self.with_timeout(CommandType::Sync.timeout(), |connection| { connection.command(Command::Sync)?; connection.flush()?; + sleep(Duration::from_millis(10)); - for _ in 0..7 { + + for _ in 0..MAX_CONNECT_ATTEMPTS { match connection.read_response()? { Some(response) if response.return_op == CommandType::Sync as u8 => { if response.status == 1 { - let _error = connection.flush(); + connection.flush().ok(); return Err(Error::RomError(RomError::new( CommandType::Sync, RomErrorKind::from(response.error), @@ -115,47 +121,26 @@ impl Connection { // Reset the device pub fn reset(&mut self) -> Result<(), Error> { - let pid = self.port_info.pid; - Ok(reset_after_flash(&mut self.serial, pid)?) + reset_after_flash(&mut self.serial, self.port_info.pid)?; + + Ok(()) } // Reset the device to flash mode pub fn reset_to_flash(&mut self, extra_delay: bool) -> Result<(), Error> { if self.port_info.pid == USB_SERIAL_JTAG_PID { - self.serial.write_data_terminal_ready(false)?; - self.serial.write_request_to_send(false)?; - - sleep(Duration::from_millis(100)); - - self.serial.write_data_terminal_ready(true)?; - self.serial.write_request_to_send(false)?; - - sleep(Duration::from_millis(100)); - - self.serial.write_request_to_send(true)?; - self.serial.write_data_terminal_ready(false)?; - self.serial.write_request_to_send(true)?; - - sleep(Duration::from_millis(100)); - - self.serial.write_data_terminal_ready(false)?; - self.serial.write_request_to_send(false)?; + UsbJtagSerialReset.reset(&mut self.serial) } else { - self.serial.write_data_terminal_ready(false)?; - self.serial.write_request_to_send(true)?; - - sleep(Duration::from_millis(100)); - - self.serial.write_data_terminal_ready(true)?; - self.serial.write_request_to_send(false)?; - - let millis = if extra_delay { 500 } else { 50 }; - sleep(Duration::from_millis(millis)); + #[cfg(unix)] + if UnixTightReset::new(extra_delay) + .reset(&mut self.serial) + .is_ok() + { + return Ok(()); + } - self.serial.write_data_terminal_ready(false)?; + ClassicReset::new(extra_delay).reset(&mut self.serial) } - - Ok(()) } /// Set timeout for the serial port @@ -177,11 +162,10 @@ impl Connection { } /// Run a command with a timeout defined by the command type - pub fn with_timeout Result>( - &mut self, - timeout: Duration, - mut f: F, - ) -> Result { + pub fn with_timeout(&mut self, timeout: Duration, mut f: F) -> Result + where + F: FnMut(&mut Connection) -> Result, + { let old_timeout = { let serial = self.serial.serial_port_mut(); let old_timeout = serial.timeout(); diff --git a/espflash/src/connection/reset.rs b/espflash/src/connection/reset.rs new file mode 100644 index 00000000..beaa25d7 --- /dev/null +++ b/espflash/src/connection/reset.rs @@ -0,0 +1,237 @@ +//! This entire module is copied from `esptool.py` (https://github.com/espressif/esptool/blob/a8586d02b1305ebc687d31783437a7f4d4dbb70f/esptool/reset.py) + +#[cfg(unix)] +use std::{ + io, + os::{fd::AsRawFd, unix::io::RawFd}, +}; +use std::{thread::sleep, time::Duration}; + +use log::debug; + +use crate::{connection::USB_SERIAL_JTAG_PID, error::Error, interface::Interface}; + +/// Default time to wait before releasing the boot pin after a reset +const DEFAULT_RESET_DELAY: u64 = 50; // ms +/// Amount of time to wait if the default reset delay does not work +const EXTRA_RESET_DELAY: u64 = 500; // ms + +#[cfg(unix)] +mod syscalls { + use nix::{ioctl_read_bad, ioctl_write_int_bad, libc}; + + ioctl_read_bad!(tiocmget, libc::TIOCMGET, libc::c_int); + ioctl_write_int_bad!(tiocmset, libc::TIOCMSET); +} + +/// Some strategy for resting a target device +pub trait ResetStrategy { + fn reset(&self, interface: &mut Interface) -> Result<(), Error>; + + fn set_dtr(&self, interface: &mut Interface, level: bool) -> Result<(), Error> { + interface + .serial_port_mut() + .write_data_terminal_ready(level)?; + + Ok(()) + } + + fn set_rts(&self, interface: &mut Interface, level: bool) -> Result<(), Error> { + interface.serial_port_mut().write_request_to_send(level)?; + + Ok(()) + } + + #[cfg(unix)] + fn set_dtr_rts( + &self, + interface: &mut Interface, + dtr_level: bool, + rts_level: bool, + ) -> Result<(), Error> { + let fd = interface.as_raw_fd(); + let mut status = tiocmget(fd)?; + + if dtr_level { + status |= nix::libc::TIOCM_DTR + } else { + status &= !nix::libc::TIOCM_DTR + } + + if rts_level { + status |= nix::libc::TIOCM_RTS + } else { + status &= !nix::libc::TIOCM_RTS + } + + tiocmset(fd, status)?; + + Ok(()) + } +} + +/// Classic reset sequence, sets DTR and RTS sequentially. +#[derive(Debug, Clone, Copy)] +pub struct ClassicReset { + delay: u64, +} + +impl ClassicReset { + pub fn new(extra_delay: bool) -> Self { + let delay = if extra_delay { + EXTRA_RESET_DELAY + } else { + DEFAULT_RESET_DELAY + }; + + Self { delay } + } +} + +impl ResetStrategy for ClassicReset { + fn reset(&self, interface: &mut Interface) -> Result<(), Error> { + debug!( + "Using Classic reset strategy with delay of {}ms", + self.delay + ); + + self.set_dtr(interface, false)?; // IO0 = HIGH + self.set_rts(interface, true)?; // EN = LOW, chip in reset + + sleep(Duration::from_millis(100)); + + self.set_dtr(interface, true)?; // IO0 = LOW + self.set_rts(interface, false)?; // EN = HIGH, chip out of reset + + sleep(Duration::from_millis(self.delay)); + + self.set_dtr(interface, false)?; // IO0 = HIGH, done + + Ok(()) + } +} + +/// UNIX-only reset sequence with custom implementation, which allows setting +/// DTR and RTS lines at the same time. +#[cfg(unix)] +#[derive(Debug, Clone, Copy)] +pub struct UnixTightReset { + delay: u64, +} + +#[cfg(unix)] +impl UnixTightReset { + pub fn new(extra_delay: bool) -> Self { + let delay = if extra_delay { + EXTRA_RESET_DELAY + } else { + DEFAULT_RESET_DELAY + }; + + Self { delay } + } +} + +#[cfg(unix)] +impl ResetStrategy for UnixTightReset { + fn reset(&self, interface: &mut Interface) -> Result<(), Error> { + debug!( + "Using UnixTight reset strategy with delay of {}ms", + self.delay + ); + + self.set_dtr_rts(interface, false, false)?; + self.set_dtr_rts(interface, true, true)?; + self.set_dtr_rts(interface, false, true)?; // IO = HIGH, EN = LOW, chip in reset + + sleep(Duration::from_millis(100)); + + self.set_dtr_rts(interface, true, false)?; // IO0 = LOW, EN = HIGH, chip out of reset + + sleep(Duration::from_millis(self.delay)); + + self.set_dtr_rts(interface, false, false)?; // IO0 = HIGH, done + self.set_dtr(interface, false)?; // Needed in some environments to ensure IO0 = HIGH + + Ok(()) + } +} + +/// Custom reset sequence, which is required when the device is connecting via +/// its USB-JTAG-Serial peripheral. +#[derive(Debug, Clone, Copy)] +pub struct UsbJtagSerialReset; + +impl ResetStrategy for UsbJtagSerialReset { + fn reset(&self, interface: &mut Interface) -> Result<(), Error> { + debug!("Using UsbJtagSerial reset strategy"); + + self.set_dtr(interface, false)?; // Idle + self.set_rts(interface, false)?; + + sleep(Duration::from_millis(100)); + + self.set_dtr(interface, true)?; // Set IO0 + self.set_rts(interface, false)?; + + sleep(Duration::from_millis(100)); + + self.set_rts(interface, true)?; // Reset. Calls inverted to go through (1,1) instead of (0,0) + self.set_dtr(interface, false)?; + self.set_rts(interface, true)?; // RTS set as Windows only propagates DTR on RTS setting + + sleep(Duration::from_millis(100)); + + self.set_dtr(interface, false)?; + self.set_rts(interface, false)?; + + Ok(()) + } +} + +/// Construct a sequence of reset strategies based on the OS and chip. +/// +/// Returns a [Vec] containing one or more reset strategies to be attempted +/// sequentially. +pub fn construct_reset_strategy_sequence(port_name: &str, pid: u16) -> Vec> { + // USB-JTAG/Serial mode + if pid == USB_SERIAL_JTAG_PID { + return vec![Box::new(UsbJtagSerialReset)]; + } + + // USB-to-Serial bridge + if cfg!(unix) && !port_name.starts_with("rfc2217:") { + return vec![ + Box::new(UnixTightReset::new(false)), + Box::new(UnixTightReset::new(true)), + Box::new(ClassicReset::new(false)), + Box::new(ClassicReset::new(true)), + ]; + } + + // Windows + vec![ + Box::new(ClassicReset::new(false)), + Box::new(ClassicReset::new(true)), + ] +} + +/// Get the status of modem bits +#[cfg(unix)] +fn tiocmget(fd: RawFd) -> io::Result { + let mut bits: i32 = 0; + + match unsafe { syscalls::tiocmget(fd, &mut bits) } { + Ok(0) => Ok(bits), + _ => Err(io::Error::last_os_error()), + } +} + +/// Set the status of modem bits +#[cfg(unix)] +fn tiocmset(fd: RawFd, bits: i32) -> io::Result<()> { + match unsafe { syscalls::tiocmset(fd, bits) } { + Ok(0) => Ok(()), + _ => Err(io::Error::last_os_error()), + } +} diff --git a/espflash/src/interface.rs b/espflash/src/interface.rs index a999d956..fbf92c90 100644 --- a/espflash/src/interface.rs +++ b/espflash/src/interface.rs @@ -5,6 +5,8 @@ //! serial port as one normally would, ie.) via USB. use std::io::Read; +#[cfg(unix)] +use std::os::fd::{AsRawFd, RawFd}; use miette::{Context, Result}; #[cfg(feature = "raspberry")] @@ -13,6 +15,11 @@ use serialport::{FlowControl, SerialPort, SerialPortInfo}; use crate::error::Error; +#[cfg(unix)] +type Port = serialport::TTYPort; +#[cfg(windows)] +type Port = serialport::COMPort; + /// Errors relating to the configuration of a serial port #[derive(thiserror::Error, Debug)] #[non_exhaustive] @@ -29,7 +36,7 @@ pub enum SerialConfigError { /// implemented. pub struct Interface { /// Hardware serial port used for communication - pub serial_port: Box, + pub serial_port: Port, /// Data Transmit Ready pin #[cfg(feature = "raspberry")] pub dtr: Option, @@ -49,10 +56,10 @@ fn write_gpio(gpio: &mut OutputPin, level: bool) { } /// Open a serial port -fn open_port(port_info: &SerialPortInfo) -> Result> { +fn open_port(port_info: &SerialPortInfo) -> Result { serialport::new(&port_info.port_name, 115_200) .flow_control(FlowControl::None) - .open() + .open_native() .map_err(Error::from) .wrap_err_with(|| format!("Failed to open serial port {}", port_info.port_name)) } @@ -125,17 +132,17 @@ impl Interface { /// Turn an [Interface] into a [SerialPort] pub fn into_serial(self) -> Box { - self.serial_port + Box::new(self.serial_port) } /// Turn an [Interface] into a `&`[SerialPort] pub fn serial_port(&self) -> &dyn SerialPort { - self.serial_port.as_ref() + &self.serial_port } /// Turn an [Interface] into a `&mut `[SerialPort] pub fn serial_port_mut(&mut self) -> &mut dyn SerialPort { - self.serial_port.as_mut() + &mut self.serial_port } } @@ -146,3 +153,10 @@ impl Read for Interface { self.serial_port.read(buf) } } + +#[cfg(unix)] +impl AsRawFd for Interface { + fn as_raw_fd(&self) -> RawFd { + self.serial_port.as_raw_fd() + } +} From 714dc9b09d44571a4ed27982d6d6db473400295e Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 5 Oct 2023 17:42:12 +0200 Subject: [PATCH 2/5] refactor: Use libc instead of nix --- Cargo.lock | 2 +- espflash/Cargo.toml | 2 +- espflash/src/connection/reset.rs | 58 ++++++++++++-------------------- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f763cb51..da2d24f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1116,9 +1116,9 @@ dependencies = [ "hex", "indicatif", "lazy_static", + "libc", "log", "miette", - "nix 0.27.1", "parse_int", "regex", "rppal", diff --git a/espflash/Cargo.toml b/espflash/Cargo.toml index e67b1a5d..4400e78f 100644 --- a/espflash/Cargo.toml +++ b/espflash/Cargo.toml @@ -58,7 +58,7 @@ update-informer = { version = "1.1.0", optional = true } xmas-elf = "0.9.0" [target.'cfg(unix)'.dependencies] -nix = { version = "0.27.1", default-features = false, features = ["ioctl"] } +libc = "0.2.101" [features] default = ["cli"] diff --git a/espflash/src/connection/reset.rs b/espflash/src/connection/reset.rs index beaa25d7..04edbc8c 100644 --- a/espflash/src/connection/reset.rs +++ b/espflash/src/connection/reset.rs @@ -1,10 +1,7 @@ //! This entire module is copied from `esptool.py` (https://github.com/espressif/esptool/blob/a8586d02b1305ebc687d31783437a7f4d4dbb70f/esptool/reset.py) #[cfg(unix)] -use std::{ - io, - os::{fd::AsRawFd, unix::io::RawFd}, -}; +use std::{io, os::fd::AsRawFd}; use std::{thread::sleep, time::Duration}; use log::debug; @@ -17,12 +14,7 @@ const DEFAULT_RESET_DELAY: u64 = 50; // ms const EXTRA_RESET_DELAY: u64 = 500; // ms #[cfg(unix)] -mod syscalls { - use nix::{ioctl_read_bad, ioctl_write_int_bad, libc}; - - ioctl_read_bad!(tiocmget, libc::TIOCMGET, libc::c_int); - ioctl_write_int_bad!(tiocmset, libc::TIOCMSET); -} +use libc::ioctl; /// Some strategy for resting a target device pub trait ResetStrategy { @@ -50,22 +42,28 @@ pub trait ResetStrategy { rts_level: bool, ) -> Result<(), Error> { let fd = interface.as_raw_fd(); - let mut status = tiocmget(fd)?; + let mut status: i32 = 0; + match unsafe { ioctl(fd, libc::TIOCMGET, &status) } { + 0 => (), + _ => return Err(io::Error::last_os_error().into()), + } if dtr_level { - status |= nix::libc::TIOCM_DTR + status |= libc::TIOCM_DTR } else { - status &= !nix::libc::TIOCM_DTR + status &= !libc::TIOCM_DTR } if rts_level { - status |= nix::libc::TIOCM_RTS + status |= libc::TIOCM_RTS } else { - status &= !nix::libc::TIOCM_RTS + status &= !libc::TIOCM_RTS } - tiocmset(fd, status)?; - + match unsafe { ioctl(fd, libc::TIOCMSET, &status) } { + 0 => (), + _ => return Err(io::Error::last_os_error().into()), + } Ok(()) } } @@ -94,6 +92,11 @@ impl ResetStrategy for ClassicReset { "Using Classic reset strategy with delay of {}ms", self.delay ); + self.set_dtr(interface, false)?; + self.set_rts(interface, false)?; + + self.set_dtr(interface, true)?; + self.set_rts(interface, true)?; self.set_dtr(interface, false)?; // IO0 = HIGH self.set_rts(interface, true)?; // EN = LOW, chip in reset @@ -106,6 +109,7 @@ impl ResetStrategy for ClassicReset { sleep(Duration::from_millis(self.delay)); self.set_dtr(interface, false)?; // IO0 = HIGH, done + self.set_rts(interface, false)?; Ok(()) } @@ -215,23 +219,3 @@ pub fn construct_reset_strategy_sequence(port_name: &str, pid: u16) -> Vec io::Result { - let mut bits: i32 = 0; - - match unsafe { syscalls::tiocmget(fd, &mut bits) } { - Ok(0) => Ok(bits), - _ => Err(io::Error::last_os_error()), - } -} - -/// Set the status of modem bits -#[cfg(unix)] -fn tiocmset(fd: RawFd, bits: i32) -> io::Result<()> { - match unsafe { syscalls::tiocmset(fd, bits) } { - Ok(0) => Ok(()), - _ => Err(io::Error::last_os_error()), - } -} From 6d1bfd0ae9eee19e9aba43b4afd6ea9cb10b8ec2 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 5 Oct 2023 17:50:59 +0200 Subject: [PATCH 3/5] feat: Add debug message when reset fails --- espflash/src/connection/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/espflash/src/connection/mod.rs b/espflash/src/connection/mod.rs index a06b58ef..1f4ff20a 100644 --- a/espflash/src/connection/mod.rs +++ b/espflash/src/connection/mod.rs @@ -7,7 +7,7 @@ use std::{io::BufWriter, iter::zip, thread::sleep, time::Duration}; use binrw::{io::Cursor, BinRead, BinReaderExt}; -use log::{debug, info}; +use log::debug; use serialport::UsbPortInfo; use slip_codec::SlipDecoder; @@ -62,8 +62,13 @@ impl Connection { let reset_sequence = construct_reset_strategy_sequence(&port_name, self.port_info.pid); for (_, reset_strategy) in zip(0..MAX_CONNECT_ATTEMPTS, reset_sequence.iter().cycle()) { - if self.connect_attempt(reset_strategy).is_ok() { - return Ok(()); + match self.connect_attempt(reset_strategy) { + Ok(_) => { + return Ok(()); + } + Err(e) => { + debug!("Failed to reset, error {:#?}, retrying", e); + } } } From 87b9ca40cc945dd02b7a0be9be9ac896929ea2f9 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 5 Oct 2023 18:16:53 +0200 Subject: [PATCH 4/5] fix: Fix clippy lint --- espflash/src/connection/reset.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/espflash/src/connection/reset.rs b/espflash/src/connection/reset.rs index 04edbc8c..f895aa86 100644 --- a/espflash/src/connection/reset.rs +++ b/espflash/src/connection/reset.rs @@ -197,6 +197,7 @@ impl ResetStrategy for UsbJtagSerialReset { /// /// Returns a [Vec] containing one or more reset strategies to be attempted /// sequentially. +#[allow(unused_variables)] pub fn construct_reset_strategy_sequence(port_name: &str, pid: u16) -> Vec> { // USB-JTAG/Serial mode if pid == USB_SERIAL_JTAG_PID { @@ -204,6 +205,7 @@ pub fn construct_reset_strategy_sequence(port_name: &str, pid: u16) -> Vec Date: Fri, 6 Oct 2023 12:01:54 +0200 Subject: [PATCH 5/5] docs: Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a2dafb0..a89ce0ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased] ### Added +- Added reset strategies (#487) - Read esp-println generated defmt messages (#466)