Improve docs (#899)

* feat: Make try_from private

* docs: Improve docs

* feat: Make erase_parts private

* docs: Improve docs

* docs: Fix typos
This commit is contained in:
Sergio Gasquez Arcos 2025-06-20 16:08:23 +02:00 committed by GitHub
parent 61e5032d92
commit f12ecf363d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 179 additions and 49 deletions

View File

@ -17,10 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `--monitor` option to `write-bin`. (#783)
- Add `watchdog-reset` strategy to `--after` subcommand (#779)
- Add `ROM` version of `read-flash` command (#812)
- `espflash` can detect the log format automatically from ESP-HAL metadata. Reqires `esp-println` 0.14 (presumably, yet to be released) (#809)
- `espflash` can detect the log format automatically from ESP-HAL metadata. Requires `esp-println` 0.14 (presumably, yet to be released) (#809)
- Add `--output-format` option to monitor (#818)
- Added chip detection based on security info, where supported (#814)
- `espflash` can detect the chip from ESP-HAL metadata to prevent flashing firmware built for a different device. Reqires `esp-hal` 1.0.0-beta.0 (presumably, yet to be released) (#816)
- `espflash` can detect the chip from ESP-HAL metadata to prevent flashing firmware built for a different device. Requires `esp-hal` 1.0.0-beta.0 (presumably, yet to be released) (#816)
- `espflash` no longer allows flashing a too-big partition table (#830)
- Allow specifying a partition label for `write-bin`, add `--partition-table`. (#828)
- `--mmu-page-size` parameter for `flash` and `save-image` (#835)
@ -28,13 +28,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add support for the ESP32-C5 (#863)
- `--after` options now work with `espflash board-info`, `espflash read-flash` and `espflash checksum-md5` (#867)
- Add support for serial port configuration files. (#777, #883)
- Add a `check-app-descriptor` bool option to `ImageArgs` and add the flag to `flash` commad(#872)
- Add a `check-app-descriptor` bool option to `ImageArgs` and add the flag to `flash` command (#872)
- `Connection::into_serial` to get the underlying port from the connection (#882)
- All methods on the now removed `Target` & `ReadEFuse`, `UsbOtg` and `RtcWdtReset` traits have been implemented directly on (#891)
### Changed
- Split the baudrate for connecting and monitorinig in `flash` subcommand (#737)
- Split the baudrate for connecting and monitoring in `flash` subcommand (#737)
- Normalized arguments of the CLI commands (#759)
- `board-info` now prints `Security information`. (#758)
- The `command`, `elf` and `error` modules are no longer public (#772)
@ -72,7 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix `read-flash` which didn't work with some lengths (#804)
- espflash can now flash an ESP32-S2 in download mode over USB (#813)
- Fixed a case where esplash transformed the firmware elf in a way that made it unbootable (#831)
- The app descriptor is now correctly placed in the front of the bianry (#835)
- The app descriptor is now correctly placed in the front of the binary (#835)
- espflash now extracts the MMU page size from the app descriptor (#835)
- `ResetBeforeOperation` & `ResetAfterOperation` are now public, to allow the creation of a `Connection` (#895)

View File

@ -8,6 +8,7 @@ use serde::Deserialize;
use crate::error::TomlError;
/// Unstable features.
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Unstable {
@ -15,11 +16,13 @@ pub struct Unstable {
build_std: Vec<String>,
}
/// Build configuration extracted from `.cargo/config.toml`.
#[derive(Debug, Default, Deserialize)]
pub struct Build {
target: Option<String>,
}
/// Representation of a Cargo configuration extracted from `.cargo/config.toml`.
#[derive(Debug, Deserialize, Default)]
pub struct CargoConfig {
#[serde(default)]
@ -29,6 +32,8 @@ pub struct CargoConfig {
}
impl CargoConfig {
/// Load and merge Cargo configuration from the workspace and/or package
/// level.
pub fn load(workspace_root: &Path, package_root: &Path) -> Self {
// If there is a Cargo configuration file in the current package, we will
// deserialize and return it.
@ -44,10 +49,12 @@ impl CargoConfig {
}
}
/// Returns if the build has unstable `build-std` feature enabled.
pub fn has_build_std(&self) -> bool {
!self.unstable.build_std.is_empty()
}
/// Returns the build `target` specified in the configuration, if any.
pub fn target(&self) -> Option<&str> {
self.build.target.as_deref()
}

View File

@ -7,6 +7,7 @@ use espflash::target::Chip;
use miette::{Diagnostic, LabeledSpan, SourceCode};
use thiserror::Error;
/// Error type returned by `cargo-espflash`.
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
pub enum Error {
@ -64,6 +65,7 @@ pub struct TomlError {
}
impl TomlError {
/// Create a new [`TomlError`] from the raw `toml`.
pub fn new(err: toml::de::Error, source: String) -> Self {
Self { err, source }
}
@ -104,6 +106,7 @@ pub struct UnsupportedTargetError {
}
impl UnsupportedTargetError {
/// Construct a new [`UnsupportedTargetError`].
pub fn new(target: &str, chip: Chip) -> Self {
Self {
target: target.into(),
@ -124,6 +127,7 @@ pub struct NoTargetError {
}
impl NoTargetError {
/// Create a new [`NoTargetError`].
pub fn new(chip: Option<Chip>) -> Self {
Self { chip }
}

View File

@ -94,7 +94,7 @@ enum Commands {
/// Please refer to the ESP-IDF documentation for more information on the
/// binary image format:
///
/// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html
/// <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html>
Flash(FlashArgs),
/// Hold the target device in reset
HoldInReset(ConnectArgs),
@ -110,7 +110,7 @@ enum Commands {
/// Uses the ESP-IDF format for partition tables; please refer to the
/// ESP-IDF documentation for more information on this format:
///
/// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html
/// <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html>
///
/// Allows for conversion between formats via the '--to-csv' and
/// '--to-binary' options, plus the ability to print a partition table
@ -229,7 +229,7 @@ fn main() -> Result<()> {
miette::set_panic_hook();
initialize_logger(LevelFilter::Info);
// Attempt to parse any provided comand-line arguments, or print the help
// Attempt to parse any provided command-line arguments, or print the help
// message and terminate if the invocation is not correct.
let cli = Cli::parse();
let CargoSubcommand::Espflash {
@ -276,7 +276,7 @@ struct BuildContext {
pub partition_table_path: Option<PathBuf>,
}
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
return Err(EspflashError::StubRequired).into_diagnostic();
}

View File

@ -6,13 +6,18 @@ use serde::Deserialize;
use crate::error::Error;
/// Package metadata.
#[derive(Debug, Default, Clone, Deserialize)]
pub struct PackageMetadata {
/// Path to the root of the Cargo workspace the package belongs to.
pub workspace_root: PathBuf,
/// Path to the directory that contains the `Cargo.toml` for the
/// selected package.
pub package_root: PathBuf,
}
impl PackageMetadata {
/// Load package metadata.
pub fn load(package_name: &Option<String>) -> Result<Self> {
// There MUST be a cargo manifest in the executing directory, regardless of
// whether or not we are in a workspace.

View File

@ -22,6 +22,7 @@ use espflash::{
use log::{LevelFilter, debug, info};
use miette::{IntoDiagnostic, Result, WrapErr};
/// Main CLI parser.
#[derive(Debug, Parser)]
#[command(about, max_term_width = 100, propagate_version = true, version)]
pub struct Cli {
@ -65,7 +66,7 @@ enum Commands {
/// Please refer to the ESP-IDF documentation for more information on the
/// binary image format:
///
/// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html
/// <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html>
Flash(FlashArgs),
/// Hold the target device in reset
HoldInReset(ConnectArgs),
@ -81,7 +82,7 @@ enum Commands {
/// Uses the ESP-IDF format for partition tables; please refer to the
/// ESP-IDF documentation for more information on this format:
///
/// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html
/// <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html>
///
/// Allows for conversion between formats via the '--to-csv' and
/// '--to-binary' options, plus the ability to print a partition table
@ -200,7 +201,7 @@ fn main() -> Result<()> {
}
}
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
if args.connect_args.no_stub {
return Err(Error::StubRequired.into());
}

View File

@ -339,6 +339,7 @@ pub struct ChecksumMd5Args {
connect_args: ConnectArgs,
}
/// List the available serial ports.
#[derive(Debug, Args)]
#[non_exhaustive]
pub struct ListPortsArgs {
@ -490,6 +491,7 @@ pub fn checksum_md5(args: &ChecksumMd5Args, config: &Config) -> Result<()> {
Ok(())
}
/// List the available serial ports.
pub fn list_ports(args: &ListPortsArgs, config: &PortConfig) -> Result<()> {
let mut ports: Vec<SerialPortInfo> = serial::detect_usb_serial_ports(true)?
.into_iter()
@ -1141,6 +1143,7 @@ pub fn write_bin(args: WriteBinArgs, config: &Config) -> Result<()> {
Ok(())
}
/// Reset the target device.
pub fn reset(args: ConnectArgs, config: &Config) -> Result<()> {
let mut args = args.clone();
args.no_stub = true;
@ -1151,6 +1154,7 @@ pub fn reset(args: ConnectArgs, config: &Config) -> Result<()> {
Ok(())
}
/// Hold the target device in reset.
pub fn hold_in_reset(args: ConnectArgs, config: &Config) -> Result<()> {
connect(&args, config, true, true)?;
info!("Holding target device in reset");
@ -1158,6 +1162,7 @@ pub fn hold_in_reset(args: ConnectArgs, config: &Config) -> Result<()> {
Ok(())
}
/// Ensures the chip is compatible with the ELF file.
pub fn ensure_chip_compatibility(chip: Chip, elf: Option<&[u8]>) -> Result<()> {
let metadata = Metadata::from_bytes(elf);
let Some(elf_chip) = metadata.chip_name() else {

View File

@ -262,6 +262,7 @@ fn handle_key_event(key_event: KeyEvent) -> Option<Vec<u8>> {
key_str.map(|slice| slice.into())
}
/// Checks the monitor arguments and emits warnings if they are invalid.
pub fn check_monitor_args(monitor: &bool, monitor_args: &MonitorConfigArgs) -> Result<()> {
// Check if any monitor args are provided but monitor flag isn't set
if !monitor

View File

@ -203,6 +203,7 @@ impl DefmtData {
}
}
/// A parser for defmt-encoded data.
pub struct EspDefmt {
delimiter: FrameDelimiter,
defmt_data: DefmtData,
@ -215,6 +216,7 @@ impl std::fmt::Debug for EspDefmt {
}
impl EspDefmt {
/// Creates a new `EspDefmt` parser.
pub fn new(elf: Option<&[u8]>, output_format: Option<String>) -> Result<Self> {
DefmtData::load(elf, output_format).map(|defmt_data| Self {
delimiter: FrameDelimiter::new(),

View File

@ -13,6 +13,7 @@ pub mod serial;
/// Trait for parsing input data.
pub trait InputParser {
/// Feeds the parser with new data.
fn feed(&mut self, bytes: &[u8], out: &mut dyn Write);
}

View File

@ -26,7 +26,7 @@ const SYNC_FRAME: [u8; 36] = [
/// Types of commands that can be sent to a target device
///
/// https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/serial-protocol.html#supported-by-stub-loader-and-rom-loader
/// <https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/serial-protocol.html#supported-by-stub-loader-and-rom-loader>
#[derive(Copy, Clone, Debug, Display)]
#[non_exhaustive]
#[repr(u8)]
@ -50,7 +50,6 @@ pub enum CommandType {
FlashDeflData = 0x11,
FlashDeflEnd = 0x12,
FlashMd5 = 0x13,
// Not supported on ESP32
GetSecurityInfo = 0x14,
// Stub-only commands
EraseFlash = 0xD0,
@ -60,12 +59,12 @@ pub enum CommandType {
RunUserCode = 0xD3,
// Flash encryption debug mode supported command
FlashEncryptedData = 0xD4,
// Read SPI flash manufacturer and device id - Not part of the protocol
// Not part of the protocol
FlashDetect = 0x9F,
}
impl CommandType {
/// Return a timeout based on the command type
/// Return the default timeout for the [`CommandType`] variant.
pub fn timeout(&self) -> Duration {
match self {
CommandType::MemEnd => MEM_END_TIMEOUT,
@ -77,7 +76,8 @@ impl CommandType {
}
}
/// Return a timeout based on the size
/// Return a timeout for the command that scales with the amount of data
/// involved in the transfer.
pub fn timeout_for_size(&self, size: u32) -> Duration {
fn calc_timeout(timeout_per_mb: Duration, size: u32) -> Duration {
let mb = size as f64 / 1_000_000.0;
@ -99,105 +99,189 @@ impl CommandType {
}
/// Available commands
///
/// See <https://docs.espressif.com/projects/esptool/en/latest/esp32c6/advanced-topics/serial-protocol.html#commands>
#[derive(Copy, Clone, Debug)]
#[non_exhaustive]
pub enum Command<'a> {
/// Begin Flash Download
FlashBegin {
/// Size to erase
size: u32,
/// Number of data packets
blocks: u32,
/// Data size in one packet
block_size: u32,
/// Flash offset
offset: u32,
/// Supports encryption
supports_encryption: bool,
},
/// Flash Download Data
FlashData {
/// Data
data: &'a [u8],
/// Pad to
pad_to: usize,
/// Pad byte
pad_byte: u8,
/// Sequence number
sequence: u32,
},
/// Finish Flash Download
FlashEnd {
/// Reboot
///
/// 0 to reboot, 1 to run user code. Not necessary to send this command
/// if you wish to stay in the loader.
reboot: bool,
},
/// Begin RAM Download Start
MemBegin {
/// Total size
size: u32,
/// Number of data packets
blocks: u32,
/// Data size in one packet
block_size: u32,
/// Memory offset
offset: u32,
/// Supports encryption
supports_encryption: bool,
},
MemEnd {
no_entry: bool,
entry: u32,
},
/// Finish RAM Download
MemEnd { no_entry: bool, entry: u32 },
/// RAM Download Data
MemData {
/// Data size
data: &'a [u8],
/// Pad to
pad_to: usize,
/// Pad byte
pad_byte: u8,
/// Sequence number
sequence: u32,
},
/// Sync Frame
///
/// 36 bytes: 0x07 0x07 0x12 0x20, followed by 32 x 0x55
Sync,
/// Write 32-bit memory address
WriteReg {
/// Address
address: u32,
/// Value
value: u32,
/// Mask
mask: Option<u32>,
},
/// Read 32-bit memory address
ReadReg {
/// Address
address: u32,
},
SpiSetParams {
spi_params: SpiSetParams,
},
SpiAttach {
spi_params: SpiAttachParams,
},
SpiAttachStub {
spi_params: SpiAttachParams,
},
/// Configure SPI flash
SpiSetParams { spi_params: SpiSetParams },
/// Attach SPI flash
SpiAttach { spi_params: SpiAttachParams },
/// Attach SPI flash (stub)
SpiAttachStub { spi_params: SpiAttachParams },
/// Change Baud rate
ChangeBaudrate {
/// New baud rate
new_baud: u32,
/// Prior baud rate ('0' for ROM flasher)
prior_baud: u32,
},
/// Begin compressed flash download
FlashDeflBegin {
/// Uncompressed size
///
/// With stub loader the uncompressed size is exact byte count to be
/// written, whereas on ROM bootloader it is rounded up to flash erase
/// block size.
size: u32,
/// Number of data packets
blocks: u32,
/// Data packet size
block_size: u32,
/// Flash offset
offset: u32,
/// Supports encryption
///
/// ROM loader only: 1 to begin encrypted flash, 0 to not.
supports_encryption: bool,
},
/// Compressed flash download data
FlashDeflData {
/// Data size
data: &'a [u8],
/// Pad to
pad_to: usize,
/// Pad byte
pad_byte: u8,
/// Sequence number
sequence: u32,
},
/// End compressed flash download
FlashDeflEnd {
/// Reboot
///
/// 0 to reboot, 1 to run user code. Not necessary to send this command
/// if you wish to stay in the loader.
reboot: bool,
},
/// Calculate MD5 of flash region
FlashMd5 {
/// Address
offset: u32,
/// Size
size: u32,
},
/// Erase entire flash chip
///
/// Supported by Stub Loader Only
EraseFlash,
/// Erase flash region
///
/// Supported by Stub Loader Only
EraseRegion {
/// Flash offset to erase
offset: u32,
/// Erase size in bytes
size: u32,
},
/// Read flash
///
/// Supported by Stub Loader Only
ReadFlash {
/// Flash offset
offset: u32,
/// Read length
size: u32,
/// Flash sector size
block_size: u32,
/// Maximum number of un-acked packets
max_in_flight: u32,
},
/// Read flash (slow)
///
/// Supported by ROM Loader Only
ReadFlashSlow {
offset: u32,
size: u32,
block_size: u32,
max_in_flight: u32,
},
/// Exits loader and runs user code
RunUserCode,
/// Read SPI flash manufacturer and device id
///
/// Not part of the serial protocol
FlashDetect,
/// Read chip security info
///
/// Not supported in ESP322
GetSecurityInfo,
}
@ -239,7 +323,7 @@ impl Command<'_> {
/// Write a command
pub fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
// Write the Direction and Command Indentifier
// Write the Direction and Command Identifier
writer.write_all(&[0, self.command_type() as u8])?;
match *self {
Command::FlashBegin {

View File

@ -56,8 +56,11 @@ pub type Port = serialport::COMPort;
/// The value of a command response.
#[derive(Debug, Clone)]
pub enum CommandResponseValue {
/// A 32-bit value.
ValueU32(u32),
/// A 128-bit value.
ValueU128(u128),
/// A vector of bytes.
Vector(Vec<u8>),
}
@ -204,7 +207,7 @@ impl Connection {
let read_bytes = self.serial.read(&mut buff)? as u32;
if read_bytes != available_bytes {
return Err(Error::Connection(ConnectionError::ReadMissmatch(
return Err(Error::Connection(ConnectionError::ReadMismatch(
available_bytes,
read_bytes,
)));
@ -391,7 +394,7 @@ impl Connection {
Ok(())
}
// Get the current baud rate of the serial port.
/// Get the current baud rate of the serial port.
pub fn baud(&self) -> Result<u32, Error> {
Ok(self.serial.baud_rate()?)
}
@ -612,13 +615,17 @@ impl Connection {
self.port_info.pid
}
/// Returns if the connection is using USB serial JTAG.
pub(crate) fn is_using_usb_serial_jtag(&self) -> bool {
self.port_info.pid == USB_SERIAL_JTAG_PID
}
/// Returns the reset after operation.
pub fn after_operation(&self) -> ResetAfterOperation {
self.after_operation
}
/// Returns the reset before operation.
pub fn before_operation(&self) -> ResetBeforeOperation {
self.before_operation
}
@ -675,7 +682,7 @@ mod encoder {
impl<W: Write> Write for SlipEncoder<'_, W> {
/// Writes the given buffer replacing the END and ESC bytes.
///
/// See https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/serial-protocol.html#low-level-protocol
/// See <https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/serial-protocol.html#low-level-protocol>
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
for value in buf.iter() {
match *value {

View File

@ -54,7 +54,7 @@ pub enum Error {
ChipMismatch(String, String),
#[error(
"Chip not argument provided, this is required when using the `--before no-reset-no-sync` option"
"Chip argument not provided, this is required when using the `--before no-reset-no-sync` option"
)]
#[diagnostic(
code(espflash::chip_not_provided),
@ -62,11 +62,11 @@ pub enum Error {
)]
ChipNotProvided,
#[error("Corrupt data, expected {0:2x?} bytes but receved {1:2x?} bytes")]
#[error("Corrupt data, expected {0:2x?} bytes but received {1:2x?} bytes")]
#[diagnostic(code(espflash::read_flash::corrupt_data))]
CorruptData(usize, usize),
#[error("MD5 digest missmatch: expected {0:2x?}, received: {1:2x?}")]
#[error("MD5 digest mismatch: expected {0:2x?}, received: {1:2x?}")]
#[diagnostic(code(espflash::read_flash::digest_mismatch))]
DigestMismatch(Vec<u8>, Vec<u8>),
@ -369,7 +369,7 @@ pub enum ConnectionError {
)]
NoSyncReply,
#[error("Received packet to large for buffer")]
#[error("Received packet too large for buffer")]
#[diagnostic(
code(espflash::oversized_packet),
help(
@ -381,8 +381,8 @@ pub enum ConnectionError {
#[error(
"Failed to read the available bytes on the serial port. Available bytes: {0}, Read bytes: {1}"
)]
#[diagnostic(code(espflash::read_missmatch))]
ReadMissmatch(u32, u32),
#[diagnostic(code(espflash::read_mismatch))]
ReadMismatch(u32, u32),
#[cfg(feature = "serialport")]
#[error("Timeout while running {0}command")]
@ -583,10 +583,11 @@ impl From<String> for MissingPartition {
#[error("No partition table could be found")]
#[diagnostic(
code(espflash::partition_table::missing_partition_table),
help("Try providing a CSV or binary paritition table with the `--partition-table` argument.")
help("Try providing a CSV or binary partition table with the `--partition-table` argument.")
)]
pub struct MissingPartitionTable;
/// Extension helpers.
#[cfg(feature = "serialport")]
pub(crate) trait ResultExt {
/// Mark an error as having occurred during the flashing stage.

View File

@ -482,6 +482,7 @@ impl FlashSettings {
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct FlashData {
/// Flash settings.
pub flash_settings: FlashSettings,
/// Minimum chip revision.
pub min_chip_rev: u16,
@ -1168,6 +1169,7 @@ impl Flasher {
Ok(())
}
/// Erase a region of flash.
pub fn erase_region(&mut self, offset: u32, size: u32) -> Result<(), Error> {
debug!("Erasing region of 0x{:x}B at 0x{:08x}", size, offset);

View File

@ -334,7 +334,7 @@ impl<'a> IdfBootloaderFormat<'a> {
// bootloader. The hash is at the end of the bootloader segments and
// 1-byte checksum at the end of a 16-byte padded boundary.
//
// Source: Point 3 of https://docs.espressif.com/projects/esp-idf/en/v5.4/esp32c3/api-reference/system/app_image_format.html
// Source: Point 3 of <https://docs.espressif.com/projects/esp-idf/en/v5.4/esp32c3/api-reference/system/app_image_format.html>
calc_bootloader_size += 1; // add checksum size
calc_bootloader_size = calc_bootloader_size + ((16 - (calc_bootloader_size % 16)) % 16);
let bootloader_sha_start = calc_bootloader_size;

View File

@ -2,18 +2,21 @@ use std::{collections::HashMap, error::Error};
use object::{File, Object, ObjectSection, ObjectSymbol};
/// Image format metadata.
#[derive(Debug, Clone)]
pub struct Metadata {
symbols: HashMap<String, Vec<u8>>,
}
impl Metadata {
/// Creates an empty [`Metadata`].
fn empty() -> Self {
Self {
symbols: HashMap::new(),
}
}
/// Creates a new [`Metadata`] from bytes.
pub fn from_bytes(bytes: Option<&[u8]>) -> Self {
match Self::try_from(bytes) {
Ok(metadata) => metadata,
@ -21,7 +24,8 @@ impl Metadata {
}
}
pub fn try_from(bytes: Option<&[u8]>) -> Result<Self, Box<dyn Error>> {
/// Tries to create a new [`Metadata`] from bytes.
fn try_from(bytes: Option<&[u8]>) -> Result<Self, Box<dyn Error>> {
const METADATA_SECTION: &str = ".espressif.metadata";
let Some(bytes) = bytes else {
@ -57,16 +61,19 @@ impl Metadata {
Ok(this)
}
/// Reads a string from the metadata.
fn read_string<'f>(&'f self, name: &str) -> Option<&'f str> {
self.symbols
.get(name)
.and_then(|data| std::str::from_utf8(data).ok())
}
/// Returns the chip name.
pub fn chip_name(&self) -> Option<&str> {
self.read_string("build_info.CHIP_NAME")
}
/// Returns the log format.
pub fn log_format(&self) -> Option<&str> {
self.read_string("espflash.LOG_FORMAT")
}

View File

@ -85,6 +85,7 @@ pub struct Segment<'a> {
}
impl<'a> Segment<'a> {
/// Creates a new [`Segment`].
pub fn new(addr: u32, data: &'a [u8]) -> Self {
// Do not pad the data here, as it might result in overlapping segments
// in the ELF file. The padding should be done after merging adjacent segments.
@ -94,8 +95,8 @@ impl<'a> Segment<'a> {
}
}
/// Split of the first `count` bytes into a new segment, adjusting the
/// remaining segment as needed
/// Splits off the first `count` bytes into a new segment, adjusting the
/// remaining segment as needed.
pub fn split_off(&mut self, count: usize) -> Self {
if count < self.data.len() {
let (head, tail) = match take(&mut self.data) {

View File

@ -18,7 +18,7 @@
//! ```
//!
//! We add `default-features` here to disable the `cli` feature, which is
//! enabled by default. Its important to note that the cli module does not
//! enabled by default. It's important to note that the cli module does not
//! provide SemVer guarantees. You likely will not need any of these types or
//! functions in your application so there's no use pulling in the extra
//! dependencies.
@ -44,7 +44,7 @@ mod error;
#[cfg(feature = "cli")]
pub mod cli;
// Logging utilities
/// Logging utilities
#[cfg(feature = "cli")]
pub mod logging {
use env_logger::{Builder, Env};

View File

@ -497,8 +497,8 @@ impl Chip {
}
}
#[cfg(feature = "serialport")]
/// Enumerate the chip's features, read from eFuse
#[cfg(feature = "serialport")]
pub fn chip_features(&self, connection: &mut Connection) -> Result<Vec<&str>, Error> {
match self {
Chip::Esp32 => {
@ -610,8 +610,8 @@ impl Chip {
}
}
#[cfg(feature = "serialport")]
/// Determine the chip's revision number
#[cfg(feature = "serialport")]
pub fn revision(&self, connection: &mut Connection) -> Result<(u32, u32), Error> {
let major = self.major_version(connection)?;
let minor = self.minor_version(connection)?;
@ -619,6 +619,7 @@ impl Chip {
Ok((major, minor))
}
/// Returns the chip's major version.
#[cfg(feature = "serialport")]
pub fn major_version(&self, connection: &mut Connection) -> Result<u32, Error> {
match self {
@ -660,6 +661,7 @@ impl Chip {
}
}
/// Returns the chip's minor version.
#[cfg(feature = "serialport")]
pub fn minor_version(&self, connection: &mut Connection) -> Result<u32, Error> {
match self {