From f5355a5acfac65c39459557755e2e76665a3230e Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 27 Dec 2023 12:32:09 +0100 Subject: [PATCH 1/5] Add `checksum-md5` command --- Cargo.lock | 31 ------------- espflash/Cargo.toml | 1 - espflash/src/bin/espflash.rs | 42 ++++++++++++++--- espflash/src/command.rs | 16 +++++++ espflash/src/connection/mod.rs | 82 +++++++++++++++++++++++++++++++--- espflash/src/error.rs | 18 ++------ espflash/src/flasher/mod.rs | 11 +++++ 7 files changed, 143 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7bf16fa..9464c66e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,12 +125,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" -[[package]] -name = "array-init" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" - [[package]] name = "arrayvec" version = "0.5.2" @@ -194,30 +188,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "binrw" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8318fda24dc135cdd838f57a2b5ccb6e8f04ff6b6c65528c4bd9b5fcdc5cf6" -dependencies = [ - "array-init", - "binrw_derive", - "bytemuck", -] - -[[package]] -name = "binrw_derive" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0832bed83248115532dfb25af54fae1c83d67a2e4e3e2f591c13062e372e7e" -dependencies = [ - "either", - "owo-colors", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -1099,7 +1069,6 @@ version = "3.0.0-dev" dependencies = [ "addr2line", "base64", - "binrw", "bytemuck", "clap", "clap_complete", diff --git a/espflash/Cargo.toml b/espflash/Cargo.toml index bd8b66e8..84d80cd5 100644 --- a/espflash/Cargo.toml +++ b/espflash/Cargo.toml @@ -25,7 +25,6 @@ required-features = ["cli"] [dependencies] addr2line = { version = "0.21.0", optional = true } base64 = "0.21.4" -binrw = "0.12.0" bytemuck = { version = "1.14.0", features = ["derive"] } clap = { version = "4.4.6", features = ["derive", "env", "wrap_help"], optional = true } clap_complete = { version = "4.4.3", optional = true } diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index 436bf48a..02583378 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -1,17 +1,18 @@ use std::{ fs::{self, File}, io::Read, + num::ParseIntError, path::PathBuf, }; use clap::{Args, CommandFactory, Parser, Subcommand}; use espflash::{ cli::{ - self, board_info, completions, config::Config, connect, erase_flash, erase_partitions, - erase_region, flash_elf_image, monitor::monitor, parse_partition_table, parse_uint32, - partition_table, print_board_info, save_elf_as_image, serial_monitor, CompletionsArgs, - ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, FlashConfigArgs, - MonitorArgs, PartitionTableArgs, + self, board_info, completions, config::Config, connect, erase_flash, + erase_partitions, erase_region, flash_elf_image, monitor::monitor, parse_partition_table, + parse_uint32, partition_table, print_board_info, save_elf_as_image, serial_monitor, + CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, + FlashConfigArgs, MonitorArgs, PartitionTableArgs, }, error::Error, image_format::ImageFormatKind, @@ -83,6 +84,8 @@ enum Commands { SaveImage(SaveImageArgs), /// Write a binary file to a specific address in a target device's flash WriteBin(WriteBinArgs), + /// Calculate the MD5 checksum of the given region + ChecksumMd5(ChecksumMd5Args), } /// Erase named partitions based on provided partition table @@ -146,6 +149,24 @@ struct WriteBinArgs { connect_args: ConnectArgs, } +#[derive(Debug, Args)] +#[non_exhaustive] +struct ChecksumMd5Args { + /// Start address + #[clap(short, long, value_parser=parse_u32)] + address: u32, + /// Length + #[clap(short, long, value_parser=parse_u32)] + length: u32, + /// Connection configuration + #[clap(flatten)] + connect_args: ConnectArgs, +} + +pub fn parse_u32(input: &str) -> Result { + parse_int::parse(input) +} + fn main() -> Result<()> { miette::set_panic_hook(); initialize_logger(LevelFilter::Info); @@ -176,6 +197,7 @@ fn main() -> Result<()> { Commands::PartitionTable(args) => partition_table(args), Commands::SaveImage(args) => save_image(args), Commands::WriteBin(args) => write_bin(args, &config), + Commands::ChecksumMd5(args) => checksum_md5(&args, &config), } } @@ -334,3 +356,13 @@ fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> { Ok(()) } + +/// Connect to a target device and calculate the checksum of the given region +fn checksum_md5(args: &ChecksumMd5Args, config: &Config) -> Result<()> { + let mut flasher = connect(&args.connect_args, config)?; + + let checksum = flasher.checksum_md5(args.address, args.length)?; + println!("0x{:x}", checksum); + + Ok(()) +} diff --git a/espflash/src/command.rs b/espflash/src/command.rs index d71ce10f..84d9b080 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -159,6 +159,10 @@ pub enum Command<'a> { offset: u32, size: u32, }, + FlashMd5 { + offset: u32, + size: u32, + } } impl<'a> Command<'a> { @@ -184,6 +188,7 @@ impl<'a> Command<'a> { Command::FlashDetect => CommandType::FlashDetect, Command::EraseFlash { .. } => CommandType::EraseFlash, Command::EraseRegion { .. } => CommandType::EraseRegion, + Command::FlashMd5 { .. } => CommandType::FlashMd5, } } @@ -361,6 +366,17 @@ impl<'a> Command<'a> { writer.write_all(&offset.to_le_bytes())?; writer.write_all(&size.to_le_bytes())?; } + Command::FlashMd5 { offset, size } => { + // length + writer.write_all(&(16u16.to_le_bytes()))?; + // checksum + writer.write_all(&(0u32.to_le_bytes()))?; + // data + writer.write_all(&offset.to_le_bytes())?; + writer.write_all(&size.to_le_bytes())?; + writer.write_all(&(0u32.to_le_bytes()))?; + writer.write_all(&(0u32.to_le_bytes()))?; + }, }; Ok(()) } diff --git a/espflash/src/connection/mod.rs b/espflash/src/connection/mod.rs index ab885fa4..5ee99dc6 100644 --- a/espflash/src/connection/mod.rs +++ b/espflash/src/connection/mod.rs @@ -11,7 +11,6 @@ use std::{ time::Duration, }; -use binrw::{io::Cursor, BinRead, BinReaderExt}; use log::debug; use serialport::UsbPortInfo; use slip_codec::SlipDecoder; @@ -34,13 +33,41 @@ const MAX_CONNECT_ATTEMPTS: usize = 7; const MAX_SYNC_ATTEMPTS: usize = 5; pub(crate) const USB_SERIAL_JTAG_PID: u16 = 0x1001; +#[derive(Debug, Copy, Clone)] +pub enum CommandResponseValue { + ValueU32(u32), + ValueU128(u128), +} + +impl TryInto for CommandResponseValue { + type Error = crate::error::Error; + + fn try_into(self) -> Result { + match self { + CommandResponseValue::ValueU32(value) => Ok(value), + CommandResponseValue::ValueU128(_) => Err(crate::error::Error::InternalError), + } + } +} + +impl TryInto for CommandResponseValue { + type Error = crate::error::Error; + + fn try_into(self) -> Result { + match self { + CommandResponseValue::ValueU32(_) => Err(crate::error::Error::InternalError), + CommandResponseValue::ValueU128(value) => Ok(value), + } + } +} + /// A response from a target device following a command -#[derive(Debug, Copy, Clone, BinRead)] +#[derive(Debug, Copy, Clone)] pub struct CommandResponse { pub resp: u8, pub return_op: u8, pub return_length: u16, - pub value: u32, + pub value: CommandResponseValue, pub error: u8, pub status: u8, } @@ -195,8 +222,50 @@ impl Connection { match self.read(10)? { None => Ok(None), Some(response) => { - let mut cursor = Cursor::new(response); - let header = cursor.read_le()?; + // here is what esptool does: https://github.com/espressif/esptool/blob/master/esptool/loader.py#L458 + // from esptool: things are a bit weird here, bear with us + + // we rely on the known and expected response sizes + let status_len = if response.len() == 10 || response.len() == 26 { + 2 + } else { + 4 + }; + + let value = match response.len() { + 10 | 12 => CommandResponseValue::ValueU32(u32::from_le_bytes( + response[4..][..4].try_into().unwrap(), + )), + 44 => { + // MD5 is in ASCII + CommandResponseValue::ValueU128( + u128::from_str_radix( + std::str::from_utf8(&response[8..][..32]).unwrap(), + 16, + ) + .unwrap(), + ) + } + 26 => { + // MD5 is BE bytes + CommandResponseValue::ValueU128(u128::from_be_bytes( + response[8..][..16].try_into().unwrap(), + )) + } + _ => { + return Err(Error::InternalError); + } + }; + + let header = CommandResponse { + resp: response[0], + return_op: response[1], + return_length: u16::from_le_bytes(response[2..][..2].try_into().unwrap()), + value: value, + error: response[response.len() - status_len], + status: response[response.len() - status_len + 1], + }; + Ok(Some(header)) } } @@ -217,7 +286,7 @@ impl Connection { } /// Write a command and reads the response - pub fn command(&mut self, command: Command) -> Result { + pub fn command(&mut self, command: Command) -> Result { let ty = command.command_type(); self.write_command(command).for_command(ty)?; @@ -247,6 +316,7 @@ impl Connection { self.with_timeout(CommandType::ReadReg.timeout(), |connection| { connection.command(Command::ReadReg { address: reg }) }) + .map(|v| v.try_into().unwrap()) } /// Write a register command with a timeout diff --git a/espflash/src/error.rs b/espflash/src/error.rs index 178e63fe..4cdf6771 100644 --- a/espflash/src/error.rs +++ b/espflash/src/error.rs @@ -179,6 +179,9 @@ pub enum Error { #[error(transparent)] #[diagnostic(transparent)] Defmt(#[from] DefmtError), + + #[error("Internal Error")] + InternalError, } impl From for Error { @@ -187,12 +190,6 @@ impl From for Error { } } -impl From for Error { - fn from(err: binrw::Error) -> Self { - Self::Connection(err.into()) - } -} - impl From for Error { fn from(err: serialport::Error) -> Self { Self::Connection(err.into()) @@ -261,15 +258,6 @@ impl From for ConnectionError { } } -impl From for ConnectionError { - fn from(err: binrw::Error) -> Self { - match err { - binrw::Error::Io(e) => ConnectionError::from(e), - _ => unreachable!(), - } - } -} - impl From for ConnectionError { fn from(err: serialport::Error) -> Self { use serialport::ErrorKind; diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index acaa6aaf..66b050dc 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -888,6 +888,17 @@ impl Flasher { Ok(()) } + /// Get MD5 of region + pub fn checksum_md5(&mut self, addr: u32, length: u32) -> Result { + Ok(self + .connection + .command(crate::command::Command::FlashMd5 { + offset: addr, + size: length, + })? + .try_into()?) + } + /// Load an ELF image to flash and execute it pub fn load_elf_to_flash( &mut self, From 317bbe9bb6a0bdb322cde8b9e470c3cf47e0ee4d Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 27 Dec 2023 12:50:48 +0100 Subject: [PATCH 2/5] fmt --- espflash/src/bin/espflash.rs | 10 +++++----- espflash/src/command.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index 02583378..fa24e34d 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -8,11 +8,11 @@ use std::{ use clap::{Args, CommandFactory, Parser, Subcommand}; use espflash::{ cli::{ - self, board_info, completions, config::Config, connect, erase_flash, - erase_partitions, erase_region, flash_elf_image, monitor::monitor, parse_partition_table, - parse_uint32, partition_table, print_board_info, save_elf_as_image, serial_monitor, - CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, - FlashConfigArgs, MonitorArgs, PartitionTableArgs, + self, board_info, completions, config::Config, connect, erase_flash, erase_partitions, + erase_region, flash_elf_image, monitor::monitor, parse_partition_table, parse_uint32, + partition_table, print_board_info, save_elf_as_image, serial_monitor, CompletionsArgs, + ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, FlashConfigArgs, + MonitorArgs, PartitionTableArgs, }, error::Error, image_format::ImageFormatKind, diff --git a/espflash/src/command.rs b/espflash/src/command.rs index 84d9b080..584933b3 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -162,7 +162,7 @@ pub enum Command<'a> { FlashMd5 { offset: u32, size: u32, - } + }, } impl<'a> Command<'a> { @@ -376,7 +376,7 @@ impl<'a> Command<'a> { writer.write_all(&size.to_le_bytes())?; writer.write_all(&(0u32.to_le_bytes()))?; writer.write_all(&(0u32.to_le_bytes()))?; - }, + } }; Ok(()) } From aaade71e49cf3edb6ca96b74e1938350739f4487 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 27 Dec 2023 12:53:13 +0100 Subject: [PATCH 3/5] clippy --- espflash/src/connection/mod.rs | 2 +- espflash/src/flasher/mod.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/espflash/src/connection/mod.rs b/espflash/src/connection/mod.rs index 5ee99dc6..ffb73040 100644 --- a/espflash/src/connection/mod.rs +++ b/espflash/src/connection/mod.rs @@ -261,7 +261,7 @@ impl Connection { resp: response[0], return_op: response[1], return_length: u16::from_le_bytes(response[2..][..2].try_into().unwrap()), - value: value, + value, error: response[response.len() - status_len], status: response[response.len() - status_len + 1], }; diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 66b050dc..f62d5b81 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -890,13 +890,12 @@ impl Flasher { /// Get MD5 of region pub fn checksum_md5(&mut self, addr: u32, length: u32) -> Result { - Ok(self - .connection + self.connection .command(crate::command::Command::FlashMd5 { offset: addr, size: length, })? - .try_into()?) + .try_into() } /// Load an ELF image to flash and execute it From 98c8135b71c42dcdd629298d0f66cbf4cc636a9f Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 27 Dec 2023 12:56:32 +0100 Subject: [PATCH 4/5] CHANGELOG.md entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b49991ac..6bd85df6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add --chip argument for flash and write-bin commands (#514) - Add --partition-table-offset argument for specifying the partition table offset (#516) - Add `Serialize` and `Deserialize` to `FlashFrequency`, `FlashMode` and `FlashSize`. (#528) +- Add `checksum-md5` command (#536) ### Fixed From 7e0552ddca8470fc958de53131d0c3753e115d90 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 27 Dec 2023 16:37:44 +0100 Subject: [PATCH 5/5] `checksum-md5` for cargo-espflash, add timeout --- cargo-espflash/src/main.rs | 13 +++++++----- espflash/src/bin/espflash.rs | 39 +++++----------------------------- espflash/src/cli/mod.rs | 28 ++++++++++++++++++++++++ espflash/src/command.rs | 2 ++ espflash/src/connection/mod.rs | 8 ++++++- espflash/src/flasher/mod.rs | 13 +++++++----- 6 files changed, 58 insertions(+), 45 deletions(-) diff --git a/cargo-espflash/src/main.rs b/cargo-espflash/src/main.rs index 67664caa..8de23b3c 100644 --- a/cargo-espflash/src/main.rs +++ b/cargo-espflash/src/main.rs @@ -8,11 +8,11 @@ use cargo_metadata::Message; use clap::{Args, CommandFactory, Parser, Subcommand}; use espflash::{ cli::{ - self, board_info, completions, config::Config, connect, erase_flash, erase_partitions, - erase_region, flash_elf_image, monitor::monitor, parse_partition_table, partition_table, - print_board_info, save_elf_as_image, serial_monitor, CompletionsArgs, ConnectArgs, - EraseFlashArgs, EraseRegionArgs, EspflashProgress, FlashConfigArgs, MonitorArgs, - PartitionTableArgs, + self, board_info, checksum_md5, completions, config::Config, connect, erase_flash, + erase_partitions, erase_region, flash_elf_image, monitor::monitor, parse_partition_table, + partition_table, print_board_info, save_elf_as_image, serial_monitor, ChecksumMd5Args, + CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, + FlashConfigArgs, MonitorArgs, PartitionTableArgs, }, error::Error as EspflashError, image_format::ImageFormatKind, @@ -106,6 +106,8 @@ enum Commands { /// Otherwise, each segment will be saved as individual binaries, prefixed /// with their intended addresses in flash. SaveImage(SaveImageArgs), + /// Calculate the MD5 checksum of the given region + ChecksumMd5(ChecksumMd5Args), } #[derive(Debug, Args)] @@ -217,6 +219,7 @@ fn main() -> Result<()> { Commands::Monitor(args) => serial_monitor(args, &config), Commands::PartitionTable(args) => partition_table(args), Commands::SaveImage(args) => save_image(args), + Commands::ChecksumMd5(args) => checksum_md5(&args, &config), } } diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index fa24e34d..66208237 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -1,18 +1,17 @@ use std::{ fs::{self, File}, io::Read, - num::ParseIntError, path::PathBuf, }; use clap::{Args, CommandFactory, Parser, Subcommand}; use espflash::{ cli::{ - self, board_info, completions, config::Config, connect, erase_flash, erase_partitions, - erase_region, flash_elf_image, monitor::monitor, parse_partition_table, parse_uint32, - partition_table, print_board_info, save_elf_as_image, serial_monitor, CompletionsArgs, - ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, FlashConfigArgs, - MonitorArgs, PartitionTableArgs, + self, board_info, checksum_md5, completions, config::Config, connect, erase_flash, + erase_partitions, erase_region, flash_elf_image, monitor::monitor, parse_partition_table, + parse_uint32, partition_table, print_board_info, save_elf_as_image, serial_monitor, + ChecksumMd5Args, CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, + EspflashProgress, FlashConfigArgs, MonitorArgs, PartitionTableArgs, }, error::Error, image_format::ImageFormatKind, @@ -149,24 +148,6 @@ struct WriteBinArgs { connect_args: ConnectArgs, } -#[derive(Debug, Args)] -#[non_exhaustive] -struct ChecksumMd5Args { - /// Start address - #[clap(short, long, value_parser=parse_u32)] - address: u32, - /// Length - #[clap(short, long, value_parser=parse_u32)] - length: u32, - /// Connection configuration - #[clap(flatten)] - connect_args: ConnectArgs, -} - -pub fn parse_u32(input: &str) -> Result { - parse_int::parse(input) -} - fn main() -> Result<()> { miette::set_panic_hook(); initialize_logger(LevelFilter::Info); @@ -356,13 +337,3 @@ fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> { Ok(()) } - -/// Connect to a target device and calculate the checksum of the given region -fn checksum_md5(args: &ChecksumMd5Args, config: &Config) -> Result<()> { - let mut flasher = connect(&args.connect_args, config)?; - - let checksum = flasher.checksum_md5(args.address, args.length)?; - println!("0x{:x}", checksum); - - Ok(()) -} diff --git a/espflash/src/cli/mod.rs b/espflash/src/cli/mod.rs index 4c3d959e..5d1c9a21 100644 --- a/espflash/src/cli/mod.rs +++ b/espflash/src/cli/mod.rs @@ -231,6 +231,24 @@ pub struct MonitorArgs { pub log_format: LogFormat, } +#[derive(Debug, Args)] +#[non_exhaustive] +pub struct ChecksumMd5Args { + /// Start address + #[clap(short, long, value_parser=parse_u32)] + address: u32, + /// Length + #[clap(short, long, value_parser=parse_u32)] + length: u32, + /// Connection configuration + #[clap(flatten)] + connect_args: ConnectArgs, +} + +pub fn parse_u32(input: &str) -> Result { + parse_int::parse(input) +} + /// Select a serial port and establish a connection with a target device pub fn connect(args: &ConnectArgs, config: &Config) -> Result { let port_info = get_serial_port_info(args, config)?; @@ -284,6 +302,16 @@ pub fn board_info(args: &ConnectArgs, config: &Config) -> Result<()> { Ok(()) } +/// Connect to a target device and calculate the checksum of the given region +pub fn checksum_md5(args: &ChecksumMd5Args, config: &Config) -> Result<()> { + let mut flasher = connect(&args.connect_args, config)?; + + let checksum = flasher.checksum_md5(args.address, args.length)?; + println!("0x{:x}", checksum); + + Ok(()) +} + /// Generate shell completions for the given shell pub fn completions(args: &CompletionsArgs, app: &mut clap::Command, bin_name: &str) -> Result<()> { clap_complete::generate(args.shell, app, bin_name, &mut std::io::stdout()); diff --git a/espflash/src/command.rs b/espflash/src/command.rs index 584933b3..1bc4f76e 100644 --- a/espflash/src/command.rs +++ b/espflash/src/command.rs @@ -14,6 +14,7 @@ const ERASE_CHIP_TIMEOUT: Duration = Duration::from_secs(120); const MEM_END_TIMEOUT: Duration = Duration::from_millis(50); const SYNC_TIMEOUT: Duration = Duration::from_millis(100); const FLASH_DEFLATE_END_TIMEOUT: Duration = Duration::from_secs(10); +const FLASH_MD5_TIMEOUT: Duration = Duration::from_secs(8); /// Types of commands that can be sent to a target device #[derive(Copy, Clone, Debug, Display)] @@ -51,6 +52,7 @@ impl CommandType { CommandType::Sync => SYNC_TIMEOUT, CommandType::EraseFlash => ERASE_CHIP_TIMEOUT, CommandType::FlashDeflateEnd => FLASH_DEFLATE_END_TIMEOUT, + CommandType::FlashMd5 => FLASH_MD5_TIMEOUT, _ => DEFAULT_TIMEOUT, } } diff --git a/espflash/src/connection/mod.rs b/espflash/src/connection/mod.rs index ffb73040..ca76a9ba 100644 --- a/espflash/src/connection/mod.rs +++ b/espflash/src/connection/mod.rs @@ -225,7 +225,13 @@ impl Connection { // here is what esptool does: https://github.com/espressif/esptool/blob/master/esptool/loader.py#L458 // from esptool: things are a bit weird here, bear with us - // we rely on the known and expected response sizes + // we rely on the known and expected response sizes which should be fine for now - if that changes we need to pass the command type + // we are parsing the response for + // for most commands the response length is 10 (for the stub) or 12 (for ROM code) + // the MD5 command response is 44 for ROM loader, 26 for the stub + // see https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#response-packet + // see https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#status-bytes + // see https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#verifying-uploaded-data let status_len = if response.len() == 10 || response.len() == 26 { 2 } else { diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index f62d5b81..fe28f38e 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -891,11 +891,14 @@ impl Flasher { /// Get MD5 of region pub fn checksum_md5(&mut self, addr: u32, length: u32) -> Result { self.connection - .command(crate::command::Command::FlashMd5 { - offset: addr, - size: length, - })? - .try_into() + .with_timeout(CommandType::FlashMd5.timeout(), |connection| { + connection + .command(crate::command::Command::FlashMd5 { + offset: addr, + size: length, + })? + .try_into() + }) } /// Load an ELF image to flash and execute it