Skip to content

Commit

Permalink
feat(esptool): add option to dump whole flash based on detected size
Browse files Browse the repository at this point in the history
Closes #461
  • Loading branch information
peterdragun authored and radimkarnis committed May 26, 2023
1 parent f558f22 commit 049baaa
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
8 changes: 8 additions & 0 deletions docs/en/esptool/basic-commands.rst
Expand Up @@ -105,6 +105,14 @@ The read_flash command allows reading back the contents of flash. The arguments

esptool.py -p PORT -b 460800 read_flash 0 0x200000 flash_contents.bin


It is also possible to autodetect flash size by using ``ALL`` as size. The above example with autodetection would look like this:

::

esptool.py -p PORT -b 460800 read_flash 0 ALL flash_contents.bin


.. 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.
Expand Down
32 changes: 29 additions & 3 deletions esptool/__init__.py
Expand Up @@ -39,6 +39,7 @@
import traceback

from esptool.cmds import (
DETECTED_FLASH_SIZES,
chip_id,
detect_chip,
detect_flash_size,
Expand Down Expand Up @@ -526,7 +527,9 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect):
add_spi_connection_arg(parser_read_flash)
parser_read_flash.add_argument("address", help="Start address", type=arg_auto_int)
parser_read_flash.add_argument(
"size", help="Size of region to dump", type=arg_auto_int
"size",
help="Size of region to dump. Use `ALL` to read to the end of flash.",
type=arg_auto_size,
)
parser_read_flash.add_argument("filename", help="Name of binary dump")
parser_read_flash.add_argument(
Expand Down Expand Up @@ -570,8 +573,9 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect):
)
parser_erase_region.add_argument(
"size",
help="Size of region to erase (must be multiple of 4096)",
type=arg_auto_int,
help="Size of region to erase (must be multiple of 4096). "
"Use `ALL` to erase to the end of flash.",
type=arg_auto_size,
)

parser_merge_bin = subparsers.add_parser(
Expand Down Expand Up @@ -827,6 +831,23 @@ def flash_xmc_startup():
"than 16MB, in case of failure use --no-stub."
)

if getattr(args, "size", "") == "all":
if esp.secure_download_mode:
raise FatalError(
"Detecting flash size is not supported in secure download mode. "
"Set an exact size value."
)
# detect flash size
flash_id = esp.flash_id()
size_id = flash_id >> 16
size_str = DETECTED_FLASH_SIZES.get(size_id)
if size_str is None:
raise FatalError(
"Detecting flash size failed. Set an exact size value."
)
print(f"Detected flash size: {size_str}")
args.size = flash_size_bytes(size_str)

if esp.IS_STUB and hasattr(args, "address") and hasattr(args, "size"):
if args.address + args.size > 0x1000000:
print(
Expand Down Expand Up @@ -871,6 +892,11 @@ def arg_auto_int(x):
return int(x, 0)


def arg_auto_size(x):
x = x.lower()
return x if x == "all" else arg_auto_int(x)


def get_port_list():
if list_ports is None:
raise FatalError(
Expand Down
4 changes: 4 additions & 0 deletions test/test_esptool.py
Expand Up @@ -776,6 +776,10 @@ def test_region_erase(self):
empty = self.readback(0x10000, 0x1000)
assert empty == b"\xFF" * 0x1000

def test_region_erase_all(self):
res = self.run_esptool("erase_region 0x0 ALL")
assert re.search(r"Detected flash size: \d+[KM]B", res) is not None

def test_large_region_erase(self):
# verifies that erasing a large region doesn't time out
self.run_esptool("erase_region 0x0 0x100000")
Expand Down

0 comments on commit 049baaa

Please sign in to comment.