mirror of
https://github.com/esp-rs/espflash.git
synced 2026-03-12 08:39:56 +00:00
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:
parent
61e5032d92
commit
f12ecf363d
10
CHANGELOG.md
10
CHANGELOG.md
@ -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)
|
||||
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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};
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user