Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix image upload hanging when MTU is increased #21

Merged
merged 2 commits into from
Feb 22, 2024
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
14 changes: 11 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ pub struct Cli {
#[arg(short, long)]
pub verbose: bool,

/// maximum timeout in seconds
#[arg(short, long, default_value_t = 60)]
pub timeout: u32,
/// initial timeout in seconds
#[arg(short = 't', long = "initial_timeout", default_value_t = 60)]
pub initial_timeout_s: u32,

/// subsequent timeout in msec
#[arg(short = 'u', long = "subsequent_timeout", default_value_t = 200)]
pub subsequent_timeout_ms: u32,

// number of retry per packet
#[arg(long, default_value_t = 4)]
pub nb_retry: u32,

/// maximum length per line
#[arg(short, long, default_value_t = 128)]
Expand Down
6 changes: 3 additions & 3 deletions src/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use crate::transfer::transceive;

pub fn reset(cli: &Cli) -> Result<(), Error> {
info!("send reset request");

// open serial port
let mut port = open_port(cli)?;

// send request
let body = Vec::new();
let (data, request_header) = encode_request(
Expand All @@ -29,7 +29,7 @@ pub fn reset(cli: &Cli) -> Result<(), Error> {
&body,
next_seq_id(),
)?;
let (response_header, response_body) = transceive(&mut *port, data)?;
let (response_header, response_body) = transceive(&mut *port, &data)?;

// verify sequence id
if response_header.seq != request_header.seq {
Expand Down
31 changes: 26 additions & 5 deletions src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
use anyhow::{bail, Error, Result};
use humantime::format_duration;
use indicatif::{ProgressBar, ProgressStyle};
use log::debug;
use log::info;
use log::{debug, info, warn};
use serde_cbor;
use serde_json;
use sha2::{Digest, Sha256};
Expand Down Expand Up @@ -37,7 +36,7 @@ pub fn list(cli: &Cli) -> Result<(), Error> {
&body,
next_seq_id(),
)?;
let (response_header, response_body) = transceive(&mut *port, data)?;
let (response_header, response_body) = transceive(&mut *port, &data)?;

// verify sequence id
if response_header.seq != request_header.seq {
Expand Down Expand Up @@ -89,7 +88,10 @@ pub fn upload(cli: &Cli, filename: &PathBuf) -> Result<(), Error> {
// transfer in blocks
let mut off: usize = 0;
let start_time = Instant::now();
let mut sent_blocks: u32 = 0;
let mut confirmed_blocks: u32 = 0;
loop {
let mut nb_retry = cli.nb_retry;
let off_start = off;
let mut try_length = cli.mtu;
debug!("try_length: {}", try_length);
Expand Down Expand Up @@ -151,7 +153,19 @@ pub fn upload(cli: &Cli, filename: &PathBuf) -> Result<(), Error> {
}

// send request
let (response_header, response_body) = transceive(&mut *port, chunk)?;
sent_blocks += 1;
let (response_header, response_body) = match transceive(&mut *port, &chunk) {
Ok(ret) => ret,
Err(e) if e.to_string() == "Operation timed out" => {
if nb_retry == 0 {
return Err(e);
}
nb_retry -= 1;
debug!("missed answer, nb_retry: {}", nb_retry);
continue;
}
Err(e) => return Err(e),
};

// verify sequence id
if response_header.seq != request_header.seq {
Expand Down Expand Up @@ -187,7 +201,7 @@ pub fn upload(cli: &Cli, filename: &PathBuf) -> Result<(), Error> {
}
}
}

confirmed_blocks += 1;
break;
}

Expand All @@ -200,13 +214,20 @@ pub fn upload(cli: &Cli, filename: &PathBuf) -> Result<(), Error> {
if off == data.len() {
break;
}

// The first packet was sent and the device has cleared its internal flash
// We can now lower the timeout in case of failed transmission
port.set_timeout(Duration::from_millis(cli.subsequent_timeout_ms as u64))?;
}
pb.finish_with_message("upload complete");

let elapsed = start_time.elapsed().as_secs_f64().round();
let elapsed_duration = Duration::from_secs(elapsed as u64);
let formatted_duration = format_duration(elapsed_duration);
info!("upload took {}", formatted_duration);
if confirmed_blocks != sent_blocks {
warn!("upload packet loss {}%", 100 - confirmed_blocks * 100 / sent_blocks);
}

Ok(())
}
6 changes: 3 additions & 3 deletions src/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn open_port(cli: &Cli) -> Result<Box<dyn SerialPort>, Error> {
Ok(Box::new(TestSerialPort::new()))
} else {
serialport::new(&cli.device, cli.baudrate)
.timeout(Duration::from_secs(cli.timeout as u64))
.timeout(Duration::from_secs(cli.initial_timeout_s as u64))
.open()
.with_context(|| format!("failed to open serial port {}", &cli.device))
}
Expand Down Expand Up @@ -110,7 +110,7 @@ pub fn encode_request(

pub fn transceive(
port: &mut dyn SerialPort,
data: Vec<u8>,
data: &Vec<u8>,
) -> Result<(NmpHdr, serde_cbor::Value), Error> {
// empty input buffer
let to_read = port.bytes_to_read()?;
Expand All @@ -119,7 +119,7 @@ pub fn transceive(
}

// write request
port.write_all(&data)?;
port.write_all(data)?;

// read result
let mut bytes_read = 0;
Expand Down