feat(core): 更新py-esptool (version: 4.8.1)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# PYTHON_ARGCOMPLETE_OK
|
||||
__all__ = [
|
||||
"chip_id",
|
||||
"detect_chip",
|
||||
@@ -28,7 +28,7 @@ __all__ = [
|
||||
"write_mem",
|
||||
]
|
||||
|
||||
__version__ = "4.7.0"
|
||||
__version__ = "4.8.1"
|
||||
|
||||
import argparse
|
||||
import inspect
|
||||
@@ -38,8 +38,8 @@ import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from bin_image import intel_hex_to_bin
|
||||
from cmds import (
|
||||
from esptool.bin_image import intel_hex_to_bin
|
||||
from esptool.cmds import (
|
||||
DETECTED_FLASH_SIZES,
|
||||
chip_id,
|
||||
detect_chip,
|
||||
@@ -49,6 +49,7 @@ from cmds import (
|
||||
erase_flash,
|
||||
erase_region,
|
||||
flash_id,
|
||||
read_flash_sfdp,
|
||||
get_security_info,
|
||||
image_info,
|
||||
load_ram,
|
||||
@@ -65,15 +66,22 @@ from cmds import (
|
||||
write_flash_status,
|
||||
write_mem,
|
||||
)
|
||||
from config import load_config_file
|
||||
from loader import DEFAULT_CONNECT_ATTEMPTS, ESPLoader, list_ports
|
||||
from targets import CHIP_DEFS, CHIP_LIST, ESP32ROM
|
||||
from util import (
|
||||
from esptool.config import load_config_file
|
||||
from esptool.loader import (
|
||||
DEFAULT_CONNECT_ATTEMPTS,
|
||||
DEFAULT_OPEN_PORT_ATTEMPTS,
|
||||
StubFlasher,
|
||||
ESPLoader,
|
||||
list_ports,
|
||||
)
|
||||
from esptool.targets import CHIP_DEFS, CHIP_LIST, ESP32ROM
|
||||
from esptool.util import (
|
||||
FatalError,
|
||||
NotImplementedInROMError,
|
||||
flash_size_bytes,
|
||||
strip_chip_name,
|
||||
)
|
||||
from itertools import chain, cycle, repeat
|
||||
|
||||
import serial
|
||||
|
||||
@@ -123,6 +131,14 @@ def main(argv=None, esp=None):
|
||||
default=os.environ.get("ESPTOOL_BAUD", ESPLoader.ESP_ROM_BAUD),
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--port-filter",
|
||||
action="append",
|
||||
help="Serial port device filter, can be vid=NUMBER, pid=NUMBER, name=SUBSTRING",
|
||||
type=str,
|
||||
default=[],
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--before",
|
||||
help="What to do before connecting to the chip",
|
||||
@@ -145,6 +161,15 @@ def main(argv=None, esp=None):
|
||||
action="store_true",
|
||||
)
|
||||
|
||||
# --stub-version can be set with --no-stub so the tests wouldn't fail if this option is implied globally
|
||||
parser.add_argument(
|
||||
"--stub-version",
|
||||
default=os.environ.get("ESPTOOL_STUB_VERSION", StubFlasher.STUB_SUBDIRS[0]),
|
||||
choices=StubFlasher.STUB_SUBDIRS,
|
||||
# not a public option and is not subject to the semantic versioning policy
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--trace",
|
||||
"-t",
|
||||
@@ -217,7 +242,12 @@ def main(argv=None, esp=None):
|
||||
default="0xFFFFFFFF",
|
||||
)
|
||||
|
||||
def add_spi_flash_subparsers(parent, allow_keep, auto_detect):
|
||||
def add_spi_flash_subparsers(
|
||||
parent: argparse.ArgumentParser,
|
||||
allow_keep: bool,
|
||||
auto_detect: bool,
|
||||
size_only: bool = False,
|
||||
):
|
||||
"""Add common parser arguments for SPI flash properties"""
|
||||
extra_keep_args = ["keep"] if allow_keep else []
|
||||
|
||||
@@ -234,33 +264,35 @@ def main(argv=None, esp=None):
|
||||
extra_fs_message = ""
|
||||
flash_sizes = []
|
||||
|
||||
parent.add_argument(
|
||||
"--flash_freq",
|
||||
"-ff",
|
||||
help="SPI Flash frequency",
|
||||
choices=extra_keep_args
|
||||
+ [
|
||||
"80m",
|
||||
"60m",
|
||||
"48m",
|
||||
"40m",
|
||||
"30m",
|
||||
"26m",
|
||||
"24m",
|
||||
"20m",
|
||||
"16m",
|
||||
"15m",
|
||||
"12m",
|
||||
],
|
||||
default=os.environ.get("ESPTOOL_FF", "keep" if allow_keep else None),
|
||||
)
|
||||
parent.add_argument(
|
||||
"--flash_mode",
|
||||
"-fm",
|
||||
help="SPI Flash mode",
|
||||
choices=extra_keep_args + ["qio", "qout", "dio", "dout"],
|
||||
default=os.environ.get("ESPTOOL_FM", "keep" if allow_keep else "qio"),
|
||||
)
|
||||
if not size_only:
|
||||
parent.add_argument(
|
||||
"--flash_freq",
|
||||
"-ff",
|
||||
help="SPI Flash frequency",
|
||||
choices=extra_keep_args
|
||||
+ [
|
||||
"80m",
|
||||
"60m",
|
||||
"48m",
|
||||
"40m",
|
||||
"30m",
|
||||
"26m",
|
||||
"24m",
|
||||
"20m",
|
||||
"16m",
|
||||
"15m",
|
||||
"12m",
|
||||
],
|
||||
default=os.environ.get("ESPTOOL_FF", "keep" if allow_keep else None),
|
||||
)
|
||||
parent.add_argument(
|
||||
"--flash_mode",
|
||||
"-fm",
|
||||
help="SPI Flash mode",
|
||||
choices=extra_keep_args + ["qio", "qout", "dio", "dout"],
|
||||
default=os.environ.get("ESPTOOL_FM", "keep" if allow_keep else "qio"),
|
||||
)
|
||||
|
||||
parent.add_argument(
|
||||
"--flash_size",
|
||||
"-fs",
|
||||
@@ -468,7 +500,7 @@ def main(argv=None, esp=None):
|
||||
parser_elf2image.add_argument(
|
||||
"--use_segments",
|
||||
help="If set, ELF segments will be used instead of ELF sections "
|
||||
"to genereate the image.",
|
||||
"to generate the image.",
|
||||
action="store_true",
|
||||
)
|
||||
parser_elf2image.add_argument(
|
||||
@@ -489,7 +521,7 @@ def main(argv=None, esp=None):
|
||||
"quantity. This will make the other segments invisible to the ROM "
|
||||
"loader. Use this argument with care because the ROM loader will load "
|
||||
"only the RAM segments although the other segments being present in "
|
||||
"the output.",
|
||||
"the output. Implies --dont-append-digest",
|
||||
action="store_true",
|
||||
default=None,
|
||||
)
|
||||
@@ -540,7 +572,9 @@ def main(argv=None, esp=None):
|
||||
parser_read_flash = subparsers.add_parser(
|
||||
"read_flash", help="Read SPI flash content"
|
||||
)
|
||||
add_spi_connection_arg(parser_read_flash)
|
||||
add_spi_flash_subparsers(
|
||||
parser_read_flash, allow_keep=True, auto_detect=True, size_only=True
|
||||
)
|
||||
parser_read_flash.add_argument("address", help="Start address", type=arg_auto_int)
|
||||
parser_read_flash.add_argument(
|
||||
"size",
|
||||
@@ -594,6 +628,14 @@ def main(argv=None, esp=None):
|
||||
type=arg_auto_size,
|
||||
)
|
||||
|
||||
parser_read_flash_sfdp = subparsers.add_parser(
|
||||
"read_flash_sfdp",
|
||||
help="Read SPI flash SFDP (Serial Flash Discoverable Parameters)",
|
||||
)
|
||||
add_spi_flash_subparsers(parser_read_flash_sfdp, allow_keep=True, auto_detect=True)
|
||||
parser_read_flash_sfdp.add_argument("addr", type=arg_auto_int)
|
||||
parser_read_flash_sfdp.add_argument("bytes", type=int)
|
||||
|
||||
parser_merge_bin = subparsers.add_parser(
|
||||
"merge_bin",
|
||||
help="Merge multiple raw binary files into a single file for later flashing",
|
||||
@@ -664,12 +706,40 @@ def main(argv=None, esp=None):
|
||||
for operation in subparsers.choices.keys():
|
||||
assert operation in globals(), "%s should be a module function" % operation
|
||||
|
||||
# Enable argcomplete only on Unix-like systems
|
||||
if sys.platform != "win32":
|
||||
try:
|
||||
import argcomplete
|
||||
|
||||
argcomplete.autocomplete(parser)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
argv = expand_file_arguments(argv or sys.argv[1:])
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
print("esptool.py v%s" % __version__)
|
||||
load_config_file(verbose=True)
|
||||
|
||||
StubFlasher.set_preferred_stub_subdir(args.stub_version)
|
||||
|
||||
# Parse filter arguments into separate lists
|
||||
args.filterVids = []
|
||||
args.filterPids = []
|
||||
args.filterNames = []
|
||||
for f in args.port_filter:
|
||||
kvp = f.split("=")
|
||||
if len(kvp) != 2:
|
||||
raise FatalError("Option --port-filter argument must consist of key=value")
|
||||
if kvp[0] == "vid":
|
||||
args.filterVids.append(arg_auto_int(kvp[1]))
|
||||
elif kvp[0] == "pid":
|
||||
args.filterPids.append(arg_auto_int(kvp[1]))
|
||||
elif kvp[0] == "name":
|
||||
args.filterNames.append(kvp[1])
|
||||
else:
|
||||
raise FatalError("Option --port-filter argument key not recognized")
|
||||
|
||||
# operation function can take 1 arg (args), 2 args (esp, arg)
|
||||
# or be a member function of the ESPLoader class.
|
||||
|
||||
@@ -705,10 +775,31 @@ def main(argv=None, esp=None):
|
||||
initial_baud = args.baud
|
||||
|
||||
if args.port is None:
|
||||
ser_list = get_port_list()
|
||||
ser_list = get_port_list(args.filterVids, args.filterPids, args.filterNames)
|
||||
print("Found %d serial ports" % len(ser_list))
|
||||
else:
|
||||
ser_list = [args.port]
|
||||
open_port_attempts = os.environ.get(
|
||||
"ESPTOOL_OPEN_PORT_ATTEMPTS", DEFAULT_OPEN_PORT_ATTEMPTS
|
||||
)
|
||||
try:
|
||||
open_port_attempts = int(open_port_attempts)
|
||||
except ValueError:
|
||||
raise SystemExit("Invalid value for ESPTOOL_OPEN_PORT_ATTEMPTS")
|
||||
if open_port_attempts != 1:
|
||||
if args.port is None or args.chip == "auto":
|
||||
print(
|
||||
"WARNING: The ESPTOOL_OPEN_PORT_ATTEMPTS (open_port_attempts) option can only be used with --port and --chip arguments."
|
||||
)
|
||||
else:
|
||||
esp = esp or connect_loop(
|
||||
args.port,
|
||||
initial_baud,
|
||||
args.chip,
|
||||
open_port_attempts,
|
||||
args.trace,
|
||||
args.before,
|
||||
)
|
||||
esp = esp or get_default_connected_device(
|
||||
ser_list,
|
||||
port=args.port,
|
||||
@@ -770,6 +861,13 @@ def main(argv=None, esp=None):
|
||||
"Keeping initial baud rate %d" % initial_baud
|
||||
)
|
||||
|
||||
def _define_spi_conn(spi_connection):
|
||||
"""Prepare SPI configuration string and value for flash_spi_attach()"""
|
||||
clk, q, d, hd, cs = spi_connection
|
||||
spi_config_txt = f"CLK:{clk}, Q:{q}, D:{d}, HD:{hd}, CS:{cs}"
|
||||
value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk
|
||||
return spi_config_txt, value
|
||||
|
||||
# Override the common SPI flash parameter stuff if configured to do so
|
||||
if hasattr(args, "spi_connection") and args.spi_connection is not None:
|
||||
spi_config = args.spi_connection
|
||||
@@ -781,15 +879,26 @@ def main(argv=None, esp=None):
|
||||
esp.check_spi_connection(args.spi_connection)
|
||||
# Encode the pin numbers as a 32-bit integer with packed 6-bit values,
|
||||
# the same way the ESP ROM takes them
|
||||
clk, q, d, hd, cs = args.spi_connection
|
||||
spi_config = f"CLK:{clk}, Q:{q}, D:{d}, HD:{hd}, CS:{cs}"
|
||||
value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk
|
||||
spi_config, value = _define_spi_conn(args.spi_connection)
|
||||
print(f"Configuring SPI flash mode ({spi_config})...")
|
||||
esp.flash_spi_attach(value)
|
||||
elif args.no_stub:
|
||||
print("Enabling default SPI flash mode...")
|
||||
# ROM loader doesn't enable flash unless we explicitly do it
|
||||
esp.flash_spi_attach(0)
|
||||
if esp.CHIP_NAME != "ESP32" or esp.secure_download_mode:
|
||||
print("Enabling default SPI flash mode...")
|
||||
# ROM loader doesn't enable flash unless we explicitly do it
|
||||
esp.flash_spi_attach(0)
|
||||
else:
|
||||
# ROM doesn't attach in-package flash chips
|
||||
spi_chip_pads = esp.get_chip_spi_pads()
|
||||
spi_config_txt, value = _define_spi_conn(spi_chip_pads)
|
||||
if spi_chip_pads != (0, 0, 0, 0, 0):
|
||||
print(
|
||||
"Attaching flash from eFuses' SPI pads configuration"
|
||||
f"({spi_config_txt})..."
|
||||
)
|
||||
else:
|
||||
print("Enabling default SPI flash mode...")
|
||||
esp.flash_spi_attach(value)
|
||||
|
||||
# XMC chip startup sequence
|
||||
XMC_VENDOR_ID = 0x20
|
||||
@@ -879,6 +988,10 @@ def main(argv=None, esp=None):
|
||||
flash_size = detect_flash_size(esp, args)
|
||||
elif args.flash_size == "keep":
|
||||
flash_size = detect_flash_size(esp, args=None)
|
||||
if not esp.IS_STUB:
|
||||
print(
|
||||
"WARNING: In case of failure, please set a specific --flash_size."
|
||||
)
|
||||
else:
|
||||
flash_size = args.flash_size
|
||||
|
||||
@@ -968,14 +1081,29 @@ def arg_auto_chunk_size(string: str) -> int:
|
||||
return num
|
||||
|
||||
|
||||
def get_port_list():
|
||||
def get_port_list(vids=[], pids=[], names=[]):
|
||||
if list_ports is None:
|
||||
raise FatalError(
|
||||
"Listing all serial ports is currently not available. "
|
||||
"Please try to specify the port when running esptool.py or update "
|
||||
"the pyserial package to the latest version"
|
||||
)
|
||||
return sorted(ports.device for ports in list_ports.comports())
|
||||
ports = []
|
||||
for port in list_ports.comports():
|
||||
if sys.platform == "darwin" and port.device.endswith(
|
||||
("Bluetooth-Incoming-Port", "wlan-debug")
|
||||
):
|
||||
continue
|
||||
if vids and (port.vid is None or port.vid not in vids):
|
||||
continue
|
||||
if pids and (port.pid is None or port.pid not in pids):
|
||||
continue
|
||||
if names and (
|
||||
port.name is None or all(name not in port.name for name in names)
|
||||
):
|
||||
continue
|
||||
ports.append(port.device)
|
||||
return sorted(ports)
|
||||
|
||||
|
||||
def expand_file_arguments(argv):
|
||||
@@ -1001,6 +1129,53 @@ def expand_file_arguments(argv):
|
||||
return argv
|
||||
|
||||
|
||||
def connect_loop(
|
||||
port: str,
|
||||
initial_baud: int,
|
||||
chip: str,
|
||||
max_retries: int,
|
||||
trace: bool = False,
|
||||
before: str = "default_reset",
|
||||
):
|
||||
chip_class = CHIP_DEFS[chip]
|
||||
esp = None
|
||||
print(f"Serial port {port}")
|
||||
|
||||
first = True
|
||||
ten_cycle = cycle(chain(repeat(False, 9), (True,)))
|
||||
retry_loop = chain(
|
||||
repeat(False, max_retries - 1), (True,) if max_retries else cycle((False,))
|
||||
)
|
||||
|
||||
for last, every_tenth in zip(retry_loop, ten_cycle):
|
||||
try:
|
||||
esp = chip_class(port, initial_baud, trace)
|
||||
if not first:
|
||||
# break the retrying line
|
||||
print("")
|
||||
esp.connect(before)
|
||||
return esp
|
||||
except (
|
||||
FatalError,
|
||||
serial.serialutil.SerialException,
|
||||
IOError,
|
||||
OSError,
|
||||
) as err:
|
||||
if esp and esp._port:
|
||||
esp._port.close()
|
||||
esp = None
|
||||
if first:
|
||||
print(err)
|
||||
print("Retrying failed connection", end="", flush=True)
|
||||
first = False
|
||||
if last:
|
||||
raise err
|
||||
if every_tenth:
|
||||
# print a dot every second
|
||||
print(".", end="", flush=True)
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
def get_default_connected_device(
|
||||
serial_list,
|
||||
port,
|
||||
|
||||
Reference in New Issue
Block a user