Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify configuration methods #551

Merged
merged 12 commits into from
Feb 2, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Created `FlashData`, `FlashDataBuilder` and `FlashSettings` structs to reduce number of input arguments in some functions (#512, #566)
- `espflash` will now exit with an error if `defmt` is selected but not usable (#524)
- Unify configuration methods (#551)

### Removed

Expand Down
78 changes: 41 additions & 37 deletions cargo-espflash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-P4**, **ESP32-
- [Permissions on Linux](#permissions-on-linux)
- [Windows Subsystem for Linux](#windows-subsystem-for-linux)
- [Bootloader and Partition Table](#bootloader-and-partition-table)
- [Package Metadata](#package-metadata)
- [Configuration File](#configuration-file)
- [Configuration Examples](#configuration-examples)
- [Configuration precedence](#configuration-precedence)
- [Logging Format](#logging-format)
- [License](#license)
- [Contribution](#contribution)
Expand Down Expand Up @@ -83,7 +82,9 @@ Commands:
flash Flash an application in ELF format to a target device
monitor Open the serial monitor without flashing the connected target device
partition-table Convert partition tables between CSV and binary format
read-flash Read SPI flash content
save-image Generate a binary application image and save it to a local disk
checksum-md5 Calculate the MD5 checksum of the given region
help Print this message or the help of the given subcommand(s)

Options:
Expand Down Expand Up @@ -113,43 +114,46 @@ If the `--bootloader` and/or `--partition-table` options are provided then these

[esp-idf-sys]: https://github.com/esp-rs/esp-idf-sys

## Package Metadata

You're able to specify paths to bootloader and partition table files and image format in your package's Cargo metadata for per-project configuration:

```toml
[package.metadata.espflash]
bootloader = "bootloader.bin" # Must be a binary file
partition_table = "partitions.csv" # Supports CSV and binary formats
format = "direct-boot" # Can be 'esp-bootloader' or 'direct-boot'
```

## Configuration File

It's possible to specify a serial port and/or USB VID/PID values by setting them in a configuration file. The location of this file differs based on your operating system:

| Operating System | Configuration Path |
| :--------------- | :---------------------------------------------------------------- |
| Linux | `$HOME/.config/espflash/espflash.toml` |
| macOS | `$HOME/Library/Application Support/rs.esp.espflash/espflash.toml` |
| Windows | `%APPDATA%\esp\espflash\espflash.toml` |

### Configuration Examples

You can either configure the serial port name like so:

```
[connection]
serial = "/dev/ttyUSB0"
```

Or specify one or more USB `vid`/`pid` couple:

```
[[usb_device]]
vid = "303a"
pid = "1001"
```
The configuration file allows you to define various parameters for your application:
- Serial port:
- By name:
```toml
[connection]
serial = "/dev/ttyUSB0"
```
- By USB VID/PID values:
```toml
[[usb_device]]
vid = "303a"
pid = "1001"
```
- Baudrate:
```toml
baudrate = 460800
```
- Bootloader:
```toml
bootloader = "path/to/custom/bootloader.bin"
```
- Partition table
```toml
partition_table = "path/to/custom/partition-table.bin"
```

You can have a local and/or a global configuration file:
- For local configurations, store the file under the current working directory with the name `espflash.toml`
- Global file location differs based on your operating system:
- Linux: `$HOME/.config/espflash/espflash.toml`
- macOS: `$HOME/Library/Application Support/rs.esp.espflash/espflash.toml`
- Windows: `%APPDATA%\esp\espflash\espflash.toml`

### Configuration precedence

1. Environment variables: If `ESPFLASH_PORT` or `ESPFLASH_BAUD` are set, the will be used instead of the config file value.
2. Local configuration file
3. Global configuration file

## Logging Format

Expand Down
8 changes: 0 additions & 8 deletions cargo-espflash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ use thiserror::Error;
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
pub enum Error {
#[error("Specified bootloader path is not a .bin file")]
#[diagnostic(code(cargo_espflash::invalid_bootloader_path))]
InvalidBootloaderPath,

#[error("Specified partition table path is not a .bin or .csv file")]
#[diagnostic(code(cargo_espflash::invalid_partition_table_path))]
InvalidPartitionTablePath,

#[error("The current workspace is invalid, and could not be loaded")]
#[diagnostic(
code(cargo_espflash::invalid_workspace),
Expand Down
22 changes: 9 additions & 13 deletions cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ fn main() -> Result<()> {
Commands::Monitor(args) => serial_monitor(args, &config),
Commands::PartitionTable(args) => partition_table(args),
Commands::ReadFlash(args) => read_flash(args, &config),
Commands::SaveImage(args) => save_image(args),
Commands::SaveImage(args) => save_image(args, &config),
Commands::ChecksumMd5(args) => checksum_md5(&args, &config),
}
}
Expand All @@ -239,14 +239,10 @@ pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
return Err(EspflashError::StubRequired).into_diagnostic();
}

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());
.or(config.partition_table.as_deref());

let mut flash = connect(&args.connect_args, config, false, false)?;
let partition_table = match partition_table {
Expand Down Expand Up @@ -303,14 +299,14 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
.flash_args
.bootloader
.as_deref()
.or(metadata.bootloader.as_deref())
.or(config.bootloader.as_deref())
.or(build_ctx.bootloader_path.as_deref());

let partition_table = args
.flash_args
.partition_table
.as_deref()
.or(metadata.partition_table.as_deref())
.or(config.partition_table.as_deref())
.or(build_ctx.partition_table_path.as_deref());

if let Some(path) = &bootloader {
Expand All @@ -330,7 +326,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
bootloader,
partition_table,
args.flash_args.partition_table_offset,
args.flash_args.format.or(metadata.format),
args.flash_args.format,
args.flash_args.target_app_partition,
flash_settings,
args.flash_args.min_chip_rev,
Expand Down Expand Up @@ -534,7 +530,7 @@ fn build(
Ok(build_ctx)
}

fn save_image(args: SaveImageArgs) -> Result<()> {
fn save_image(args: SaveImageArgs, config: &Config) -> Result<()> {
let metadata = PackageMetadata::load(&args.build_args.package)?;
let cargo_config = CargoConfig::load(&metadata.workspace_root, &metadata.package_root);

Expand All @@ -545,15 +541,15 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
.save_image_args
.bootloader
.as_deref()
.or(metadata.bootloader.as_deref())
.or(config.bootloader.as_deref())
.or(build_ctx.bootloader_path.as_deref())
.map(|p| p.to_path_buf());

let partition_table = args
.save_image_args
.partition_table
.as_deref()
.or(metadata.partition_table.as_deref())
.or(config.partition_table.as_deref())
.or(build_ctx.partition_table_path.as_deref())
.map(|p| p.to_path_buf());

Expand Down Expand Up @@ -582,7 +578,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
bootloader.as_deref(),
partition_table.as_deref(),
args.save_image_args.partition_table_offset,
args.format.or(metadata.format),
args.format,
args.save_image_args.target_app_partition,
flash_settings,
args.save_image_args.min_chip_rev,
Expand Down
45 changes: 2 additions & 43 deletions cargo-espflash/src/package_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::{ffi::OsStr, path::PathBuf, str::FromStr};
use std::path::PathBuf;

use cargo::{
core::{Package, Workspace},
util::Config,
};
use espflash::image_format::ImageFormatKind;
use miette::{IntoDiagnostic, Result};
use serde::Deserialize;

Expand All @@ -14,9 +13,6 @@ use crate::error::Error;
pub struct PackageMetadata {
pub workspace_root: PathBuf,
pub package_root: PathBuf,
pub bootloader: Option<PathBuf>,
pub format: Option<ImageFormatKind>,
pub partition_table: Option<PathBuf>,
}

impl PackageMetadata {
Expand All @@ -37,19 +33,6 @@ impl PackageMetadata {
let package = Self::load_package(&workspace, package_name)?;
let metadata = Self::load_metadata(&workspace, &package)?;

if let Some(table) = &metadata.partition_table {
match table.extension() {
Some(ext) if ext == "bin" || ext == "csv" => {}
_ => return Err(Error::InvalidPartitionTablePath.into()),
}
}

if let Some(bootloader) = &metadata.bootloader {
if bootloader.extension() != Some(OsStr::new("bin")) {
return Err(Error::InvalidBootloaderPath.into());
}
}

Ok(metadata)
}

Expand All @@ -72,35 +55,11 @@ impl PackageMetadata {
}

fn load_metadata(workspace: &Workspace, package: &Package) -> Result<PackageMetadata> {
let mut espflash_meta = PackageMetadata {
let espflash_meta = PackageMetadata {
workspace_root: workspace.root_manifest().parent().unwrap().to_path_buf(),
package_root: package.root().to_path_buf(),

..PackageMetadata::default()
};

match package.manifest().custom_metadata() {
Some(meta) if meta.is_table() => match meta.as_table().unwrap().get("espflash") {
Some(meta) if meta.is_table() => {
let meta = meta.as_table().unwrap();

espflash_meta.bootloader = meta
.get("bootloader")
.map(|bl| package.root().join(bl.as_str().unwrap()));

espflash_meta.format = meta
.get("format")
.map(|fmt| ImageFormatKind::from_str(fmt.as_str().unwrap()).unwrap());

espflash_meta.partition_table = meta
.get("partition_table")
.map(|pt| package.root().join(pt.as_str().unwrap()));
}
_ => {}
},
_ => {}
}

Ok(espflash_meta)
}
}
66 changes: 41 additions & 25 deletions espflash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-P4**,**ESP32-S
- [Cargo Runner](#cargo-runner)
- [Using `espflash` as a Library](#using-espflash-as-a-library)
- [Configuration File](#configuration-file)
- [Configuration Examples](#configuration-examples)
- [Configuration precedence](#configuration-precedence)
- [Logging Format](#logging-format)
- [License](#license)
- [Contribution](#contribution)
Expand Down Expand Up @@ -78,8 +78,10 @@ Commands:
flash Flash an application in ELF format to a connected target device
monitor Open the serial monitor without flashing the connected target device
partition-table Convert partition tables between CSV and binary format
read-flash Read SPI flash content
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
checksum-md5 Calculate the MD5 checksum of the given region
help Print this message or the help of the given subcommand(s)

Options:
Expand Down Expand Up @@ -133,30 +135,44 @@ espflash = { version = "2.1", default-features = false, features = ["raspberry"]

## Configuration File

It's possible to specify a serial port and/or USB VID/PID values by setting them in a configuration file. The location of this file differs based on your operating system:

| Operating System | Configuration Path |
| :--------------- | :---------------------------------------------------------------- |
| Linux | `$HOME/.config/espflash/espflash.toml` |
| macOS | `$HOME/Library/Application Support/rs.esp.espflash/espflash.toml` |
| Windows | `%APPDATA%\esp\espflash\espflash.toml` |

### Configuration Examples

You can either configure the serial port name like so:

```
[connection]
serial = "/dev/ttyUSB0"
```

Or specify one or more USB `vid`/`pid` couple:

```
[[usb_device]]
vid = "303a"
pid = "1001"
```
The configuration file allows you to define various parameters for your application:
- Serial port:
- By name:
```toml
[connection]
serial = "/dev/ttyUSB0"
```
- By USB VID/PID values:
```toml
[[usb_device]]
vid = "303a"
pid = "1001"
```
- Baudrate:
```toml
baudrate = 460800
```
- Bootloader:
```toml
bootloader = "path/to/custom/bootloader.bin"
```
- Partition table
```toml
partition_table = "path/to/custom/partition-table.bin"
```

You can have a local and/or a global configuration file:
- For local configurations, store the file under the current working directory with the name `espflash.toml`
- Global file location differs based on your operating system:
- Linux: `$HOME/.config/espflash/espflash.toml`
- macOS: `$HOME/Library/Application Support/rs.esp.espflash/espflash.toml`
- Windows: `%APPDATA%\esp\espflash\espflash.toml`

### Configuration precedence

1. Environment variables: If `ESPFLASH_PORT` or `ESPFLASH_BAUD` are set, the will be used instead of the config file value.
2. Local configuration file
3. Global configuration file

## Logging Format

Expand Down
Loading
Loading