Skip to content

Commit be61f8a

Browse files
Add read-flash support (#558)
* feat: Standarize names and add missing commands * feat: Add missing commands and documentation * feat: Implement read_flash * feat: Add block_size and max_in_flight args * docs: Remove todos * feat: Only support read-flash when using stub * feat: Add read_flash support to cargo-espflash * docs: Update changelog
1 parent d7f800e commit be61f8a

File tree

9 files changed

+302
-74
lines changed

9 files changed

+302
-74
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323
- Add support for 26 MHz bootloader for ESP32 and ESP32-C2 (#553)
2424
- Add CI check to verify that CHANGELOG is updated (#560)
2525
- Add `--before` and `--after` reset arguments (#561)
26+
- Add `read-flash` command (#558)
2627

2728
### Fixed
2829

cargo-espflash/src/main.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use espflash::{
1010
cli::{
1111
self, board_info, checksum_md5, completions, config::Config, connect, erase_flash,
1212
erase_partitions, erase_region, flash_elf_image, monitor::monitor, partition_table,
13-
print_board_info, save_elf_as_image, serial_monitor, ChecksumMd5Args, CompletionsArgs,
14-
ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress, FlashConfigArgs,
15-
MonitorArgs, PartitionTableArgs,
13+
print_board_info, read_flash, save_elf_as_image, serial_monitor, ChecksumMd5Args,
14+
CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress,
15+
FlashConfigArgs, MonitorArgs, PartitionTableArgs, ReadFlashArgs,
1616
},
1717
error::Error as EspflashError,
1818
flasher::{parse_partition_table, FlashData, FlashSettings},
@@ -100,6 +100,8 @@ enum Commands {
100100
/// '--to-binary' options, plus the ability to print a partition table
101101
/// in tabular format.
102102
PartitionTable(PartitionTableArgs),
103+
/// Read SPI flash content
104+
ReadFlash(ReadFlashArgs),
103105
/// Generate a binary application image and save it to a local disk
104106
///
105107
/// If the '--merge' option is used, then the bootloader, partition table,
@@ -219,6 +221,7 @@ fn main() -> Result<()> {
219221
Commands::Flash(args) => flash(args, &config),
220222
Commands::Monitor(args) => serial_monitor(args, &config),
221223
Commands::PartitionTable(args) => partition_table(args),
224+
Commands::ReadFlash(args) => read_flash(args, &config),
222225
Commands::SaveImage(args) => save_image(args),
223226
Commands::ChecksumMd5(args) => checksum_md5(&args, &config),
224227
}
@@ -233,7 +236,7 @@ struct BuildContext {
233236

234237
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
235238
if args.connect_args.no_stub {
236-
return Err(EspflashError::StubRequiredToEraseFlash).into_diagnostic();
239+
return Err(EspflashError::StubRequired).into_diagnostic();
237240
}
238241

239242
let metadata_partition_table = PackageMetadata::load(&args.package)

espflash/src/bin/espflash.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use espflash::{
99
cli::{
1010
self, board_info, checksum_md5, completions, config::Config, connect, erase_flash,
1111
erase_partitions, erase_region, flash_elf_image, monitor::monitor, parse_uint32,
12-
partition_table, print_board_info, save_elf_as_image, serial_monitor, ChecksumMd5Args,
13-
CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs, EspflashProgress,
14-
FlashConfigArgs, MonitorArgs, PartitionTableArgs,
12+
partition_table, print_board_info, read_flash, save_elf_as_image, serial_monitor,
13+
ChecksumMd5Args, CompletionsArgs, ConnectArgs, EraseFlashArgs, EraseRegionArgs,
14+
EspflashProgress, FlashConfigArgs, MonitorArgs, PartitionTableArgs, ReadFlashArgs,
1515
},
1616
error::Error,
1717
flasher::{parse_partition_table, FlashData, FlashSettings},
@@ -75,6 +75,8 @@ enum Commands {
7575
/// '--to-binary' options, plus the ability to print a partition table
7676
/// in tabular format.
7777
PartitionTable(PartitionTableArgs),
78+
/// Read SPI flash content
79+
ReadFlash(ReadFlashArgs),
7880
/// Generate a binary application image and save it to a local disk
7981
///
8082
/// If the '--merge' option is used, then the bootloader, partition table,
@@ -178,14 +180,15 @@ fn main() -> Result<()> {
178180
Commands::Monitor(args) => serial_monitor(args, &config),
179181
Commands::PartitionTable(args) => partition_table(args),
180182
Commands::SaveImage(args) => save_image(args),
183+
Commands::ReadFlash(args) => read_flash(args, &config),
181184
Commands::WriteBin(args) => write_bin(args, &config),
182185
Commands::ChecksumMd5(args) => checksum_md5(&args, &config),
183186
}
184187
}
185188

186189
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
187190
if args.connect_args.no_stub {
188-
return Err(Error::StubRequiredToEraseFlash).into_diagnostic();
191+
return Err(Error::StubRequired.into());
189192
}
190193

191194
let mut flash = connect(&args.connect_args, config, false, false)?;

espflash/src/cli/mod.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,32 @@ pub struct PartitionTableArgs {
194194
to_csv: bool,
195195
}
196196

197+
/// Reads the content of flash memory and saves it to a file
198+
#[derive(Debug, Args)]
199+
#[non_exhaustive]
200+
pub struct ReadFlashArgs {
201+
/// Offset to start reading from
202+
#[arg(value_name = "OFFSET", value_parser = parse_uint32)]
203+
pub addr: u32,
204+
/// Size of each individual packet of data
205+
///
206+
/// Defaults to 0x1000 (FLASH_SECTOR_SIZE)
207+
#[arg(long, default_value = "0x1000", value_parser = parse_uint32)]
208+
pub block_size: u32,
209+
/// Connection configuration
210+
#[clap(flatten)]
211+
connect_args: ConnectArgs,
212+
/// Size of the region to erase
213+
#[arg(value_name = "SIZE", value_parser = parse_uint32)]
214+
pub size: u32,
215+
/// Name of binary dump
216+
#[arg(value_name = "FILE")]
217+
pub file: PathBuf,
218+
/// Maximum number of un-acked packets
219+
#[arg(long, default_value = "64", value_parser = parse_uint32)]
220+
pub max_in_flight: u32,
221+
}
222+
197223
/// Save the image to disk instead of flashing to device
198224
#[derive(Debug, Args)]
199225
#[non_exhaustive]
@@ -558,7 +584,7 @@ impl ProgressCallbacks for EspflashProgress {
558584

559585
pub fn erase_flash(args: EraseFlashArgs, config: &Config) -> Result<()> {
560586
if args.connect_args.no_stub {
561-
return Err(Error::StubRequiredToEraseFlash).into_diagnostic();
587+
return Err(Error::StubRequired.into());
562588
}
563589

564590
let mut flash = connect(&args.connect_args, config, true, true)?;
@@ -575,7 +601,7 @@ pub fn erase_flash(args: EraseFlashArgs, config: &Config) -> Result<()> {
575601

576602
pub fn erase_region(args: EraseRegionArgs, config: &Config) -> Result<()> {
577603
if args.connect_args.no_stub {
578-
return Err(Error::StubRequiredToEraseFlash).into_diagnostic();
604+
return Err(Error::StubRequired).into_diagnostic();
579605
}
580606

581607
let mut flash = connect(&args.connect_args, config, true, true)?;
@@ -677,6 +703,25 @@ fn erase_partition(flasher: &mut Flasher, part: &Partition) -> Result<()> {
677703
flasher.erase_region(offset, size).into_diagnostic()
678704
}
679705

706+
/// Read flash content and write it to a file
707+
pub fn read_flash(args: ReadFlashArgs, config: &Config) -> Result<()> {
708+
if args.connect_args.no_stub {
709+
return Err(Error::StubRequired.into());
710+
}
711+
712+
let mut flasher = connect(&args.connect_args, config, false, false)?;
713+
print_board_info(&mut flasher)?;
714+
flasher.read_flash(
715+
args.addr,
716+
args.size,
717+
args.block_size,
718+
args.max_in_flight,
719+
args.file,
720+
)?;
721+
722+
Ok(())
723+
}
724+
680725
/// Convert and display CSV and binary partition tables
681726
pub fn partition_table(args: PartitionTableArgs) -> Result<()> {
682727
if args.to_binary {

0 commit comments

Comments
 (0)