mirror of
https://github.com/espressif/esptool.git
synced 2025-10-21 15:10:33 +08:00
feat(espefuse): Adds efuse dump formats: separated(default) and united(new)
Added features: - read cmds can be run after burn cmds - the dump cmd can be used to create a united efuse file in --virt mode - the dump cmd can be used a few times without changing original data - updated the doc
This commit is contained in:

committed by
Radim Karniš

parent
c2448436fc
commit
fc2856ae5f
@@ -10,7 +10,11 @@ The ``espefuse.py dump`` command allows:
|
|||||||
|
|
||||||
Optional arguments:
|
Optional arguments:
|
||||||
|
|
||||||
- ``--file_name`` - Saves dump for each block into separate file. Provide the common path name like /path/blk.bin, it will create: blk0.bin, blk1.bin ... blkN.bin. Then using ``burn_block_data`` command these dump files can be written to another chip.
|
- ``--format`` - Selects the dump format:
|
||||||
|
- ``default`` - Usual console eFuse dump;
|
||||||
|
- ``united`` - All eFuse blocks are stored in one file;
|
||||||
|
- ``separated`` - Each eFuse block is placed in a separate file. The tool will create multiple files based on the given the ``--file_name`` argument. Example: "--file_name /path/blk.bin", blk0.bin, blk1.bin ... blkN.bin. Use the ``burn_block_data`` cmd to write it back to another chip.
|
||||||
|
- ``--file_name`` - The path to the file in which to save the dump, if not specified, output to the console.
|
||||||
|
|
||||||
Raw Values Of Efuse Registers
|
Raw Values Of Efuse Registers
|
||||||
-----------------------------
|
-----------------------------
|
||||||
@@ -89,7 +93,7 @@ This command saves dump for each block into a separate file. You need to provide
|
|||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
> espefuse.py dump --file_name backup/chip1/blk.bin
|
> espefuse.py dump --format separated --file_name backup/chip1/blk.bin
|
||||||
|
|
||||||
=== Run "dump" command ===
|
=== Run "dump" command ===
|
||||||
backup/chip1/blk0.bin
|
backup/chip1/blk0.bin
|
||||||
@@ -111,3 +115,12 @@ These dump files can be written to another chip:
|
|||||||
> espefuse.py burn_block_data BLOCK0 backup/chip1/blk0.bin \
|
> espefuse.py burn_block_data BLOCK0 backup/chip1/blk0.bin \
|
||||||
BLOCK1 backup/chip1/blk1.bin \
|
BLOCK1 backup/chip1/blk1.bin \
|
||||||
BLOCK2 backup/chip1/blk2.bin
|
BLOCK2 backup/chip1/blk2.bin
|
||||||
|
|
||||||
|
To save all eFuse blocks in one file, use the following command:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
> espefuse.py dump --format united --file_name backup/chip1/efuses.bin
|
||||||
|
|
||||||
|
=== Run "dump" command ===
|
||||||
|
backup/chip1/efuses.bin
|
||||||
|
@@ -39,13 +39,15 @@ SUPPORTED_BURN_COMMANDS = [
|
|||||||
"execute_scripts",
|
"execute_scripts",
|
||||||
]
|
]
|
||||||
|
|
||||||
SUPPORTED_COMMANDS = [
|
SUPPORTED_READ_COMMANDS = [
|
||||||
"summary",
|
"summary",
|
||||||
"dump",
|
"dump",
|
||||||
"get_custom_mac",
|
"get_custom_mac",
|
||||||
"adc_info",
|
"adc_info",
|
||||||
"check_error",
|
"check_error",
|
||||||
] + SUPPORTED_BURN_COMMANDS
|
]
|
||||||
|
|
||||||
|
SUPPORTED_COMMANDS = SUPPORTED_READ_COMMANDS + SUPPORTED_BURN_COMMANDS
|
||||||
|
|
||||||
SUPPORTED_CHIPS = {
|
SUPPORTED_CHIPS = {
|
||||||
"esp32": DefChip("ESP32", esp32_efuse, esptool.targets.ESP32ROM),
|
"esp32": DefChip("ESP32", esp32_efuse, esptool.targets.ESP32ROM),
|
||||||
@@ -228,7 +230,7 @@ def main(custom_commandline=None, esp=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
common_args, remaining_args = init_parser.parse_known_args(custom_commandline)
|
common_args, remaining_args = init_parser.parse_known_args(custom_commandline)
|
||||||
debug_mode = common_args.debug or ("dump" in remaining_args)
|
debug_mode = common_args.debug
|
||||||
just_print_help = [
|
just_print_help = [
|
||||||
True for arg in remaining_args if arg in ["--help", "-h"]
|
True for arg in remaining_args if arg in ["--help", "-h"]
|
||||||
] or remaining_args == []
|
] or remaining_args == []
|
||||||
@@ -304,6 +306,22 @@ def main(custom_commandline=None, esp=None):
|
|||||||
if not efuses.burn_all(check_batch_mode=True):
|
if not efuses.burn_all(check_batch_mode=True):
|
||||||
raise esptool.FatalError("BURN was not done")
|
raise esptool.FatalError("BURN was not done")
|
||||||
print("Successful")
|
print("Successful")
|
||||||
|
|
||||||
|
if (
|
||||||
|
sum(cmd in SUPPORTED_BURN_COMMANDS for cmd in used_cmds) > 0
|
||||||
|
and sum(cmd in SUPPORTED_READ_COMMANDS for cmd in used_cmds) > 0
|
||||||
|
):
|
||||||
|
# [burn_cmd1] [burn_cmd2] [read_cmd1] [burn_cmd3] [read_cmd2]
|
||||||
|
print("\n=== Run read commands after burn commands ===")
|
||||||
|
for rem_args in grouped_remaining_args:
|
||||||
|
args, unused_args = parser.parse_known_args(
|
||||||
|
rem_args, namespace=common_args
|
||||||
|
)
|
||||||
|
current_cmd = args.operation
|
||||||
|
if current_cmd in SUPPORTED_READ_COMMANDS:
|
||||||
|
print(f"\n=== Run {args.operation} command ===")
|
||||||
|
operation_func = vars(efuse_operations)[current_cmd]
|
||||||
|
operation_func(esp, efuses, args)
|
||||||
finally:
|
finally:
|
||||||
if not external_esp and not common_args.virt and esp._port:
|
if not external_esp and not common_args.virt and esp._port:
|
||||||
esp._port.close()
|
esp._port.close()
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import os
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -173,12 +174,22 @@ def add_common_commands(subparsers, efuses):
|
|||||||
help="Display information about ADC calibration data stored in efuse.",
|
help="Display information about ADC calibration data stored in efuse.",
|
||||||
)
|
)
|
||||||
|
|
||||||
dump_cmd = subparsers.add_parser("dump", help="Dump raw hex values of all efuses")
|
dump_cmd = subparsers.add_parser("dump", help="Dump raw hex values of all eFuses")
|
||||||
|
dump_cmd.add_argument(
|
||||||
|
"--format",
|
||||||
|
help="Select the dump format: "
|
||||||
|
"default - usual console eFuse dump; "
|
||||||
|
"united - all eFuse blocks are stored in one file; "
|
||||||
|
"separated - each eFuse block is placed in a separate file. Tool will create multiple files based on "
|
||||||
|
"the given --file_name (/path/blk.bin): blk0.bin, blk1.bin ... blkN.bin. Use the burn_block_data cmd "
|
||||||
|
"to write it back to another chip.",
|
||||||
|
choices=["default", "separated", "united"],
|
||||||
|
default="default",
|
||||||
|
)
|
||||||
dump_cmd.add_argument(
|
dump_cmd.add_argument(
|
||||||
"--file_name",
|
"--file_name",
|
||||||
help="Saves dump for each block into separate file. Provide the common "
|
help="The path to the file in which to save the dump, if not specified, output to the console.",
|
||||||
"path name /path/blk.bin, it will create: blk0.bin, blk1.bin ... blkN.bin. "
|
default=sys.stdout,
|
||||||
"Use burn_block_data to write it back to another chip.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
summary_cmd = subparsers.add_parser(
|
summary_cmd = subparsers.add_parser(
|
||||||
@@ -379,23 +390,48 @@ def summary(esp, efuses, args):
|
|||||||
|
|
||||||
def dump(esp, efuses, args):
|
def dump(esp, efuses, args):
|
||||||
"""Dump raw efuse data registers"""
|
"""Dump raw efuse data registers"""
|
||||||
# Using --debug option allows to print dump.
|
dump_file = args.file_name
|
||||||
# Nothing to do here. The log will be printed
|
to_console = args.file_name == sys.stdout
|
||||||
# during EspEfuses.__init__() in self.read_blocks()
|
|
||||||
if args.file_name:
|
def output_block_to_file(block, f, to_console):
|
||||||
# save dump to the file
|
block_dump = BitStream(block.get_bitstring())
|
||||||
|
block_dump.byteswap()
|
||||||
|
if to_console:
|
||||||
|
f.write(block_dump.hex + "\n")
|
||||||
|
else:
|
||||||
|
block_dump.tofile(f)
|
||||||
|
|
||||||
|
if args.format == "default":
|
||||||
|
if to_console:
|
||||||
|
# for "espefuse.py dump" cmd
|
||||||
|
for block in efuses.blocks:
|
||||||
|
block.print_block(block.get_bitstring(), "dump", debug=True)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# for back compatibility to support "espefuse.py dump --file_name dump.bin"
|
||||||
|
args.format = "separated"
|
||||||
|
|
||||||
|
if args.format == "separated":
|
||||||
|
# each efuse block is placed in a separate file
|
||||||
for block in efuses.blocks:
|
for block in efuses.blocks:
|
||||||
file_dump_name = args.file_name
|
if not to_console:
|
||||||
place_for_index = file_dump_name.find(".bin")
|
file_dump_name = args.file_name
|
||||||
file_dump_name = (
|
fname, fextension = os.path.splitext(file_dump_name)
|
||||||
file_dump_name[:place_for_index]
|
file_dump_name = f"{fname}{block.id}{fextension}"
|
||||||
+ str(block.id)
|
print(f"Dump efuse block{block.id} -> {file_dump_name}")
|
||||||
+ file_dump_name[place_for_index:]
|
dump_file = open(file_dump_name, "wb")
|
||||||
)
|
output_block_to_file(block, dump_file, to_console)
|
||||||
print(file_dump_name)
|
if not to_console:
|
||||||
with open(file_dump_name, "wb") as f:
|
dump_file.close()
|
||||||
block.get_bitstring().byteswap()
|
elif args.format == "united":
|
||||||
block.get_bitstring().tofile(f)
|
# all efuse blocks are stored in one file
|
||||||
|
if not to_console:
|
||||||
|
print(f"Dump efuse blocks -> {args.file_name}")
|
||||||
|
dump_file = open(args.file_name, "wb")
|
||||||
|
for block in efuses.blocks:
|
||||||
|
output_block_to_file(block, dump_file, to_console)
|
||||||
|
if not to_console:
|
||||||
|
dump_file.close()
|
||||||
|
|
||||||
|
|
||||||
def burn_efuse(esp, efuses, args):
|
def burn_efuse(esp, efuses, args):
|
||||||
|
@@ -38,12 +38,7 @@ class EmulateEfuseController(EmulateEfuseControllerBase):
|
|||||||
if addr == self.REGS.APB_CTL_DATE_ADDR:
|
if addr == self.REGS.APB_CTL_DATE_ADDR:
|
||||||
return self.REGS.APB_CTL_DATE_V << self.REGS.APB_CTL_DATE_S
|
return self.REGS.APB_CTL_DATE_V << self.REGS.APB_CTL_DATE_S
|
||||||
else:
|
else:
|
||||||
val = 0
|
return super(EmulateEfuseController, self).read_reg(addr)
|
||||||
if addr == self.REGS.EFUSE_BLK0_RDATA3_REG:
|
|
||||||
val = self.REGS.EFUSE_RD_CHIP_VER_REV1
|
|
||||||
if addr == self.REGS.EFUSE_BLK0_RDATA5_REG:
|
|
||||||
val = self.REGS.EFUSE_RD_CHIP_VER_REV2
|
|
||||||
return val | super(EmulateEfuseController, self).read_reg(addr)
|
|
||||||
|
|
||||||
""" << esptool method end """
|
""" << esptool method end """
|
||||||
|
|
||||||
|
@@ -73,6 +73,7 @@ class EfuseTestCase:
|
|||||||
f"{sys.executable} -m espefuse --chip {arg_chip} "
|
f"{sys.executable} -m espefuse --chip {arg_chip} "
|
||||||
f"--virt --path-efuse-file {self.efuse_file.name} -d"
|
f"--virt --path-efuse-file {self.efuse_file.name} -d"
|
||||||
)
|
)
|
||||||
|
self._set_target_wafer_version()
|
||||||
else:
|
else:
|
||||||
self.base_cmd = (
|
self.base_cmd = (
|
||||||
f"{sys.executable} -m espefuse --chip {arg_chip} "
|
f"{sys.executable} -m espefuse --chip {arg_chip} "
|
||||||
@@ -117,6 +118,11 @@ class EfuseTestCase:
|
|||||||
def _set_none_recovery_coding_scheme(self):
|
def _set_none_recovery_coding_scheme(self):
|
||||||
self.espefuse_py("burn_efuse CODING_SCHEME 3")
|
self.espefuse_py("burn_efuse CODING_SCHEME 3")
|
||||||
|
|
||||||
|
def _set_target_wafer_version(self):
|
||||||
|
# ESP32 has to be ECO3 (v3.0) for tests
|
||||||
|
if arg_chip == "esp32":
|
||||||
|
self.espefuse_py("burn_efuse CHIP_VER_REV1 1 CHIP_VER_REV2 1")
|
||||||
|
|
||||||
def check_data_block_in_log(
|
def check_data_block_in_log(
|
||||||
self, log, file_path, repeat=1, reverse_order=False, offset=0
|
self, log, file_path, repeat=1, reverse_order=False, offset=0
|
||||||
):
|
):
|
||||||
@@ -177,6 +183,18 @@ class TestReadCommands(EfuseTestCase):
|
|||||||
self.espefuse_py("dump -h")
|
self.espefuse_py("dump -h")
|
||||||
self.espefuse_py("dump")
|
self.espefuse_py("dump")
|
||||||
|
|
||||||
|
def test_dump_format_united(self):
|
||||||
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
self.espefuse_py(f"dump --format united --file_name {tmp_file.name}")
|
||||||
|
|
||||||
|
def test_dump_separated_default(self):
|
||||||
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
self.espefuse_py(f"dump --file_name {tmp_file.name}")
|
||||||
|
|
||||||
|
def test_dump_separated(self):
|
||||||
|
tmp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
self.espefuse_py(f"dump --format separated --file_name {tmp_file.name}")
|
||||||
|
|
||||||
def test_summary(self):
|
def test_summary(self):
|
||||||
self.espefuse_py("summary -h")
|
self.espefuse_py("summary -h")
|
||||||
self.espefuse_py("summary")
|
self.espefuse_py("summary")
|
||||||
|
Reference in New Issue
Block a user