Skip to content

Commit

Permalink
Address PR comments. Add subcommands to cargo-espflash too.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnross committed Sep 24, 2023
1 parent 5a10de8 commit 8037dee
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 64 deletions.
2 changes: 1 addition & 1 deletion cargo-espflash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub enum Error {
#[error("No package could be located in the current workspace")]
#[diagnostic(
code(cargo_espflash::no_package),
help("Ensure that you are executing from a valid package, and that the specified package name\
help("Ensure that you are executing from a valid package, and that the specified package name \
exists in the current workspace.")
)]
NoPackage,
Expand Down
61 changes: 59 additions & 2 deletions cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{

use cargo_metadata::Message;
use clap::{Args, CommandFactory, Parser, Subcommand};
use espflash::cli::{erase_flash, erase_region, EraseFlashArgs, EraseRegionArgs};
use espflash::{
cli::{
self, board_info, completions, config::Config, connect, erase_partitions, flash_elf_image,
Expand All @@ -18,8 +19,8 @@ use espflash::{
targets::Chip,
update::check_for_update,
};
use log::{debug, LevelFilter};
use miette::{IntoDiagnostic, Result, WrapErr};
use log::{debug, info, LevelFilter};
use miette::{bail, IntoDiagnostic, Result, WrapErr};

use crate::{
cargo_config::CargoConfig,
Expand Down Expand Up @@ -66,6 +67,12 @@ enum Commands {
/// depending on which shell is being used; consult your shell's
/// documentation to determine the appropriate path.
Completions(CompletionsArgs),
/// Erase Flash entirely
EraseFlash(EraseFlashArgs),
/// Erase specified partitions
EraseParts(ErasePartsArgs),
/// Erase specified region
EraseRegion(EraseRegionArgs),
/// Flash an application in ELF format to a target device
///
/// First convert the ELF file produced by cargo into the appropriate
Expand Down Expand Up @@ -137,6 +144,26 @@ struct BuildArgs {
pub flash_config_args: FlashConfigArgs,
}

/// Erase named partitions based on provided partition table
#[derive(Debug, Args)]
pub struct ErasePartsArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,

/// Labels of the partitions to be erased
#[arg(value_name = "LABELS", value_delimiter = ',')]
pub erase_parts: Vec<String>,

/// Input partition table
#[arg(long, value_name = "FILE")]
pub partition_table: Option<PathBuf>,

/// Specify a (binary) package within a workspace which may provide a partition table
#[arg(long)]
pub package: Option<String>,
}

/// Build and flash an application to a target device
#[derive(Debug, Args)]
struct FlashArgs {
Expand Down Expand Up @@ -182,6 +209,9 @@ fn main() -> Result<()> {
match args {
Commands::BoardInfo(args) => board_info(&args, &config),
Commands::Completions(args) => completions(&args, &mut Cli::command(), "cargo"),
Commands::EraseFlash(args) => erase_flash(args, &config),
Commands::EraseParts(args) => erase_parts(args, &config),
Commands::EraseRegion(args) => erase_region(args, &config),
Commands::Flash(args) => flash(args, &config),
Commands::Monitor(args) => serial_monitor(args, &config),
Commands::PartitionTable(args) => partition_table(args),
Expand All @@ -196,6 +226,33 @@ struct BuildContext {
pub partition_table_path: Option<PathBuf>,
}

pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
bail!("Cannot erase flash without the RAM stub")
}

let metadata_partition_table = PackageMetadata::load(&args.package)
.ok()
.and_then(|m| m.partition_table);

let partition_table = args
.partition_table
.as_deref()
.or(metadata_partition_table.as_deref());

let mut flash = connect(&args.connect_args, config)?;
let partition_table = match partition_table {
Some(path) => Some(parse_partition_table(&path)?),
None => None,
};

info!("Erasing the following partitions: {:?}", args.erase_parts);
erase_partitions(&mut flash, partition_table, Some(args.erase_parts), None)?;
flash.connection().reset()?;

Ok(())
}

fn flash(args: FlashArgs, config: &Config) -> Result<()> {
let metadata = PackageMetadata::load(&args.build_args.package)?;
let cargo_config = CargoConfig::load(&metadata.workspace_root, &metadata.package_root);
Expand Down
76 changes: 18 additions & 58 deletions espflash/src/bin/espflash.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use std::{
fs::{self, File},
io::Read,
num::ParseIntError,
path::PathBuf,
};

use clap::{Args, CommandFactory, Parser, Subcommand};
use espflash::cli::{EraseFlashArgs, EraseRegionArgs};
use espflash::{
cli::{
self, board_info, completions, config::Config, connect, erase_partitions, flash_elf_image,
monitor::monitor, parse_partition_table, partition_table, print_board_info,
save_elf_as_image, serial_monitor, CompletionsArgs, ConnectArgs, 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, EspflashProgress, FlashConfigArgs, MonitorArgs, PartitionTableArgs,
},
image_format::ImageFormatKind,
logging::initialize_logger,
targets::Chip,
update::check_for_update,
};
use log::{debug, info, LevelFilter};
use miette::{IntoDiagnostic, Result, WrapErr};
use miette::{bail, IntoDiagnostic, Result, WrapErr};

#[derive(Debug, Parser)]
#[command(about, max_term_width = 100, propagate_version = true, version)]
Expand Down Expand Up @@ -84,43 +84,20 @@ enum Commands {
WriteBin(WriteBinArgs),
}

/// Erase entire flash of target device
#[derive(Debug, Args)]
pub struct EraseFlashArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,
}

/// Erase named partitions based on provided partition table
#[derive(Debug, Args)]
pub struct ErasePartsArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,

/// Labels of the partitions to be erased
#[arg(value_name = "LABELS", value_delimiter = ',')]
pub erase_parts: Vec<String>,

/// Input partition table
#[arg(long, value_name = "FILE")]
pub partition_table: PathBuf,
}

/// Erase specified region of flash
#[derive(Debug, Args)]
pub struct EraseRegionArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,

/// Offset to start erasing from
#[arg(value_name = "OFFSET", value_parser = parse_uint32)]
pub addr: u32,

/// Size of the region to erase
#[arg(value_name = "SIZE", value_parser = parse_uint32)]
pub size: u32,
pub partition_table: Option<PathBuf>,
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -166,11 +143,6 @@ struct WriteBinArgs {
connect_args: ConnectArgs,
}

/// Parses a string as a 32-bit unsigned integer.
fn parse_uint32(input: &str) -> Result<u32, ParseIntError> {
parse_int::parse(input)
}

fn main() -> Result<()> {
miette::set_panic_hook();
initialize_logger(LevelFilter::Info);
Expand Down Expand Up @@ -204,31 +176,19 @@ fn main() -> Result<()> {
}
}

fn erase_flash(args: EraseFlashArgs, config: &Config) -> Result<()> {
info!("Erasing Flash...");
let mut flash = connect(&args.connect_args, config)?;
flash.erase_flash()?;

Ok(())
}
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
bail!("Cannot erase flash without the RAM stub")
}

fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
let mut flash = connect(&args.connect_args, config)?;
let partition_table = parse_partition_table(&args.partition_table)?;
erase_partitions(
&mut flash,
Some(partition_table),
Some(args.erase_parts),
None,
)?;
flash.connection().reset()?;
let partition_table = match args.partition_table {
Some(path) => Some(parse_partition_table(&path)?),
None => None,
};

Ok(())
}

fn erase_region(args: EraseRegionArgs, config: &Config) -> Result<()> {
let mut flash = connect(&args.connect_args, config)?;
flash.erase_region(args.addr, args.size)?;
info!("Erasing the following partitions: {:?}", args.erase_parts);
erase_partitions(&mut flash, partition_table, Some(args.erase_parts), None)?;
flash.connection().reset()?;

Ok(())
Expand Down
64 changes: 63 additions & 1 deletion espflash/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! [cargo-espflash]: https://crates.io/crates/cargo-espflash
//! [espflash]: https://crates.io/crates/espflash

use std::num::ParseIntError;
use std::{
collections::HashMap,
fs,
Expand All @@ -20,7 +21,7 @@ use comfy_table::{modifiers, presets::UTF8_FULL, Attribute, Cell, Color, Table};
use esp_idf_part::{DataType, Partition, PartitionTable};
use indicatif::{style::ProgressStyle, HumanCount, ProgressBar};
use log::{debug, info};
use miette::{IntoDiagnostic, Result, WrapErr};
use miette::{bail, IntoDiagnostic, Result, WrapErr};
use serialport::{SerialPortType, UsbPortInfo};

use self::{config::Config, monitor::monitor, serial::get_serial_port_info};
Expand Down Expand Up @@ -67,6 +68,30 @@ pub struct CompletionsArgs {
pub shell: Shell,
}

/// Erase entire flash of target device
#[derive(Debug, Args)]
pub struct EraseFlashArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,
}

/// Erase specified region of flash
#[derive(Debug, Args)]
pub struct EraseRegionArgs {
/// Connection configuration
#[clap(flatten)]
pub connect_args: ConnectArgs,

/// Offset to start erasing from
#[arg(value_name = "OFFSET", value_parser = parse_uint32)]
pub addr: u32,

/// Size of the region to erase
#[arg(value_name = "SIZE", value_parser = parse_uint32)]
pub size: u32,
}

/// Configure communication with the target device's flash
#[derive(Debug, Args)]
pub struct FlashConfigArgs {
Expand Down Expand Up @@ -445,6 +470,38 @@ impl ProgressCallbacks for EspflashProgress {
}
}

pub fn erase_flash(args: EraseFlashArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
bail!("Cannot erase flash without the RAM stub")
}

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

info!("Erasing Flash...");
flash.erase_flash()?;

flash.connection().reset()?;

Ok(())
}

pub fn erase_region(args: EraseRegionArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
bail!("Cannot erase flash without the RAM stub")
}

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

info!(
"Erasing region at 0x{:08x} ({} bytes)",
args.addr, args.size
);
flash.erase_region(args.addr, args.size)?;
flash.connection().reset()?;

Ok(())
}

/// Write an ELF image to a target device's flash
pub fn flash_elf_image(
flasher: &mut Flasher,
Expand Down Expand Up @@ -637,3 +694,8 @@ fn pretty_print(table: PartitionTable) {

println!("{pretty}");
}

/// Parses a string as a 32-bit unsigned integer.
pub fn parse_uint32(input: &str) -> Result<u32, ParseIntError> {
parse_int::parse(input)
}
4 changes: 2 additions & 2 deletions espflash/src/flasher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,15 +865,15 @@ impl Flasher {
}

pub fn erase_flash(&mut self) -> Result<(), Error> {
debug!("Erasing the entire flash");

self.connection
.with_timeout(CommandType::EraseFlash.timeout(), |connection| {
connection.command(Command::EraseFlash)
})?;
sleep(Duration::from_secs_f32(0.05));
self.connection.flush()?;

self.connection.reset()?;

Ok(())
}

Expand Down

0 comments on commit 8037dee

Please sign in to comment.