fix: V4 also uses DIO, boot monitor on all full flashes, find ~/.local/bin/esptool

This commit is contained in:
James L
2026-03-01 19:49:25 -05:00
parent 8ce5ba2d06
commit e33008cf86

View File

@@ -75,7 +75,7 @@ BOARD_PROFILES = {
"merged_filename": "rnodethv4_firmware.bin", "merged_filename": "rnodethv4_firmware.bin",
"flash_size": "16MB", "flash_size": "16MB",
"baud_rate": "921600", "baud_rate": "921600",
"flash_mode": "qio", # V4 flash chips support QIO reliably "flash_mode": "dio", # DIO is universally compatible with all flash chips
}, },
"v3": { "v3": {
"name": "Heltec WiFi LoRa 32 V3", "name": "Heltec WiFi LoRa 32 V3",
@@ -317,18 +317,26 @@ def detect_board(port, esptool_cmd):
# ── Helpers ──────────────────────────────────────────────────────────────────── # ── Helpers ────────────────────────────────────────────────────────────────────
def find_esptool(): def find_esptool():
"""Find esptool.py — pip-installed, bundled, or PlatformIO's copy. """Find esptool — pip-installed, user-local, bundled, or PlatformIO's copy.
Prefer pip-installed esptool first (handles its own deps), then fall Prefer pip/pipx-installed esptool first (handles its own deps and is
back to the bundled script — but only if pyserial is importable in usually the newest version), then fall back to the bundled script.
the current Python interpreter.
""" """
# 1. pip-installed esptool (standalone executable, no dep issues) # 1. pip-installed esptool on PATH
if shutil.which("esptool.py"): if shutil.which("esptool.py"):
return ["esptool.py"] return ["esptool.py"]
if shutil.which("esptool"): if shutil.which("esptool"):
return ["esptool"] return ["esptool"]
# 2. Common user-local install locations (pip install --user)
for candidate in [
os.path.expanduser("~/.local/bin/esptool"),
os.path.expanduser("~/.local/bin/esptool.py"),
]:
if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
print(f" Found user-local esptool: {candidate}")
return [candidate]
# Check if pyserial is available before using script-based esptool # Check if pyserial is available before using script-based esptool
try: try:
import serial # noqa: F401 import serial # noqa: F401
@@ -1235,24 +1243,23 @@ Examples:
# #
# Strategy: # Strategy:
# 1. Flash with the board's default flash mode # 1. Flash with the board's default flash mode
# 2. If this is a full/erase flash, always add --verify # 2. If this is a full flash (any path), always add --verify
# 3. After successful flash+verify, monitor serial for bootloop # 3. After successful flash+verify, monitor serial for bootloop
# 4. If bootloop detected and current mode != DIO, auto-retry with DIO # 4. If bootloop detected and current mode != DIO, auto-retry with DIO
# #
full_flash_verify = args.full or args.erase
current_mode = BOARD_FLASH_MODE() current_mode = BOARD_FLASH_MODE()
ok = flash_firmware(firmware_path, port, esptool_cmd, baud, ok = flash_firmware(firmware_path, port, esptool_cmd, baud,
no_reset_before=erase_performed, no_reset_before=erase_performed,
verify=full_flash_verify) verify=full_flash)
if not ok: if not ok:
print("\nFlash FAILED. Check connection and try again.") print("\nFlash FAILED. Check connection and try again.")
print("You may need to hold BOOT while pressing RESET.") print("You may need to hold BOOT while pressing RESET.")
sys.exit(1) sys.exit(1)
# ── Post-flash boot monitoring (only on full/erase flashes) ───────────── # ── Post-flash boot monitoring (on any full flash) ──────────────────────
if full_flash_verify: if full_flash:
print("\n Verifying device boots correctly...") print("\n Verifying device boots correctly...")
time.sleep(2) # Give device time to start booting time.sleep(2) # Give device time to start booting
boot_ok, boot_output = _monitor_boot(port, timeout=8) boot_ok, boot_output = _monitor_boot(port, timeout=8)