- 开发工具
- 嵌入式
- 硬件开发
【免费下载链接】esptool
Serial utility for flashing, provisioning, and interacting with Espressif SoCs
espefuse summary 是 ESP-IDF 官方工具 esptool 套件中用于读取芯片 eFuse(电子熔丝)并生成文本或 JSON 格式摘要的核心命令。本文以当前仓库 docs/en/espefuse/summary-cmd.rst 文档为主线,结合 espefuse/efuse/base_operations.py 等源码实现,系统讲解该命令的参数用法、文本/JSON 输出格式、读写保护状态语义、按名称过滤与 value_only 模式,并给出完整的可复现实战示例。读完本文,你将掌握如何快速查看芯片 eFuse 烧录状态、定位安全配置(如安全启动、Flash 加密、MAC 地址)并理解每个字段的含义。
命令概览:读取 eFuse 并输出摘要
espefuse summary命令用于从芯片读取 eFuse 内容,并以文本或 JSON 格式输出,也可以将结果直接保存到文件,同时支持按 eFuse 名称进行过滤。其底层实现在 espefuse/efuse/base_operations.py 中:命令行定义位于 base_operations.py 第 424-441 行,核心逻辑summary()方法位于 base_operations.py 第 693-847 行。
命令的完整用法如下:
espefuse summary [OPTIONS] [EFUSES_TO_SHOW]...可选参数一览
| 参数 | 说明 | 示例 |
|---|---|---|
--format | 选择摘要输出格式:summary(默认,文本格式)、json(JSON 格式)、value_only(仅显示指定 eFuse 的值) | --format json |
--active | 只显示活跃字段(至少有一位被置位、被读/写保护、或存在编码错误的字段) | --active |
--file | 将摘要保存到指定文件 | --file efuses.json |
EFUSES_TO_SHOW | 位置参数,指定要过滤显示的 eFuse 名称列表(不指定则显示全部摘要) | summary ABS_DONE_0 BLOCK1 |
从源码看,--format的可选值通过click.Choice(["summary", "json", "value_only"])校验(base_operations.py 第 426-431 行),--active是布尔开关,--file通过click.File("w")打开用于写入的文件。底层summary()方法接受四个参数:efuses_to_show(eFuse 名称列表)、format(输出格式)、file(输出文件,默认sys.stdout)、active(是否只显示活跃字段)。
文本格式摘要(默认)
文本格式(--format summary)是默认输出方式,每一行由 3 个主要列组成:
- eFuse 名称及附加信息:包含 eFuse 名称、该字段所属的块(Block),以及存在的编码错误信息(如果有)。
- 字段描述:对 eFuse 字段用途的说明。
- 可读值、读写保护状态、原始值:人类可读的值、读/写保护状态,以及原始值(十六进制或二进制)。
对应源码中ROW_FORMAT = "%-50s %-50s%s = %s %s %s"定义了这六列的对齐格式(base_operations.py 第 710 行),表头为EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)。
每个 eFuse 字段按类别(Category)分组输出,类别包括 Calibration、Config、Flash、Identity、Jtag、Mac、Security、Spi Pad、Vdd 等,分组顺序按类别名排序(base_operations.py 第 735-737 行)。输出末尾还会追加整个 eFuse 系统的汇总信息(如 Flash 电压判定结论),以及编码方案警告(若存在编码位错误,会追加WARNING: Coding scheme has encoding bit error warnings,见 base_operations.py 第 832-838 行)。
读写保护状态(R/W 标记)
文本摘要中每个字段末尾的R/W标记表示该字段/块的读、写保护状态:
| 标记 | 含义 |
|---|---|
-/W | 已设置读保护。此类 eFuse 字段的值始终显示为全零,即使硬件实际使用正确值。espefuse v2.6 及更新版本中,读保护 eFuse 的值显示为问号(??);更早版本显示为零 |
R/- | 已设置写保护。不能再置位任何额外的位 |
-/- | 读保护和写保护均已设置 |
部分 eFuse 没有任何保护,部分 eFuse 只有读保护或只有写保护,摘要中没有任何标记来区分这些情况。
读保护场景的典型输出如下:
BLOCK1 (BLOCK1): = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/W从源码实现看,保护状态的计算逻辑位于 base_operations.py 第 745-753 行:通过e.is_readable()与e.is_writeable()判断后映射为R/W、R/-、-/W、-/-四种标记。而“不可读字段显示问号”的逻辑在 base_operations.py 第 756-768 行:当字段不可读且位全为 0 时,将值中的0替换为?;对于 ESP32-C2 等具有两个读保护位的块(如 BLOCK_KEY0 的低半部与高半部),会分别处理两部分(第 759-766 行)。
显示 eFuse 摘要(ESP32 芯片示例)
eFuse 摘要可能随工具版本不同、芯片不同而有所差异。以下为当前仓库中 ESP32 芯片的摘要示例(完整内容见 docs/en/espefuse/inc/summary_ESP32.rst):
> espefuse -p PORT summary Connecting........__ Detecting chip type... ESP32 === Run "summary" command === EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) ---------------------------------------------------------------------------------------- Calibration fuses: ADC_VREF (BLOCK0): True ADC reference voltage = 1121 R/W (0b00011) Config fuses: WR_DIS (BLOCK0): Efuse write disable mask = 0 R/W (0x0000) RD_DIS (BLOCK0): Disable reading from BlOCK1-3 = 0 R/W (0x0) DISABLE_APP_CPU (BLOCK0): Disables APP CPU = False R/W (0b0) DISABLE_BT (BLOCK0): Disables Bluetooth = False R/W (0b0) DIS_CACHE (BLOCK0): Disables cache = False R/W (0b0) CHIP_CPU_FREQ_LOW (BLOCK0): If set alongside EFUSE_RD_CHIP_CPU_FREQ_RATED; the = False R/W (0b0) ESP32's max CPU frequency is rated for 160MHz. 24 0MHz otherwise CHIP_CPU_FREQ_RATED (BLOCK0): If set; the ESP32's maximum CPU frequency has been = True R/W (0b1) rated BLK3_PART_RESERVE (BLOCK0): BLOCK3 partially served for ADC calibration data = False R/W (0b0) CLK8M_FREQ (BLOCK0): 8MHz clock freq override = 51 R/W (0x33) VOL_LEVEL_HP_INV (BLOCK0): This field stores the voltage level for CPU to run = 0 R/W (0b00) at 240 MHz; or for flash/PSRAM to run at 80 MHz.0 x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: leve l 4. (RO) CODING_SCHEME (BLOCK0): Efuse variable block length scheme = NONE (BLK1-3 len=256 bits) R/W (0b00) CONSOLE_DEBUG_DISABLE (BLOCK0): Disable ROM BASIC interpreter fallback = True R/W (0b1) DISABLE_SDIO_HOST (BLOCK0): = False R/W (0b0) DISABLE_DL_CACHE (BLOCK0): Disable flash cache in UART bootloader = False R/W (0b0) Flash fuses: FLASH_CRYPT_CNT (BLOCK0): Flash encryption is enabled if this field has an o = 0 R/W (0b0000000) dd number of bits set FLASH_CRYPT_CONFIG (BLOCK0): Flash encryption config (key tweak bits) = 0 R/W (0x0) Identity fuses: CHIP_PACKAGE_4BIT (BLOCK0): Chip package identifier #4bit = False R/W (0b0) CHIP_PACKAGE (BLOCK0): Chip package identifier = 1 R/W (0b001) CHIP_VER_REV1 (BLOCK0): bit is set to 1 for rev1 silicon = True R/W (0b1) CHIP_VER_REV2 (BLOCK0): = True R/W (0b1) WAFER_VERSION_MINOR (BLOCK0): = 0 R/W (0b00) WAFER_VERSION_MAJOR (BLOCK0): calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CH = 3 R/W (0b011) IP_VER_REV2 and apb_ctl_date (read only) PKG_VERSION (BLOCK0): calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_ = 1 R/W (0x1) PACKAGE (read only) Jtag fuses: JTAG_DISABLE (BLOCK0): Disable JTAG = False R/W (0b0) Mac fuses: MAC (BLOCK0): MAC address = 94:b9:7e:5a:6e:58 (CRC 0xe2 OK) R/W MAC_CRC (BLOCK0): CRC8 for MAC address = 226 R/W (0xe2) MAC_VERSION (BLOCK3): Version of the MAC field = 0 R/W (0x00) Security fuses: UART_DOWNLOAD_DIS (BLOCK0): Disable UART download mode. Valid for ESP32 V3 and = False R/W (0b0) newer; only ABS_DONE_0 (BLOCK0): Secure boot V1 is enabled for bootloader image = False R/W (0b0) ABS_DONE_1 (BLOCK0): Secure boot V2 is enabled for bootloader image = False R/W (0b0) DISABLE_DL_ENCRYPT (BLOCK0): Disable flash encryption in UART bootloader = False R/W (0b0) DISABLE_DL_DECRYPT (BLOCK0): Disable flash decryption in UART bootloader = False R/W (0b0) KEY_STATUS (BLOCK0): Usage of efuse block 3 (reserved) = False R/W (0b0) SECURE_VERSION (BLOCK3): Secure version for anti-rollback = 0 R/W (0x00000000) BLOCK1 (BLOCK1): Flash encryption key = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK2 (BLOCK2): Security boot key = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK3 (BLOCK3): Variable Block 3 = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W Spi Pad fuses: SPI_PAD_CONFIG_HD (BLOCK0): read for SPI_pad_config_hd = 0 R/W (0b00000) SPI_PAD_CONFIG_CLK (BLOCK0): Override SD_CLK pad (GPIO6/SPICLK) = 0 R/W (0b00000) SPI_PAD_CONFIG_Q (BLOCK0): Override SD_DATA_0 pad (GPIO7/SPIQ) = 0 R/W (0b00000) SPI_PAD_CONFIG_D (BLOCK0): Override SD_DATA_1 pad (GPIO8/SPID) = 0 R/W (0b00000) SPI_PAD_CONFIG_CS0 (BLOCK0): Override SD_CMD pad (GPIO11/SPICS0) = 0 R/W (0b00000) Vdd fuses: XPD_SDIO_REG (BLOCK0): read for XPD_SDIO_REG = False R/W (0b0) XPD_SDIO_TIEH (BLOCK0): If XPD_SDIO_FORCE & XPD_SDIO_REG = 1.8V R/W (0b0) XPD_SDIO_FORCE (BLOCK0): Ignore MTDI pin (GPIO12) for VDD_SDIO on reset = False R/W (0b0) Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V)解读要点:
- 每个字段的原始值列在行末的括号中:
(0b0)为二进制、(0x00)为十六进制,而bytes类型字段(如BLOCK1、BLOCK2、BLOCK3)不显示括号原始值,直接给出按字节排列的十六进制序列。 - 字段值带有描述性含义:例如
CODING_SCHEME显示为NONE (BLK1-3 len=256 bits),MAC显示为带 CRC 校验的地址(CRC 0xe2 OK),这些都是通过字段的“字典值/含义解析”得到的人类可读结果。 - 最后一行的
Flash voltage (VDD_SDIO) determined by GPIO12 on reset是整个 eFuse 系统的汇总信息,由各芯片的summary()实现(各芯片fields.py中的summary()方法,如 esp32/fields.py 第 199 行)生成。
除 ESP32 外,当前仓库还为 ESP32-C2/C3/C5/C6/C61、ESP32-H2/H21/H4、ESP32-P4、ESP32-S2/S3/S31 等芯片提供了对应的摘要示例文件,位于 docs/en/espefuse/inc/ 目录(summary_<CHIP>.rst),不同芯片的 eFuse 字段布局和类别划分可能不同。
JSON 格式摘要
--format json将 eFuse 摘要输出为 JSON 对象,每个字段是一个以字段名为 key 的条目。以下为 ESP32 芯片的 JSON 摘要示例:
> espefuse summary --format json { "ABS_DONE_0": { "bit_len": 1, "block": 0, "category": "security", "description": "Secure boot V1 is enabled for bootloader image", "efuse_type": "bool", "name": "ABS_DONE_0", "pos": 4, "raw_value": "0x0", "readable": true, "value": false, "word": 6, "writeable": true }, "BLOCK1": { "bit_len": 256, "block": 1, "category": "security", "description": "Flash encryption key", "efuse_type": "bytes:32", "name": "BLOCK1", "pos": 0, "raw_value": "0x0000000000000000000000000000000000000000000000000000000000000000", "readable": true, "value": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "word": 0, "writeable": true }, ... "CODING_SCHEME": { "bit_len": 2, "block": 0, "category": "config", "description": "Efuse variable block length scheme", "efuse_type": "uint:2", "name": "CODING_SCHEME", "pos": 0, "raw_value": "0x0", "readable": true, "value": "NONE (BLK1-3 len=256 bits)", "word": 6, "writeable": true }, ... }JSON 字段结构说明
从源码 base_operations.py 第 810-825 行 可以看到,每个 JSON 条目包含以下字段:
| 键 | 含义 |
|---|---|
name | eFuse 字段名称 |
value | 可读时的含义值(human readable);若不可读则为问号掩码后的值 |
raw_value | 熔丝位的原始十六进制字符串(小写、带0x前缀) |
readable/writeable | 读 / 写保护状态(布尔值) |
description | 字段描述 |
category | 字段类别(如security、config) |
block/word/pos | 字段所在的物理位置:块号、字序号、位偏移 |
efuse_type | 字段类型(如bool、uint:2、bytes:32) |
bit_len | 字段位长度 |
JSON 对象通过json.dump(json_efuse, file, sort_keys=True, indent=4)输出(base_operations.py 第 843 行),key 按字典序排序、缩进 4 个空格。
raw_value 的编码规则
raw_value由util.json_raw_value_hex()生成(espefuse/efuse/util.py 第 17-31 行),规则如下:
- 每个字段的
raw_value都是带0x前缀的小写十六进制字符串,格式对所有字段一致。 - 非
bytes字段:将字段位模式前置补零到 nibble(4 位)边界,使十六进制表示成立。例如ABS_DONE_0(1 bit)显示为0x0,CODING_SCHEME(2 bits)显示为0x0。 bytes字段:与文本摘要中value十六进制(如00 00 ... 00)保持相同的字节序,即bits.bytes[::-1]反转后的连续十六进制串,0x前缀后无空格。例如 256 位的BLOCK1显示为 64 个十六进制字符的连续串。
保存 JSON 摘要到文件
使用--file参数可将摘要保存到文件(不仅限于 JSON,文本格式同样支持):
> espefuse summary --format json --file efuses.json Connecting.... Detecting chip type... ESP32 === Run "summary" command === Saving efuse values to efuses.json源码中--file参数通过click.File("w")打开写入文件(base_operations.py 第 433-438 行),保存时会先打印Saving efuse values to <文件名>,完成后打印Done并关闭文件(base_operations.py 第 720-721 行与第 845-847 行)。JSON 摘要保存后,可直接供脚本、CI 流水线或其他工具做进一步解析处理,例如通过jq提取安全配置状态。
过滤 eFuse 与仅显示数值
espefuse summary支持按名称过滤 eFuse。要过滤的 eFuse 以位置参数形式给出;如果未指定任何 eFuse,则显示完整摘要。
> espefuse summary ABS_DONE_0 BLOCK1 === Run "summary" command === EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) ---------------------------------------------------------------------------------------- Security fuses: ABS_DONE_0 (BLOCK0) Secure boot V1 is enabled for bootloader image = False R/W (0b0) BLOCK1 (BLOCK1) Flash encryption key = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W从源码看,过滤逻辑为:do_filtering = bool(efuses_to_show),只有名称在efuses_to_show列表中的字段才会被输出(base_operations.py 第 717、784、808 行);过滤时如果某类别下没有匹配的字段,则该类别的空标题会被移除(base_operations.py 第 826-831 行)。
value_only:仅输出单个 eFuse 的值
指定--format value_only时,只显示作为参数指定的那一个 eFuse 的值。此格式下只能指定一个 eFuse,源码在 base_operations.py 第 713-716 行 做了强制校验:if value_only and len(efuses_to_show) != 1: raise esptool.FatalError("The 'value_only' format can be used exactly for one eFuse.")。
> espefuse summary --format value_only MAC === Run "summary" command === 00:00:00:00:00:00 (CRC 0x00 OK)value_only 的输出直接是字段的含义值(summary_efuse.append(f"{value}"),见 base_operations.py 第 805-806 行),不包含表头、类别分组和权限列,非常适合在脚本中提取单个配置值。
--active:只显示活跃字段
当 eFuse 表很大时,查找已置位的具体值可能很耗时。使用--active标志只显示活跃字段——即至少有一位被置位、被读保护或写保护、或存在编码错误的字段。这样能产生更短、更易读的表格。
源码中--active的判定逻辑在 base_operations.py 第 771-781 行:当满足以下任一条件时字段被视为活跃:
- 字段信息中包含
[error](存在编码错误); - 字段位不全为 0(至少一位被置位);
- 字段不可读(
not readable); - 字段不可写(
not writeable)。
不活跃的字段会被跳过(continue),从而快速聚焦到真正被改动过的配置上。这特别适合用于安全审计:快速找出哪些安全相关 eFuse 已经被烧录或保护。
深入:summary 的底层实现链路
了解源码实现有助于正确解读输出结果。summary()的完整处理流程如下(base_operations.py 第 693-847 行):
- 格式与参数校验:
value_only要求恰好一个 eFuse 名称;format必须是summary、json、value_only之一。 - 遍历所有 eFuse 字段:按类别分组(类别名按字母序排序),对每个字段获取
get_meaning()含义值、get_bitstring()位串、is_readable()/is_writeable()保护状态、get_info()字段信息(含所属块与错误标记)。 - 保护与可读性处理:不可读字段用
?掩码(多读保护位的芯片分半处理);R/W等权限标记据此生成。 - 活跃过滤:启用
--active时跳过非活跃字段。 - 输出:文本格式按
ROW_FORMAT拼行(描述超长时分行续接),末尾追加系统级summary()汇总(espefuse/efuse/base_fields.py 第 811-813 行 中定义为抽象方法,由各芯片fields.py实现)与编码方案警告;JSON 格式组装字典后json.dump输出。
关于字段在芯片物理位置的定位:block(块号)、word(字序号)、pos(位偏移)在EfuseFieldBase.__init__中从字段定义(Field参数)解析得到(espefuse/efuse/base_fields.py 第 820-839 行),这些信息在 JSON 输出中完整暴露,便于精确索引某个熔丝位。
此外,summary命令被列入 espefuse 的命令清单中(espefuse/efuse_interface.py 第 51 行),与burn、dump、check-error等命令并列;通过espefuse/__main__.py入口(espefuse/main.py)调用即可运行。
实战建议与使用场景
安全状态审计:用
espefuse summary(不加过滤)查看Security fuses分组,确认ABS_DONE_0(Secure Boot V1)、ABS_DONE_1(Secure Boot V2)、BLOCK1(Flash 加密密钥)等字段是否已烧录;结合--active快速发现已变更的字段。脚本化解析:在 CI 或自动化产线中用
espefuse summary --format json --file efuses.json导出结构化数据,再用jq等工具提取特定字段,例如:espefuse -p /dev/ttyUSB0 summary --format json --file efuses.json jq '.MAC.value' efuses.json只读操作安全:
summary是纯读取命令,不会烧录任何 eFuse,可放心用于产线抽检与售后诊断;而burn类命令涉及一次性不可逆烧录,务必先通过 summary 确认现状。注意平台差异:不同芯片(ESP32 / ESP32-C3 / ESP32-S3 等)的 eFuse 字段、类别和块布局不同,摘要输出会随芯片而变;跨芯片做自动化解析时,应依据 JSON 输出中的
category/efuse_type/bit_len等元信息而非固定列位置编写逻辑。当前仓库中 docs/en/espefuse/inc/ 下的summary_<CHIP>.rst汇总了各芯片的文本摘要样例,可作为对照参考。
相关资源
- 命令文档原文:docs/en/espefuse/summary-cmd.rst
- 各芯片文本摘要示例:docs/en/espefuse/inc/(如 summary_ESP32.rst、summary_ESP32-C3.rst)
- 命令实现:espefuse/efuse/base_operations.py(
summary()在 693-847 行) - raw_value 编码规则:espefuse/efuse/util.py(
json_raw_value_hex()在 17-31 行) - eFuse 字段基类:espefuse/efuse/base_fields.py
- 各芯片字段实现示例:espefuse/efuse/esp32/fields.py
- espefuse 命令入口:espefuse/main.py
- 开发工具
- 嵌入式
- 硬件开发
【免费下载链接】esptool
Serial utility for flashing, provisioning, and interacting with Espressif SoCs
相关推荐
espefuse summary 命令实战:ESP32-P4 eFuse 摘要输出全解析
espefuse summary 命令实战:ESP32 P4 eFuse 摘要输出全解析 本篇指南以 docs/en/espefuse/inc/summary_
开发工具嵌入式硬件开发基于 MXNet 的 DDPG 连续控制强化学习实现:以 rllab CartPole 环境为例
基于 MXNet 的 DDPG 连续控制强化学习实现:以 rllab CartPole 环境为例 导读 本文围绕 MXNet 仓库中 example/reinf
开发工具嵌入式硬件开发ESP-IDF eFuse 管理器:以 ESP32-S3 `idf.py efuse-summary` 输出为例,逐字段解读芯片熔丝
ESP IDF eFuse 管理器:以 ESP32 S3 idf.py efuse summary 输出为例,逐字段解读芯片熔丝 eFuse(Electroni
物联网嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考