mirror of
https://github.com/espressif/esptool.git
synced 2025-10-16 23:06:31 +08:00
feat(esptool): add new command SFDP read
This commit is contained in:
@@ -120,6 +120,18 @@ A second option ``--non-volatile`` can be used in order to send a ``WREN`` (06h)
|
||||
|
||||
Setting status bits (particularly non-volatile ones) can have permanent side effects for some flash chips, so check carefully before using this command to set any bits!
|
||||
|
||||
.. _read-flash-sfdp:
|
||||
|
||||
Read Serial Flash Discoverable Parameters (SFDP)
|
||||
------------------------------------------------
|
||||
|
||||
The Serial Flash Discoverable Parameters (SFDP) store essential vendor-specific configuration data of the flash memory chip. These parameters help identify and interact with different flash devices. Usage:
|
||||
|
||||
::
|
||||
esptool.py read_flash_sfdp 16 4
|
||||
|
||||
This will read 4 bytes from SFDP address 16.
|
||||
|
||||
.. only:: esp8266
|
||||
|
||||
.. _chip-id:
|
||||
|
@@ -338,6 +338,7 @@ The following commands are less commonly used, or only of interest to advanced u
|
||||
* :ref:`read-mem-write-mem`
|
||||
* :ref:`read-flash-status`
|
||||
* :ref:`write-flash-status`
|
||||
* :ref:`read-flash-sfdp`
|
||||
:esp8266: * :ref:`chip-id`
|
||||
:esp8266: * :ref:`make-image`
|
||||
:esp8266: * :ref:`run`
|
||||
|
@@ -49,6 +49,7 @@ from esptool.cmds import (
|
||||
erase_flash,
|
||||
erase_region,
|
||||
flash_id,
|
||||
read_flash_sfdp,
|
||||
get_security_info,
|
||||
image_info,
|
||||
load_ram,
|
||||
@@ -627,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",
|
||||
|
@@ -1164,7 +1164,7 @@ def run(esp, args):
|
||||
esp.run()
|
||||
|
||||
|
||||
def flash_id(esp, args):
|
||||
def detect_flash_id(esp):
|
||||
flash_id = esp.flash_id()
|
||||
print("Manufacturer: %02x" % (flash_id & 0xFF))
|
||||
flid_lowbyte = (flash_id >> 16) & 0xFF
|
||||
@@ -1172,6 +1172,10 @@ def flash_id(esp, args):
|
||||
print(
|
||||
"Detected flash size: %s" % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown"))
|
||||
)
|
||||
|
||||
|
||||
def flash_id(esp, args):
|
||||
detect_flash_id(esp)
|
||||
flash_type = esp.flash_type()
|
||||
flash_type_dict = {0: "quad (4 data lines)", 1: "octal (8 data lines)"}
|
||||
flash_type_str = flash_type_dict.get(flash_type)
|
||||
@@ -1180,6 +1184,17 @@ def flash_id(esp, args):
|
||||
esp.get_flash_voltage()
|
||||
|
||||
|
||||
def read_flash_sfdp(esp, args):
|
||||
detect_flash_id(esp)
|
||||
|
||||
sfdp = esp.read_spiflash_sfdp(args.addr, args.bytes * 8)
|
||||
print(f"SFDP[{args.addr}..{args.addr+args.bytes-1}]: ", end="")
|
||||
for i in range(args.bytes):
|
||||
print(f"{sfdp&0xff:02X} ", end="")
|
||||
sfdp = sfdp >> 8
|
||||
print()
|
||||
|
||||
|
||||
def read_flash(esp, args):
|
||||
if args.no_progress:
|
||||
flash_progress = None
|
||||
|
@@ -268,6 +268,9 @@ class ESPLoader(object):
|
||||
|
||||
UART_DATE_REG_ADDR = 0x60000078
|
||||
|
||||
# Whether the SPI peripheral sends from MSB of 32-bit register, or the MSB of valid LSB bits.
|
||||
SPI_ADDR_REG_MSB = True
|
||||
|
||||
# This ROM address has a different value on each chip model
|
||||
CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000
|
||||
|
||||
@@ -1392,7 +1395,9 @@ class ESPLoader(object):
|
||||
self.write_reg(
|
||||
SPI_USR2_REG, (7 << SPI_USR2_COMMAND_LEN_SHIFT) | spiflash_command
|
||||
)
|
||||
if addr and addr_len > 0:
|
||||
if addr_len > 0:
|
||||
if self.SPI_ADDR_REG_MSB:
|
||||
addr = addr << (32 - addr_len)
|
||||
self.write_reg(SPI_ADDR_REG, addr)
|
||||
if data_bits == 0:
|
||||
self.write_reg(SPI_W0_REG, 0) # clear data register before we read it
|
||||
|
@@ -28,6 +28,8 @@ class ESP32C3ROM(ESP32ROM):
|
||||
SPI_MISO_DLEN_OFFS = 0x28
|
||||
SPI_W0_OFFS = 0x58
|
||||
|
||||
SPI_ADDR_REG_MSB = False
|
||||
|
||||
BOOTLOADER_FLASH_OFFSET = 0x0
|
||||
|
||||
# Magic values for ESP32-C3 eco 1+2, eco 3, eco 6, and eco 7 respectively
|
||||
|
@@ -38,6 +38,8 @@ class ESP32P4ROM(ESP32ROM):
|
||||
SPI_MISO_DLEN_OFFS = 0x28
|
||||
SPI_W0_OFFS = 0x58
|
||||
|
||||
SPI_ADDR_REG_MSB = False
|
||||
|
||||
EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address
|
||||
|
||||
EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34
|
||||
|
@@ -32,6 +32,8 @@ class ESP32S2ROM(ESP32ROM):
|
||||
SPI_MISO_DLEN_OFFS = 0x28
|
||||
SPI_W0_OFFS = 0x58
|
||||
|
||||
SPI_ADDR_REG_MSB = False
|
||||
|
||||
MAC_EFUSE_REG = 0x3F41A044 # ESP32-S2 has special block for MAC efuses
|
||||
|
||||
UART_CLKDIV_REG = 0x3F400014
|
||||
|
@@ -35,6 +35,8 @@ class ESP32S3ROM(ESP32ROM):
|
||||
SPI_MISO_DLEN_OFFS = 0x28
|
||||
SPI_W0_OFFS = 0x58
|
||||
|
||||
SPI_ADDR_REG_MSB = False
|
||||
|
||||
BOOTLOADER_FLASH_OFFSET = 0x0
|
||||
|
||||
SUPPORTS_ENCRYPTED_FLASH = True
|
||||
|
@@ -841,6 +841,14 @@ class TestFlashDetection(EsptoolTestCase):
|
||||
for line in lines:
|
||||
assert "embedded flash" not in line.lower()
|
||||
|
||||
@pytest.mark.quick_test
|
||||
def test_flash_sfdp(self):
|
||||
"""Test manufacturer and device response of flash detection."""
|
||||
res = self.run_esptool("read_flash_sfdp 0 4")
|
||||
assert "SFDP[0..3]: 53 46 44 50" in res
|
||||
res = self.run_esptool("read_flash_sfdp 1 3")
|
||||
assert "SFDP[1..3]: 46 44 50 " in res
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.getenv("ESPTOOL_TEST_SPI_CONN") is None, reason="Needs external flash"
|
||||
|
Reference in New Issue
Block a user