Merge pull request 'feature/espflash2' (#1) from feature/espflash2 into main
Reviewed-on: #1
This commit is contained in:
commit
a2dc8726c1
70
.github/workflows/ci.yml
vendored
Normal file
70
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- "**/README.md"
|
||||
- "**/release.yml"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**/README.md"
|
||||
- "**/release.yml"
|
||||
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
cargo-checks:
|
||||
name: CI checks
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
action:
|
||||
- command: build
|
||||
args: --release
|
||||
- command: fmt
|
||||
args: --all -- --check
|
||||
- command: clippy
|
||||
args: --all-targets --all-features --workspace -- -D warnings
|
||||
- command: doc
|
||||
args: --no-deps --document-private-items --all-features --workspace --examples
|
||||
- command: publish
|
||||
args: --dry-run
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo sed -i 's/azure.archive.ubuntu.com/archive.ubuntu.com/' /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install libudev-dev
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Enable caching
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Cargo command
|
||||
run: cargo ${{ matrix.action.command }} ${{ matrix.action.args }}
|
||||
msrv:
|
||||
name: MSRV check
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo sed -i 's/azure.archive.ubuntu.com/archive.ubuntu.com/' /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install musl-tools libudev-dev
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.65.0
|
||||
- name: Enable caching
|
||||
uses: Swatinem/rust-cache@v2
|
||||
- name: Cargo check
|
||||
run: cargo check
|
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@ -45,6 +45,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
if: matrix.job.os == 'ubuntu-20.04'
|
||||
run: |
|
||||
sudo sed -i 's/azure.archive.ubuntu.com/archive.ubuntu.com/' /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install libudev-dev librust-libudev-sys-dev pkg-config
|
||||
|
||||
|
2438
Cargo.lock
generated
2438
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
27
Cargo.toml
27
Cargo.toml
@ -1,11 +1,26 @@
|
||||
[package]
|
||||
name = "web-flash"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
edition = "2021"
|
||||
description = "A web server to flash Espressif devices given an ELF file."
|
||||
rust-version = "1.65"
|
||||
authors = [
|
||||
"Björn Quentin <bjoern.quentin@mobile-j.de>",
|
||||
"Sergio Gasquez Arcos <sergio.gasquez@gmail.com>",
|
||||
"Fabian Stamm <dev@fabianstamm.de>",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/esp-rs/esp-web-flash-server"
|
||||
keywords = ["cli", "embedded", "esp"]
|
||||
categories = ["command-line-utilities", "development-tools", "embedded"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
rocket = "0.5.0-rc.2"
|
||||
espflash = { rev = "55bce336c6718c1c7f019e4da718f97c8cdf1b95", git = "https://github.com/esp-rs/espflash" }
|
||||
clap = { version = "4.1.4", features = ["env", "derive"] }
|
||||
opener = "0.5.2"
|
||||
anyhow = "1.0.69"
|
||||
rocket = "0.5"
|
||||
espflash = "2.1"
|
||||
esp-idf-part = "0.4"
|
||||
clap = { version = "4", features = ["env", "derive"] }
|
||||
opener = "0.6"
|
||||
anyhow = "1"
|
||||
xmas-elf = "0.9"
|
||||
|
52
README.md
52
README.md
@ -1,20 +1,42 @@
|
||||
# esp-web-flash-server
|
||||
# web-flash
|
||||
|
||||
Starts a local server serving a web page to flash a given ELF file.
|
||||
|
||||
## Installation
|
||||
```
|
||||
web-flash 0.1.0
|
||||
|
||||
USAGE:
|
||||
web-flash.exe [OPTIONS] --chip <CHIP> <ELF>
|
||||
|
||||
ARGS:
|
||||
<ELF>
|
||||
|
||||
OPTIONS:
|
||||
-b, --bootloader <BOOTLOADER> path to bootloader
|
||||
-c, --chip <CHIP> chip name
|
||||
-h, --help Print help information
|
||||
-p, --partition-table <PARTITION_TABLE> path to partition table csv
|
||||
-V, --version Print version information
|
||||
cargo install web-flash
|
||||
```
|
||||
## Usage
|
||||
```
|
||||
Usage: web-flash [OPTIONS] --chip <CHIP> <ELF>
|
||||
|
||||
Arguments:
|
||||
<ELF>
|
||||
Path to the ELF file
|
||||
|
||||
Options:
|
||||
-c, --chip <CHIP>
|
||||
Chip name
|
||||
|
||||
Possible values:
|
||||
- esp32: ESP32
|
||||
- esp32c2: ESP32-C2, ESP8684
|
||||
- esp32c3: ESP32-C3, ESP8685
|
||||
- esp32c6: ESP32-C6
|
||||
- esp32s2: ESP32-S2
|
||||
- esp32s3: ESP32-S3
|
||||
- esp32h2: ESP32-H2
|
||||
- esp8266: ESP8266
|
||||
|
||||
-b, --bootloader <BOOTLOADER>
|
||||
Path to bootloader
|
||||
|
||||
-p, --partition-table <PARTITION_TABLE>
|
||||
Path to partition table CSV
|
||||
|
||||
-h, --help
|
||||
Print help (see a summary with '-h')
|
||||
|
||||
-V, --version
|
||||
Print version
|
||||
```
|
||||
|
5
Rocket.toml
Normal file
5
Rocket.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[default.shutdown]
|
||||
ctrlc = true
|
||||
signals = ["term", "hup"]
|
||||
grace = 5
|
||||
mercy = 4
|
223
src/main.rs
223
src/main.rs
@ -3,7 +3,8 @@ use anyhow::Result;
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use clap::Parser;
|
||||
use espflash::{elf::FirmwareImageBuilder, Chip, FlashSize, PartitionTable};
|
||||
use esp_idf_part::PartitionTable;
|
||||
use espflash::{elf::ElfFirmwareImage, flasher::FlashSize::_4Mb, targets::Chip};
|
||||
use rocket::{response::content, State};
|
||||
|
||||
#[macro_use]
|
||||
@ -12,18 +13,19 @@ extern crate rocket;
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// chip name
|
||||
#[arg(short, long)]
|
||||
/// Chip name
|
||||
#[clap(short, long)]
|
||||
chip: Chip,
|
||||
|
||||
/// path to bootloader
|
||||
#[arg(short, long)]
|
||||
/// Path to bootloader
|
||||
#[clap(short, long)]
|
||||
bootloader: Option<PathBuf>,
|
||||
|
||||
/// path to partition table csv
|
||||
#[arg(short, long)]
|
||||
/// Path to partition table CSV
|
||||
#[clap(short, long)]
|
||||
partition_table: Option<PathBuf>,
|
||||
|
||||
/// Path to the ELF file
|
||||
elf: PathBuf,
|
||||
}
|
||||
|
||||
@ -47,6 +49,19 @@ fn index() -> content::RawHtml<&'static str> {
|
||||
content::RawHtml(
|
||||
"
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
background-color: #cdcdcd;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
color: #343434;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-left: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>ESP Web Flasher</h1>
|
||||
@ -54,11 +69,13 @@ fn index() -> content::RawHtml<&'static str> {
|
||||
<div id=\"main\" style=\"display: none;\">
|
||||
|
||||
<br>
|
||||
<script type=\"module\" src=\"https://unpkg.com/esp-web-tools@8.0.2/dist/web/install-button.js?module\">
|
||||
<script type=\"module\" src=\"https://unpkg.com/esp-web-tools@9.4.3/dist/web/install-button.js?module\">
|
||||
</script>
|
||||
<esp-web-install-button id=\"installButton\" manifest=\"manifest.json\"></esp-web-install-button>
|
||||
<br>
|
||||
<span><i>NOTE: Make sure to close anything using your devices com port (e.g. Serial monitor)</i></span>
|
||||
<br>
|
||||
<br>
|
||||
<span><i>NOTE: Make sure to close anything using your device's com port (e.g. serial monitor)</i></span>
|
||||
</div>
|
||||
<div id=\"notSupported\" style=\"display: none;\">
|
||||
Your browser does not support the Web Serial API. Try Chrome
|
||||
@ -90,72 +107,123 @@ fn manifest() -> content::RawJson<&'static str> {
|
||||
"new_install_prompt_erase": true,
|
||||
"builds": [
|
||||
{
|
||||
"chipFamily": "ESP32",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 4096
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
"chipFamily": "ESP32",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 4096
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-C3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
"chipFamily": "ESP32-C2",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S2",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 4096
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
"chipFamily": "ESP32-C3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
"chipFamily": "ESP32-C6",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-H2",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S2",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 4096
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "bootloader.bin",
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"path": "partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -164,7 +232,7 @@ fn manifest() -> content::RawJson<&'static str> {
|
||||
}
|
||||
|
||||
struct PartsData {
|
||||
chip: String,
|
||||
_chip: String,
|
||||
bootloader: Vec<u8>,
|
||||
partitions: Vec<u8>,
|
||||
firmware: Vec<u8>,
|
||||
@ -174,6 +242,7 @@ fn prepare() -> Result<PartsData> {
|
||||
let opts = Args::parse();
|
||||
|
||||
let elf = std::fs::read(opts.elf)?;
|
||||
let elf = xmas_elf::ElfFile::new(&elf).expect("Invalid elf file");
|
||||
|
||||
let p = if let Some(p) = &opts.partition_table {
|
||||
Some(PartitionTable::try_from_bytes(std::fs::read(p)?)?)
|
||||
@ -187,9 +256,7 @@ fn prepare() -> Result<PartsData> {
|
||||
None
|
||||
};
|
||||
|
||||
let firmware = FirmwareImageBuilder::new(&elf)
|
||||
.flash_size(Some(FlashSize::Flash4Mb)) // TODO make configurable
|
||||
.build()?;
|
||||
let firmware = ElfFirmwareImage::new(elf);
|
||||
|
||||
let chip = opts.chip;
|
||||
let chip_name = match chip {
|
||||
@ -198,16 +265,22 @@ fn prepare() -> Result<PartsData> {
|
||||
Chip::Esp32s2 => "ESP32-S2",
|
||||
Chip::Esp32s3 => "ESP32-S3",
|
||||
Chip::Esp8266 => "ESP8266",
|
||||
Chip::Esp32c2 => "ESP32-C2",
|
||||
Chip::Esp32c6 => "ESP32-C6",
|
||||
Chip::Esp32h2 => "ESP32-H2",
|
||||
_ => panic!("Unsupported chip"),
|
||||
};
|
||||
|
||||
let image = chip.get_flash_image(&firmware, b, p, None, None)?;
|
||||
let image =
|
||||
chip.into_target()
|
||||
.get_flash_image(&firmware, b, p, None, None, None, Some(_4Mb), None)?;
|
||||
let parts: Vec<_> = image.flash_segments().collect();
|
||||
let bootloader = &parts[0];
|
||||
let partitions = &parts[1];
|
||||
let app = &parts[2];
|
||||
|
||||
Ok(PartsData {
|
||||
chip: chip_name.to_string(),
|
||||
_chip: chip_name.to_string(),
|
||||
bootloader: bootloader.data.to_vec(),
|
||||
partitions: partitions.data.to_vec(),
|
||||
firmware: app.data.to_vec(),
|
||||
|
Loading…
Reference in New Issue
Block a user