From 1e71305c8d14d4d92328efaec2ac82dc46d5797e Mon Sep 17 00:00:00 2001 From: Tobias Breitwieser Date: Tue, 3 Oct 2023 14:29:45 +0200 Subject: [PATCH] add configurable cycle delay and maximum time for probe reappearing --- teleprobe/src/api.rs | 6 +++++- teleprobe/src/config.rs | 16 +++++++++++++++- teleprobe/src/probe/mod.rs | 39 ++++++++++++++++++++++++++++++++------ teleprobe/src/server.rs | 8 ++++++++ 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/teleprobe/src/api.rs b/teleprobe/src/api.rs index 29e3008..c038dfb 100644 --- a/teleprobe/src/api.rs +++ b/teleprobe/src/api.rs @@ -11,7 +11,11 @@ pub struct Target { pub speed: Option, pub up: bool, #[cfg(feature = "power_reset")] - pub power_reset: bool + pub power_reset: bool, + #[cfg(feature = "power_reset")] + pub cycle_delay_seconds: f64, + #[cfg(feature = "power_reset")] + pub max_settle_time_millis: u64, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/teleprobe/src/config.rs b/teleprobe/src/config.rs index 2b36235..d7fce12 100644 --- a/teleprobe/src/config.rs +++ b/teleprobe/src/config.rs @@ -67,7 +67,21 @@ pub struct Target { pub speed: Option, #[cfg(feature = "power_reset")] #[serde(default)] - pub power_reset: bool + pub power_reset: bool, + #[cfg(feature = "power_reset")] + #[serde(default = "default_cycle_delay_seconds")] + pub cycle_delay_seconds: f64, + #[cfg(feature = "power_reset")] + #[serde(default = "default_max_settle_time_millis")] + pub max_settle_time_millis: u64, +} + +fn default_cycle_delay_seconds() -> f64 { + 1.0 +} + +fn default_max_settle_time_millis() -> u64 { + 2000 } #[derive(Clone, Serialize, Deserialize)] diff --git a/teleprobe/src/probe/mod.rs b/teleprobe/src/probe/mod.rs index 962effe..9bd7b43 100644 --- a/teleprobe/src/probe/mod.rs +++ b/teleprobe/src/probe/mod.rs @@ -1,7 +1,9 @@ mod specifier; +use std::fmt; use std::process::Command; use std::sync::Mutex; +use std::time::Instant; use anyhow::{bail, Result}; use clap::Parser; use probe_rs::{DebugProbeInfo, MemoryInterface, Permissions, Probe, Session}; @@ -9,6 +11,8 @@ pub use specifier::ProbeSpecifier; static UHUBCTL_MUTEX: Mutex<()> = Mutex::new(()); +const SETTLE_REPROBE_INTERVAL: std::time::Duration = std::time::Duration::from_millis(100); + #[derive(Clone, Parser)] pub struct Opts { /// The probe to use (specified by eg. `VID:PID`, `VID:PID:Serial`, or just `Serial`). @@ -31,6 +35,14 @@ pub struct Opts { #[cfg(feature = "power_reset")] #[clap(long)] pub power_reset: bool, + + #[cfg(feature = "power_reset")] + #[clap(long, default_value = "1")] + pub cycle_delay_seconds: f64, + + #[cfg(feature = "power_reset")] + #[clap(long, default_value = "2000")] + pub max_settle_time_millis: u64, } pub fn list() -> Result<()> { @@ -59,15 +71,29 @@ pub fn connect(opts: &Opts) -> Result { #[cfg(feature = "power_reset")] { if opts.power_reset { - if probes[0].serial_number.is_none(){ + if probes[0].serial_number.is_none() { bail!("power reset requires a serial number"); } log::debug!("probe power reset"); - if let Err(err) = power_reset(&probes[0].serial_number.as_ref().unwrap()){ + if let Err(err) = power_reset(&probes[0].serial_number.as_ref().unwrap(), 0.5) { log::warn!("power reset failed for: {}", err); } + + + let end = Instant::now() + std::time::Duration::from_millis(opts.max_settle_time_millis); + probes = vec![]; + while Instant::now() < end && probes.is_empty() { + std::thread::sleep(SETTLE_REPROBE_INTERVAL); + probes = match get_probe(&opts) { + Ok(p) => {p} + Err(_) => {probes} + } + } + if probes.is_empty() { + bail!("Probe not reappeared after power reset") + } + } - probes = get_probe(&opts)?; } @@ -170,11 +196,13 @@ pub fn probes_filter(probes: &[DebugProbeInfo], selector: &ProbeSpecifier) -> Ve } #[cfg(feature = "power_reset")] -fn power_reset(probe_serial: &str) -> Result<()> { +fn power_reset(probe_serial: &str, cycle_delay_seconds: f64) -> Result<()> { let _guard = UHUBCTL_MUTEX.lock(); let output = Command::new("uhubctl") .arg("-a") .arg("cycle") + .arg("-d") + .arg(format!("{:.2}", cycle_delay_seconds)) .arg("-s") .arg(probe_serial) .output(); @@ -183,10 +211,9 @@ fn power_reset(probe_serial: &str) -> Result<()> { match output { Ok(output) => { if output.status.success() { - std::thread::sleep(std::time::Duration::from_millis(1000)); Ok(()) } else { - bail!("uhubctl failed for serial \'{}\': {}", probe_serial, String::from_utf8_lossy(&output.stderr)) + bail!("uhubctl failed for serial \'{}\' with delay {}: {}", cycle_delay_seconds, probe_serial, String::from_utf8_lossy(&output.stderr)) } } Err(e) => bail!("uhubctl failed: {}", e) diff --git a/teleprobe/src/server.rs b/teleprobe/src/server.rs index 683e723..8248028 100644 --- a/teleprobe/src/server.rs +++ b/teleprobe/src/server.rs @@ -193,6 +193,10 @@ async fn handle_run(name: String, args: RunArgs, elf: Bytes, cx: Arc>) -> api::TargetList { up: is_up, #[cfg(feature = "power_reset")] power_reset: target.power_reset, + #[cfg(feature = "power_reset")] + cycle_delay_seconds: target.cycle_delay_seconds, + #[cfg(feature = "power_reset")] + max_settle_time_millis: target.max_settle_time_millis, }); }