mirror of
https://github.com/espressif/esptool.git
synced 2025-10-19 20:13:00 +08:00
fix(read_flash): add flash size arg to enable reading past 2MB without stub
This commit is contained in:

committed by
Radim Karniš

parent
8ce5ed3c2b
commit
f1eb65f885
@@ -113,6 +113,11 @@ It is also possible to autodetect flash size by using ``ALL`` as size. The above
|
||||
esptool.py -p PORT -b 460800 read_flash 0 ALL flash_contents.bin
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
When using the ``read_flash`` command in combination with the ``--no-stub`` argument, it may be necessary to also set the ``--flash_size`` argument to ensure proper reading of the flash contents by the ROM.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
If ``write_flash`` updated the boot image's :ref:`flash mode and flash size <flash-modes>` during flashing then these bytes may be different when read back.
|
||||
|
@@ -217,7 +217,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 +239,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",
|
||||
@@ -540,7 +547,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",
|
||||
|
@@ -329,11 +329,17 @@ class ESP32ROM(ESPLoader):
|
||||
data = b""
|
||||
while len(data) < length:
|
||||
block_len = min(BLOCK_LEN, length - len(data))
|
||||
r = self.check_command(
|
||||
"read flash block",
|
||||
self.ESP_READ_FLASH_SLOW,
|
||||
struct.pack("<II", offset + len(data), block_len),
|
||||
)
|
||||
try:
|
||||
r = self.check_command(
|
||||
"read flash block",
|
||||
self.ESP_READ_FLASH_SLOW,
|
||||
struct.pack("<II", offset + len(data), block_len),
|
||||
)
|
||||
except FatalError:
|
||||
print(
|
||||
"Hint: Consider specifying flash size using '--flash_size' argument"
|
||||
)
|
||||
raise
|
||||
if len(r) < block_len:
|
||||
raise FatalError(
|
||||
"Expected %d byte block, got %d bytes. Serial errors?"
|
||||
|
@@ -251,6 +251,12 @@ class EsptoolTestCase:
|
||||
dump_file.close()
|
||||
os.unlink(dump_file.name)
|
||||
|
||||
def diff(self, readback, compare_to):
|
||||
for rb_b, ct_b, offs in zip(readback, compare_to, range(len(readback))):
|
||||
assert (
|
||||
rb_b == ct_b
|
||||
), f"First difference at offset {offs:#x} Expected {ct_b} got {rb_b}"
|
||||
|
||||
def verify_readback(
|
||||
self, offset, length, compare_to, is_bootloader=False, spi_connection=None
|
||||
):
|
||||
@@ -268,10 +274,7 @@ class EsptoolTestCase:
|
||||
assert ct[0] == rb[0], "First bytes should be identical"
|
||||
rb = rb[8:]
|
||||
ct = ct[8:]
|
||||
for rb_b, ct_b, offs in zip(rb, ct, range(len(rb))):
|
||||
assert (
|
||||
rb_b == ct_b
|
||||
), f"First difference at offset {offs:#x} Expected {ct_b} got {rb_b}"
|
||||
self.diff(rb, ct)
|
||||
|
||||
|
||||
@pytest.mark.skipif(arg_chip != "esp32", reason="ESP32 only")
|
||||
@@ -735,6 +738,32 @@ class TestFlashSizes(EsptoolTestCase):
|
||||
# header should be the same as in the .bin file
|
||||
self.verify_readback(offset, image_len, image)
|
||||
|
||||
@pytest.mark.skipif(
|
||||
arg_chip == "esp8266", reason="ESP8266 does not support read_flash_slow"
|
||||
)
|
||||
def test_read_nostub_high_offset(self):
|
||||
offset = 0x300000
|
||||
length = 1024
|
||||
self.run_esptool(f"write_flash -fs detect {offset} images/one_kb.bin")
|
||||
dump_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
# readback with no-stub and flash-size set
|
||||
try:
|
||||
self.run_esptool(
|
||||
f"--no-stub read_flash -fs detect {offset} 1024 {dump_file.name}"
|
||||
)
|
||||
with open(dump_file.name, "rb") as f:
|
||||
rb = f.read()
|
||||
assert length == len(
|
||||
rb
|
||||
), f"read_flash length {length} offset {offset:#x} yielded {len(rb)} bytes!"
|
||||
finally:
|
||||
dump_file.close()
|
||||
os.unlink(dump_file.name)
|
||||
# compare files
|
||||
with open("images/one_kb.bin", "rb") as f:
|
||||
ct = f.read()
|
||||
self.diff(rb, ct)
|
||||
|
||||
|
||||
class TestFlashDetection(EsptoolTestCase):
|
||||
@pytest.mark.quick_test
|
||||
@@ -1337,10 +1366,7 @@ class TestMakeImage(EsptoolTestCase):
|
||||
f"WARNING: Expected length {len(ct)} doesn't match comparison {len(rb)}"
|
||||
)
|
||||
print(f"Readback {len(rb)} bytes")
|
||||
for rb_b, ct_b, offs in zip(rb, ct, range(len(rb))):
|
||||
assert (
|
||||
rb_b == ct_b
|
||||
), f"First difference at offset {offs:#x} Expected {ct_b} got {rb_b}"
|
||||
self.diff(rb, ct)
|
||||
|
||||
def test_make_image(self):
|
||||
output = self.run_esptool(
|
||||
|
Reference in New Issue
Block a user