Skip to content

Commit

Permalink
[cargo-espflash]: Add write-bin subcommand (#789)
Browse files Browse the repository at this point in the history
* feat: Add write-bin subcommand

* docs: Update changelog

* docs: Add docstring
  • Loading branch information
SergioGasquez authored Feb 27, 2025
1 parent e41be4f commit 1b23853
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `no-reset` flag to `monitor` subcommands (#737)
- Add an environment variable to set monitoring baudrate (`MONITOR_BAUD`) (#737)
- Add list-ports command to list available serial ports. (#761)
- [cargo-espflash]: Add `write-bin` subcommand (#789)

### Changed

Expand Down
1 change: 1 addition & 0 deletions cargo-espflash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Commands:
read-flash Read SPI flash content
reset Reset the target device
save-image Generate a binary application image and save it to a local disk
write-bin Write a binary file to a specific address in a target device's flash
help Print this message or the help of the given subcommand(s)
Options:
Expand Down
3 changes: 3 additions & 0 deletions cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ enum Commands {
/// Otherwise, each segment will be saved as individual binaries, prefixed
/// with their intended addresses in flash.
SaveImage(SaveImageArgs),
/// Write a binary file to a specific address in a target device's flash
WriteBin(WriteBinArgs),
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -240,6 +242,7 @@ fn main() -> Result<()> {
Commands::ReadFlash(args) => read_flash(args, &config),
Commands::Reset(args) => reset(args, &config),
Commands::SaveImage(args) => save_image(args, &config),
Commands::WriteBin(args) => write_bin(args, &config),
}
}

Expand Down
45 changes: 1 addition & 44 deletions espflash/src/bin/espflash.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::{
fs::{self, File},
io::Read,
path::PathBuf,
};
use std::{fs, path::PathBuf};

use clap::{Args, CommandFactory, Parser, Subcommand};
use espflash::{
Expand Down Expand Up @@ -140,20 +136,6 @@ struct SaveImageArgs {
save_image_args: cli::SaveImageArgs,
}

/// Writes a binary file to a specific address in the chip's flash
#[derive(Debug, Args)]
#[non_exhaustive]
struct WriteBinArgs {
/// Address at which to write the binary file
#[arg(value_parser = parse_u32)]
pub address: u32,
/// File containing the binary data to write
pub file: String,
/// Connection configuration
#[clap(flatten)]
connect_args: ConnectArgs,
}

fn main() -> Result<()> {
miette::set_panic_hook();
initialize_logger(LevelFilter::Info);
Expand Down Expand Up @@ -341,28 +323,3 @@ fn save_image(args: SaveImageArgs, config: &Config) -> Result<()> {

Ok(())
}

fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> {
let mut flasher = connect(&args.connect_args, config, false, false)?;
print_board_info(&mut flasher)?;

let mut f = File::open(&args.file).into_diagnostic()?;

// If the file size is not divisible by 4, we need to pad `FF` bytes to the end
let size = f.metadata().into_diagnostic()?.len();
let mut padded_bytes = 0;
if size % 4 != 0 {
padded_bytes = 4 - (size % 4);
}
let mut buffer = Vec::with_capacity(size.try_into().into_diagnostic()?);
f.read_to_end(&mut buffer).into_diagnostic()?;
buffer.extend(std::iter::repeat(0xFF).take(padded_bytes as usize));

flasher.write_bin_to_flash(
args.address,
&buffer,
Some(&mut EspflashProgress::default()),
)?;

Ok(())
}
44 changes: 42 additions & 2 deletions espflash/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
use std::{
collections::HashMap,
fs,
io::Write,
fs::{self, File},
io::{Read, Write},
num::ParseIntError,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -315,6 +315,20 @@ pub struct ListPortsArgs {
pub name_only: bool,
}

/// Writes a binary file to a specific address in the chip's flash
#[derive(Debug, Args)]
#[non_exhaustive]
pub struct WriteBinArgs {
/// Address at which to write the binary file
#[arg(value_parser = parse_u32)]
pub address: u32,
/// File containing the binary data to write
pub file: String,
/// Connection configuration
#[clap(flatten)]
connect_args: ConnectArgs,
}

/// Parses an integer, in base-10 or hexadecimal format, into a [u32]
pub fn parse_u32(input: &str) -> Result<u32, ParseIntError> {
let input: &str = &input.replace('_', "");
Expand Down Expand Up @@ -972,6 +986,32 @@ pub fn make_flash_data(
)
}

/// Write a binary to the flash memory of a target device
pub fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> {
let mut flasher = connect(&args.connect_args, config, false, false)?;
print_board_info(&mut flasher)?;

let mut f = File::open(&args.file).into_diagnostic()?;

// If the file size is not divisible by 4, we need to pad `FF` bytes to the end
let size = f.metadata().into_diagnostic()?.len();
let mut padded_bytes = 0;
if size % 4 != 0 {
padded_bytes = 4 - (size % 4);
}
let mut buffer = Vec::with_capacity(size.try_into().into_diagnostic()?);
f.read_to_end(&mut buffer).into_diagnostic()?;
buffer.extend(std::iter::repeat(0xFF).take(padded_bytes as usize));

flasher.write_bin_to_flash(
args.address,
&buffer,
Some(&mut EspflashProgress::default()),
)?;

Ok(())
}

mod test {
use clap::Parser;

Expand Down

0 comments on commit 1b23853

Please sign in to comment.