Skip to content

Commit

Permalink
feat(espefuse): Adds efuse dump formats: separated(default) and unite…
Browse files Browse the repository at this point in the history
…d(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
  • Loading branch information
KonstantinKondrashov authored and radimkarnis committed Jun 18, 2024
1 parent c244843 commit fc2856a
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 31 deletions.
17 changes: 15 additions & 2 deletions docs/en/espefuse/dump-cmd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ The ``espefuse.py dump`` command allows:

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
-----------------------------
Expand Down Expand Up @@ -89,7 +93,7 @@ This command saves dump for each block into a separate file. You need to provide

.. 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 ===
backup/chip1/blk0.bin
Expand All @@ -111,3 +115,12 @@ These dump files can be written to another chip:
> espefuse.py burn_block_data BLOCK0 backup/chip1/blk0.bin \
BLOCK1 backup/chip1/blk1.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
24 changes: 21 additions & 3 deletions espefuse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
"execute_scripts",
]

SUPPORTED_COMMANDS = [
SUPPORTED_READ_COMMANDS = [
"summary",
"dump",
"get_custom_mac",
"adc_info",
"check_error",
] + SUPPORTED_BURN_COMMANDS
]

SUPPORTED_COMMANDS = SUPPORTED_READ_COMMANDS + SUPPORTED_BURN_COMMANDS

SUPPORTED_CHIPS = {
"esp32": DefChip("ESP32", esp32_efuse, esptool.targets.ESP32ROM),
Expand Down Expand Up @@ -228,7 +230,7 @@ def main(custom_commandline=None, esp=None):
)

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 = [
True for arg in remaining_args if arg in ["--help", "-h"]
] or remaining_args == []
Expand Down Expand Up @@ -304,6 +306,22 @@ def main(custom_commandline=None, esp=None):
if not efuses.burn_all(check_batch_mode=True):
raise esptool.FatalError("BURN was not done")
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:
if not external_esp and not common_args.virt and esp._port:
esp._port.close()
Expand Down
76 changes: 56 additions & 20 deletions espefuse/efuse/base_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later

import argparse
import os
import json
import sys

Expand Down Expand Up @@ -173,12 +174,22 @@ def check_efuse_name(efuse_name, efuse_list):
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(
"--file_name",
help="Saves dump for each block into separate file. Provide the common "
"path name /path/blk.bin, it will create: blk0.bin, blk1.bin ... blkN.bin. "
"Use burn_block_data to write it back to another chip.",
help="The path to the file in which to save the dump, if not specified, output to the console.",
default=sys.stdout,
)

summary_cmd = subparsers.add_parser(
Expand Down Expand Up @@ -379,23 +390,48 @@ def summary(esp, efuses, args):

def dump(esp, efuses, args):
"""Dump raw efuse data registers"""
# Using --debug option allows to print dump.
# Nothing to do here. The log will be printed
# during EspEfuses.__init__() in self.read_blocks()
if args.file_name:
# save dump to the file
dump_file = args.file_name
to_console = args.file_name == sys.stdout

def output_block_to_file(block, f, to_console):
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:
file_dump_name = args.file_name
place_for_index = file_dump_name.find(".bin")
file_dump_name = (
file_dump_name[:place_for_index]
+ str(block.id)
+ file_dump_name[place_for_index:]
)
print(file_dump_name)
with open(file_dump_name, "wb") as f:
block.get_bitstring().byteswap()
block.get_bitstring().tofile(f)
if not to_console:
file_dump_name = args.file_name
fname, fextension = os.path.splitext(file_dump_name)
file_dump_name = f"{fname}{block.id}{fextension}"
print(f"Dump efuse block{block.id} -> {file_dump_name}")
dump_file = open(file_dump_name, "wb")
output_block_to_file(block, dump_file, to_console)
if not to_console:
dump_file.close()
elif args.format == "united":
# 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):
Expand Down
7 changes: 1 addition & 6 deletions espefuse/efuse/esp32/emulate_efuse_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,7 @@ def read_reg(self, addr):
if addr == self.REGS.APB_CTL_DATE_ADDR:
return self.REGS.APB_CTL_DATE_V << self.REGS.APB_CTL_DATE_S
else:
val = 0
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)
return super(EmulateEfuseController, self).read_reg(addr)

""" << esptool method end """

Expand Down
18 changes: 18 additions & 0 deletions test/test_espefuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def setup_method(self):
f"{sys.executable} -m espefuse --chip {arg_chip} "
f"--virt --path-efuse-file {self.efuse_file.name} -d"
)
self._set_target_wafer_version()
else:
self.base_cmd = (
f"{sys.executable} -m espefuse --chip {arg_chip} "
Expand Down Expand Up @@ -117,6 +118,11 @@ def _set_34_coding_scheme(self):
def _set_none_recovery_coding_scheme(self):
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(
self, log, file_path, repeat=1, reverse_order=False, offset=0
):
Expand Down Expand Up @@ -177,6 +183,18 @@ def test_dump(self):
self.espefuse_py("dump -h")
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):
self.espefuse_py("summary -h")
self.espefuse_py("summary")
Expand Down

0 comments on commit fc2856a

Please sign in to comment.