Skip to content

Commit 77fd5b4

Browse files
Add min_chip_rev argument (#525)
* Verify the minimum supported chip revision when flashing * Allow specifying a minimum chip revision when saving an image * feat: Use value parser * docs: Update chip revision docstring * feat: Update default value of mon_chip_rev --------- Co-authored-by: Jesse Braham <[email protected]>
1 parent 2665054 commit 77fd5b4

File tree

16 files changed

+101
-1
lines changed

16 files changed

+101
-1
lines changed

cargo-espflash/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
259259
let cargo_config = CargoConfig::load(&metadata.workspace_root, &metadata.package_root);
260260

261261
let mut flasher = connect(&args.connect_args, config)?;
262+
flasher.verify_minimum_revision(args.flash_args.min_chip_rev)?;
262263

263264
// If the user has provided a flash size via a command-line argument, we'll
264265
// override the detected (or default) value with this.
@@ -329,6 +330,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
329330
args.build_args.flash_config_args.flash_size,
330331
args.build_args.flash_config_args.flash_freq,
331332
args.flash_args.partition_table_offset,
333+
args.flash_args.min_chip_rev,
332334
)?;
333335
}
334336

@@ -556,6 +558,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
556558

557559
save_elf_as_image(
558560
args.save_image_args.chip,
561+
args.save_image_args.min_chip_rev,
559562
&elf_data,
560563
args.save_image_args.file,
561564
args.format.or(metadata.format),

espflash/src/bin/espflash.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
199199

200200
fn flash(args: FlashArgs, config: &Config) -> Result<()> {
201201
let mut flasher = connect(&args.connect_args, config)?;
202+
flasher.verify_minimum_revision(args.flash_args.min_chip_rev)?;
202203

203204
// If the user has provided a flash size via a command-line argument, we'll
204205
// override the detected (or default) value with this.
@@ -253,6 +254,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
253254
args.flash_config_args.flash_size,
254255
args.flash_config_args.flash_freq,
255256
args.flash_args.partition_table_offset,
257+
args.flash_args.min_chip_rev,
256258
)?;
257259
}
258260

@@ -301,6 +303,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
301303

302304
save_elf_as_image(
303305
args.save_image_args.chip,
306+
args.save_image_args.min_chip_rev,
304307
&elf_data,
305308
args.save_image_args.file,
306309
args.format,

espflash/src/cli/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ pub struct FlashArgs {
142142
/// Logging format.
143143
#[arg(long, short = 'L', default_value = "serial", requires = "monitor")]
144144
pub log_format: LogFormat,
145+
/// Minimum chip revision supported by image, in format: major.minor
146+
#[arg(long, default_value = "0.0", value_parser = parse_chip_rev)]
147+
pub min_chip_rev: u16,
145148
/// Open a serial monitor after flashing
146149
#[arg(short = 'M', long)]
147150
pub monitor: bool,
@@ -193,6 +196,9 @@ pub struct SaveImageArgs {
193196
pub chip: Chip,
194197
/// File name to save the generated image to
195198
pub file: PathBuf,
199+
/// Minimum chip revision supported by image, in format: major.minor
200+
#[arg(long, default_value = "0.0", value_parser = parse_chip_rev)]
201+
pub min_chip_rev: u16,
196202
/// Boolean flag to merge binaries into single binary
197203
#[arg(long)]
198204
pub merge: bool,
@@ -285,6 +291,36 @@ pub fn completions(args: &CompletionsArgs, app: &mut clap::Command, bin_name: &s
285291
Ok(())
286292
}
287293

294+
/// Parses chip revision from string to major * 100 + minor format
295+
pub fn parse_chip_rev(chip_rev: &str) -> Result<u16> {
296+
let mut split = chip_rev.split('.');
297+
298+
let parse_or_error = |value: Option<&str>| {
299+
value
300+
.ok_or_else(|| Error::ParseChipRevError {
301+
chip_rev: chip_rev.to_string(),
302+
})
303+
.and_then(|v| {
304+
v.parse::<u16>().map_err(|_| Error::ParseChipRevError {
305+
chip_rev: chip_rev.to_string(),
306+
})
307+
})
308+
.into_diagnostic()
309+
};
310+
311+
let major = parse_or_error(split.next())?;
312+
let minor = parse_or_error(split.next())?;
313+
314+
if split.next().is_some() {
315+
return Err(Error::ParseChipRevError {
316+
chip_rev: chip_rev.to_string(),
317+
})
318+
.into_diagnostic();
319+
}
320+
321+
Ok(major * 100 + minor)
322+
}
323+
288324
/// Print information about a chip
289325
pub fn print_board_info(flasher: &mut Flasher) -> Result<()> {
290326
let info = flasher.device_info()?;
@@ -342,6 +378,7 @@ pub fn serial_monitor(args: MonitorArgs, config: &Config) -> Result<()> {
342378
/// Convert the provided firmware image from ELF to binary
343379
pub fn save_elf_as_image(
344380
chip: Chip,
381+
min_rev_full: u16,
345382
elf_data: &[u8],
346383
image_path: PathBuf,
347384
image_format: Option<ImageFormatKind>,
@@ -397,6 +434,7 @@ pub fn save_elf_as_image(
397434
target_app_partition,
398435
image_format,
399436
None,
437+
min_rev_full,
400438
flash_mode,
401439
flash_size,
402440
flash_freq,
@@ -439,6 +477,7 @@ pub fn save_elf_as_image(
439477
None,
440478
image_format,
441479
None,
480+
min_rev_full,
442481
flash_mode,
443482
flash_size,
444483
flash_freq,
@@ -557,6 +596,7 @@ pub fn flash_elf_image(
557596
flash_size: Option<FlashSize>,
558597
flash_freq: Option<FlashFrequency>,
559598
partition_table_offset: Option<u32>,
599+
min_rev_full: u16,
560600
) -> Result<()> {
561601
// If the '--bootloader' option is provided, load the binary file at the
562602
// specified path.
@@ -581,6 +621,7 @@ pub fn flash_elf_image(
581621
flash_size,
582622
flash_freq,
583623
partition_table_offset,
624+
min_rev_full,
584625
Some(&mut EspflashProgress::default()),
585626
)?;
586627
info!("Flashing has completed!");

espflash/src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ pub enum Error {
138138
frequency: FlashFrequency,
139139
},
140140

141+
#[error(
142+
"Minimum supported revision is {major}.{minor}, connected device's revision is {found_major}.{found_minor}"
143+
)]
144+
#[diagnostic(code(espflash::unsupported_chip_revision))]
145+
UnsupportedChipRevision {
146+
major: u16,
147+
minor: u16,
148+
found_major: u16,
149+
found_minor: u16,
150+
},
151+
152+
#[error("Failed to parse chip revision: {chip_rev}. Chip revision must be in the format `major.minor`")]
153+
#[diagnostic(code(espflash::cli::parse_chip_rev_error))]
154+
ParseChipRevError { chip_rev: String },
155+
141156
#[error("Error while connecting to device")]
142157
#[diagnostic(transparent)]
143158
Connection(#[source] ConnectionError),

espflash/src/flasher/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@ impl Flasher {
809809
flash_size: Option<FlashSize>,
810810
flash_freq: Option<FlashFrequency>,
811811
partition_table_offset: Option<u32>,
812+
min_rev_full: u16,
812813
mut progress: Option<&mut dyn ProgressCallbacks>,
813814
) -> Result<(), Error> {
814815
let image = ElfFirmwareImage::try_from(elf_data)?;
@@ -835,6 +836,7 @@ impl Flasher {
835836
target_app_partition,
836837
image_format,
837838
chip_revision,
839+
min_rev_full,
838840
flash_mode,
839841
flash_size.or(Some(self.flash_size)),
840842
flash_freq,
@@ -897,6 +899,7 @@ impl Flasher {
897899
flash_size: Option<FlashSize>,
898900
flash_freq: Option<FlashFrequency>,
899901
partition_table_offset: Option<u32>,
902+
min_rev_full: u16,
900903
progress: Option<&mut dyn ProgressCallbacks>,
901904
) -> Result<(), Error> {
902905
self.load_elf_to_flash_with_format(
@@ -909,6 +912,7 @@ impl Flasher {
909912
flash_size,
910913
flash_freq,
911914
partition_table_offset,
915+
min_rev_full,
912916
progress,
913917
)
914918
}
@@ -976,6 +980,21 @@ impl Flasher {
976980
Ok(())
977981
}
978982

983+
pub fn verify_minimum_revision(&mut self, minimum: u16) -> Result<(), Error> {
984+
let (major, minor) = self.chip.into_target().chip_revision(self.connection())?;
985+
let revision = (major * 100 + minor) as u16;
986+
if revision < minimum {
987+
return Err(Error::UnsupportedChipRevision {
988+
major: minimum / 100,
989+
minor: minimum % 100,
990+
found_major: revision / 100,
991+
found_minor: revision % 100,
992+
});
993+
}
994+
995+
Ok(())
996+
}
997+
979998
pub fn into_interface(self) -> Interface {
980999
self.connection.into_interface()
9811000
}

espflash/src/image_format/idf_bootloader.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl<'a> IdfBootloaderFormat<'a> {
3434
pub fn new(
3535
image: &'a dyn FirmwareImage<'a>,
3636
chip: Chip,
37+
min_rev_full: u16,
3738
params: Esp32Params,
3839
partition_table: Option<PartitionTable>,
3940
target_app_partition: Option<String>,
@@ -80,6 +81,7 @@ impl<'a> IdfBootloaderFormat<'a> {
8081

8182
header.wp_pin = WP_PIN_DISABLED;
8283
header.chip_id = params.chip_id;
84+
header.min_chip_rev_full = min_rev_full;
8385
header.append_digest = 1;
8486

8587
let mut data = bytes_of(&header).to_vec();
@@ -364,6 +366,7 @@ pub mod tests {
364366
let flash_image = IdfBootloaderFormat::new(
365367
&image,
366368
Chip::Esp32,
369+
0,
367370
PARAMS,
368371
None,
369372
None,

espflash/src/image_format/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ struct ImageHeader {
5656
gd_wp_drv: u8,
5757
chip_id: u16,
5858
min_rev: u8,
59-
/// Minimal chip revision supported by image, in format: major * 100 + minor
59+
/// Minimum chip revision supported by image, in format: major * 100 + minor
6060
min_chip_rev_full: u16,
6161
/// Maximal chip revision supported by image, in format: major * 100 + minor
6262
max_chip_rev_full: u16,

espflash/src/targets/esp32.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ impl Target for Esp32 {
158158
target_app_partition: Option<String>,
159159
image_format: Option<ImageFormatKind>,
160160
_chip_revision: Option<(u32, u32)>,
161+
min_rev_full: u16,
161162
flash_mode: Option<FlashMode>,
162163
flash_size: Option<FlashSize>,
163164
flash_freq: Option<FlashFrequency>,
@@ -169,6 +170,7 @@ impl Target for Esp32 {
169170
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
170171
image,
171172
Chip::Esp32,
173+
min_rev_full,
172174
PARAMS,
173175
partition_table,
174176
target_app_partition,

espflash/src/targets/esp32c2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ impl Target for Esp32c2 {
9292
target_app_partition: Option<String>,
9393
image_format: Option<ImageFormatKind>,
9494
_chip_revision: Option<(u32, u32)>,
95+
min_rev_full: u16,
9596
flash_mode: Option<FlashMode>,
9697
flash_size: Option<FlashSize>,
9798
flash_freq: Option<FlashFrequency>,
@@ -103,6 +104,7 @@ impl Target for Esp32c2 {
103104
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
104105
image,
105106
Chip::Esp32c2,
107+
min_rev_full,
106108
PARAMS,
107109
partition_table,
108110
target_app_partition,

espflash/src/targets/esp32c3.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl Target for Esp32c3 {
7979
target_app_partition: Option<String>,
8080
image_format: Option<ImageFormatKind>,
8181
chip_revision: Option<(u32, u32)>,
82+
min_rev_full: u16,
8283
flash_mode: Option<FlashMode>,
8384
flash_size: Option<FlashSize>,
8485
flash_freq: Option<FlashFrequency>,
@@ -90,6 +91,7 @@ impl Target for Esp32c3 {
9091
(ImageFormatKind::EspBootloader, _) => Ok(Box::new(IdfBootloaderFormat::new(
9192
image,
9293
Chip::Esp32c3,
94+
min_rev_full,
9395
PARAMS,
9496
partition_table,
9597
target_app_partition,

espflash/src/targets/esp32c6.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl Target for Esp32c6 {
7676
target_app_partition: Option<String>,
7777
image_format: Option<ImageFormatKind>,
7878
_chip_revision: Option<(u32, u32)>,
79+
min_rev_full: u16,
7980
flash_mode: Option<FlashMode>,
8081
flash_size: Option<FlashSize>,
8182
flash_freq: Option<FlashFrequency>,
@@ -87,6 +88,7 @@ impl Target for Esp32c6 {
8788
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
8889
image,
8990
Chip::Esp32c6,
91+
min_rev_full,
9092
PARAMS,
9193
partition_table,
9294
target_app_partition,

espflash/src/targets/esp32h2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ impl Target for Esp32h2 {
8484
target_app_partition: Option<String>,
8585
image_format: Option<ImageFormatKind>,
8686
_chip_revision: Option<(u32, u32)>,
87+
min_rev_full: u16,
8788
flash_mode: Option<FlashMode>,
8889
flash_size: Option<FlashSize>,
8990
flash_freq: Option<FlashFrequency>,
@@ -95,6 +96,7 @@ impl Target for Esp32h2 {
9596
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
9697
image,
9798
Chip::Esp32h2,
99+
min_rev_full,
98100
PARAMS,
99101
partition_table,
100102
target_app_partition,

espflash/src/targets/esp32s2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl Target for Esp32s2 {
144144
target_app_partition: Option<String>,
145145
image_format: Option<ImageFormatKind>,
146146
_chip_revision: Option<(u32, u32)>,
147+
min_rev_full: u16,
147148
flash_mode: Option<FlashMode>,
148149
flash_size: Option<FlashSize>,
149150
flash_freq: Option<FlashFrequency>,
@@ -155,6 +156,7 @@ impl Target for Esp32s2 {
155156
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
156157
image,
157158
Chip::Esp32s2,
159+
min_rev_full,
158160
PARAMS,
159161
partition_table,
160162
target_app_partition,

espflash/src/targets/esp32s3.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ impl Target for Esp32s3 {
9898
target_app_partition: Option<String>,
9999
image_format: Option<ImageFormatKind>,
100100
_chip_revision: Option<(u32, u32)>,
101+
min_rev_full: u16,
101102
flash_mode: Option<FlashMode>,
102103
flash_size: Option<FlashSize>,
103104
flash_freq: Option<FlashFrequency>,
@@ -109,6 +110,7 @@ impl Target for Esp32s3 {
109110
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
110111
image,
111112
Chip::Esp32s3,
113+
min_rev_full,
112114
PARAMS,
113115
partition_table,
114116
target_app_partition,

espflash/src/targets/esp8266.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ impl Target for Esp8266 {
7878
_target_app_partition: Option<String>,
7979
image_format: Option<ImageFormatKind>,
8080
_chip_revision: Option<(u32, u32)>,
81+
_min_rev_full: u16,
8182
flash_mode: Option<FlashMode>,
8283
flash_size: Option<FlashSize>,
8384
flash_freq: Option<FlashFrequency>,

espflash/src/targets/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ pub trait Target: ReadEFuse {
300300
target_app_partition: Option<String>,
301301
image_format: Option<ImageFormatKind>,
302302
chip_revision: Option<(u32, u32)>,
303+
min_rev_full: u16,
303304
flash_mode: Option<FlashMode>,
304305
flash_size: Option<FlashSize>,
305306
flash_freq: Option<FlashFrequency>,

0 commit comments

Comments
 (0)