bringup and order sensors
This commit is contained in:
108
bringup/flash.py
Normal file
108
bringup/flash.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""Wrap esptool to flash the SC-F001 firmware from a build directory.
|
||||
|
||||
Reads `build/flasher_args.json` (produced by `idf.py build`) to get the
|
||||
authoritative list of offsets + binaries, then invokes esptool once with all
|
||||
of them — no hardcoded offsets here.
|
||||
|
||||
Requires esptool reachable either as a Python module (`pip install esptool`)
|
||||
or as `esptool.py` on PATH (e.g., from an ESP-IDF activation).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class FlashError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def _default_build_dir() -> Path:
|
||||
# bringup dir sits at SC-F001/bringup; build sits at SC-F001/build
|
||||
return Path(__file__).resolve().parent.parent / "build"
|
||||
|
||||
|
||||
def _resolve_esptool_invocation() -> list[str]:
|
||||
"""Return the command prefix to run esptool, preferring the installed
|
||||
module in the current interpreter, falling back to esptool.py on PATH.
|
||||
|
||||
Raises FlashError with an actionable message if neither is available.
|
||||
"""
|
||||
if importlib.util.find_spec("esptool") is not None:
|
||||
return [sys.executable, "-m", "esptool"]
|
||||
fallback = shutil.which("esptool.py") or shutil.which("esptool")
|
||||
if fallback:
|
||||
return [fallback]
|
||||
raise FlashError(
|
||||
"esptool is not installed in this Python and not on PATH.\n"
|
||||
" Install with: "
|
||||
f"{sys.executable} -m pip install -r "
|
||||
f"{Path(__file__).parent / 'requirements.txt'}\n"
|
||||
" Or activate an ESP-IDF shell that provides esptool.py."
|
||||
)
|
||||
|
||||
|
||||
def _load_manifest(build_dir: Path) -> dict:
|
||||
manifest = build_dir / "flasher_args.json"
|
||||
if not manifest.exists():
|
||||
raise FlashError(
|
||||
f"Build manifest not found: {manifest}\n"
|
||||
f"Run `idf.py build` from SC-F001/ first, or pass --build-dir."
|
||||
)
|
||||
return json.loads(manifest.read_text())
|
||||
|
||||
|
||||
def _resolve_flash_args(build_dir: Path, manifest: dict) -> list[str]:
|
||||
"""Expand manifest into a (offset, abs-path) list suitable for esptool."""
|
||||
args: list[str] = []
|
||||
# flasher_args.json's flash_files is {offset_hex: relpath}.
|
||||
for offset_hex, rel in manifest["flash_files"].items():
|
||||
p = (build_dir / rel).resolve()
|
||||
if not p.exists():
|
||||
raise FlashError(f"Missing firmware binary: {p}")
|
||||
args.append(offset_hex)
|
||||
args.append(str(p))
|
||||
return args
|
||||
|
||||
|
||||
def flash(
|
||||
port: str,
|
||||
build_dir: Path | None = None,
|
||||
baud: int = 460800,
|
||||
erase_all: bool = False,
|
||||
log: callable = print,
|
||||
) -> None:
|
||||
build_dir = (build_dir or _default_build_dir()).resolve()
|
||||
manifest = _load_manifest(build_dir)
|
||||
|
||||
chip = manifest.get("extra_esptool_args", {}).get("chip", "esp32")
|
||||
before = manifest.get("extra_esptool_args", {}).get("before", "default_reset")
|
||||
after = manifest.get("extra_esptool_args", {}).get("after", "hard_reset")
|
||||
|
||||
esptool_cmd = _resolve_esptool_invocation()
|
||||
base_cmd = esptool_cmd + [
|
||||
"--chip", chip,
|
||||
"--port", port,
|
||||
"--baud", str(baud),
|
||||
"--before", before,
|
||||
"--after", after,
|
||||
]
|
||||
|
||||
if erase_all:
|
||||
log(f" erase_flash @ {port}")
|
||||
subprocess.check_call(base_cmd + ["erase_flash"])
|
||||
|
||||
write_args = manifest.get("write_flash_args", [])
|
||||
cmd = base_cmd + ["write_flash"] + write_args + _resolve_flash_args(build_dir, manifest)
|
||||
|
||||
log(f" flashing from {build_dir}")
|
||||
log(f" files: {list(manifest['flash_files'].items())}")
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise FlashError(f"esptool failed (exit {e.returncode})") from e
|
||||
Reference in New Issue
Block a user