# 芯片版本

[English]

## 概述

ESP32-S2 可能包含多个芯片版本。引入不同的版本主要用于修复问题，有时也用于添加新功能。版本控制方案 描述了这些芯片修订的版本以及运行时读取版本信息所用的 API。

须考虑应用程序、ESP-IDF 版本和芯片版本之间的兼容性：

- 应用程序可能依赖于某个芯片版本的修复内容或功能。

- 较新版本的硬件可能与较早版本的 ESP-IDF 不兼容。

本文档的 ESP-IDF 兼容性检查 部分描述了应用程序如何明确芯片版本需求，以及 ESP-IDF 如何对兼容性进行检查。文档最后提供了此方案的故障排除相关信息。

## 版本控制方案

芯片版本号通常以 `vX.Y` 的形式表示，其中：

- `X` 表示主版本号。该号码变更表示在旧版芯片上使用的软件与新版芯片不兼容，必须升级软件方可使用。

- `Y` 表示次版本号。该号码变更表示在旧版芯片上使用的软件与新版芯片兼容，无需升级软件。

如果新版芯片不包含重大变更，则可以兼容旧版芯片上运行的软件。此时，新版芯片的主版本号不变，次版本号加 1。例如，版本号从 `v1.1` 变为 `v1.2`。

相反，如果新版芯片包含重大变更，则 无法兼容 旧版芯片的软件。此时，新版芯片的主版本号增加，次版本号设置为 0。例如，版本号从 `v1.1` 变为 `v2.0`。

此版本控制方式能够表示芯片版本之间的衍生关系，并清晰表明芯片变更是否为重大变更。

在芯片发生非重大变更时，ESP-IDF 的执行逻辑应与此前最近版本的逻辑相同，从而达到无缝衔接。在这样便可直接将编译后的二进制文件迁移到更新了次版本的芯片上，无需升级 ESP-IDF 版本并重新编译整个项目。

当二进制文件在更新了主版本的芯片上意外执行时，软件也能够根据主版本报告问题。此主次版本方案还允许硬件变更分支化。

备注

目前的主次版本号芯片版本方案是从 ESP-IDF v5.0 开始引入的。因此，早期 ESP-IDF 创建的引导加载程序将继续使用晶圆版本表示的芯片版本方案。

### 用于芯片版本的 eFuse 位

芯片使用以下几个 eFuse 字段来进行版本控制：

- 主芯片版本号 (`WAFER_VERSION_MAJOR` eFuse)

- 次芯片版本号 (`WAFER_VERSION_MINOR` eFuse)

- 忽略最大芯片版本限制位 (`DISABLE_WAFER_VERSION_MAJOR` eFuse)。请参考 ESP-IDF 兼容性检查 了解此 eFuse 字段。

备注

此前的版本控制逻辑基于单一的 eFuse 版本字段，即 `WAFER_VERSION`。这种方式无法表明芯片的更新是否为重大更新，是一种线性的版本控制逻辑。

### 用于 eFuse 块版本的 eFuse 位

EFuse 既有以下几个版本字段：

- 主 eFuse 块版本号 (`BLK_VERSION_MAJOR` eFuse)

- 次 efuse 块版本号 (`BLK_VERSION_MINOR` eFuse)

- 忽略最大 efuse 块版本限制位 (`DISABLE_BLK_VERSION_MAJOR` eFuse). 请参考 ESP-IDF 兼容性检查 了解此 eFuse 字段。

### 芯片版本 API

使用下列 API 从 eFuse 中读取芯片版本：

- `efuse_hal_chip_revision()`，返回的版本格式为 `major * 100 + minor`。

- `efuse_hal_get_major_chip_version()` 返回主芯片版本号。

- `efuse_hal_get_minor_chip_version()` 返回次芯片版本号。

下列 Kconfig 选项（格式为 `major * 100 + minor`）可以将芯片版本依赖添加到代码中：

- `CONFIG_ESP32S2_REV_MIN_FULL`

- `CONFIG_ESP_REV_MIN_FULL`

- `CONFIG_ESP32S2_REV_MAX_FULL`

- `CONFIG_ESP_REV_MAX_FULL`

### EFuse 块版本 API

使用下列 API 从 eFuse 中读取 eFuse 块版本：

- `efuse_hal_blk_version()`，返回的版本格式为 `major * 100 + minor`。

- `efuse_ll_get_blk_version_major()`。 返回主 eFuse 块版本号

- `efuse_ll_get_blk_version_minor()`。 返回次 eFuse 块版本号

下列 Kconfig 选项（格式为 `major * 100 + minor`）可以将 eFuse 块版本依赖添加到代码中：

- `CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL`

- `CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL`

## ESP-IDF 兼容性检查

如果构建的应用程序需要支持特定芯片的多个版本，可通过 Kconfig 指定支持的最小和最大芯片版本号。

最小芯片版本号可以通过 Kconfig 选项 CONFIG_ESP32S2_REV_MIN 来选择。设置最小芯片版本后，软件只能在较新的芯片版本上运行，以便支持某些功能或修复某些错误。

最大芯片版本号无法指定，只能由当前使用的 ESP-IDF 版本自动决定。ESP-IDF 会拒绝启动任何超过最大芯片版本号的芯片版本。由于特定版本的 ESP-IDF 无法预知未来的芯片版本更新，因此最大芯片版本号通常设置为 `maximum supported MAJOR version + 99`。可以设置 “忽略最大版本” eFuse 来绕过最大版本限制，但这不能确保软件正常工作。

EFuse 块版本号与芯片版本号类似，但是它主要影响在 eFuse 中指定的参数（如 ADC 校正参数等）。

下文介绍了芯片版本未通过兼容性检查时显示的故障排除信息及解决方法，并描述了在早期 ESP-IDF 版本中与软件行为和兼容性检查相关的技术细节。

### 故障排除

1. 如果二级引导加载程序所运行的芯片版本低于镜像（如软件镜像）中指定的最小版本，会发生重启并显示以下消息：

    Image requires chip rev >= v3.0, but chip is v1.0

要解决此问题，

- 确保使用的芯片达到了要求的最低版本及以上。

- 减小 CONFIG_ESP32S2_REV_MIN 的值并重建镜像，使镜像的版本与当前芯片版本兼容。

1. 如果应用程序所需的芯片版本不处于最小和最大芯片版本的区间范围内，会发生重启并显示以下消息：

    Image requires chip rev <= v2.99, but chip is v3.0

为解决此问题，需更新 ESP-IDF 到较新版本，以支持该芯片版本 (`CONFIG_ESP32S2_REV_MAX_FULL`)。也可以在 eFuse 中设置 `Ignore maximal revision` 位，或使用与当前 ESP-IDF 版本兼容的其他芯片版本。

### 二进制镜像的常见版本需求

芯片版本号检查主要根据二级引导加载程序和应用程序二进制镜像中包含的 `esp_image_header_t` 标头，其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段：

- `min_chip_rev` - 镜像所需芯片的最小主版本号（但对于 ESP32-C3，该字段指次版本号）。其值由 CONFIG_ESP32S2_REV_MIN 确定。

- `min_chip_rev_full` - 镜像所需芯片的最小版本号，格式为 `major * 100 + minor`。其值由 CONFIG_ESP32S2_REV_MIN 确定。

- `max_chip_rev_full` - 镜像所需芯片的最大版本号，格式为 `major * 100 + minor`。其值由 `CONFIG_ESP32S2_REV_MAX_FULL` 确定。用户无法对其进行修改，仅当 ESP-IDF 支持新版本时由乐鑫官方进行更改。

而 eFuse 块版本的要求则存储在 `esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准，而二级引导加载程序的镜像不涉及 ADC，因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段：

- `min_efuse_blk_rev_full` - 镜像所需 eFuse 块的最小版本号，格式为 `major * 100 + minor`。其值由 `CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL` 确定。

- `max_efuse_blk_rev_full` - 镜像所需 eFuse 块的最大版本号，格式为 `major * 100 + minor`。其值由 `CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL` 确定。它反映了当前 ESP-IDF 版本能支持的最大 eFuse 块版本号，不应由用户修改。

### 最大和最小版本限制

应用启动过程中，检查最小和最大版本的顺序如下：

1. 在运行二级引导加载程序前，一级 (ROM) 引导加载程序不会在 `esp_image_header_t` 中检查最小和最大版本字段。

2. 在二级引导加载程序的初始化阶段，会检查引导加载程序自身是否可以在此版本的芯片上启动。它从引导加载程序镜像的标头中读取最小版本，并与 eFuse 中的芯片版本进行比较。如果芯片版本低于最小版本，引导加载程序会拒绝启动并中止运行。此阶段不检查最大版本。

3. 然后，二级引导加载程序会检查应用程序的版本要求。它从应用程序镜像的标头中读取支持的芯片最小和最大版本，以及从段的标头中读取 eFuse 块版本信息，并与 eFuse 中的芯片版本进行比较。如果该芯片版本或 eFuse 块版本低于各自的最小版本或高于最大版本，引导加载程序会拒绝启动并中止。然而，如果设置了忽略最大版本位，则可以忽略最大版本限制。软件确定可以使用此芯片版本时，用户可以自行设置忽略位。

4. 在空中升级 (OTA) 阶段，运行中的应用程序会检查新软件是否与芯片版本及 eFuse 块版本相匹配。它会从新应用程序镜像的标头中提取最小和最大芯片版本，以及应用程序描述中提取最大和最小 eFuse 块版本，并与 eFuse 中的芯片版本和块版本进行比较。应用程序检查版本匹配的方式与引导加载程序相同，即芯片版本和 eFuse 块版本须处在最小和最大版本之间（忽略最大版本的逻辑也相同）。

### 向后兼容旧版 ESP-IDF 构建的引导加载程序

主要版本号和次版本号的 eFuse 位对于旧版引导加载程序（由早于 v5.0 版本的 ESP-IDF 进行构建）而言是未知的。旧版引导加载程序只使用一个 eFuse 位来表示芯片版本。

在 ESP-IDF v4.2 中添加了对 ESP32-S2 芯片的支持。 由于 `Minimum Supported ESP32-S2 Revision` Kconfig 选项未引入，ESP32-S2 芯片在 `esp_image_header_t` 头文件中将 `rev_min` 设置为 0。这表明旧版引导加载程序不会检查芯片版本。在 v0.0 至 v3.15 范围内，任何应用程序都可以通过此类引导加载程序加载。

请使用 `esptool chip_id` 命令查看芯片版本。

## 参考链接

- 芯片版本编号方案兼容指南

- ESP-IDF 版本与乐鑫芯片版本兼容性

- SoC Errata

- ESP-IDF 版本简介

## API 参考

### Header File

- components/hal/include/hal/efuse_hal.h

- This header file can be included with:

  >     #include "hal/efuse_hal.h"

### Functions

void efuse_hal_get_mac(uint8_t *mac)

  get factory mac address

uint32_t efuse_hal_chip_revision(void)

  Returns chip version.

  返回:

    Chip version in format: Major * 100 + Minor

uint32_t efuse_hal_blk_version(void)

  Return block version.

  返回:

    Block version in format: Major * 100 + Minor

bool efuse_hal_flash_encryption_enabled(void)

  Is flash encryption currently enabled in hardware?

  Flash encryption is enabled if the FLASH_CRYPT_CNT efuse has an odd number of bits set.

  返回:

    true if flash encryption is enabled.

bool efuse_hal_get_disable_wafer_version_major(void)

  Returns the status of whether the bootloader (and OTA) will check the maximum chip version or not.

  返回:

    true - Skip the maximum chip version check.

bool efuse_hal_get_disable_blk_version_major(void)

  Returns the status of whether the app start-up (and OTA) will check the efuse block version or not.

  返回:

    true - Skip the efuse block version check.

uint32_t efuse_hal_get_major_chip_version(void)

  Returns major chip version.

uint32_t efuse_hal_get_minor_chip_version(void)

  Returns minor chip version.

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。