☰
esptool 系列之 espefuse summary 命令全解析:ESP32 eFuse 状态查看、JSON 导出与过滤实战指南
2026/10/3 13:47:13 网站建设 项目流程
  • 开发工具
  • 嵌入式
  • 硬件开发

【免费下载链接】esptool

Serial utility for flashing, provisioning, and interacting with Espressif SoCs

项目地址:https://gitcode.com/gh_mirrors/es/esptool
点击查看免费下载

导读

本文以 esptool 仓库中espefuse summary命令的完整文档(docs/en/espefuse/summary-cmd.rst 及其引用的 docs/en/espefuse/inc/summary_ESP32.rst)为主线,系统讲解如何读取并解读 ESP32 芯片上的一次性可编程 eFuse 状态:包括文本格式与 JSON 格式输出、按名称过滤、只输出值、仅显示激活字段、导出到文件,以及读写保护状态(R/W / R/- / -/W / -/-)的准确含义。读完本文,你将能够熟练使用espefuse summary检查芯片的 MAC 地址、Flash 加密状态、Secure Boot 使能情况、eFuse 编码方案与校准数据,并能在 CI 或脚本环境中通过 JSON 输出与value_only模式自动化解析关键 eFuse 值。

命令概述:从 eFuse 硬件寄存器到可读摘要

espefuse summary是 espefuse(随 esptool v2.0+ 一起安装)提供的核心只读命令之一,用于读取芯片 eFuse 内容并以文本或 JSON 形式输出,也可保存到文件,还支持按名称过滤 eFuse 字段。在了解输出格式之前,先明确 eFuse 的本质:

  • eFuse 是芯片上的一次性可编程(One-Time-Programmable)存储器,烧录方向只能从 0 变为 1,永远无法 1→0 清除(见 docs/en/espefuse/index.rst)。
  • 新芯片出厂时绝大多数 eFuse 为 0,但 MAC 地址、ADC 校准数据、芯片封装与版本等信息已在工厂阶段烧录。
  • summary命令是只读操作,不会触发任何烧录,因此可安全反复执行。

从源码实现看,summary命令定义在 espefuse/efuse/base_operations.py,其核心逻辑位于同一文件的summary()方法(espefuse/efuse/base_operations.py,其中包括每个字段的寄存器位置、位宽、类型、读写保护控制位等。

summary命令的可选参数如下:

参数说明
--format选择输出格式:summary(文本,默认)、json(JSON)、value_only(仅输出值,需指定一个 eFuse)
--active只显示激活字段(至少有一个 bit 置位、或已设置读写保护、或存在编码错误的字段)
--file将摘要保存到文件,例如--file efuses.json
位置参数要过滤的 eFuse 名称列表,例如espefuse summary ABS_DONE_0 BLOCK1;不传则输出完整摘要

在命令行解析层,--format由click.Choice(["summary", "json", "value_only"])限定取值,--file通过click.File("w")打开写入,默认输出到 stdout(espefuse/efuse/base_operations.py)。

文本格式摘要:三大列与完整输出示例

文本格式摘要由三个主要列构成:

  1. eFuse 名称列:包含 eFuse 字段名、所属 Block(如BLOCK0、BLOCK3)以及可能的编码错误标记;
  2. 描述列:字段的语义说明;
  3. 值列:人类可读值、读写保护状态、原始十六进制/二进制值。

以 ESP32 芯片为例,直接执行espefuse -p PORT summary得到的完整文本输出如下(出自 docs/en/espefuse/inc/summary_ESP32.rst,该文件通过.. include::被 docs/en/espefuse/summary-cmd.rst 引用,并在构建时替换{IDF_TARGET_NAME}占位符为具体芯片名):

> 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)

这个真实输出样例呈现了几个关键信息点:

  • 分类组织:输出按 Calibration、Config、Flash、Identity、Jtag、Mac、Security、Spi Pad、Vdd 等类别分段;源码中类别来自每个字段的category属性并按标题排序(espefuse/efuse/base_operations.py)。
  • 原始值格式:非 bytes 类型字段以二进制或十六进制显示(如(0b00011)、(0x33)),bytes 类型字段(如 MAC、BLOCK1/2/3)只显示可读值,不显示原始值。
  • 计算字段:WAFER_VERSION_MAJOR、PKG_VERSION这类带 "calc" 与 "(read only)" 描述的字段,是由其他字段组合推导出来的只读值,并非直接存储的 eFuse 位。其定义可在 espefuse/efuse/esp32/mem_definition.py 中看到(例如PKG_VERSION = CHIP_PACKAGE_4BIT << 3 + CHIP_PACKAGE)。
  • 尾部附加信息:文本摘要末尾会追加一行 Flash 电压(VDD_SDIO)的推导结论。这段由 espefuse/efuse/esp32/fields.py 的summary()方法生成,它依据XPD_SDIO_FORCE、XPD_SDIO_REG、XPD_SDIO_TIEH三个 eFuse 的状态组合判断 VDD_SDIO 电压:未强制时由 GPIO12 电平决定(高 1.8V、低/悬空 3.3V),强制后则输出内部稳压器禁用或 1.8V/3.3V 的结论。
  • 不同芯片、不同 espefuse 版本的摘要内容会有差异,应以实际连接芯片为准。

读写保护状态标记:R/W、R/-、-/W、-/- 与 ??

值列中的[Readable/Writeable]标记表达字段/Block 的保护状态,含义如下:

标记含义
R/W可读且可写,未设置任何保护
-/W已设置读保护。软件读到的值恒为全零(但硬件仍可能使用真实值);espefuse v2.6 及更新版本将不可读字段显示为问号??,更早版本显示为 0
R/-已设置写保护,后续任何 bit 都无法再被烧录
-/-读保护与写保护均已设置

其中-/W的典型输出形态(来自 docs/en/espefuse/read-write-protections-cmd.rst):

BLOCK1 (BLOCK1): = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/W

源码中保护标记的计算位于 espefuse/efuse/base_operations.py:根据is_readable()与is_writeable()组合输出R/W、R/-、-/W、-/-;当字段不可读且其位全为 0 时,将值中的0替换为?(espefuse/efuse/base_operations.py)。部分 eFuse 没有保护、部分只有读或写单侧保护,摘要中对此没有额外标记,需结合芯片手册确认。

需要注意的是:ESP32 的 eFuse 常以组为单位被整体读写保护,因此保护其中一个字段可能连带保护相关字段;执行写保护命令时工具会列出全部受影响的字段清单。另外,读取受读保护的字段时“读到的全零”是硬件层面的行为,并不能代表其真实值——这正是工具用??提示的原因。

解读示例:从摘要判断芯片安全状态

以上面的 ESP32 输出为例,可以快速判断:

  • MAC = 94:b9:7e:5a:6e:58 (CRC 0xe2 OK):工厂 MAC 地址及其 CRC8 校验通过;MAC_CRC对应 226(0xe2)。
  • CHIP_VER_REV1 = True、CHIP_VER_REV2 = True:硅片版本为 rev2(WAFER_VERSION_MAJOR 计算值为 3)。
  • CODING_SCHEME = NONE (BLK1-3 len=256 bits):BLOCK1-3 使用 256 位完整长度,无额外编码数据。
  • FLASH_CRYPT_CNT = 0、ABS_DONE_0/1 = False:Flash 加密与 Secure Boot 均未启用。
  • BLOCK1/BLOCK2/BLOCK3全 0:Flash 加密密钥、Secure Boot 密钥、可变 Block3 均为空。

这些状态正是部署量产固件前(启用 Flash 加密 / Secure Boot)必须核对的基线信息。

JSON 格式摘要:机器可解析的结构化输出

使用--format json可得到适合脚本与 CI 解析的结构化输出:

> 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, "writeable": true, "value": false, "word": 6 }, "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 格式的每个字段包含以下键:

  • name:eFuse 字段名;
  • value:人类可读值(bool为 true/false,bytes类型为空格分隔的十六进制字节串);
  • raw_value:小写十六进制字符串,带0x前缀。所有字段的原始值统一补齐到 nibble(4 bit)边界;bytes类型字段则与value保持相同的字节序,作为0x后无空格的连续数字串;
  • readable/writeable:布尔型,指示当前读写保护状态;
  • description:字段描述;
  • category:所属类别(如security、config);
  • block:所属 Block 索引;
  • word/pos:字段在 Block 内的字与位偏移;
  • efuse_type:字段类型(如bool、uint:2、bytes:32);
  • bit_len:字段位宽。

该结构由 espefuse/efuse/base_operations.py 组装,最终通过json.dump(..., sort_keys=True, indent=4)输出,因而键按字母排序、缩进固定,非常适合程序化读取。raw_value的规范化由工具内部的util.json_raw_value_hex()生成。

保存 JSON 摘要到文件

--file选项可将输出重定向到文件(既支持 JSON 也支持文本格式):

> espefuse summary --format json --file efuses.json Connecting.... Detecting chip type... ESP32 === Run "summary" command === Saving efuse values to efuses.json

保存成功后工具会打印Saving efuse values to <文件名>,全部写入完成后再打印Done(espefuse/efuse/base_operations.py)。这非常适合把芯片出厂基线固化为审计记录,或在烧录前后对比 eFuse 状态。

按名称过滤与 value_only 模式

summary命令支持将 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

过滤生效时,源码会移除“没有任何匹配字段”的空类别段(espefuse/efuse/base_operations.py),因此输出干净聚焦。值得注意,过滤匹配的是 eFuse 的主名称;ESP32 部分字段还存在别名(如MAC的别名MAC_FACTORY、BLOCK1的别名flash_encryption,见 espefuse/efuse_defs/esp32.yaml),实际使用时以summary输出的主名为准。

如果指定--format value_only,则只输出一个 eFuse 的值本身,且位置参数只能指定一个eFuse:

> espefuse summary --format value_only MAC === Run "summary" command === 00:00:00:00:00:00 (CRC 0x00 OK)

value_only模式非常适合在 shell 脚本中直接捕获返回值。源码会严格校验:value_only模式下传入的 eFuse 数量必须恰好为 1,否则抛出"The 'value_only' format can be used exactly for one eFuse."错误(espefuse/efuse/base_operations.py)。这一行为在测试中被覆盖:test_espefuse.py的test_summary_filter同时验证了summary MAC、summary --format value_only MAC正常执行,以及summary --format value_only MAC WR_DIS因传了多个 eFuse 而报错(test/test_espefuse.py)。

使用 --active 聚焦已设置字段

当 eFuse 表很大时,逐行检查哪些字段被设置过非常耗时。--active标志可以只显示“激活”字段,即满足以下任一条件的字段:

  • 至少有一个 bit 被置位(非全 0);
  • 设置了读保护或写保护;
  • 存在编码错误(summary 中带[error]标记)。

其判定逻辑在 espefuse/efuse/base_operations.py:is_active = "[error]" in field_info or not bitstring.all(False) or not readable or not writeable,不满足条件的字段直接跳过。由此得到的表格更短、更易读。测试用例test_summary_active验证了summary --active的行数少于完整summary行数的一半(test/test_espefuse.py),可见在出厂默认状态的芯片上该标志能显著精简输出。

结合仓库源码理解 summary 的完整执行链路

为了准确理解summary的输出规则,可以从源码层面梳理其数据流:

  1. 字段来源:ESP32 的 eFuse 字段定义在 espefuse/efuse_defs/esp32.yaml,包含每个字段的寄存器位域(word/pos/len)、类型(bool、uint:N、bytes:N)、读写保护控制位(wr_dis/rd_dis)、别名与描述。运行时由 espefuse/efuse/esp32/mem_definition.py 的EfuseDefineFields加载,并做若干动态加工:例如MAC_VERSION被用作模板派生出BLOCK3整块字段;WAFER_VERSION_MAJOR、PKG_VERSION作为计算字段加入;SPI pad 类字段标记为spipin类型。
  2. 寄存器读取:命令通过串口驱动芯片 eFuse 控制器,向EFUSE_REG_CONF/EFUSE_REG_CMD写入读命令并等待空闲(见 espefuse/efuse/esp32/fields.py 的efuse_read()),再按字段位域拼出各字段值。
  3. 格式输出:summary()方法按类别遍历字段,计算保护标记、激活状态、原始值,分别渲染文本行或 JSON 键值对;文本模式末尾追加编码方案错误警告(若有)与 VDD_SDIO 电压结论。
  4. 测试保障:仓库测试 test/test_espefuse.py 覆盖了summary -h、完整 summary、JSON 输出、JSON 写入文件并重新json.load校验、raw_value存在性、过滤、value_only 唯一性约束以及--active精简输出等场景,可作为理解命令行为的参考。

实战建议与注意事项

  • 只读安全:summary不会烧录任何 eFuse,可放心反复执行;真正危险的写操作(burn-*)会要求输入BURN确认,或使用--do-not-confirm跳过(务必谨慎,eFuse 烧录不可逆,可能永久损坏芯片,详见 docs/en/espefuse/index.rst 的警告)。
  • 指定芯片型号:若当前串口未连接芯片,用-c esp32、-c esp32c3、-c esp32s2等参数明确目标芯片,以获得正确的字段清单与帮助信息;--token选项甚至可以在不连接芯片的情况下,从 eFuse token dump 直接查看 summary。
  • 自动化集成:CI 中建议使用--format json输出并配合--file归档基线;需要提取单个值时优先用--format value_only <NAME>;需要快速巡检“芯片是否动过”时用--active。
  • 解读权威性:每个 eFuse 字段的硬件级语义(如电压等级、频率评级、编码方案)最终以对应芯片的 Technical Reference Manual 为准,工具输出为便捷摘要。
  • 与 dump 命令的区别:summary输出的是按字段解析后的可读摘要;dump则输出各 Block 的原始十六进制值,适合底层对比。二者组合使用可覆盖“人读”与“机读”两种场景。

通过掌握summary的三种格式(文本 / JSON / value_only)、过滤与--active用法,以及 R/W 保护标记的精确含义,你将能够快速、可靠地审计任何 ESP32 芯片的 eFuse 状态,为 Flash 加密、Secure Boot 与量产安全配置打下坚实的排查基础。

  • 开发工具
  • 嵌入式
  • 硬件开发

【免费下载链接】esptool

Serial utility for flashing, provisioning, and interacting with Espressif SoCs

项目地址:https://gitcode.com/gh_mirrors/es/esptool
点击查看免费下载
上一篇:generative-ai-for-beginners 云环境配置指南:用 GitHub Codespaces 零安装跑通全部课程代码
下一篇:ppt-master 中的 update_spec.py:spec_lock.md 与 SVG 的同步批量样式改写机制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询