chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:04:25 +08:00
commit 548b49ebc0
20937 changed files with 5455372 additions and 0 deletions
@@ -0,0 +1,160 @@
App Image Format
================
:link_to_translation:`zh_CN:[中文]`
.. _app-image-structures:
Application Image Structures
----------------------------
An application image consists of the following:
1. The :cpp:type:`esp_image_header_t` structure describes the mode of SPI flash and the count of memory segments.
2. The :cpp:type:`esp_image_segment_header_t` structure describes each segment, its length, and its location in {IDF_TARGET_NAME}'s memory, followed by the data with a length of ``data_len``. The data offset for each segment in the image is calculated in the following way:
* offset for 0 Segment = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`)
* offset for 1 Segment = offset for 0 Segment + length of 0 Segment + sizeof(:cpp:type:`esp_image_segment_header_t`)
* offset for 2 Segment = offset for 1 Segment + length of 1 Segment + sizeof(:cpp:type:`esp_image_segment_header_t`)
* ...
The count of each segment is defined in the ``segment_count`` field that is stored in :cpp:type:`esp_image_header_t`. The count cannot be more than :c:macro:`ESP_IMAGE_MAX_SEGMENTS`.
To get the list of your image segments, please run the following command:
.. code-block::
esptool --chip {IDF_TARGET_PATH_NAME} image-info build/app.bin
.. code-block::
esptool v5.0.2
Image size: 137312 bytes
ESP32 Image Header
==================
Image version: 1
Entry point: 0x40081214
Segments: 6
Flash size: 2MB
Flash freq: 40m
Flash mode: DIO
ESP32 Extended Image Header
===========================
WP pin: 0xee (disabled)
Flash pins drive settings: clk_drv: 0x0, q_drv: 0x0, d_drv: 0x0, cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0
Chip ID: 0 (ESP32)
Minimal chip revision: v0.0, (legacy min_rev = 0)
Maximal chip revision: v3.99
Segments Information
====================
Segment Length Load addr File offs Memory types
------- ------- ---------- ---------- ------------
0 0x0711c 0x3f400020 0x00000018 DROM
1 0x0241c 0x3ffb0000 0x0000713c BYTE_ACCESSIBLE, DRAM
2 0x06ab0 0x40080000 0x00009560 IRAM
3 0x0b724 0x400d0020 0x00010018 IROM
4 0x060c0 0x40086ab0 0x0001b744 IRAM
5 0x00024 0x50000000 0x0002180c RTC_DATA
ESP32 Image Footer
==================
Checksum: 0x4b (valid)
Validation hash: 8808f05a62fe1a6e1e6830414b95229454b012eb2001511ca434d34e9e63c962 (valid)
Application Information
=======================
Project name: hello_world
App version: qa-test-esp32c61-master-2025070
Compile time: Aug 12 2025 16:36:40
ELF file SHA256: 10972f521b52276e988631d7408de388d639437118e8217c366f2bd93b52e1b6
ESP-IDF: v6.0-dev-1692-g7aad0d47e66-dirt
Minimal eFuse block revision: 0.0
Maximal eFuse block revision: 0.99
MMU page size: 64 KB
Secure version: 0
You can also see the information on segments in the ESP-IDF logs while your application is booting:
.. code-block::
I (443) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x13ce0 ( 81120) map
I (489) esp_image: segment 1: paddr=0x00033d08 vaddr=0x3ff80000 size=0x00000 ( 0) load
I (530) esp_image: segment 2: paddr=0x00033d10 vaddr=0x3ff80000 size=0x00000 ( 0) load
I (571) esp_image: segment 3: paddr=0x00033d18 vaddr=0x3ffb0000 size=0x028e0 ( 10464) load
I (612) esp_image: segment 4: paddr=0x00036600 vaddr=0x3ffb28e0 size=0x00000 ( 0) load
I (654) esp_image: segment 5: paddr=0x00036608 vaddr=0x40080000 size=0x00400 ( 1024) load
I (695) esp_image: segment 6: paddr=0x00036a10 vaddr=0x40080400 size=0x09600 ( 38400) load
I (737) esp_image: segment 7: paddr=0x00040018 vaddr=0x400d0018 size=0x62e4c (405068) map
I (847) esp_image: segment 8: paddr=0x000a2e6c vaddr=0x40089a00 size=0x06cec ( 27884) load
I (888) esp_image: segment 9: paddr=0x000a9b60 vaddr=0x400c0000 size=0x00000 ( 0) load
I (929) esp_image: segment 10: paddr=0x000a9b68 vaddr=0x50000000 size=0x00004 ( 4) load
I (971) esp_image: segment 11: paddr=0x000a9b74 vaddr=0x50000004 size=0x00000 ( 0) load
I (1012) esp_image: segment 12: paddr=0x000a9b7c vaddr=0x50000004 size=0x00000 ( 0) load
.. only:: esp32
For more details on the type of memory segments and their address ranges, see **{IDF_TARGET_NAME} Technical Reference Manual** > **System and Memory** > **Embedded Memory** [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__].
.. only:: not esp32
For more details on the type of memory segments and their address ranges, see **{IDF_TARGET_NAME} Technical Reference Manual** > **System and Memory** > **Internal Memory** [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__].
3. The image has a single checksum byte after the last segment. This byte is written on a sixteen byte padded boundary, so the application image might need padding.
4. If the ``hash_appended`` field from :cpp:type:`esp_image_header_t` is set then a SHA256 checksum will be appended. The value of the SHA256 hash is calculated on the range from the first byte and up to this field. The length of this field is 32 bytes.
5. If the option :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` is set to ECDSA then the application image will have an additional 68 bytes for an ECDSA signature, which includes:
* version word (4 bytes)
* signature data (64 bytes)
6. If the option :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` is set to RSA or ECDSA (V2) then the application image will have an additional signature sector of 4 KB in size. For more details on the format of this signature sector, please refer to :ref:`signature-block-format`.
.. _app-image-format-application-description:
Application Description
-----------------------
The ``DROM`` segment of the application binary starts with the :cpp:type:`esp_app_desc_t` structure which carries specific fields describing the application:
* ``magic_word``: the magic word for the :cpp:type:`esp_app_desc_t` structure
* ``secure_version``: see :doc:`Anti-rollback </api-reference/system/ota>`
* ``version``: see :doc:`App version </api-reference/system/misc_system_api>` [#f1]_
* ``project_name``: filled from ``PROJECT_NAME`` [#f1]_
* ``time`` and ``date``: compile time and date
* ``idf_ver``: version of ESP-IDF [#f1]_
* ``app_elf_sha256``: contains SHA256 hash for the application ELF file
* ``min_efuse_blk_rev_full``: minimal eFuse block revision supported by the image, in format: major * 100 + minor
* ``max_efuse_blk_rev_full``: maximal eFuse block revision supported by the image, in format: major * 100 + minor
* ``mmu_page_size``: MMU page size in log base 2 format
* ``spi_flash_mode``: SPI flash mode as per ``CONFIG_ESPTOOLPY_FLASHMODE_VAL`` for compatibility check during OTA
.. [#f1] The maximum length is 32 characters, including null-termination character. For example, if the length of ``PROJECT_NAME`` exceeds 31 characters, the excess characters will be disregarded.
This structure is useful for identification of images uploaded via Over-the-Air (OTA) updates because it has a fixed offset = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`). As soon as a device receives the first fragment containing this structure, it has all the information to determine whether the update should be continued with or not.
To obtain the :cpp:type:`esp_app_desc_t` structure for the currently running application, use :cpp:func:`esp_app_get_description`.
To obtain the :cpp:type:`esp_app_desc_t` structure for another OTA partition, use :cpp:func:`esp_ota_get_partition_description`.
Adding a Custom Structure to an Application
-------------------------------------------
Users also have the opportunity to have similar structure with a fixed offset relative to the beginning of the image.
The following pattern can be used to add a custom structure to your image:
.. code-block:: c
const __attribute__((section(".rodata_custom_desc"))) esp_custom_app_desc_t custom_app_desc = { ... }
Offset for custom structure is sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`) + sizeof(:cpp:type:`esp_app_desc_t`).
To guarantee that the custom structure is located in the image even if it is not used, you need to add ``target_link_libraries(${COMPONENT_TARGET} "-u custom_app_desc")`` into ``CMakeLists.txt``.
API Reference
-------------
.. include-build-file:: inc/esp_app_format.inc
@@ -0,0 +1,27 @@
Application Level Tracing
=========================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
ESP-IDF provides a useful feature for application behavior analysis called **Application Level Tracing**. The feature can be enabled in menuconfig and allows transfer of arbitrary data between the host and {IDF_TARGET_NAME} via JTAG interface with minimal overhead on program execution.
Developers can use this library to send application specific state of execution to the host, and receive commands or other types of information in the opposite direction at runtime. The main use cases of this library are:
1. Collecting application specific data, see :ref:`app_trace-application-specific-tracing`.
2. Lightweight logging to the host, see :ref:`app_trace-logging-to-host`.
3. System behaviour analysis, see :ref:`app_trace-system-behaviour-analysis-with-segger-systemview`.
Application Examples
--------------------
- :example:`system/app_trace_to_plot` demonstrates how to use the Application Level Tracing Library to send and plot dummy sensor data to a host via JTAG, providing a faster alternative to logging via UART.
- :example:`system/app_trace_basic` demonstrates how to use the Application Level Tracing Library to log messages to a host via JTAG, providing a faster alternative to UART logs.
API Reference
-------------
.. include-build-file:: inc/esp_app_trace.inc
@@ -0,0 +1,82 @@
Bootloader Image Format
=======================
:link_to_translation:`zh_CN:[中文]`
The bootloader image consists of the same structures as the application image, see :ref:`Application Image Structures <app-image-structures>`. The only difference is in the :ref:`image-format-bootloader-description` structure.
To get information about the bootloader image, please run the following command:
.. code-block::
esptool --chip {IDF_TARGET_PATH_NAME} image-info ./build/bootloader/bootloader.bin
The resultant output will resemble the following:
.. code-block::
esptool v5.0.2
Image size: 26352 bytes
ESP32 Image Header
==================
Image version: 1
Entry point: 0x40080644
Segments: 3
Flash size: 2MB
Flash freq: 40m
Flash mode: DIO
ESP32 Extended Image Header
===========================
WP pin: 0xee (disabled)
Flash pins drive settings: clk_drv: 0x0, q_drv: 0x0, d_drv: 0x0, cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0
Chip ID: 0 (ESP32)
Minimal chip revision: v0.0, (legacy min_rev = 0)
Maximal chip revision: v3.99
Segments Information
====================
Segment Length Load addr File offs Memory types
------- ------- ---------- ---------- ------------
0 0x018e8 0x3fff0030 0x00000018 BYTE_ACCESSIBLE, DRAM, DIRAM_DRAM
1 0x03e58 0x40078000 0x00001908 CACHE_APP
2 0x00f5c 0x40080400 0x00005768 IRAM
ESP32 Image Footer
==================
Checksum: 0x6b (valid)
Validation hash: 09fdc81d436a927b5018e19073a787cd37ffce655f505ad92675edd784419034 (valid)
Bootloader Information
======================
Bootloader version: 1
ESP-IDF: v6.0-dev-1620-g15d7e41a848-dirt
Compile time: Aug 8 2025 16:22:1
.. _image-format-bootloader-description:
Bootloader Description
----------------------
The ``DRAM0`` segment of the bootloader binary starts with the :cpp:type:`esp_bootloader_desc_t` structure which carries specific fields describing the bootloader. This structure is located at a fixed offset = sizeof(:cpp:type:`esp_image_header_t`) + sizeof(:cpp:type:`esp_image_segment_header_t`).
* ``magic_byte``: the magic byte for the esp_bootloader_desc structure
* ``reserved``: reserved for the future IDF use
* ``secure_version``: the secure version used by the bootloader anti-rollback feature, see :ref:`CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE`.
* ``version``: bootloader version, see :ref:`CONFIG_BOOTLOADER_PROJECT_VER`
* ``idf_ver``: ESP-IDF version. [#f1]_
* ``date`` and ``time``: compile date and time
* ``reserved2``: reserved for the future IDF use
.. [#f1] The maximum length is 32 characters, including null-termination character.
To get the :cpp:type:`esp_bootloader_desc_t` structure from the running bootloader, use :cpp:func:`esp_bootloader_get_description`.
To get the :cpp:type:`esp_bootloader_desc_t` structure from a running application, use :cpp:func:`esp_ota_get_bootloader_description`.
API Reference
-------------
.. include-build-file:: inc/esp_bootloader_desc.inc
@@ -0,0 +1,195 @@
Chip Revision
=============
:link_to_translation:`zh_CN:[中文]`
Overview
--------
{IDF_TARGET_NAME} may have different revisions. These revisions mainly fix some issues, and sometimes also bring new features to the chip. :ref:`versioning scheme` describes the versioning of these chip revisions, and the APIs to read the versions at runtime.
There are some considerations of compatibility among application, ESP-IDF version, and chip revisions:
- Applications may depend on some fixes/features provided by a chip revision.
- When using updated version of hardware, the hardware may be incompatible with earlier versions of ESP-IDF.
:ref:`revision_limitation` describes how the application can specify its chip revision requirements, and the way ESP-IDF checks the compatibility. After that, there is troubleshooting information for this mechanism.
.. _versioning scheme:
Versioning Scheme
-----------------
A chip's revision number is typically expressed as ``vX.Y``, where:
- ``X`` means a **Major** wafer version. If it is changed, it means that the current software version is not compatible with this released chip and the software must be updated to use this chip.
- ``Y`` means a **Minor** wafer version. If it is changed that means the current software version is compatible with the released chip, and there is no need to update the software.
If a newly released chip does not contain breaking changes, the chip can run the same software as the previous chip. As such, the new chip's revision number will only increment the minor version while keeping the major version the same (e.g., ``v1.1`` to ``v1.2``).
Conversely, if a newly released chip contains breaking changes, the chip **cannot** run the same software as the previous chip. As such, the new chip's revision number will increment the major version and set the minor version to 0 (e.g., ``v1.1`` to ``v2.0``).
This versioning scheme was selected to indicate the derivation relationship of chip revisions, and clearly distinguish changes in chips between breaking changes and non-breaking changes.
ESP-IDF is designed to execute seamlessly on future chip minor revisions with the same logic as the chip's nearest previous minor revision. Thususers can directly port their compiled binaries to newer MINOR chip revisions without upgrading their ESP-IDF version and re-compile the whole project.
When a binary is executed on a chip revision of unexpected MAJOR revision, the software is also able to report issues according to the MAJOR revision. The major and minor versioning scheme also allows hardware changes to be branchable.
.. note::
The current chip revision scheme using major and minor versions was introduced from ESP-IDF v5.0 onwards. Thus bootloaders built using earlier versions of ESP-IDF will still use the legacy chip revision scheme of wafer versions.
EFuse Bits for Chip Revisions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Chips have several eFuse version fields:
- Major wafer version (``WAFER_VERSION_MAJOR`` eFuse)
- Minor wafer version (``WAFER_VERSION_MINOR`` eFuse)
- Ignore maximum wafer revision (``DISABLE_WAFER_VERSION_MAJOR`` eFuse). See :ref:`revision_limitation` on how this is used.
.. note::
The previous versioning logic was based on a single eFuse version field (``WAFER_VERSION``). This approach makes it impossible to mark chips as breaking or non-breaking changes, and the versioning logic becomes linear.
EFuse Bits for eFuse Block Revisions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
EFuse block has version fields:
- Major efuse block version (``BLK_VERSION_MAJOR`` eFuse)
- Minor efuse block version (``BLK_VERSION_MINOR`` eFuse)
- Ignore maximum efuse block revision (``DISABLE_BLK_VERSION_MAJOR`` eFuse). See :ref:`revision_limitation` on how this is used.
Chip Revision APIs
^^^^^^^^^^^^^^^^^^
These APIs helps to get chip revision from eFuses:
- :cpp:func:`efuse_hal_chip_revision`. It returns revision in the ``major * 100 + minor`` format.
- :cpp:func:`efuse_hal_get_major_chip_version`. It returns Major revision of wafer.
- :cpp:func:`efuse_hal_get_minor_chip_version`. It returns Minor revision of wafer.
The following Kconfig definitions (in ``major * 100 + minor`` format) that can help add the chip revision dependency to the code:
- ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN_FULL``
- ``CONFIG_ESP_REV_MIN_FULL``
- ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL``
- ``CONFIG_ESP_REV_MAX_FULL``
EFuse Block Revision APIs
^^^^^^^^^^^^^^^^^^^^^^^^^
These APIs helps to get eFuse block revision from eFuses:
- :cpp:func:`efuse_hal_blk_version`. It returns revision in the ``major * 100 + minor`` format.
- :cpp:func:`efuse_ll_get_blk_version_major`. It returns Major revision of eFuse block.
- :cpp:func:`efuse_ll_get_blk_version_minor`. It returns Minor revision of eFuse block.
The following Kconfig definitions (in ``major * 100 + minor`` format) that can help add the eFuse block revision dependency to the code:
- ``CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL``
- ``CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL``
.. _revision_limitation:
Compatibility Checks of ESP-IDF
-------------------------------
When building an application that needs to support multiple revisions of a particular chip, the minimum and maximum chip revision numbers supported by the build are specified via Kconfig.
The minimum chip revision can be configured via the :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` option. Specifying the minimum chip revision will limit the software to only run on a chip revisions that are high enough to support some features or bugfixes.
The maximum chip revision cannot be configured and is automatically determined by the current ESP-IDF version being used. ESP-IDF will refuse to boot any chip revision exceeding the maximum chip revision. Given that it is impossible for a particular ESP-IDF version to foresee all future chip revisions, the maximum chip revision is usually set to ``maximum supported MAJOR version + 99``. The "Ignore Maximum Revision" eFuse can be set to bypass the maximum revision limitation. However, the software is not guaranteed to work if the maximum revision is ignored.
The eFuse block revision is similar to the chip revision, but it mainly affects the coefficients that are specified in the eFuse (e.g. ADC calibration coefficients).
Below is the information about troubleshooting when the chip revision fails the compatibility check. Then there are technical details of the checking and software behavior on earlier version of ESP-IDF.
Troubleshooting
^^^^^^^^^^^^^^^
1. If the second stage bootloader is run on a chip revision smaller than minimum revision specified in the image (i.e., the application), a reboot occurs. The following message will be printed:
.. code-block:: none
Image requires chip rev >= v3.0, but chip is v1.0
To resolve this issue,
- Use a chip with the required minimum revision or higher.
- Lower the :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` value and rebuild the image so that it is compatible with the chip revision being used.
2. If application does not match minimum and maximum chip revisions, a reboot occurs. The following message will be printed:
.. code-block:: none
Image requires chip rev <= v2.99, but chip is v3.0
To resolve this issue, update ESP-IDF to a newer version that supports the chip's revision (``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL``). Alternatively, set the ``Ignore maximal revision`` bit in eFuse or use a chip revision that is compatible with the current version of ESP-IDF.
Representing Revision Requirements of a Binary Image
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For the chip revision, the second stage bootloader and the application binary images contain the :cpp:type:`esp_image_header_t` header, which stores information specifying the chip revisions that the image is permitted to run on. This header has 3 fields related to the chip revisions:
- ``min_chip_rev`` - Minimum chip MAJOR revision required by image (but for ESP32-C3 it is MINOR revision). Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`.
- ``min_chip_rev_full`` - Minimum chip MINOR revision required by image in format: ``major * 100 + minor``. Its value is determined by :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN`.
- ``max_chip_rev_full`` - Maximum chip revision required by image in format: ``major * 100 + minor``. Its value is determined by ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL``. It can not be changed by user. Only Espressif can change it when a new version will be supported in ESP-IDF.
For the eFuse revision, the requirements are stored in :cpp:type:`esp_app_desc_t`, which is contained in the application binary image. We only check the application image because the eFuse block revision mostly affects the ADC calibration, which does not really matter in the bootloader. There are 2 fields related to eFuse block revisions:
- ``min_efuse_blk_rev_full`` - Minimum eFuse block MINOR revision required by image in format: ``major * 100 + minor``. Its value is determined by ``CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL``.
- ``max_efuse_blk_rev_full`` - Maximum eFuse block MINOR revision required by image in format: ``major * 100 + minor``. Its value is determined by ``CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL``. It reflects whether the current IDF version supports this efuse block format or not, and should not be changed by the user.
Maximum And Minimum Revision Restrictions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The order for checking the minimum and maximum revisions during application boot up is as follows:
1. The first stage (ROM) bootloader does not check minimum and maximum revision fields from :cpp:type:`esp_image_header_t` before running the 2nd stage bootloader.
2. The initialization phase of the second stage bootloader checks that the second stage bootloader itself can be launched on the chip of this revision. It extracts the minimum revision from the header of the bootloader image and checks against the chip revision from eFuses. If the chip revision is less than the minimum revision, the bootloader refuses to boot up and aborts. The maximum revision is not checked at this phase.
3. Then the second stage bootloader checks the revision requirements of the application. It extracts the minimum and maximum revisions of the chip from the application image header, and the eFuse block from the segment header. Then the bootloader checks these versions against the chip and eFuse block revision from eFuses. If the these revisions are less than their minimum revision or higher than the maximum revision, the bootloader refuses to boot up and aborts. However, if the ignore maximum revision bit is set, the maximum revision constraint can be ignored. The ignore bits are set by the customer themselves when there is confirmation that the software is able to work with this chip revision or eFuse block revision.
4. Furthermore, at the OTA update stage, the running application checks if the new software matches the chip revision and eFuse block revision. It extracts the minimum and maximum chip revisions from the header of the new application image and the eFuse block constraints from the application description to check against the these revisions from eFuses. It checks for revisions matching in the same way that the bootloader does, so that the chip and eFuse block revisions are between their min and max revisions (logic of ignoring max revision also applies).
Backward Compatibility with Bootloaders Built by Older ESP-IDF Versions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. only:: esp32 or esp32c3 or esp32s2 or esp32s3
The old bootloaders (ESP-IDF < v5.0) do not know about Major and Minor wafer version eFuses. They use one single eFuse for this - wafer version.
.. only:: esp32
The old bootloaders did not read the minor wafer version eFuse, and the major version can be only lower than or equal to v3. This means that the old bootloader can detect correctly only chip version in range ``v0.0`` to ``v3.0``, where the minor version is always set to ``0``.
.. only:: esp32c2
{IDF_TARGET_NAME} chip support was added in ESP-IDF v5.0. The bootloader is able to detect any chip versions in range ``v0.0`` to ``v3.15``.
.. only:: esp32c3
{IDF_TARGET_NAME} chip support was added in ESP-IDF v4.3. The old bootloaders cannot read all bits of the wafer version eFuse, it can read only the first 3 least significant bits. This means that the old bootloader cannot detect chip version correctly. Chips ``v0.0`` to ``v0.8`` are detected correctly, but other chip versions will be recognized as a version from this range.
.. only:: esp32s2 or esp32s3
{IDF_TARGET_NAME} chip support was added in ESP-IDF v4.2. {IDF_TARGET_NAME} chips have ``rev_min`` in :cpp:type:`esp_image_header_t` header set to ``0`` because ``Minimum Supported ESP32-S2 Revision`` Kconfig option was not introduced, which means that the old bootloader does not check the chip revision. Any app can be loaded by such bootloader in range ``v0.0`` to ``v3.15``.
Please check the chip version using ``esptool chip-id`` command.
References
----------
- `Compatibility Advisory for Chip Revision Numbering Scheme <https://www.espressif.com.cn/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf>`_
- `Compatibility Between ESP-IDF Releases and Revisions of Espressif SoCs <https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md>`_
- `SoC Errata <https://www.espressif.com.cn/en/support/documents/technical-documents?keys=errata>`_
- :doc:`/versions`
API Reference
-------------
.. include-build-file:: inc/efuse_hal.inc
+203
View File
@@ -0,0 +1,203 @@
Console
=======
:link_to_translation:`zh_CN:[中文]`
ESP-IDF provides ``console`` component, which includes building blocks needed to develop an interactive console over serial port. This component includes the following features:
- Line editing, provided by `linenoise`_ library. This includes handling of backspace and arrow keys, scrolling through command history, command auto-completion, and argument hints.
- Splitting of command line into arguments.
- Argument parsing, provided by `argtable3`_ library. This library includes APIs used for parsing GNU style command line arguments.
- Functions for registration and dispatching of commands.
- Functions to establish a basic REPL (Read-Evaluate-Print-Loop) environment.
.. note::
These features can be used together or independently. For example, it is possible to use line editing and command registration features, but use ``getopt`` or custom code for argument parsing, instead of `argtable3`_. Likewise, it is possible to use simpler means of command input (such as ``fgets``) together with the rest of the means for command splitting and argument parsing.
.. note::
When using a console application on a chip that supports a hardware USB serial interface, we suggest disabling the secondary serial console output. The secondary output will be output-only and consequently does not make sense in an interactive application.
Line Editing
------------
Line editing feature lets users compose commands by typing them, erasing symbols using the ``backspace`` key, navigating within the command using the left/right keys, navigating to previously typed commands using the up/down keys, and performing autocompletion using the ``tab`` key.
.. note::
This feature relies on ANSI escape sequence support in the terminal application. As such, serial monitors which display raw UART data can not be used together with the line editing library. If you see ``[6n`` or similar escape sequence when running :example:`system/console` example instead of a command prompt (e.g., ``esp>`` ), it means that the serial monitor does not support escape sequences. Programs which are known to work are GNU screen, minicom, and esp-idf-monitor (which can be invoked using ``idf.py monitor`` from project directory).
Here is an overview of functions provided by `linenoise <https://github.com/antirez/linenoise>`_ library.
Configuration
^^^^^^^^^^^^^
Linenoise library does not need explicit initialization. However, some configuration defaults may need to be changed before invoking the main line editing function.
- :cpp:func:`linenoiseClearScreen`
Clear terminal screen using an escape sequence and position the cursor at the top left corner.
- :cpp:func:`linenoiseSetMultiLine`
Switch between single line and multi line editing modes. In single line mode, if the length of the command exceeds the width of the terminal, the command text is scrolled within the line to show the end of the text. In this case the beginning of the text is hidden. Single line mode needs less data to be sent to refresh screen on each key press, so exhibits less glitching compared to the multi line mode. On the flip side, editing commands and copying command text from terminal in single line mode is harder. Default is single line mode.
- :cpp:func:`linenoiseAllowEmpty`
Set whether linenoise library returns a zero-length string (if ``true``) or ``NULL`` (if ``false``) for empty lines. By default, zero-length strings are returned.
- :cpp:func:`linenoiseSetMaxLineLen`
Set maximum length of the line for linenoise library. Default length is 4096 bytes. The default value can be updated to optimize RAM memory usage.
- :cpp:func:`linenoiseSetReadFunction`
Set the read function to be used by linenoise.
- :cpp:func:`linenoiseSetReadCharacteristics`
Set the characteristics of the read file descriptor (e.g., blocking or non-blocking mode). The function has a weak definition in ``linenoise.c`` that can be overridden by providing a strong definition of the function.
Main Loop
^^^^^^^^^
- :cpp:func:`linenoise`
In most cases, console applications have some form of read/eval loop. :cpp:func:`linenoise` is the single function which handles user's key presses and returns the completed line once the ``enter`` key is pressed. As such, it handles the ``read`` part of the loop.
- :cpp:func:`linenoiseFree`
This function must be called to release the command line buffer obtained from :cpp:func:`linenoise` function.
Hints and Completions
^^^^^^^^^^^^^^^^^^^^^
- :cpp:func:`linenoiseSetCompletionCallback`
When the user presses the ``tab`` key, linenoise library invokes the completion callback. The callback should inspect the contents of the command typed so far and provide a list of possible completions using calls to :cpp:func:`linenoiseAddCompletion` function. :cpp:func:`linenoiseSetCompletionCallback` function should be called to register this completion callback, if completion feature is desired.
``console`` component provides a ready made function to provide completions for registered commands, :cpp:func:`esp_console_get_completion` (see below).
- :cpp:func:`linenoiseAddCompletion`
Function to be called by completion callback to inform the library about possible completions of the currently typed command.
- :cpp:func:`linenoiseSetHintsCallback`
Whenever user input changes, linenoise invokes the hints callback. This callback can inspect the command line typed so far, and provide a string with hints (which can include list of command arguments, for example). The library then displays the hint text on the same line where editing happens, possibly with a different color.
- :cpp:func:`linenoiseSetFreeHintsCallback`
If the hint string returned by hints callback is dynamically allocated or needs to be otherwise recycled, the function which performs such cleanup should be registered via :cpp:func:`linenoiseSetFreeHintsCallback`.
History
^^^^^^^
- :cpp:func:`linenoiseHistorySetMaxLen`
This function sets the number of most recently typed commands to be kept in memory. Users can navigate the history using the up/down arrows keys.
- :cpp:func:`linenoiseHistoryAdd`
Linenoise does not automatically add commands to history. Instead, applications need to call this function to add command strings to the history.
- :cpp:func:`linenoiseHistorySave`
Function saves command history from RAM to a text file, for example on an SD card or on a filesystem in flash memory.
- :cpp:func:`linenoiseHistoryLoad`
Counterpart to :cpp:func:`linenoiseHistorySave`, loads history from a file.
- :cpp:func:`linenoiseHistoryFree`
Releases memory used to store command history. Call this function when done working with linenoise library.
Splitting of Command Line into Arguments
----------------------------------------
``console`` component provides :cpp:func:`esp_console_split_argv` function to split command line string into arguments. The function returns the number of arguments found (``argc``) and fills an array of pointers which can be passed as ``argv`` argument to any function which accepts arguments in ``argc, argv`` format.
The command line is split into arguments according to the following rules:
- Arguments are separated by spaces
- If spaces within arguments are required, they can be escaped using ``\`` (backslash) character.
- Other escape sequences which are recognized are ``\\`` (which produces literal backslash) and ``\"``, which produces a double quote.
- Arguments can be quoted using double quotes. Quotes may appear only in the beginning and at the end of the argument. Quotes within the argument must be escaped as mentioned above. Quotes surrounding the argument are stripped by ``esp_console_split_argv`` function.
Examples:
- ``abc def 1 20 .3`` > [ ``abc``, ``def``, ``1``, ``20``, ``.3`` ]
- ``abc "123 456" def`` > [ ``abc``, ``123 456``, ``def`` ]
- ```a\ b\\c\"`` > [ ``a b\c"`` ]
Argument Parsing
----------------
For argument parsing, ``console`` component includes `argtable3 <https://www.argtable.org/>`_ library. Please see `tutorial <https://www.argtable.org/tutorial/>`_ for an introduction to `argtable3 <https://www.argtable.org/>`_. Github repository also includes `examples <https://github.com/argtable/argtable3/tree/master/examples>`_.
Command Registration and Dispatching
------------------------------------
``console`` component includes utility functions which handle registration of commands, matching commands typed by the user to registered ones, and calling these commands with the arguments given on the command line.
Application first initializes command registration module using a call to :cpp:func:`esp_console_init`, and calls :cpp:func:`esp_console_cmd_register` function to register command handlers.
For each command, application provides the following information (in the form of ``esp_console_cmd_t`` structure):
- Command name (string without spaces)
- Help text explaining what the command does
- Optional hint text listing the arguments of the command. If application uses Argtable3 for argument parsing, hint text can be generated automatically by providing a pointer to argtable argument definitions structure instead.
- Command handler function (without context), or
- Command handler function (with context). If this function is given, an additional call to :cpp:func:`esp_console_cmd_set_context` must follow *before* the command may be called to initialize the context.
.. note::
You can either use a command handler function which takes a context or a command handler function which does not take a context, not both. If you use the command handler function which takes a context, you MUST call :cpp:func:`esp_console_cmd_set_context` to initialize its context, otherwise the function may access the uninitialized context.
A few other functions are provided by the command registration module:
- :cpp:func:`esp_console_run`
This function takes the command line string, splits it into argc/argv argument list using :cpp:func:`esp_console_split_argv`, looks up the command in the list of registered components, and if it is found, executes its handler.
- :cpp:func:`esp_console_register_help_command`
Adds ``help`` command to the list of registered commands. This command prints the list of all the registered commands, along with their arguments and help texts.
- :cpp:func:`esp_console_get_completion`
Callback function to be used with :cpp:func:`linenoiseSetCompletionCallback` from linenoise library. Provides completions to linenoise based on the list of registered commands.
- :cpp:func:`esp_console_get_hint`
Callback function to be used with :cpp:func:`linenoiseSetHintsCallback` from linenoise library. Provides argument hints for registered commands to linenoise.
Initialize Console REPL Environment
-----------------------------------
To establish a basic REPL environment, ``console`` component provides several useful APIs, combining those functions described above.
In a typical application, you only need to call :cpp:func:`esp_console_new_repl_stdio` to initialize the REPL environment, including driver install, basic console configuration, spawning a thread to do REPL task and register several useful commands (e.g., `help`).
After that, you can register your own commands with :cpp:func:`esp_console_cmd_register`. The REPL environment keeps in initialized state until you call :cpp:func:`esp_console_start_repl`.
Application Examples
--------------------
- :example:`system/console/basic` demonstrates how to use the REPL (Read-Eval-Print Loop) APIs of the Console Component to create an interactive shell on {IDF_TARGET_NAME}, which can be controlled over a serial interface, supporting UART and USB interfaces, and can serve as a basis for applications requiring a command-line interface.
- :example:`system/console/advanced` demonstrates how to use the Console Component to create an interactive shell on {IDF_TARGET_NAME}, which can be controlled over a serial interface, supporting UART and USB interfaces, providing a basis for applications that require a command-line interface.
API Reference
-------------
.. include-build-file:: inc/esp_console.inc
+797
View File
@@ -0,0 +1,797 @@
eFuse Manager
=============
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_CODING_SCHEMES:default="Reed-Solomon", esp32="3/4 or Repeat"}
Introduction
------------
eFuse (Electronic Fuses) are microscopic one-time programmable fuses that can be "burned" (i.e., programmed) to store data into the {IDF_TARGET_NAME}. eFuse bits are organized into different data fields, and these data fields could be used for system parameters (i.e., data parameters used by ESP-IDF of {IDF_TARGET_NAME}) or user defined parameters.
The eFuse Manager component is a collection of tools and APIs that assist with defining, burning, accessing eFuses parameters. The notable tools and APIs include:
* A table format used to define eFuse data fields in CSV file.
* ``efuse_table_gen.py`` tool to generate C structure representation of eFuse data fields specified by the CSV file.
* Collection of C API to read/write eFuse data fields.
eFuse Manager vs ``idf.py``
---------------------------
``idf.py`` provides a subset of the functionality of the eFuse Manager via the ``idf.py efuse-<subcommand>`` commands. In this documentation, mostly ``idf.py`` based commands will be used, although you can still see some ``espefuse`` based commands for advanced or rare cases. To see all available commands, run ``idf.py --help`` and search for those prefixed with ``efuse-``.
Hardware Description
--------------------
The {IDF_TARGET_NAME} has a number of eFuses which can store system and user parameters. Each eFuse is a one-bit field which can be programmed to 1 after which it cannot be reverted back to 0. The eFuse bits are grouped into blocks of 256 bits, where each block is further divided into 8 32-bit registers. Some blocks are reserved for system parameters while the remaining blocks can be used for user parameters.
For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *eFuse Controller (eFuse)* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__].
.. only:: esp32
{IDF_TARGET_NAME} has 4 eFuse blocks each containing 256 bits (not all bits can be used for user parameters):
* EFUSE_BLK0 is used entirely for system purposes
* EFUSE_BLK1 is used for Flash Encryption keys. If the Flash Encryption feature is not used, this block can be used for user parameters.
* EFUSE_BLK2 is used for the Secure Boot key. If the Secure Boot feature is not used, this block can be used for user parameters.
* EFUSE_BLK3 can be partially reserved to store a custom MAC address, or can be used entirely for user parameters. Note that some bits are already used in ESP-IDF.
.. only:: not esp32 and not esp32c2
{IDF_TARGET_NAME} has 11 eFuse blocks each containing 256 bits (not all bits can be used for user parameters):
.. list::
* EFUSE_BLK0 is used entirely for system parameters
* EFUSE_BLK1 is used entirely for system parameters
* EFUSE_BLK2 is used entirely for system parameters
* EFUSE_BLK3 (also named EFUSE_BLK_USER_DATA) can be used for user parameters
* EFUSE_BLK4 to EFUSE_BLK8 (also named EFUSE_BLK_KEY0 to EFUSE_BLK_KEY4) can be used to store keys for Secure Boot or Flash Encryption. If both features are unused, these blocks can be used for user parameters.
:SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK and SOC_ECDSA_SUPPORTED: * EFUSE_BLK9 (also named EFUSE_BLK_KEY5) can be used for any purpose except for Flash Encryption or ECDSA (due to a HW errata);
:SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK and not SOC_ECDSA_SUPPORTED: * EFUSE_BLK9 (also named EFUSE_BLK_KEY5) can be used for any purpose except for Flash Encryption (due to a HW errata);
:not SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK: * EFUSE_BLK9 (also named EFUSE_BLK_KEY5) can be used to store keys for Secure Boot or Flash Encryption. If both features are unused, these blocks can be used for user parameters.
* EFUSE_BLK10 (also named EFUSE_BLK_SYS_DATA_PART2) is reserved for system parameters.
.. only:: esp32c2
{IDF_TARGET_NAME} has 4 eFuse blocks each containing 256 bits (not all bits can be used for user parameters):
* EFUSE_BLK0 is used entirely for system parameters
* EFUSE_BLK1 is used entirely for system parameters
* EFUSE_BLK2 is used entirely for system parameters
* EFUSE_BLK3 (also named EFUSE_BLK_KEY0) can be used to store keys for Secure Boot or Flash Encryption. If both features are unused, these blocks can be used for user parameters.
Defining eFuse Fields
---------------------
eFuse fields are defined as a table of records in a CSV file according to a specific format. This record format provides the ability to form eFuse fields of any length and from any number of individual bits.
Moreover, the record format allows structured definition of eFuse fields consisting of sub-fields, meaning that a parent eFuse field may consist of multiple child eFuse fields occupying the same eFuse bits.
Record Format
^^^^^^^^^^^^^
In simple cases, each record occupies a single row in the table. Each record contains the following values (i.e., columns):
{IDF_TARGET_MAX_EFUSE_BLK:default = "EFUSE_BLK10", esp32 = "EFUSE_BLK3", esp32c2 = "EFUSE_BLK3", esp32s31 = "EFUSE_BLK9"}
.. code-block:: none
# field_name, efuse_block(EFUSE_BLK0..{IDF_TARGET_MAX_EFUSE_BLK}), bit_start(0..255), bit_count(1..256), comment
- ``field_name``
- Name of the eFuse field.
- The prefix ``ESP_EFUSE_`` is automatically added to the name, and this name will be used when referring to the field in C code.
- ``field_name`` unique across all eFuse fields.
- If this value is left empty, then this record is combined with the previous record. This allows you define an eFuse field with arbitrary bit ordering (see ``MAC_FACTORY`` field in the common table).
- Using ``.`` will define a child eFuse field. See :ref:`structured-efuse-fields` for more details.
- ``efuse_block``
- The eFuse field's block number. E.g., EFUSE_BLK0 to {IDF_TARGET_MAX_EFUSE_BLK}.
- This determines which block the eFuse field is placed.
- ``bit_start``
- Bit offset (0 to 255) of the eFuse within the block.
- ``bit_start`` is optional and can be omitted.
- In this case, it is set to ``bit_start + bit_count`` from the previous record, given that the previous record is in the same eFuse block.
- If the previous record is in a different eFuse block, an error will be generated.
- ``bit_count``
- The size of the eFuse field in bits (1 to N).
- ``bit_count`` cannot be omitted.
- If set to ``MAX_BLK_LEN`` the eFuse field's size will be the maximum allowable eFuse field size in the block.
.. only:: esp32
- ``MAX_BLK_LEN`` takes into account the coding scheme of eFuse.
- Depending on the coding scheme selected via :ref:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR`, ``MAX_BLK_LEN`` could be 256 ("None"), 192 ("3/4"), or 128 ("REPEAT").
- ``comment``
- Comment describing the eFuse field.
- The comment is copied verbatim into the C header file.
If an eFuse field requires non-sequential bit ordering, then the eFuse field will span multiple records (i.e., multiple rows). The first record's ``field_name`` should specify the eFuse field's name, and the following records should leave ``field_name`` blank to indicate that they belong to the same eFuse field.
The following example demonstrates the records to specify the non-sequential eFuse field ``MAC_FACTORY`` followed by a regular eFuse field ``MAC_FACTORY_CRC``:
.. code-block:: none
# Factory MAC address #
#######################
MAC_FACTORY, EFUSE_BLK0, 72, 8, Factory MAC addr [0]
, EFUSE_BLK0, 64, 8, Factory MAC addr [1]
, EFUSE_BLK0, 56, 8, Factory MAC addr [2]
, EFUSE_BLK0, 48, 8, Factory MAC addr [3]
, EFUSE_BLK0, 40, 8, Factory MAC addr [4]
, EFUSE_BLK0, 32, 8, Factory MAC addr [5]
MAC_FACTORY_CRC, EFUSE_BLK0, 80, 8, CRC8 for factory MAC address
This eFuse fields will be made available in C code as ``ESP_EFUSE_MAC_FACTORY`` and ``ESP_EFUSE_MAC_FACTORY_CRC``.
.. _structured-efuse-fields:
Structured eFuse Fields
-----------------------
Typically, an eFuse field represents a particular parameter. However, in some cases where an eFuse field consists of multiple sub-fields, it may be useful to have isolated access to those sub-fields. For example, if an eFuse field contained a floating point parameter, it may be useful to be access the sign, exponent, and mantissa fields of the floating as separate eFuse fields.
Therefore, it is possible for records to define eFuse fields in a structured manner using the ``.`` operator in ``field_name``. For example, ``XX.YY.ZZ`` defines a eFuse field ``ZZ`` that is a child of eFuse field ``YY`` which in turn is a child field of eFuse field ``XX``.
The following records demonstrate the definition of eFuse fields in a structured manner:
.. code-block:: none
WR_DIS, EFUSE_BLK0, 0, 32, Write protection
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, Write protection for RD_DIS
WR_DIS.FIELD_1, EFUSE_BLK0, 1, 1, Write protection for FIELD_1
WR_DIS.FIELD_2, EFUSE_BLK0, 2, 4, Write protection for FIELD_2 (includes B1 and B2)
WR_DIS.FIELD_2.B1, EFUSE_BLK0, 2, 2, Write protection for FIELD_2.B1
WR_DIS.FIELD_2.B2, EFUSE_BLK0, 4, 2, Write protection for FIELD_2.B2
WR_DIS.FIELD_3, EFUSE_BLK0, 5, 1, Write protection for FIELD_3
WR_DIS.FIELD_3.ALIAS, EFUSE_BLK0, 5, 1, Write protection for FIELD_3 (just a alias for WR_DIS.FIELD_3)
WR_DIS.FIELD_4, EFUSE_BLK0, 7, 1, Write protection for FIELD_4
Some things to note regarding the example above:
* The ``WR_DIS`` record defines the parent eFuse field. All the other records are child fields of ``WR_DIS`` due to their ``WR_DIS.`` prefix.
* The child fields must utilize the same bits as their parent field. Take note of ``bit_start`` and ``bit_count`` of the child and parent fields:
* The bits of the child fields are always in the range of their parent field. For example, ``WR_DIS.RD_DIS`` and ``WR_DIS.RD_DIS`` occupy the first and second bit of ``WR_DIS``.
* Child fields cannot use overlapping bits (except for when aliasing).
* It is possible to create aliases as a child field. For example, ``WR_DIS.FIELD_3.ALIAS`` is a child field and alias of ``WR_DIS.FIELD_3`` as they both occupy the same bits.
All eFuse Fields are eventually converted to C structures via the ``efuse_table_gen.py`` tool. The C structure for each eFuse field will derive their identifier from the ``field_name`` of the eFuse field's record, where all ``.`` are replaced with ``_``. For example, the C symbols for ``WR_DIS.RD_DIS`` and ``WR_DIS.FIELD_2.B1`` will be ``ESP_EFUSE_WR_DIS_RD_DIS`` and ``ESP_EFUSE_WR_DIS_FIELD_2_B1`` respectively.
The ``efuse_table_gen.py`` tool also checks that the fields do not overlap each other and must be within the range of a field. If there is a violation, then the following error is generated:
.. code-block:: none
Field at USER_DATA, EFUSE_BLK3, 0, 256 intersected with SERIAL_NUMBER, EFUSE_BLK3, 0, 32
In this case, the error can be resolved by making ``SERIAL_NUMBER`` a child field of ``USER_DATA`` via ``USER_DATA.SERIAL_NUMBER``.
.. code-block:: none
Field at FIELD, EFUSE_BLK3, 0, 50 out of range FIELD.MAJOR_NUMBER, EFUSE_BLK3, 60, 32
In this case, the error can be resolved by changing ``bit_start`` for ``FIELD.MAJOR_NUMBER`` from ``60`` to ``0`` so that ``MAJOR_NUMBER`` overlaps with ``FIELD``.
``efuse_table_gen.py`` Tool
---------------------------
The ``efuse_table_gen.py`` tool is designed to generate C source files containing C structures (of type :cpp:type:`esp_efuse_desc_t`) representing the eFuse fields defined in CSV files. Moreover, the tool also runs some checks on the provided CSV files before generation to ensure that:
- the names of the eFuse fields are unique
- the eFuse fields do not use overlapping bits
As mentioned previously, eFuse fields can be used to hold either system parameters or user parameters. Given that system parameter eFuse fields are inherently required by ESP-IDF and {IDF_TARGET_NAME}, those eFuse fields are defined in a **common** CSV file (``esp_efuse_table.csv``) and distributed as part of ESP-IDF. For user parameter eFuse fields, users should define those fields in a **custom** CSV file (e.g., ``esp_efuse_custom_table.csv``).
To generate C source files using the **common** CSV file, use the ``idf.py efuse-common-table`` or the following:
.. code-block:: bash
cd $IDF_PATH/components/efuse/
./efuse_table_gen.py --idf_target {IDF_TARGET_PATH_NAME} {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv
The following C source/header files will be generated by the tool in ``$IDF_PATH/components/efuse/{IDF_TARGET_PATH_NAME}``:
* ``esp_efuse_table.c`` file containing the C structures of the system parameter eFuse fields
* ``esp_efuse_table.h`` file in the ``include`` folder. This header can be included by the application to use those C structures.
To generate C source files using a **custom** CSV file, use the command ``idf.py efuse-custom-table`` or the following:
.. code-block:: bash
cd $IDF_PATH/components/efuse/
./efuse_table_gen.py --idf_target {IDF_TARGET_PATH_NAME} {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv PROJECT_PATH/main/esp_efuse_custom_table.csv
The following C source/header files will be generated by the tool in ``PROJECT_PATH/main``:
* ``esp_efuse_custom_table.c`` file containing the C structures of the user parameter eFuse fields
* ``esp_efuse_custom_table.h`` file in the ``include`` folder. This header can be included by the application to use those C structures.
To use the generated fields, you need to include two files:
.. code-block:: c
#include "esp_efuse.h"
#include "esp_efuse_table.h" // or "esp_efuse_custom_table.h"
Supported Coding Schemes
------------------------
Various coding schemes are supported by eFuses which can protect eFuses against data corruption by detecting and/or correcting for errors.
.. only:: esp32
{IDF_TARGET_NAME} supports the following eFuse coding schemes:
* ``None`` (value 0), meaning no coding scheme is applied.
* ``3/4`` (value 1).
* ``Repeat`` (value 2). It is not entirely supported by IDF, not recommended for use.
The coding schemes will encode each eFuse block individually. Furthermore, only EFUSE_BLK1, EFUSE_BLK2 and EFUSE_BLK3 will be encoded, meaning EUSE_BLK0 always uses the ``None`` coding scheme.
Coding schemes require some bits within an eFuse block to be used as overhead. Thus, by applying a coding scheme, only a subset of the 256 bits within an eFuse block will be usable as eFuse fields.
* ``None``: 256 usable bits
* ``3/4``: 192 usable bits
* ``Repeat``: 128 usable bits
When using a coding scheme, the length of the payload that can be written is limited. For more details, Please Refer to *{IDF_TARGET_NAME} Technical Reference Manual* > *Chapter 20 eFuse Controller* [`PDF <{IDF_TARGET_TRM_EN_URL}#efuse>`__] > *Section 20.3.1.3 System Parameter coding_scheme*.
You can find out the coding scheme of your chip:
* run the ``idf.py efuse-summary`` command.
* from ``esptool`` utility logs (during flashing).
* calling the function :cpp:func:`esp_efuse_get_coding_scheme` in the application for the EFUSE_BLK3 block.
The eFuse fields specified in the CSV files must always comply with the eFuse coding scheme used by the chip. The :ref:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR` option selects which coding scheme is used by the CSV files. When generating source files, if the records in the CSV files do not adhere to the coding scheme, an error message will be displayed. In that case, you must adjust the ``bit_start`` and ``bit_count`` of the records to comply with the limitations of the selected coding scheme.
.. note::
After changing the coding scheme, run ``efuse_common_table`` and ``efuse_custom_table`` commands to check the tables of the new coding scheme.
If your program was compiled with ``None`` encoding but ``3/4`` is used by the chip, then the ``ESP_ERR_CODING`` error may occur when calling the eFuse API (The field is outside the block boundaries). If the field matches the new block boundaries, then the API will work without errors.
``None`` Coding Scheme
^^^^^^^^^^^^^^^^^^^^^^
The ``None`` coding scheme indicates that no coding scheme is applied, thus all 256 bits of each eFuse block are usable. However, there will be no protection against the corruption of eFuse bits.
``3/4`` Coding Scheme
^^^^^^^^^^^^^^^^^^^^^
The ``3/4`` coding scheme imposes restrictions on writing bits belonging to one coding unit. The whole block with a length of 256 bits is divided into 4 coding units. In each coding unit there are 6 bytes of useful data and 2 service bytes. These 2 service bytes contain the checksum of the previous 6 data bytes.
Due to the calculation of the checksum for each coding unit, the writing process must be divided into the coding units. As such, the normal method (used by the ``None`` coding scheme) of burning eFuse bits separately over multiple write operations will no longer work. The data for the eFuse fields of a particular coding unit and the unit's associated checksum must be burned in one go. This is known as Batch Writing Mode.
As a result of Batch Writing Mode, a particular coding unit can only be written once (i.e., repeated writing to the same coding unit is prohibited). Thus, any coding unit that is written at run time can only contain one eFuse field. However, if the eFuse fields of a coding unit was specified in advance (via CSV records) or written to via :cpp:func:`esp_efuse_write_block`, then a coding unit can still contain multiple eFuse fields.
``Repeat`` Coding Scheme
^^^^^^^^^^^^^^^^^^^^^^^^
The ``Repeat`` coding scheme simply repeats each eFuse bit, thus does not impose the same Batch Writing Mode restrictions as the ``3/4`` coding scheme. However, this comes at the cost of a larger overhead, leaving only 128 usable bits per eFuse block.
.. only:: not esp32
{IDF_TARGET_NAME} does not support selection of coding schemes. The following coding schemes are automatically applied to various eFuse blocks:
* ``None``: Applied to EFUSE_BLK0
* ``RS``: Applied to EFUSE_BLK1 - {IDF_TARGET_MAX_EFUSE_BLK}
``None`` Coding Scheme
^^^^^^^^^^^^^^^^^^^^^^
The ``None`` coding scheme is automatically applied to EFUSE_BLK0. This scheme does not involve any encoding, but simply maintains four backups of EFUSE_BLK0 in hardware, meaning each bit is stored four times. As a result, EFUSE_BLK0 can be written many times.
This scheme is automatically applied by the hardware and is not visible to software.
``RS`` Coding Scheme
^^^^^^^^^^^^^^^^^^^^^^
The ``RS`` coding scheme uses Reed-Solomon encoding and is automatically applied to EFUSE_BLK1 to {IDF_TARGET_MAX_EFUSE_BLK}. The coding scheme supports up to 6 bytes of automatic error correction.
Software encodes the 32-byte EFUSE_BLKx using ``RS(44, 32)`` to generate a 12-byte check-symbols, and then burn the EFUSE_BLKx and the check-symbols into eFuse at the same time.
The eFuse Controller automatically decodes the ``RS`` encoding and applies error correction when reading back the eFuse block. Because the ``RS`` check-symbols are generated across the entire 256-bit eFuse block, each block can only be written to one time. As a result of the check-symbols, Batch Writing Mode must be used.
Batch Writing Mode
^^^^^^^^^^^^^^^^^^
When writing to eFuse fields at run time, it may be necessary to use the Batch Writing Mode depending on the coding scheme used for eFuse block. Batch writing mode can be used as follows:
#. Enable batch writing mode by calling :cpp:func:`esp_efuse_batch_write_begin`
#. Write to the eFuse fields as usual using various ``esp_efuse_write_...`` functions.
#. Once all writes are complete, call :cpp:func:`esp_efuse_batch_write_commit` which burns prepared data to the eFuse blocks.
.. warning::
If there is already pre-written data in the eFuse block using the ``{IDF_TARGET_CODING_SCHEMES}`` encoding scheme, then it is not possible to write anything extra (even if the required bits are empty) without breaking the previous data's checksums/check-symbols.
The checksums/check-symbols will be overwritten with new checksums/check-symbols and be completely destroyed (however, the payload eFuses are not damaged).
If you happen to find pre-written data in CUSTOM_MAC, SPI_PAD_CONFIG_HD, SPI_PAD_CONFIG_CS, etc., please contact Espressif to obtain the required pre-burnt eFuses.
FOR TESTING ONLY (NOT RECOMMENDED): You can ignore or suppress errors that violate encoding scheme data in order to burn the necessary bits in the eFuse block.
.. _efuse_API:
eFuse API
---------
Access to the fields is via a pointer to the description structure. API functions have some basic operation:
* :cpp:func:`esp_efuse_read_field_blob` - returns an array of read eFuse bits.
* :cpp:func:`esp_efuse_read_field_cnt` - returns the number of bits programmed as "1".
* :cpp:func:`esp_efuse_write_field_blob` - writes an array.
* :cpp:func:`esp_efuse_write_field_cnt` - writes a required count of bits as "1".
* :cpp:func:`esp_efuse_get_field_size` - returns the number of bits by the field name.
* :cpp:func:`esp_efuse_read_reg` - returns value of eFuse register.
* :cpp:func:`esp_efuse_write_reg` - writes value to eFuse register.
* :cpp:func:`esp_efuse_get_coding_scheme` - returns eFuse coding scheme for blocks.
* :cpp:func:`esp_efuse_read_block` - reads a key from an eFuse block starting at the offset with required size.
* :cpp:func:`esp_efuse_write_block` - writes a key to an eFuse block starting at the offset with required size.
* :cpp:func:`esp_efuse_batch_write_begin` - set the batch mode of writing fields.
* :cpp:func:`esp_efuse_batch_write_commit` - writes all prepared data for batch writing mode and reset the batch writing mode.
* :cpp:func:`esp_efuse_batch_write_cancel` - reset the batch writing mode and prepared data.
* :cpp:func:`esp_efuse_get_key_dis_read` - Returns a read protection for the key block.
* :cpp:func:`esp_efuse_set_key_dis_read` - Sets a read protection for the key block.
* :cpp:func:`esp_efuse_get_key_dis_write` - Returns a write protection for the key block.
* :cpp:func:`esp_efuse_set_key_dis_write` - Sets a write protection for the key block.
* :cpp:func:`esp_efuse_get_key_purpose` - Returns the current purpose set for an eFuse key block.
* :cpp:func:`esp_efuse_write_key` - Programs a block of key data to an eFuse block.
* :cpp:func:`esp_efuse_write_keys` - Programs keys to unused eFuse blocks.
* :cpp:func:`esp_efuse_find_purpose` - Finds a key block with the particular purpose set.
* :cpp:func:`esp_efuse_get_keypurpose_dis_write` - Returns a write protection of the key purpose field for an eFuse key block (for esp32 always true).
* :cpp:func:`esp_efuse_key_block_unused` - Returns true if the key block is unused, false otherwise.
* :cpp:func:`esp_efuse_destroy_block` - Destroys the data in this eFuse block. There are two things to do: (1) if write protection is not set, then the remaining unset bits are burned, (2) set read protection for this block if it is not locked.
* :cpp:func:`esp_efuse_token_dump` - Generates a compact, single-line eFuse token (``EFSR``, ``EFSW``, or ``EFSRW``) that can be copied from device logs and decoded on the host with ``espefuse --token ...`` (useful when direct eFuse access is not available).
* :cpp:func:`esp_efuse_token_burn` - Applies an ``EFSW`` token on the device by burning the staged eFuse writes encoded in the token (other token types are rejected).
For frequently used fields, special functions are made, like this :cpp:func:`esp_efuse_get_pkg_ver`.
.. only:: SOC_EFUSE_KEY_PURPOSE_FIELD or SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY
eFuse API for Keys
------------------
.. only:: SOC_EFUSE_KEY_PURPOSE_FIELD
EFUSE_BLK_KEY0 - EFUSE_BLK_KEY5 are intended to keep up to 6 keys with a length of 256-bits. Each key has an ``ESP_EFUSE_KEY_PURPOSE_x`` field which defines the purpose of these keys. The purpose field is described in :cpp:type:`esp_efuse_purpose_t`.
The purposes like ``ESP_EFUSE_KEY_PURPOSE_XTS_AES_...`` are used for flash encryption.
The purposes like ``ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST...`` are used for secure boot.
There are some eFuse APIs useful to work with states of keys:
* :cpp:func:`esp_efuse_get_purpose_field` - Returns a pointer to a key purpose for an eFuse key block.
* :cpp:func:`esp_efuse_get_key` - Returns a pointer to a key block.
* :cpp:func:`esp_efuse_set_key_purpose` - Sets a key purpose for an eFuse key block.
* :cpp:func:`esp_efuse_set_keypurpose_dis_write` - Sets a write protection of the key purpose field for an eFuse key block.
* :cpp:func:`esp_efuse_find_unused_key_block` - Search for an unused key block and return the first one found.
* :cpp:func:`esp_efuse_count_unused_key_blocks` - Returns the number of unused eFuse key blocks in the range EFUSE_BLK_KEY0 to EFUSE_BLK_KEY_MAX
.. only:: SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY
* :cpp:func:`esp_efuse_get_digest_revoke` - Returns the status of the Secure Boot public key digest revocation bit.
* :cpp:func:`esp_efuse_set_digest_revoke` - Sets the Secure Boot public key digest revocation bit.
* :cpp:func:`esp_efuse_get_write_protect_of_digest_revoke` - Returns a write protection of the Secure Boot public key digest revocation bit.
* :cpp:func:`esp_efuse_set_write_protect_of_digest_revoke` - Sets a write protection of the Secure Boot public key digest revocation bit.
How to Add a New Field
----------------------
1. Find free bits for field. Refer to the ``esp_efuse_table.csv`` file, running ``idf.py show-efuse-table``, or running the following command:
.. include:: inc/show-efuse-table_{IDF_TARGET_NAME}.rst
The number of bits not included in square brackets are free (some bits are reserved by Espressif). All fields are checked for overlapping bits.
To add child fields to an existing field, :ref:`structured-efuse-fields` can be used. The following example demonstrates adding of the the fields ``SERIAL_NUMBER``, ``MODEL_NUMBER`` and ``HARDWARE_REV`` to an existing ``USER_DATA`` field by using the ``.`` operator:
.. code-block:: none
USER_DATA.SERIAL_NUMBER, EFUSE_BLK3, 0, 32,
USER_DATA.MODEL_NUMBER, EFUSE_BLK3, 32, 10,
USER_DATA.HARDWARE_REV, EFUSE_BLK3, 42, 10,
In general, to add new eFuse Fields:
#. Add a record for each eFuse field in CSV file.
#. Run the ``show_efuse_table`` command to check eFuse table.
#. To generate source files run the ``efuse_common_table`` or ``efuse_custom_table`` commands.
You may get errors such as ``intersects with`` or ``out of range``. Please see how to solve them in the :ref:`structured-efuse-fields` article.
Bit Order
---------
The eFuses bit order is little endian (see the example below), meaning that eFuse bits are read and written from LSB to MSB:
.. code-block:: none
$ idf.py efuse-dump
USER_DATA (BLOCK3 ) [3 ] read_regs: 03020100 07060504 0B0A0908 0F0E0D0C 13121111 17161514 1B1A1918 1F1E1D1C
BLOCK4 (BLOCK4 ) [4 ] read_regs: 03020100 07060504 0B0A0908 0F0E0D0C 13121111 17161514 1B1A1918 1F1E1D1C
where is the register representation:
EFUSE_RD_USR_DATA0_REG = 0x03020100
EFUSE_RD_USR_DATA1_REG = 0x07060504
EFUSE_RD_USR_DATA2_REG = 0x0B0A0908
EFUSE_RD_USR_DATA3_REG = 0x0F0E0D0C
EFUSE_RD_USR_DATA4_REG = 0x13121111
EFUSE_RD_USR_DATA5_REG = 0x17161514
EFUSE_RD_USR_DATA6_REG = 0x1B1A1918
EFUSE_RD_USR_DATA7_REG = 0x1F1E1D1C
where is the byte representation:
byte[0] = 0x00, byte[1] = 0x01, ... byte[3] = 0x03, byte[4] = 0x04, ..., byte[31] = 0x1F
For example, CSV file describes the ``USER_DATA`` field, which occupies all 256 bits (a whole block).
.. code-block:: none
USER_DATA, EFUSE_BLK3, 0, 256, User data
USER_DATA.FIELD1, EFUSE_BLK3, 16, 16, Field1
ID, EFUSE_BLK4, 8, 3, ID bit[0..2]
, EFUSE_BLK4, 16, 2, ID bit[3..4]
, EFUSE_BLK4, 32, 3, ID bit[5..7]
Thus, reading the eFuse ``USER_DATA`` block written as above gives the following results:
.. code-block:: c
uint8_t buf[32] = { 0 };
esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA, &buf, sizeof(buf) * 8);
// buf[0] = 0x00, buf[1] = 0x01, ... buf[31] = 0x1F
uint32_t field1 = 0;
size_t field1_size = ESP_EFUSE_USER_DATA[0]->bit_count; // can be used for this case because it only consists of one entry
esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA, &field1, field1_size);
// field1 = 0x0302
uint32_t field1_1 = 0;
esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA, &field1_1, 2); // reads only first 2 bits
// field1 = 0x0002
uint8_t id = 0;
size_t id_size = esp_efuse_get_field_size(ESP_EFUSE_ID); // returns 6
// size_t id_size = ESP_EFUSE_USER_DATA[0]->bit_count; // cannot be used because it consists of 3 entries. It returns 3 not 6
esp_efuse_read_field_blob(ESP_EFUSE_ID, &id, id_size);
// id = 0x91
// b'100 10 001
// [3] [2] [3]
uint8_t id_1 = 0;
esp_efuse_read_field_blob(ESP_EFUSE_ID, &id_1, 3);
// id = 0x01
// b'001
Get eFuses During Build
-----------------------
There is a way to get the state of eFuses at the build stage of the project. There are two CMake functions for this:
* ``espefuse_get_json_summary()`` - It calls the ``espefuse summary --format json`` command and returns a JSON string (it is not stored in a file).
* ``espefuse_get_efuse()`` - It finds a given eFuse name in the JSON string and returns its property.
The JSON string has the following properties:
.. code-block:: json
{
"MAC": {
"bit_len": 48,
"block": 0,
"category": "identity",
"description": "Factory MAC Address",
"efuse_type": "bytes:6",
"name": "MAC",
"pos": 0,
"readable": true,
"value": "94:b9:7e:5a:6e:58 (CRC 0xe2 OK)",
"word": 1,
"writeable": true
},
}
These functions can be used from a top-level project ``CMakeLists.txt`` (:example_file:`system/efuse/CMakeLists.txt`):
.. code-block:: cmake
# ...
project(hello_world)
espefuse_get_json_summary(efuse_json)
espefuse_get_efuse(ret_data ${efuse_json} "MAC" "value")
message("MAC:" ${ret_data})
The format of the ``value`` property is the same as shown in ``espefuse summary`` or ``idf.py efuse-summary``.
.. code-block:: none
MAC:94:b9:7e:5a:6e:58 (CRC 0xe2 OK)
There is an example test :example_file:`system/efuse/CMakeLists.txt` which adds a custom target ``efuse-filter``. This allows you to run the ``idf.py efuse-filter`` command to read the required eFuses (specified in the ``efuse_names`` list) at any time, not just during the project build.
Debug eFuse & Unit Tests
------------------------
.. _virtual-efuses:
Virtual eFuses
^^^^^^^^^^^^^^
The Kconfig option :ref:`CONFIG_EFUSE_VIRTUAL` virtualizes eFuse values inside the eFuse Manager, so writes are emulated and no eFuse values are permanently changed. This can be useful for debugging and unit testing.
During startup, the eFuses are copied to RAM. All eFuse operations (read and write) are performed with RAM instead of the real eFuse registers.
In addition to the :ref:`CONFIG_EFUSE_VIRTUAL` option, there is the :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` option that adds a feature to keep eFuses in flash memory. To use this mode, the partition_table should have include an ``efuse`` partition in ``partition.csv``:
.. code-block:: none
efuse_em, data, efuse, , 0x2000,
During startup, the eFuses are copied from flash, or in case where flash is empty, copied from real eFuse to RAM and then write flash. This option allows keeping eFuses after reboots, making it possible to test Secure Boot and Flash Encryption features.
Flash Encryption Testing
""""""""""""""""""""""""
Flash encryption is a hardware feature that requires the physical burning of eFuses ``key`` and ``FLASH_CRYPT_CNT``. If flash encryption is not actually enabled, then enabling the :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` option just provides testing possibilities and does not encrypt anything in the flash, even though the logs indicates that encryption happens.
The :cpp:func:`bootloader_flash_write` is adapted for this purpose. But if flash encryption is already enabled on the chip when the application is run, or if the bootloader is created with the :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` option, then the flash encryption/decryption operations will work properly. This means that data are encrypted as it is written into an encrypted flash partition and decrypted when they are read from an encrypted partition.
``espefuse``
^^^^^^^^^^^^
esptool includes a useful tool for reading/writing {IDF_TARGET_NAME} eFuse bits - `espefuse <https://docs.espressif.com/projects/esptool/en/latest/{IDF_TARGET_PATH_NAME}/espefuse/index.html>`_.
Part of the functionality of this tool is also provided directly by ``idf.py`` commands. For example, the ``idf.py efuse-summary`` command is equivalent to ``espefuse summary``.
.. include:: inc/espefuse_summary_{IDF_TARGET_NAME}.rst
To get a dump for all eFuse registers.
.. include:: inc/espefuse_summary_{IDF_TARGET_NAME}_dump.rst
Deferred WR_DIS Burning
-----------------------
``WR_DIS`` (Write Disable) is a special eFuse field that implements permanent write-protection. Each bit in ``WR_DIS`` disables further programming of one (or more) associated eFuse fields. Once a ``WR_DIS`` bit is burned, its associated fields can no longer be modified.
When burning staged data in BLOCK0, the ``WR_DIS`` bits are burned separately after all other BLOCK0 data to ensure the burn function can recover from coding errors via its retry mechanism. This approach guarantees that write-protection is applied only after other BLOCK0 data is successfully burned.
Token Dump
----------
The *token dump* feature provides a compact, single-line representation of an eFuse state that can be copied from device logs and decoded later on the host. This is designed for cases where reading eFuses directly with host tools is not possible or not convenient (for example, UART download is disabled, secure download is enabled, secure boot/flash encryption is deployed, or the device is remote).
.. code-block:: none
EFSR:esp32c3:004:AAGAAAEAAAAAAAAEAAAAAAAAAAAAAAAA:AAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAA:AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::::::::::epNVBg
A token can represent:
* the currently programmed eFuses (read snapshot, `EFSR`),
* the staged (not yet burned) write set (write snapshot, `EFSW`) — in batch write mode you can dump the pending writes **before** calling :cpp:func:`esp_efuse_batch_write_commit`,
* both the programmed eFuses and the staged writes in a single token (combined snapshot, `EFSRW`).
Tokens include a CRC32 checksum to detect truncation and accidental modifications.
Typical Use Cases
^^^^^^^^^^^^^^^^^
* **Production/field diagnostics:** export the eFuse state from a locked-down device and decode it offline.
* **Post-provisioning verification:** confirm security configuration and key purposes after manufacturing steps.
* **Coding error investigation:** capture and share coding-error register snapshots alongside block data.
* **Audit and traceability:** store a token as a provisioning artifact for later review.
* **Staged write transfer:** generate ``EFSW`` in firmware (or on the host) and apply it later using a controlled workflow.
Supported Workflows
^^^^^^^^^^^^^^^^^^^
* On the device:
* :cpp:func:`esp_efuse_token_dump()` — always supports ``EFSR`` tokens; ``EFSW`` and ``EFSRW`` require :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API` because they expose staged values that are not yet burned and not yet read-protected.
* :cpp:func:`esp_efuse_token_burn()` — accepts an ``EFSW`` token and applies staged writes on the device.
* On the host:
* ``espefuse --token EFS... summary`` — decodes tokens and shows the eFuse summary without connecting to a device.
* ``espefuse dump --format EFSR`` — generates an ``EFSR`` token from a connected chip for sharing/backup.
* ``espefuse burn-efuse ... --show-token`` — generates an ``EFSW`` token representing staged writes.
Security Note
^^^^^^^^^^^^^
.. important::
Tokens are not encrypted. Treat tokens as sensitive data:
* Tokens can include **unique identifiers** (for example MAC/UUID-like fields) and **security-relevant configuration bits** (secure boot, flash encryption, JTAG/UART disablement, key purposes).
* ``EFSW`` tokens represent **staged writes**. They may include **write-only key data in plaintext** because the staged view shows values that have not yet been burned and are not yet protected by the eFuse read-protection bits. This can disclose provisioning intent and secret material before it is irreversibly locked down.
* ``EFSRW`` tokens include the same staged portion and therefore carry the same plaintext key-exposure risk.
* Even when certain eFuses are read-protected on the target, the token may still carry **operationally sensitive values**.
If firmware exposes a console command, remote endpoint, or other runtime API that prints eFuse tokens, the firmware must authenticate and authorize that request before generating the token.
Recommendations:
* Share tokens only with trusted parties and via trusted channels (avoid public issue trackers).
* Store tokens as you would store other manufacturing/provisioning artifacts (restricted access, limited retention).
* Prefer ``EFSR`` tokens for diagnostics and auditing; use ``EFSW`` tokens only when you explicitly need to transfer staged write state.
Token format
^^^^^^^^^^^^
A token is a colon-separated sequence:
.. code-block:: none
<token_name>:<chip>:<ver>:<b64_block0>:...:<b64_blockN>:<b64_cerr>:<b64_crc32>
Fields:
* ``token_name`` — one of ``EFSR``, ``EFSW``, or ``EFSRW``.
* ``chip`` — chip name (lowercase, without dashes), for example ``esp32c3``.
* ``ver`` — chip revision as three decimal digits (leading zeros), for example ``004``. Constructed from major and minor wafer version fields using the formula ``ver = major * 100 + minor``, where the major version occupies the first digit and the minor version occupies the last two digits.
* ``b64_block0 ... b64_blockN`` — Base64URL-encoded per-block data. Each block is a concatenation of 32-bit words in little-endian byte order. The number of blocks is not explicitly encoded in the format. It is derived from the chip type. The number of blocks can be determined by counting the colon separators (``:``) in the token. Empty blocks are represented as consecutive colons (``::``).
* ``b64_cerr`` — optional Base64URL-encoded coding-error registers snapshot. It may be empty if there are no errors.
* ``b64_crc32`` — Base64URL-encoded CRC32 over whole token ``"<token_name>:<chip>:<ver>:<b64_block0>:...:<b64_blockN>:<b64_cerr>:"``. CRC32 is stored little-endian and encoded as unpadded Base64URL.
A token can be decoded and interpreted correctly only when it is processed using the same target it was created for. ESP-IDF APIs and ``espefuse`` validate and rely on the following fields: chip name, chip revision, and block layout, as well as CRC32 integrity. If any of these do not match the target chip, decoding errors or missing fields may occur.
Base64URL uses the same alphabet as Base64 but replaces ``+`` with ``-`` and ``/`` with ``_``, and omits padding (``=``).
Generating Token On-Device
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use :cpp:func:`esp_efuse_token_dump()` to create a token in a buffer or print it to the log:
.. code-block:: c
char token[1024]; /* size depends on target and eFuses */
esp_efuse_token_type_t token_type = ESP_EFUSE_TOKEN_FROM_READ;
ESP_ERROR_CHECK(esp_efuse_token_dump(token_type, token, sizeof(token)));
ESP_LOGI(TAG, "IDF_MONITOR_EXECUTE_ESPEFUSE_SUMMARY %s", token);
Token type values:
* ``ESP_EFUSE_TOKEN_FROM_READ`` — token of programmed eFuses (starts with ``EFSR``).
* ``ESP_EFUSE_TOKEN_FROM_STAGED`` — token of staged writes (starts with ``EFSW``). It can expose keys in plaintext because it shows values that are not yet burned and not yet read-protected. Requires :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`. Only this type can be burned back.
* ``ESP_EFUSE_TOKEN_FROM_READ_STAGED`` — combined token (starts with ``EFSRW``). It includes the same staged portion and the same plaintext key-exposure risk. Requires :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`.
If ``buf == NULL``, the token is printed to the console (INFO level) without colors, tag, or timestamp.
Burn Token On-Device
^^^^^^^^^^^^^^^^^^^^
Use :cpp:func:`esp_efuse_token_burn()` to apply an ``EFSW`` token on the device by burning the staged eFuse writes encoded in the token. The function validates the token integrity (CRC32) and checks compatibility using the chip name and revision. The token is rejected if the **major** wafer version does not match the target chip. To bypass the version check, use the ignore argument. Example of burning a token:
.. code-block:: c
esp_efuse_batch_write_begin();
esp_efuse_token_burn(token, false); // set true to ignore major version mismatch
esp_efuse_batch_write_commit();
You can skip the major-version check only when you know the token was generated for the same eFuse layout (for example, the same target with only a minor wafer revision difference); in that case the token version may differ only in the last two digits, while the first digit (major version) must normally match.
ESP-IDF Monitor Integration
^^^^^^^^^^^^^^^^^^^^^^^^^^^
When running ``idf.py monitor``, the host can automatically decode eFuse tokens printed by the target and display the result inline if the log line starts with one of the following markers:
* ``IDF_MONITOR_EXECUTE_ESPEFUSE_SUMMARY````espefuse --token {ARGS} summary --active``
* ``IDF_MONITOR_EXECUTE_ESPEFUSE_DUMP````espefuse --token <TOKEN> dump``
``{ARGS}`` must include an eFuse token (``EFSR/EFSW/EFSRW``) and may include ``--extend-efuse-table <csv>`` to load custom eFuse definitions.
Example: The following shows executing the summary command with ``--active`` to display only non-zero eFuse fields, which reduces output size. The ``--extend-efuse-table`` option loads a custom eFuse table definition:
.. code-block:: text
I (441) example: IDF_MONITOR_EXECUTE_ESPEFUSE_SUMMARY EFSR:esp32c3:100:AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA:zIH3-VVgAAAAAAAAAAAAS8kmEVKwQgYB:ZSd8yloMSAJssOWmfZQw8lFbphuTZH574QcV3ggAAAA:AAAAAAAAAAEayAcAAAAAAAAAAAAAAAAAAAAAAAAAAAA:::::::::ydrNkQ --extend-efuse-table main/esp_efuse_custom_table.csv
--- Executing monitor command: espefuse --token EFSR:esp32c3:100:AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA:zIH3-VVgAAAAAAAAAAAAS8kmEVKwQgYB:ZSd8yloMSAJssOWmfZQw8lFbphuTZH574QcV3ggAAAA:AAAAAAAAAAEayAcAAAAAAAAAAAAAAAAAAAAAAAAAAAA:::::::::ydrNkQ --extend-efuse-table main/esp_efuse_custom_table.csv summary --active
espefuse v5.1.0
=== Run "summary" command ===
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = 77 R/W (0b1001101)
K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = 68 R/W (0b1000100)
V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = 144 R/W (0x90)
V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = 130 R/W (0x82)
DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = 21 R/W (0b10101)
THRES_HVT (BLOCK1) BLOCK1 pvt threshold when hvt = 400 R/W (0b0110010000)
TEMP_CALIB (BLOCK2) Temperature calibration data = -10.600000000000001 R/W (0b101101010)
OCODE (BLOCK2) ADC OCode = 101 R/W (0x65)
ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 442 R/W (0b0110111010)
ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = 588 R/W (0b1001001100)
ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = 612 R/W (0b1001100100)
ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = 735 R/W (0b1011011111)
ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = 535 R/W (0b1000010111)
ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = 31 R/W (0b0000011111)
ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = 533 R/W (0b1000010101)
ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = 567 R/W (0b1000110111)
Config fuses:
ERR_RST_ENABLE (BLOCK0) Use BLOCK0 to check error record registers = with check R/W (0b1)
BLOCK_USR_DATA (BLOCK3) User data
= 00 00 00 00 00 00 00 01 1a c8 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Flash fuses:
FLASH_CAP (BLOCK1) Flash capacity = 4M R/W (0b001)
FLASH_TEMP (BLOCK1) Flash temperature = 105C R/W (0b01)
FLASH_VENDOR (BLOCK1) Flash vendor = XMC R/W (0b001)
Identity fuses:
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 3 R/W (0b011)
WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 1 R/W (0b01)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 65 27 7c ca 5a 0c 48 02 6c b0 e5 a6 7d 94 30 f2 R/W
BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = With calibration R/W (0b01)
Mac fuses:
MAC (BLOCK1) MAC address
= 60:55:f9:f7:81:cc (OK) R/W
User fuses:
MODULE_VERSION (BLOCK3) Module version (56-63) = 1 R/W (0x01)
DEVICE_ROLE (BLOCK3) Device role (64-66) = 2 R/W (0b010)
SETTING_1 (BLOCK3) Setting 1 (67-72) = 3 R/W (0b000011)
SETTING_2 (BLOCK3) Setting 2 (73-77) = 4 R/W (0b00100)
CUSTOM_SECURE_VERSION (BLOCK3) Custom secure version (78-93) = 31 R/W (0x001f)
...
Example (dump):
.. code-block:: text
I (441) example: IDF_MONITOR_EXECUTE_ESPEFUSE_DUMP EFSR:esp32c3:100:AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA:zIH3-VVgAAAAAAAAAAAAS8kmEVKwQgYB:ZSd8yloMSAJssOWmfZQw8lFbphuTZH574QcV3ggAAAA:AAAAAAAAAAEayAcAAAAAAAAAAAAAAAAAAAAAAAAAAAA:::::::::ydrNkQ
--- Executing monitor command: espefuse --token EFSR:esp32c3:100:AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA:zIH3-VVgAAAAAAAAAAAAS8kmEVKwQgYB:ZSd8yloMSAJssOWmfZQw8lFbphuTZH574QcV3ggAAAA:AAAAAAAAAAEayAcAAAAAAAAAAAAAAAAAAAAAAAAAAAA:::::::::ydrNkQ dump
espefuse v5.1.0
=== Run "dump" command ===
BLOCK0 ( ) [0 ] dump: 00000000 00000000 00000000 00000000 80000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] dump: f9f781cc 00006055 00000000 4b000000 521126c9 010642b0
BLOCK_SYS_DATA (BLOCK2 ) [2 ] dump: ca7c2765 02480c5a a6e5b06c f230947d 1ba65b51 7b7e6493 de1507e1 00000008
BLOCK_USR_DATA (BLOCK3 ) [3 ] dump: 00000000 01000000 0007c81a 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Application Examples
--------------------
- :example:`system/efuse` demonstrates how to use the eFuse API on {IDF_TARGET_NAME}, showing read and write operations with fields from the common and custom eFuse tables, and explaining the use of virtual eFuses for debugging purposes.
API Reference
-------------
.. include-build-file:: inc/esp_efuse_chip.inc
.. include-build-file:: inc/esp_efuse.inc
+88
View File
@@ -0,0 +1,88 @@
Error Code and Helper Functions
================================
:link_to_translation:`zh_CN:[中文]`
This section lists definitions of common ESP-IDF error codes and several helper functions related to error handling.
For general information about error codes in ESP-IDF, see :doc:`Error Handling <../../api-guides/error-handling>`.
For the full list of error codes defined in ESP-IDF, see :doc:`Error Codes Reference <../error-codes>`.
.. _registering-error-codes:
Registering Error Codes
------------------------
ESP-IDF uses a composable error code registration system that automatically collects error code definitions from all components at build time. This allows :cpp:func:`esp_err_to_name` and :cpp:func:`esp_err_to_name_r` to look up error codes defined across the entire project without requiring manual maintenance of a central registry.
How It Works
^^^^^^^^^^^^
Error codes are registered at link time using a linker section called ``.esp_err_msg_tbl``. When you define error codes in your component's header files, you need to register those headers with the build system, which will:
1. Extract the error code definitions during the build
2. Generate C code that places them into the ``.esp_err_msg_tbl`` section
3. Link them into your application automatically
The linker collects all error code entries from all components into a single array that :cpp:func:`esp_err_to_name` searches at runtime.
Registering Your Component's Error Codes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To register error codes from your component, add the following line to your component's ``CMakeLists.txt``:
.. code-block:: cmake
idf_define_esp_err_codes(HEADERS include/my_component.h)
Replace ``include/my_component.h`` with the path to your header file(s) that contain error code definitions. You can specify multiple headers:
.. code-block:: cmake
idf_define_esp_err_codes(HEADERS
include/my_api.h
include/my_driver.h
)
The build system will automatically process these headers and register any ``#define`` directives that match the error code pattern (typically starting with ``ESP_ERR_`` or similar).
Example
^^^^^^^
In your component's header file ``include/my_component.h``:
.. code-block:: c
#pragma once
#include "esp_err.h"
#define ESP_ERR_MY_COMPONENT_BASE 0x7000
#define ESP_ERR_MY_COMPONENT_INIT (ESP_ERR_MY_COMPONENT_BASE + 1) /*!< Component initialization failed */
#define ESP_ERR_MY_COMPONENT_BUSY (ESP_ERR_MY_COMPONENT_BASE + 2) /*!< Component is busy */
In your component's ``CMakeLists.txt``:
.. code-block:: cmake
idf_component_register(SRCS "my_component.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES esp_common)
# Register error codes
idf_define_esp_err_codes(HEADERS include/my_component.h)
After building your project, calls to ``esp_err_to_name(ESP_ERR_MY_COMPONENT_INIT)`` will return the string ``"ESP_ERR_MY_COMPONENT_INIT"``.
.. note::
Most ESP-IDF components already have their error codes registered. You only need to add ``idf_define_esp_err_codes()`` for your own custom components or when adding new error codes to existing components.
.. _esp-check-api-ref:
API Reference
-------------
.. include-build-file:: inc/esp_check.inc
.. include-build-file:: inc/esp_err.inc
+232
View File
@@ -0,0 +1,232 @@
Event Loop Library
==================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
The event loop library allows components to declare events so that other components can register handlers -- codes that executes when those events occur. This allows loosely-coupled components to attach desired behavior to state changes of other components without application involvement. This also simplifies event processing by serializing and deferring code execution to another context.
.. only:: SOC_WIFI_SUPPORTED
One common case is, if a high-level library is using the Wi-Fi library: it may subscribe to :ref:`ESP32 Wi-Fi Programming Model <wifi-programming-model>` directly and act on those events.
.. only:: SOC_BT_SUPPORTED
.. note::
Various modules of the Bluetooth stack deliver events to applications via dedicated callback functions instead of via the Event Loop Library.
Using ``esp_event`` APIs
------------------------
There are two objects of concern for users of this library: events and event loops.
An event indicates an important occurrence, such as a successful Wi-Fi connection to an access point. A two-part identifier should be used when referencing events, see :ref:`declaring and defining events <esp-event-declaring-defining-events>` for details. The event loop is the bridge between events and event handlers. The event source publishes events to the event loop using the APIs provided by the event loop library, and event handlers registered to the event loop respond to specific types of events.
Using this library roughly entails the following flow:
1. The user defines a function that should run when an event is posted to a loop. This function is referred to as the event handler, and should have the same signature as :cpp:type:`esp_event_handler_t`.
2. An event loop is created using :cpp:func:`esp_event_loop_create`, which outputs a handle to the loop of type :cpp:type:`esp_event_loop_handle_t`. Event loops created using this API are referred to as user event loops. There is, however, a special type of event loop called the default event loop which is discussed in :ref:`default event loop <esp-event-default-loops>`.
3. Components register event handlers to the loop using :cpp:func:`esp_event_handler_register_with`. Handlers can be registered with multiple loops, see :ref:`notes on handler registration <esp-event-handler-registration>`.
4. Event sources post an event to the loop using :cpp:func:`esp_event_post_to`.
5. Components wanting to remove their handlers from being called can do so by unregistering from the loop using :cpp:func:`esp_event_handler_unregister_with`.
6. Event loops that are no longer needed can be deleted using :cpp:func:`esp_event_loop_delete`.
In code, the flow above may look like as follows:
.. code-block:: c
// 1. Define the event handler
void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
// Event handler logic
}
void app_main()
{
// 2. A configuration structure of type esp_event_loop_args_t is needed to specify the properties of the loop to be created. A handle of type esp_event_loop_handle_t is obtained, which is needed by the other APIs to reference the loop to perform their operations.
esp_event_loop_args_t loop_args = {
.queue_size = ...,
.task_name = ...
.task_priority = ...,
.task_stack_size = ...,
.task_core_id = ...
};
esp_event_loop_handle_t loop_handle;
esp_event_loop_create(&loop_args, &loop_handle);
// 3. Register event handler defined in (1). MY_EVENT_BASE and MY_EVENT_ID specify a hypothetical event that handler run_on_event should execute when it gets posted to the loop.
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event, ...);
...
// 4. Post events to the loop. This queues the event on the event loop. At some point, the event loop executes the event handler registered to the posted event, in this case, run_on_event. To simplify the process, this example calls esp_event_post_to from app_main, but posting can be done from any other task (which is the more interesting use case).
esp_event_post_to(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, ...);
...
// 5. Unregistering an unneeded handler
esp_event_handler_unregister_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event);
...
// 6. Deleting an unneeded event loop
esp_event_loop_delete(loop_handle);
}
.. _esp-event-declaring-defining-events:
Declaring and Defining Events
-----------------------------
As mentioned previously, events consist of two-part identifiers: the event base and the event ID. The event base identifies an independent group of events; the event ID identifies the event within that group. Think of the event base and event ID as a person's last name and first name, respectively. A last name identifies a family, and the first name identifies a person within that family.
The event loop library provides macros to declare and define the event base easily.
Event base declaration:
.. code-block:: c
ESP_EVENT_DECLARE_BASE(EVENT_BASE);
Event base definition:
.. code-block:: c
ESP_EVENT_DEFINE_BASE(EVENT_BASE);
.. note::
In ESP-IDF, the base identifiers for system events are uppercase and are postfixed with ``_EVENT``. For example, the base for Wi-Fi events is declared and defined as ``WIFI_EVENT``, the Ethernet event base ``ETHERNET_EVENT``, and so on. The purpose is to have event bases look like constants (although they are global variables considering the definitions of macros ``ESP_EVENT_DECLARE_BASE`` and ``ESP_EVENT_DEFINE_BASE``).
For event IDs, declaring them as enumerations is recommended. Once again, for visibility, these are typically placed in public header files.
Event ID:
.. code-block:: c
enum {
EVENT_ID_1,
EVENT_ID_2,
EVENT_ID_3,
...
}
.. _esp-event-default-loops:
Default Event Loop
------------------
The default event loop is a special type of loop used for system events (Wi-Fi events, for example). The handle for this loop is hidden from the user, and the creation, deletion, handler registration/deregistration, and posting of events are done through a variant of the APIs for user event loops. The table below enumerates those variants, and the user event loops equivalent.
.. list-table::
:header-rows: 1
:widths: 60 60
:align: center
* - User Event Loops
- Default Event Loops
* - :cpp:func:`esp_event_loop_create`
- :cpp:func:`esp_event_loop_create_default`
* - :cpp:func:`esp_event_loop_delete`
- :cpp:func:`esp_event_loop_delete_default`
* - :cpp:func:`esp_event_handler_register_with`
- :cpp:func:`esp_event_handler_register`
* - :cpp:func:`esp_event_handler_unregister_with`
- :cpp:func:`esp_event_handler_unregister`
* - :cpp:func:`esp_event_post_to`
- :cpp:func:`esp_event_post`
If you compare the signatures for both, they are mostly similar except for the lack of loop handle specification for the default event loop APIs.
Other than the API difference and the special designation to which system events are posted, there is no difference in how default event loops and user event loops behave. It is even possible for users to post their own events to the default event loop, should the user opt to not create their own loops to save memory.
.. _esp-event-handler-registration:
Notes on Handler Registration
-----------------------------
It is possible to register a single handler to multiple events individually by using multiple calls to :cpp:func:`esp_event_handler_register_with`. For those multiple calls, the specific event base and event ID can be specified with which the handler should execute.
However, in some cases, it is desirable for a handler to execute on the following situations:
(1) all events that get posted to a loop
(2) all events of a particular base identifier
This is possible using the special event base identifier ``ESP_EVENT_ANY_BASE`` and special event ID ``ESP_EVENT_ANY_ID``. These special identifiers may be passed as the event base and event ID arguments for :cpp:func:`esp_event_handler_register_with`.
Therefore, the valid arguments to :cpp:func:`esp_event_handler_register_with` are:
1. <event base>, <event ID> - handler executes when the event with base <event base> and event ID <event ID> gets posted to the loop
2. <event base>, ESP_EVENT_ANY_ID - handler executes when any event with base <event base> gets posted to the loop
3. ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID - handler executes when any event gets posted to the loop
As an example, suppose the following handler registrations were performed:
.. code-block:: c
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event_1, ...);
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, ESP_EVENT_ANY_ID, run_on_event_2, ...);
esp_event_handler_register_with(loop_handle, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, run_on_event_3, ...);
If the hypothetical event ``MY_EVENT_BASE``, ``MY_EVENT_ID`` is posted, all three handlers ``run_on_event_1``, ``run_on_event_2``, and ``run_on_event_3`` would execute.
If the hypothetical event ``MY_EVENT_BASE``, ``MY_OTHER_EVENT_ID`` is posted, only ``run_on_event_2`` and ``run_on_event_3`` would execute.
If the hypothetical event ``MY_OTHER_EVENT_BASE``, ``MY_OTHER_EVENT_ID`` is posted, only ``run_on_event_3`` would execute.
Handler Un-Registering Itself
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In general, an event handler run by an event loop is **not allowed to do any registering/unregistering activity on that event loop**. There is one exception, though: un-registering itself is allowed for the handler. E.g., it is possible to do the following:
.. code-block:: c
void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
esp_event_loop_handle_t *loop_handle = (esp_event_loop_handle_t*) handler_arg;
esp_event_handler_unregister_with(*loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event);
}
void app_main(void)
{
esp_event_loop_handle_t loop_handle;
esp_event_loop_create(&loop_args, &loop_handle);
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event, &loop_handle);
// ... post-event MY_EVENT_BASE, MY_EVENT_ID and run loop at some point
}
Handler Registration and Handler Dispatch Order
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The general rule is that, for handlers that match a certain posted event during dispatch, those which are registered first also get executed first. The user can then control which handlers get executed first by registering them before other handlers, provided that all registrations are performed using a single task. If the user plans to take advantage of this behavior, caution must be exercised if there are multiple tasks registering handlers. While the 'first registered, first executed' behavior still holds true, the task which gets executed first also gets its handlers registered first. Handlers registered one after the other by a single task are still dispatched in the order relative to each other, but if that task gets pre-empted in between registration by another task that also registers handlers; then during dispatch those handlers also get executed in between.
Event Loop Profiling
--------------------
A configuration option :ref:`CONFIG_ESP_EVENT_LOOP_PROFILING` can be enabled in order to activate statistics collection for all event loops created. The function :cpp:func:`esp_event_dump` can be used to output the collected statistics to a file stream. More details on the information included in the dump can be found in the :cpp:func:`esp_event_dump` API Reference.
Application Examples
--------------------
- :example:`system/esp_event/default_event_loop` demonstrates how to use the default event loop system of {IDF_TARGET_NAME} to post and handle events, including declaring and defining events, creating the default event loop, posting events to the loop, and registering/unregistering event handlers.
- :example:`system/esp_event/user_event_loops` demonstrates how to create and use user event loops on {IDF_TARGET_NAME}, including creating and running event loops, registering and unregistering handlers, and posting events, with the ability to handle different use cases beyond the default event loop.
API Reference
-------------
.. include-build-file:: inc/esp_event.inc
.. include-build-file:: inc/esp_event_base.inc
Related Documents
-----------------
.. toctree::
:maxdepth: 1
@@ -0,0 +1,74 @@
Call Function with External Stack
=================================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
A given function can be executed with a user-allocated stack space which is independent of current task's stack. This mechanism helps reduce stack usage for tasks that call common functions with heavy stack demands such as ``printf``. The given function can be executed on the shared stack space by calling :cpp:func:`esp_execute_shared_stack_function` and passing it as a parameter.
.. warning::
:cpp:func:`esp_execute_shared_stack_function` does only minimal preparation of the provided shared stack memory. The function passed to it for execution on the shared stack space or any of that function's callees should not do any of the following:
.. list::
- Use thread-local storage
:esp32p4: - Use the floating-point unit
:esp32p4: - Use the AI co-processor
- Call vTaskDelete(NULL) to delete the currently running task
Furthermore, backtraces will be wrong when called from the function running on the shared stack or any of its callees. The limitations are quite severe, so that we might deprecate :cpp:func:`esp_execute_shared_stack_function` in the future. If you have any use case which can only be implemented using :cpp:func:`esp_execute_shared_stack_function`, please open a `GitHub Issue <https://github.com/espressif/esp-idf/issues>`_.
Usage
-----
:cpp:func:`esp_execute_shared_stack_function` takes four arguments:
- a mutex object allocated by the caller, which is used to protect the shared stack space
- a pointer to the stack used for that function
- the size of stack in bytes
- a pointer to the shared stack function
The user-defined function is executed immediately as a callback, using a userallocated stack instead of the current tasks stack.
The usage may look like the code below:
.. code-block:: c
void external_stack_function(void)
{
printf("Executing this printf from external stack! \n");
}
//Let us suppose we want to call printf using a separated stack space
//allowing the app to reduce its stack size.
void app_main()
{
//Allocate a stack buffer, from heap or as a static form:
StackType_t *shared_stack = malloc(8192 * sizeof(StackType_t));
assert(shared_stack != NULL);
//Allocate a mutex to protect its usage:
SemaphoreHandle_t printf_lock = xSemaphoreCreateMutex();
assert(printf_lock != NULL);
//Call the desired function using the macro helper:
esp_execute_shared_stack_function(printf_lock,
shared_stack,
8192,
external_stack_function);
vSemaphoreDelete(printf_lock);
free(shared_stack);
}
.. _esp-call-with-stack-basic_usage:
API Reference
-------------
.. include-build-file:: inc/esp_expression_with_stack.inc
@@ -0,0 +1,180 @@
ESP HTTPS OTA
=============
:link_to_translation:`zh_CN:[中文]`
Overview
--------
``esp_https_ota`` provides simplified APIs to perform firmware upgrades over HTTPS. It is an abstraction layer over the existing OTA APIs.
.. code-block:: c
esp_err_t do_firmware_upgrade()
{
esp_http_client_config_t config = {
.url = CONFIG_FIRMWARE_UPGRADE_URL,
.cert_pem = (char *)server_cert_pem_start,
};
esp_https_ota_config_t ota_config = {
.http_config = &config,
};
esp_err_t ret = esp_https_ota(&ota_config);
if (ret == ESP_OK) {
esp_restart();
} else {
return ESP_FAIL;
}
return ESP_OK;
}
Server Verification
-------------------
Please refer to :ref:`ESP-TLS: TLS Server Verification <esp_tls_server_verification>` for more information on server verification. The root certificate in PEM format needs to be provided to the :cpp:member:`esp_http_client_config_t::cert_pem` member.
.. note::
The server-endpoint **root** certificate should be used for verification instead of any intermediate ones from the certificate chain. The reason is that the root certificate has the maximum validity and usually remains the same for a long period of time. Users can also use the :cpp:member:`esp_http_client_config_t::crt_bundle_attach` member for verification by the ``ESP x509 Certificate Bundle`` feature, which covers most of the trusted root certificates.
Partial Image Download over HTTPS
---------------------------------
To use the partial image download feature, you need to:
* **Enable the component-level configuration**: Enable :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config````ESP HTTPS OTA````Enable partial HTTP download for OTA``)
* **Enable the feature in your application**: Set the ``partial_http_download`` field in :cpp:struct:`esp_https_ota_config_t` configuration structure
When this configuration is enabled, firmware image will be downloaded in multiple HTTP requests of specified sizes. Maximum content length of each request can be specified by setting ``max_http_request_size`` to the required value.
This option is useful while fetching image from a service like AWS S3, where mbedTLS Rx buffer size (:ref:`CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN`) can be set to a lower value which is not possible without enabling this configuration.
Default value of mbedTLS Rx buffer size is set to 16 KB. By using ``partial_http_download`` with ``max_http_request_size`` of 4 KB, size of mbedTLS Rx buffer can be reduced to 4 KB. With this configuration, memory saving of around 12 KB is expected.
.. note::
If the server uses chunked transfer encoding, partial downloads are not feasible because the total content length is not known in advance.
OTA Resumption
--------------
To use the OTA resumption feature, enable the ``ota_resumption`` configuration in the :cpp:struct:`esp_https_ota_config_t`. When OTA resumption is enabled, an OTA image download which has failed previously can be resumed from its intermediate state instead of restarting the whole OTA process from the beginning. This is implemented using the HTTP partial range request feature.
To specify the point from where the image download should resume, you need to set the ``ota_image_bytes_written`` field in :cpp:struct:`esp_https_ota_config_t`. This value indicates the number of bytes already written to the OTA partition in the previous OTA attempt.
For reference, you can check the :example:`system/ota/advanced_https_ota`, which demonstrates OTA resumption. In this example, the intermediate OTA state is saved in NVS, allowing the OTA process to resume seamlessly from the last saved state and continue the download.
Signature Verification
----------------------
For additional security, signature of OTA firmware images can be verified. For more information, please refer to :ref:`secure-ota-updates`.
.. _ota_updates_pre-encrypted-firmware:
OTA Upgrades with Pre-Encrypted Firmware
----------------------------------------
Pre-encrypted firmware is a completely independent scheme from :doc:`../../security/flash-encryption`. Primary reasons for this are as follows:
* Flash encryption scheme recommends using per-device unique encryption key that is internally generated. This makes pre-encryption of the firmware on OTA update server infeasible.
* Flash encryption scheme depends on the flash offset and generates different ciphertext for different flash offset. And hence it becomes difficult to manage different OTA update images based on the partition slots like ``ota_0``, ``ota_1`` etc.
* Even for devices where flash encryption is not enabled, it could be requirement that firmware image over OTA is still encrypted in nature.
Pre-encrypted firmware distribution ensures that the firmware image stays encrypted **in transit** from the server to the device (irrespective of the underlying transport security). First the pre-encrypted software layer will decrypt the firmware (received over network) on device and then re-encrypt the contents using platform flash encryption (if enabled) before writing to flash.
Design
^^^^^^
Pre-encrypted firmware is a **transport security scheme** that ensures firmware images remain encrypted **in transit** from the OTA server to the device (irrespective of the underlying transport security). This approach differs from :doc:`../../security/flash-encryption` in several key ways:
* **Key Management**: Uses externally managed encryption keys rather than per-device unique keys generated internally
* **Flash Offset Independence**: Generates consistent ciphertext regardless of flash partition location (``ota_0``, ``ota_1``, etc.)
* **Transport Protection**: Provides encryption protection during firmware distribution, not device-level storage security
**Important Security Note**: Pre-encrypted firmware does not provide device-level security on its own. Once received, the firmware is decrypted on the device and stored according to the device's flash encryption configuration. For device-level security, flash encryption must be separately enabled.
This process is managed by the `esp_encrypted_img <https://github.com/espressif/idf-extra-components/tree/master/esp_encrypted_img>`_ component, which integrates with the OTA update framework via the decryption callback (:cpp:member:`esp_https_ota_config_t::decrypt_cb`).
For detailed information on the image format, key generation, and implementation details, refer to the `esp_encrypted_img component documentation <https://github.com/espressif/idf-extra-components/tree/master/esp_encrypted_img>`_.
OTA System Events
-----------------
ESP HTTPS OTA has various events for which a handler can be triggered by the :doc:`../system/esp_event` when the particular event occurs. The handler has to be registered using :cpp:func:`esp_event_handler_register`. This helps the event handling for ESP HTTPS OTA.
:cpp:enum:`esp_https_ota_event_t` has all possible events that can occur when performing OTA upgrade using ESP HTTPS OTA.
Event Handler Example
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
/* Event handler for catching system events */
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == ESP_HTTPS_OTA_EVENT) {
switch (event_id) {
case ESP_HTTPS_OTA_START:
ESP_LOGI(TAG, "OTA started");
break;
case ESP_HTTPS_OTA_CONNECTED:
ESP_LOGI(TAG, "Connected to server");
break;
case ESP_HTTPS_OTA_GET_IMG_DESC:
ESP_LOGI(TAG, "Reading Image Description");
break;
case ESP_HTTPS_OTA_VERIFY_CHIP_ID:
ESP_LOGI(TAG, "Verifying chip id of new image: %d", *(esp_chip_id_t *)event_data);
break;
case ESP_HTTPS_OTA_VERIFY_CHIP_REVISION:
ESP_LOGI(TAG, "Verifying chip revision of new image: %d", *(uint16_t *)event_data);
break;
case ESP_HTTPS_OTA_DECRYPT_CB:
ESP_LOGI(TAG, "Callback to decrypt function");
break;
case ESP_HTTPS_OTA_WRITE_FLASH:
ESP_LOGD(TAG, "Writing to flash: %d written", *(int *)event_data);
break;
case ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION:
ESP_LOGI(TAG, "Boot partition updated. Next Partition: %d", *(esp_partition_subtype_t *)event_data);
break;
case ESP_HTTPS_OTA_FINISH:
ESP_LOGI(TAG, "OTA finish");
break;
case ESP_HTTPS_OTA_ABORT:
ESP_LOGI(TAG, "OTA abort");
break;
}
}
}
Expected data type for different ESP HTTPS OTA events in the system event loop:
- ESP_HTTPS_OTA_START : ``NULL``
- ESP_HTTPS_OTA_CONNECTED : ``NULL``
- ESP_HTTPS_OTA_GET_IMG_DESC : ``NULL``
- ESP_HTTPS_OTA_VERIFY_CHIP_ID : ``esp_chip_id_t``
- ESP_HTTPS_OTA_VERIFY_CHIP_REVISION : ``uint16_t``
- ESP_HTTPS_OTA_DECRYPT_CB : ``NULL``
- ESP_HTTPS_OTA_WRITE_FLASH : ``int``
- ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION : ``esp_partition_subtype_t``
- ESP_HTTPS_OTA_FINISH : ``NULL``
- ESP_HTTPS_OTA_ABORT : ``NULL``
Application Examples
--------------------
- :example:`system/ota/advanced_https_ota` demonstrates how to use the Advanced HTTPS OTA update functionality on {IDF_TARGET_NAME} using the `esp_https_ota` component's APIs. For the applicable SoCs, please refer to :example_file:`system/ota/advanced_https_ota/README.md`.
- :example:`system/ota/partitions_ota` demonstrates how to perform OTA updates for various partitions (app, bootloader, partition table, storage) using the `esp_https_ota` component's APIs.
- :example:`system/ota/simple_ota_example` demonstrates how to use the `esp_https_ota` component's APIs to support firmware upgrades through specific networking interfaces such as Ethernet or Wi-Fi Station on {IDF_TARGET_NAME}. For the applicable SoCs, please refer to :example_file:`system/ota/simple_ota_example/README.md`.
API Reference
-------------
.. include-build-file:: inc/esp_https_ota.inc
+330
View File
@@ -0,0 +1,330 @@
ESP Timer (High Resolution Timer)
=================================
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_HR_TIMER:default = "SYSTIMER", esp32 = "LAC timer"}
{IDF_TARGET_HR_TIMER_Resolution:default = "52", esp32 = "64", esp32s2 = "64"}
.. only:: html
This document covers the ESP-IDF feature called ESP Timer. The contents are as follows:
.. contents::
:local:
:depth: 2
Overview
--------
The ESP Timer feature allows for creating software timers and invoking their callback functions (dispatching callbacks) on timeout. ESP Timer is useful when user software needs to perform delayed or periodic actions, such as delayed device start/stop or periodic sampling of sensor data.
ESP Timer hides the complexity associated with managing multiple timers, dispatching callbacks, accounting for clock frequency changes (if dynamic frequency scaling is enabled), and maintaining correct time after light sleep.
For application scenarios that require better real-time performance (such as generating waveforms) or configurable timer resolution, it is recommended that :doc:`GPTimer </api-reference/peripherals/gptimer>` be used instead. Also, GPTimer has features not available in ESP Timer, such as event capture.
Finally, FreeRTOS has its own software timers. As explained in :ref:`FreeRTOS Timers`, they have much lower resolution compared to ESP Timer, but FreeRTOS timers are portable (non-dependent on ESP-IDF) which might be an advantage in some cases.
Features and Concepts
---------------------
The ESP Timer API provides:
- One-shot and periodic timers
- Relative and absolute timing
- Multiple callback dispatch methods
- Handling overdue callbacks
- Bit range: {IDF_TARGET_HR_TIMER_Resolution} bits
- Time resolution: one microsecond
One-Shot and Periodic Timers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A one-shot timer invokes its callback function only once upon expiration and then stops operation. One-shot timers are useful for single delayed or timed actions, such as turning off a device or reading a sensor after a specified time interval or at a specified time point.
A periodic timer invokes its callback function upon expiration and restarts itself automatically, resulting in the callback function being invoked at a defined interval until the periodic timer is manually stopped. Periodic timers are useful for repeated actions, such as sampling sensor data, updating display information, or generating a waveform.
.. _Callback Methods:
Callback Dispatch Methods
^^^^^^^^^^^^^^^^^^^^^^^^^
Timer callbacks can be dispatched using the following methods:
- Task Dispatch method (default):
- Dispatches timer callbacks from a single high-priority ESP Timer task (esp_timer task (notified by ISR) > callback).
- Suitable for handling timer callbacks that are not time-critical.
- Interrupt Dispatch method (:cpp:enumerator:`ESP_TIMER_ISR <esp_timer_dispatch_t::ESP_TIMER_ISR>`):
- Dispatches timer callbacks directly from an interrupt handler (ISR > callback).
- Suitable for simple, low-latency timer callbacks which take a few microseconds to run.
- Ensures shorter delay between the event and the callback execution.
- Not affected by other active tasks.
Task Dispatch Specifics
~~~~~~~~~~~~~~~~~~~~~~~
The execution of callbacks in the ESP Timer task is serialized. Thus, when multiple timeouts occur simultaneously, the execution time of one callback will delay the execution of subsequent callbacks. For this reason, it is recommended to keep the callbacks short. If the callback needs to perform more work, the work should be deferred to a lower-priority task using FreeRTOS primitives, such as queues and semaphores.
If other FreeRTOS tasks with higher priority are running, such as an SPI flash operation, callback dispatching will be delayed until the ESP Timer task has a chance to run.
To maintain predictable and timely execution of tasks, callbacks should never attempt block (waiting for resources) or yield (give up control) operations, because such operations disrupt the serialized execution of callbacks.
Interrupt Dispatch Specifics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Timers using the Interrupt Dispatch method have their callbacks executed from an interrupt handler. As interrupts can preempt all tasks, the Interrupt Dispatch method offers lower latency. Interrupt dispatched timer callbacks should never attempt to block and should not attempt to trigger a context switch via ``portYIELD_FROM_ISR()``. Instead, the function :cpp:func:`esp_timer_isr_dispatch_need_yield` should be used. The context switch will happen after all timers using the ISR dispatch method are processed.
While using interrupt dispatched timers, the standard logging or debugging methods, such as ``printf`` should be avoided. To debug an application or display certain information in the console, the ESP-IDF logging macros should be used, such as :c:macro:`ESP_DRAM_LOGI`, :c:macro:`ESP_EARLY_LOGI`, etc. These macros are specifically designed to work in various contexts, including interrupt service routines.
Obtaining Current Time
^^^^^^^^^^^^^^^^^^^^^^
The time passed since the initialization of ESP Timer can be obtained using the convenience function :cpp:func:`esp_timer_get_time`. The initialization happens shortly before the ``app_main`` function is called. This function is fast and has no locking mechanisms that could potentially introduce delays or conflicts. As a result, it can be useful for fine-grained timing, with the accuracy of 1 μs, in tasks as well as in ISR routines.
Unlike the ``gettimeofday()`` function, :cpp:func:`esp_timer_get_time` has the following specifics:
- Upon wakeup from deep sleep, the initialization timer restarts from zero.
- The returned value has no timezone settings or daylight saving time adjustments.
System Integration
------------------
This section mainly covers some aspects of how to optimize the operation of ESP Timer and integrate it with other ESP-IDF features.
Timeout Value Limits
^^^^^^^^^^^^^^^^^^^^
As callback dispatching can never be instantaneous, the one-shot and periodic timers created with ESP Timer also have timeout value limits. These limits cannot be estimated precisely, because they depend on multiple factors.
For reference, the ESP32 running at 240 MHz and using the Task Dispatch method has the approximate minimum timeout values as follows:
* One-shot timers: ~20 μs
* If :cpp:func:`esp_timer_start_once` is called, this is the earliest time after which the system will be able to dispatch a callback.
* Periodic timers: ~50 μs
* Periodic software timers with a smaller timeout value would simply consume most of the CPU time, which is impractical.
The lower the CPU frequency, the higher the minimum timeout values will be. The general guideline is if the required timeout values are in the order of tens of microseconds, the user application needs to undergo thorough testing to ensure stable operation.
If the minimum timeout values slightly exceed the requirements, the Interrupt Dispatch method might offer an improvement.
.. only:: not SOC_PARLIO_SUPPORTED and SOC_RMT_SUPPORTED
For even smaller timeout values, for example, to generate or receive waveforms or do bit banging, the resolution of ESP Timer may be insufficient. In this case, it is recommended to use dedicated peripherals, such as :doc:`GPTimer </api-reference/peripherals/gptimer>` or :doc:`RMT </api-reference/peripherals/rmt>`, and their DMA features if available.
.. only:: SOC_PARLIO_SUPPORTED
For even smaller timeout values, for example, to generate or receive waveforms or do bit banging, the resolution of ESP Timer may be insufficient. In this case, it is recommended to use dedicated peripherals, such as :doc:`Parallel IO </api-reference/peripherals/parlio/index>`, and their DMA features if available.
Sleep Mode Considerations
^^^^^^^^^^^^^^^^^^^^^^^^^
If a timer is started, and there are no other tasks being executed during the wait time, the chip can be put into sleep to optimize power consumption.
Sleep can be induced in the following ways:
* **Automatic sleep** provided by :doc:`Power Management APIs <power_management>`: If no tasks are being executed, the chip can automatically enter light sleep and automatically wake up at the appropriate time for ESP Timer to dispatch a pending callback.
* **Manual sleep** provided by :doc:`Sleep Mode APIs <sleep_modes>`: The chip can be put into sleep regardless of whether other tasks are being executed.
For manually induced sleep, the following sleep modes exist:
* Deep-sleep mode: ESP Timer is deactivated
The user application restarts from scratch upon wakeup from deep sleep. This makes deep sleep unsuitable for continuous ESP Timer operation. However, deep sleep can be used if the running timers are not expected to persist across wakeups.
* Light-sleep mode: ESP Timer is suspended
While in light sleep, ESP Timer counter and callbacks are suspended. Timekeeping is done by the RTC timer. Once the chip is woken up, the counter of ESP Timer is automatically advanced by the amount of time spent in sleep, then timekeeping and callback execution is resumed.
At this point, ESP Timer will attempt to dispatch all unhandled callbacks if there are any. It can potentially lead to the overflow of ESP Timer callback execution queue. This behavior may be undesirable for certain applications, and the ways to avoid it are covered in :ref:`Handling Callbacks in Light Sleep`.
.. _FreeRTOS Timers:
FreeRTOS Timers
^^^^^^^^^^^^^^^
Although FreeRTOS provides `software timers <https://www.freertos.org/RTOS-software-timer.html>`_, they have limitations:
- FreeRTOS timer resolution is bound by the `tick frequency <https://www.freertos.org/a00110.html#configTICK_RATE_HZ>`_, which is typically in the range of 100 to 1000 Hz.
- Timer callbacks are dispatched from a low-priority timer task that can be preempted by other tasks, leading to decreased timer precision and accuracy.
However, FreeRTOS timers are portable (non-dependent on ESP-IDF) and are written to be deterministic as they do not dispatch callbacks from ISRs.
.. only:: SOC_ETM_SUPPORTED and SOC_SYSTIMER_SUPPORT_ETM
ETM Events
^^^^^^^^^^
ESP Timer has connection to the :doc:`Event Task Matrix </api-reference/peripherals/etm>` (ETM) module. This module allows notifying a number of peripherals about events without involving CPU interrupts. Direct notifications reduce latency and decrease CPU workload. The function :cpp:func:`esp_timer_new_etm_alarm_event` can be called to get the corresponding ETM event handle.
Usage
-----
While setting up your ESP-IDF project, make sure to:
- Add required component dependencies to your ``CMakeLists.txt``.
- Include required header files in your ``.c`` files.
- (Optional) Set Kconfig options. For this, see :ref:`Kconfig Options <component-config-esp-timer-high-resolution-timer->` > *ESP Timer (High Resolution Timer)*
.. _General Procedure:
General Procedure
^^^^^^^^^^^^^^^^^
The general procedure to create, start, stop, and delete a timer is as follows:
1. Create a timer
- Define a timer handle using the type :cpp:type:`esp_timer_handle_t`.
- Set the timer configuration parameters by defining the structure :cpp:struct:`esp_timer_create_args_t` which also includes the callback function.
.. note::
It is recommended to keep callbacks as short as possible to avoid delaying other callbacks.
- To create a timer, call the function :cpp:func:`esp_timer_create`.
2. Start the timer in one-shot mode or periodic mode depending on your requirements
- To start the timer in one-shot mode, call :cpp:func:`esp_timer_start_once` to invoke the callback after a specified timeout duration, or :cpp:func:`esp_timer_start_once_at` to invoke it at a specific absolute time.
- To start the timer in periodic mode, call :cpp:func:`esp_timer_start_periodic` to invoke the callback repeatedly at regular intervals, or :cpp:func:`esp_timer_start_periodic_at` to start the first invocation at a specific absolute time and then repeat at regular intervals; the timer will continue running until you explicitly stop it using :cpp:func:`esp_timer_stop`.
.. note::
When executing a start function, ensure that the timer is not running. If a timer is running, either call :cpp:func:`esp_timer_restart` / :cpp:func:`esp_timer_restart_at` or stop it first using :cpp:func:`esp_timer_stop` and then call one of the start functions.
3. Stop the timer
- To stop the running timer, call the function :cpp:func:`esp_timer_stop`. But it does not guarantee that after this call, the callback will not be running one or more times. To check if the callback is not running after stopping the timer, you can use :cpp:func:`esp_timer_is_active`. Another approach is to use a blocking stop API.
- To block the timer stop operation until any in-flight callback completes, use :cpp:func:`esp_timer_stop_blocking`.
4. Delete the timer
- When the timer is no longer needed, delete it to free up memory using the function :cpp:func:`esp_timer_delete`.
.. _Using ESP_TIMER_ISR Callback Method:
Using the Interrupt Dispatch Method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Out of the available :ref:`callback dispatch methods <Callback Methods>`, if you choose the Interrupt Dispatch method, follow these steps:
1. Set Kconfig options
- Enable :ref:`CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD`.
2. Create a timer
- Set the timer configuration parameters by defining the structure :cpp:struct:`esp_timer_create_args_t`:
.. code-block:: c
const esp_timer_create_args_t timer = {
... ,
.dispatch_method = ESP_TIMER_ISR,
...
};
- To create a timer, call the function :cpp:func:`esp_timer_create`.
For further steps, refer to :ref:`General Procedure`.
.. _Handling Callbacks in Light Sleep:
Handling Callbacks in Light-sleep Mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Light sleep allows you to save power while maintaining the ability to quickly wake up for specific actions. To use ESP Timer in conjunction with Light-sleep mode, see :doc:`Sleep Mode APIs <sleep_modes>`.
During light sleep, to keep unhandled callbacks under control and avoid potential overflow of ESP Timer callback execution queue on wakeup, do one of the following:
- Prevent the invocation of callbacks in the first place: stop the timer before entering light sleep by using :cpp:func:`esp_timer_stop`.
- If calling the stop function is not desirable for any reason, use the option :cpp:member:`esp_timer_create_args_t::skip_unhandled_events`. In this case, if a periodic timer expires one or more times during light sleep, then only one callback is executed on wakeup.
Debugging Timers
^^^^^^^^^^^^^^^^
The function :cpp:func:`esp_timer_dump` allows dumping information about either all or only running timers: the parameters for timers, the number of times the timers were started, triggered, skipped, and time taken by timer callbacks to execute. This information can be helpful in debugging.
To debug timers, use the following procedure:
1. Set Kconfig options for more detailed output:
- Enable :ref:`CONFIG_ESP_TIMER_PROFILING`.
.. note::
Enabling this option increases code size and heap memory usage.
2. Wherever required in your code, call the function :cpp:func:`esp_timer_dump` to print the information and use it to debug your timers.
3. Once debugging is complete, consider disabling :ref:`CONFIG_ESP_TIMER_PROFILING`.
Troubleshooting
---------------
Unstable Callback Dispatch Time
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
While dispatching the same callback function repeatedly, if the response time varies considerably, try to stabilize it by doing the following:
.. list::
- Use the :ref:`Interrupt Dispatch method <Using ESP_TIMER_ISR Callback Method>`.
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - Use the Kconfig option :ref:`CONFIG_ESP_TIMER_TASK_AFFINITY` to run the ESP Timer task on any of the available cores.
Significant Delays while Dispatching Callbacks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If dispatching a callback function takes a considerable amount of time, the problem can lie in the callback function itself. More precisely, as all callback functions are processed one by one in a single esp_timer task, the delays might be caused by other callback functions earlier in the queue.
For this reason, make sure that all callback functions in your application can execute on their own quickly and without any blocking operations.
Repeated Callback Dispatches After Sleep
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the callback functions are executed repeatedly upon wakeup from sleep, see :ref:`Handling Callbacks in Light Sleep`.
Stack Overflow While Dispatching Callbacks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you see a stack overflow error when executing a callback function, consider reducing the stack usage within your callback function. Alternatively, try increasing the size of the ESP Timer task stack by adjusting :ref:`CONFIG_ESP_TIMER_TASK_STACK_SIZE`.
Application Examples
--------------------
- :example:`system/esp_timer` creates and starts one-shot and periodic software timers, shows how they work with Light-sleep mode, and then stops and deletes the timers.
API Reference
-------------
.. include-build-file:: inc/esp_timer.inc
+149
View File
@@ -0,0 +1,149 @@
FreeRTOS Overview
=================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
FreeRTOS is an open source RTOS (real-time operating system) kernel that is integrated into ESP-IDF as a component. Thus, all ESP-IDF applications and many ESP-IDF components are written based on FreeRTOS. The FreeRTOS kernel is ported to all architectures (i.e., Xtensa and RISC-V) available of ESP chips.
Furthermore, ESP-IDF provides different implementations of FreeRTOS in order to support SMP (Symmetric Multiprocessing) on multi-core ESP chips. This document provides an overview of the FreeRTOS component, the different FreeRTOS implementations offered by ESP-IDF, and the common aspects across all implementations.
Implementations
---------------
The `official FreeRTOS <https://www.freertos.org/index.html>`_ (henceforth referred to as Vanilla FreeRTOS) is a single-core RTOS. In order to support the various multi-core ESP targets, ESP-IDF supports different FreeRTOS implementations as listed below:
ESP-IDF FreeRTOS
^^^^^^^^^^^^^^^^
ESP-IDF FreeRTOS is a FreeRTOS implementation based on Vanilla FreeRTOS v10.5.1, but contains significant modifications to support SMP. ESP-IDF FreeRTOS only supports two cores at most (i.e., dual core SMP), but is more optimized for this scenario by design. For more details regarding ESP-IDF FreeRTOS and its modifications, please refer to the :doc:`freertos_idf` document.
.. note::
ESP-IDF FreeRTOS is currently the default FreeRTOS implementation for ESP-IDF.
.. only:: not esp32p4 and not esp32h4
.. _amazon_smp_freertos:
Amazon SMP FreeRTOS
^^^^^^^^^^^^^^^^^^^
Amazon SMP FreeRTOS is an SMP implementation of FreeRTOS that is officially supported by Amazon. Amazon SMP FreeRTOS is able to support N-cores (i.e., more than two cores). Amazon SMP FreeRTOS can be enabled via the ``CONFIG_FREERTOS_SMP`` option (only available on ESP32). For more details regarding Amazon SMP FreeRTOS, please refer to the `official Amazon SMP FreeRTOS documentation <https://freertos.org/symmetric-multiprocessing-introduction.html>`_.
.. warning::
The Amazon SMP FreeRTOS implementation (and its port in ESP-IDF) are currently in experimental/beta state. Therefore, significant behavioral changes and breaking API changes can occur.
Configuration
-------------
Kernel Configuration
^^^^^^^^^^^^^^^^^^^^
Vanilla FreeRTOS requires that ports and applications configure the kernel by adding various ``#define config...`` macro definitions to the ``FreeRTOSConfig.h`` header file. Vanilla FreeRTOS supports a list of kernel configuration options which allow various kernel behaviors and features to be enabled or disabled.
**However, for all FreeRTOS ports in ESP-IDF, the FreeRTOSConfig.h header file is considered private and must not be modified by users**. A large number of kernel configuration options in ``FreeRTOSConfig.h`` are hard-coded as they are either required/not supported by ESP-IDF. All kernel configuration options that are configurable by the user are exposed via menuconfig under ``Component Config/FreeRTOS/Kernel``.
For the full list of user configurable kernel options, see :ref:`Kconfig Options Reference <configuration-options-reference>`. The list below highlights some commonly used kernel configuration options:
- :ref:`CONFIG_FREERTOS_UNICORE` runs FreeRTOS only on Core 0. Note that this is **not equivalent to running Vanilla FreeRTOS**. Furthermore, this option may affect behavior of components other than :component:`freertos`. For more details regarding the effects of running FreeRTOS on a single core, refer to :ref:`freertos-idf-single-core` (if using ESP-IDF FreeRTOS) or the official Amazon SMP FreeRTOS documentation. Alternatively, users can also search for occurrences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
.. only:: not SOC_HP_CPU_HAS_MULTIPLE_CORES
.. note::
As {IDF_TARGET_NAME} is a single core SoC, the :ref:`CONFIG_FREERTOS_UNICORE` configuration is always set.
- :ref:`CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY` enables backward compatibility with some FreeRTOS macros/types/functions that were deprecated from v8.0 onwards.
Port Configuration
^^^^^^^^^^^^^^^^^^
All other FreeRTOS related configuration options that are not part of the kernel configuration are exposed via menuconfig under ``Component Config/FreeRTOS/Port``. These options configure aspects such as:
- The FreeRTOS ports themselves (e.g., tick timer selection, ISR stack size)
- Additional features added to the FreeRTOS implementation or ports
Using FreeRTOS
--------------
Application Entry Point
^^^^^^^^^^^^^^^^^^^^^^^
Unlike Vanilla FreeRTOS, users of FreeRTOS in ESP-IDF **must never call** :cpp:func:`vTaskStartScheduler` and :cpp:func:`vTaskEndScheduler`. Instead, ESP-IDF starts FreeRTOS automatically. Users must define a ``void app_main(void)`` function which acts as the entry point for user's application and is automatically invoked on ESP-IDF startup.
- Typically, users would spawn the rest of their application's task from ``app_main``.
- The ``app_main`` function is allowed to return at any point (i.e., before the application terminates).
- The ``app_main`` function is called from the ``main`` task.
.. _freertos_system_tasks:
Background Tasks
^^^^^^^^^^^^^^^^
During startup, ESP-IDF and the FreeRTOS kernel automatically create multiple tasks that run in the background (listed in the the table below).
.. list-table:: List of Tasks Created During Startup
:widths: 10 75 5 5 5
:header-rows: 1
* - Task Name
- Description
- Stack Size
- Affinity
- Priority
* - Idle Tasks (``IDLEx``)
- An idle task (``IDLEx``) is created for (and pinned to) each core, where ``x`` is the core's number. ``x`` is dropped when single-core configuration is enabled.
- :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE`
- Core x
- ``0``
* - FreeRTOS Timer Task (``Tmr Svc``)
- FreeRTOS will create the Timer Service/Daemon Task if any FreeRTOS Timer APIs are called by the application
- :ref:`CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH`
- Core 0
- :ref:`CONFIG_FREERTOS_TIMER_TASK_PRIORITY`
* - Main Task (``main``)
- Task that simply calls ``app_main``. This task will self delete when ``app_main`` returns
- :ref:`CONFIG_ESP_MAIN_TASK_STACK_SIZE`
- :ref:`CONFIG_ESP_MAIN_TASK_AFFINITY`
- ``1``
* - IPC Tasks (``ipcx``)
- When :ref:`CONFIG_FREERTOS_UNICORE` is false, an IPC task (``ipcx``) is created for (and pinned to) each core. IPC tasks are used to implement the Inter-processor Call (IPC) feature.
- :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE`
- Core x
- ``24``
* - ESP Timer Task (``esp_timer``)
- ESP-IDF creates the ESP Timer Task used to process ESP Timer callbacks
- :ref:`CONFIG_ESP_TIMER_TASK_STACK_SIZE`
- Core 0
- ``22``
.. note::
Note that if an application uses other ESP-IDF features (e.g., Wi-Fi or Bluetooth), those features may create their own background tasks in addition to the tasks listed in the table above.
FreeRTOS Additions
------------------
ESP-IDF provides some supplemental features to FreeRTOS such as Ring Buffers, ESP-IDF style Tick and Idle Hooks, and TLSP deletion callbacks. See :doc:`freertos_additions` for more details.
.. _freertos-heap:
FreeRTOS Heap
-------------
Vanilla FreeRTOS provides its own `selection of heap implementations <https://www.freertos.org/a00111.html>`_. However, ESP-IDF already implements its own heap (see :doc:`/api-reference/system/mem_alloc`), thus ESP-IDF does not make use of the heap implementations provided by Vanilla FreeRTOS. All FreeRTOS ports in ESP-IDF map FreeRTOS memory allocation or free calls (e.g., ``pvPortMalloc()`` and ``pvPortFree()``) to ESP-IDF heap API (i.e., :cpp:func:`heap_caps_malloc` and :cpp:func:`heap_caps_free`). However, the FreeRTOS ports ensure that all dynamic memory allocated by FreeRTOS is placed in internal memory.
.. note::
If users wish to place FreeRTOS tasks/objects in external memory, users can use the following methods:
- Allocate the task or object using one of the ``...CreateWithCaps()`` API, such as :cpp:func:`xTaskCreateWithCaps` and :cpp:func:`xQueueCreateWithCaps` (see :ref:`freertos-idf-additional-api` for more details).
- Manually allocate external memory for those objects using :cpp:func:`heap_caps_malloc`, then create the objects from the allocated memory using on of the ``...CreateStatic()`` FreeRTOS functions.
Application Examples
--------------------
- :example:`system/freertos/basic_freertos_smp_usage` demonstrates how to use basic FreeRTOS APIs for task creation, communication, synchronization, and batch processing within an SMP architecture on {IDF_TARGET_NAME}.
- :example:`system/freertos/real_time_stats` demonstrates how to use FreeRTOS's function `vTaskGetRunTimeStats()` to obtain CPU usage statistics of tasks with respect to a specified duration, rather than over the entire runtime of FreeRTOS.
@@ -0,0 +1,485 @@
FreeRTOS (Supplemental Features)
================================
:link_to_translation:`zh_CN:[中文]`
ESP-IDF provides multiple features to supplement the features offered by FreeRTOS. These supplemental features are available on all FreeRTOS implementations supported by ESP-IDF (i.e., ESP-IDF FreeRTOS and Amazon SMP FreeRTOS). This document describes these supplemental features and is split into the following sections:
.. contents:: Contents
:depth: 2
.. ---------------------------------------------------- Overview -------------------------------------------------------
Overview
--------
ESP-IDF adds various new features to supplement the capabilities of FreeRTOS as follows:
- **Ring buffers**: Ring buffers provide a FIFO buffer that can accept entries of arbitrary lengths.
- **ESP-IDF Tick and Idle Hooks**: ESP-IDF provides multiple custom tick interrupt hooks and idle task hooks that are more numerous and more flexible when compared to FreeRTOS tick and idle hooks.
- **Thread Local Storage Pointer (TLSP) Deletion Callbacks**: TLSP Deletion callbacks are run automatically when a task is deleted, thus allowing users to clean up their TLSPs automatically.
- **IDF Additional API**: ESP-IDF specific functions added to augment the features of FreeRTOS.
- **Component Specific Properties**: Currently added only one component specific property ``ORIG_INCLUDE_PATH``.
.. -------------------------------------------------- Ring Buffers -----------------------------------------------------
Ring Buffers
------------
FreeRTOS provides stream buffers and message buffers as the primary mechanisms to send arbitrarily sized data between tasks and ISRs. However, FreeRTOS stream buffers and message buffers have the following limitations:
- Strictly single sender and single receiver
- Data is passed by copy
- Unable to reserve buffer space for a deferred send (i.e., send acquire)
Therefore, ESP-IDF provides a separate ring buffer implementation to address the issues above.
ESP-IDF ring buffers are strictly FIFO buffers that supports arbitrarily sized items. Ring buffers are a more memory efficient alternative to FreeRTOS queues in situations where the size of items is variable. The capacity of a ring buffer is not measured by the number of items it can store, but rather by the amount of memory used for storing items.
The ring buffer provides APIs to send an item, or to allocate space for an item in the ring buffer to be filled manually by the user. For efficiency reasons, **items are always retrieved from the ring buffer by reference**. As a result, all retrieved items **must also be returned** to the ring buffer by using :cpp:func:`vRingbufferReturnItem` or :cpp:func:`vRingbufferReturnItemFromISR`, in order for them to be removed from the ring buffer completely.
The ring buffers are split into the three following types:
**No-Split buffers** guarantee that an item is stored in contiguous memory and does not attempt to split an item under any circumstances. Use No-Split buffers when items must occupy contiguous memory. **Only this buffer type allows reserving buffer space for deferred sending.** Refer to the documentation of the functions :cpp:func:`xRingbufferSendAcquire` and :cpp:func:`xRingbufferSendComplete` for more details.
**Allow-Split buffers** allow an item to be split in two parts when wrapping around the end of the buffer if there is enough space at the tail and the head of the buffer combined to store the item. Allow-Split buffers are more memory efficient than No-Split buffers but can return an item in two parts when retrieving.
**Byte buffers** do not store data as separate items. All data is stored as a sequence of bytes, and any number of bytes can be sent or retrieved each time. Use byte buffers when separate items do not need to be maintained, e.g., a byte stream.
.. note::
No-Split buffers and Allow-Split buffers always store items at 32-bit aligned addresses. Therefore, when retrieving an item, the item pointer is guaranteed to be 32-bit aligned. This is useful especially when you need to send some data to the DMA.
.. note::
Each item stored in No-Split or Allow-Split buffers **requires an additional 8 bytes for a header**. Item sizes are also rounded up to a 32-bit aligned size, i.e., multiple of 4 bytes. However the true item size is recorded within the header. The sizes of No-Split and Allow-Split buffers will also be rounded up when created.
Usage
^^^^^
The following example demonstrates the usage of :cpp:func:`xRingbufferCreate` and :cpp:func:`xRingbufferSend` to create a ring buffer and then send an item to it:
.. code-block:: c
#include "freertos/ringbuf.h"
static char tx_item[] = "test_item";
...
//Create ring buffer
RingbufHandle_t buf_handle;
buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
if (buf_handle == NULL) {
printf("Failed to create ring buffer\n");
}
//Send an item
UBaseType_t res = xRingbufferSend(buf_handle, tx_item, sizeof(tx_item), pdMS_TO_TICKS(1000));
if (res != pdTRUE) {
printf("Failed to send item\n");
}
The following example demonstrates the usage of :cpp:func:`xRingbufferSendAcquire` and :cpp:func:`xRingbufferSendComplete` instead of :cpp:func:`xRingbufferSend` to acquire memory on the ring buffer (of type :cpp:enumerator:`RINGBUF_TYPE_NOSPLIT`) and then send an item to it. This adds one more step, but allows getting the address of the memory to write to, and writing to the memory yourself.
.. code-block:: c
#include "freertos/ringbuf.h"
#include "soc/lldesc.h"
typedef struct {
lldesc_t dma_desc;
uint8_t buf[1];
} dma_item_t;
#define DMA_ITEM_SIZE(N) (sizeof(lldesc_t)+(((N)+3)&(~3)))
...
//Retrieve space for DMA descriptor and corresponding data buffer
//This has to be done with SendAcquire, or the address may be different when we copy
dma_item_t *item;
UBaseType_t res = xRingbufferSendAcquire(buf_handle,
(void**) &item, DMA_ITEM_SIZE(buffer_size), pdMS_TO_TICKS(1000));
if (res != pdTRUE) {
printf("Failed to acquire memory for item\n");
}
item->dma_desc = (lldesc_t) {
.size = buffer_size,
.length = buffer_size,
.eof = 0,
.owner = 1,
.buf = item->buf,
};
//Actually send to the ring buffer for consumer to use
res = xRingbufferSendComplete(buf_handle, (void *)item);
if (res != pdTRUE) {
printf("Failed to send item\n");
}
The following example demonstrates retrieving and returning an item from a **No-Split ring buffer** using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem`
.. code-block:: c
...
//Receive an item from no-split ring buffer
size_t item_size;
char *item = (char *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(1000));
//Check received item
if (item != NULL) {
//Print item
for (int i = 0; i < item_size; i++) {
printf("%c", item[i]);
}
printf("\n");
//Return Item
vRingbufferReturnItem(buf_handle, (void *)item);
} else {
//Failed to receive item
printf("Failed to receive item\n");
}
The following example demonstrates retrieving and returning an item from an **Allow-Split ring buffer** using :cpp:func:`xRingbufferReceiveSplit` and :cpp:func:`vRingbufferReturnItem`
.. code-block:: c
...
//Receive an item from allow-split ring buffer
size_t item_size1, item_size2;
char *item1, *item2;
BaseType_t ret = xRingbufferReceiveSplit(buf_handle, (void **)&item1, (void **)&item2, &item_size1, &item_size2, pdMS_TO_TICKS(1000));
//Check received item
if (ret == pdTRUE && item1 != NULL) {
for (int i = 0; i < item_size1; i++) {
printf("%c", item1[i]);
}
vRingbufferReturnItem(buf_handle, (void *)item1);
//Check if item was split
if (item2 != NULL) {
for (int i = 0; i < item_size2; i++) {
printf("%c", item2[i]);
}
vRingbufferReturnItem(buf_handle, (void *)item2);
}
printf("\n");
} else {
//Failed to receive item
printf("Failed to receive item\n");
}
The following example demonstrates retrieving and returning an item from a **byte buffer** using :cpp:func:`xRingbufferReceiveUpTo` and :cpp:func:`vRingbufferReturnItem`
.. code-block:: c
...
//Receive data from byte buffer
size_t item_size;
char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(1000), sizeof(tx_item));
//Check received data
if (item != NULL) {
//Print item
for (int i = 0; i < item_size; i++) {
printf("%c", item[i]);
}
printf("\n");
//Return Item
vRingbufferReturnItem(buf_handle, (void *)item);
} else {
//Failed to receive item
printf("Failed to receive item\n");
}
For ISR safe versions of the functions used above, call :cpp:func:`xRingbufferSendFromISR`, :cpp:func:`xRingbufferReceiveFromISR`, :cpp:func:`xRingbufferReceiveSplitFromISR`, :cpp:func:`xRingbufferReceiveUpToFromISR`, and :cpp:func:`vRingbufferReturnItemFromISR`.
.. note::
Two calls to ``RingbufferReceive[UpTo][FromISR]()`` are required if the bytes wraps around the end of the ring buffer.
Sending to Ring Buffer
^^^^^^^^^^^^^^^^^^^^^^
The following diagrams illustrate the differences between No-Split and Allow-Split buffers as compared to byte buffers with regard to sending items or data. The diagrams assume that three items of sizes **18, 3, and 27 bytes** are sent respectively to a **buffer of 128 bytes**:
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag
:caption: Sending items to No-Split or Allow-Split ring buffers
:align: center
For No-Split and Allow-Split buffers, a header of 8 bytes precedes every data item. Furthermore, the space occupied by each item is **rounded up to the nearest 32-bit aligned size** in order to maintain overall 32-bit alignment. However, the true size of the item is recorded inside the header which will be returned when the item is retrieved.
Referring to the diagram above, the 18, 3, and 27 byte items are **rounded up to 20, 4, and 28 bytes** respectively. An 8 byte header is then added in front of each item.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag
:caption: Sending items to byte buffers
:align: center
Byte buffers treat data as a sequence of bytes and does not incur any overhead (no headers). As a result, all data sent to a byte buffer is merged into a single item.
Referring to the diagram above, the 18, 3, and 27 byte items are sequentially written to the byte buffer and **merged into a single item of 48 bytes**.
Using SendAcquire and SendComplete
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Items in No-Split buffers are acquired (by ``SendAcquire``) in strict FIFO order and must be sent to the buffer by ``SendComplete`` for the data to be accessible by the consumer. Multiple items can be sent or acquired without calling ``SendComplete``, and the items do not necessarily need to be completed in the order they were acquired. However, the receiving of data items must occur in FIFO order, therefore not calling ``SendComplete`` for the earliest acquired item prevents the subsequent items from being received.
The following diagrams illustrate what will happen when ``SendAcquire`` and ``SendComplete`` do not happen in the same order. At the beginning, there is already a data item of 16 bytes sent to the ring buffer. Then ``SendAcquire`` is called to acquire space of 20, 8, 24 bytes on the ring buffer.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_acquire_complete.diag
:caption: SendAcquire/SendComplete items in No-Split ring buffers
:align: center
After that, we fill (use) the buffers, and send them to the ring buffer by ``SendComplete`` in the order of 8, 24, 20. When 8 bytes and 24 bytes data are sent, the consumer still can only get the 16 bytes data item. Hence, if ``SendComplete`` is not called for the 20 bytes, it will not be available, nor will the data items following the 20 bytes item.
When the 20 bytes item is finally completed, all the 3 data items can be received now, in the order of 20, 8, 24 bytes, right after the 16 bytes item existing in the buffer at the beginning.
Allow-Split buffers and byte buffers do not allow using ``SendAcquire`` or ``SendComplete`` since acquired buffers are required to be complete (not wrapped).
Wrap Around
^^^^^^^^^^^
The following diagrams illustrate the differences between No-Split, Allow-Split, and byte buffers when a sent item requires a wrap around. The diagrams assume a buffer of **128 bytes** with **56 bytes of free space that wraps around** and a sent item of **28 bytes**.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag
:caption: Wrap around in No-Split buffers
:align: center
No-Split buffers **only store an item in continuous free space and do not split an item under any circumstances**. When the free space at the tail of the buffer is insufficient to completely store the item and its header, the free space at the tail will be **marked as dummy data**. The buffer will then wrap around and store the item in the free space at the head of the buffer.
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient to store the 28 byte item. Therefore, the 16 bytes is marked as dummy data and the item is written to the free space at the head of the buffer instead.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag
:caption: Wrap around in Allow-Split buffers
:align: center
Allow-Split buffers will attempt to **split the item into two parts** when the free space at the tail of the buffer is insufficient to store the item data and its header. Both parts of the split item will have their own headers, therefore incurring an extra 8 bytes of overhead.
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient to store the 28 byte item. Therefore, the item is split into two parts (8 and 20 bytes) and written as two parts to the buffer.
.. note::
Allow-Split buffers treat both parts of the split item as two separate items, therefore call :cpp:func:`xRingbufferReceiveSplit` instead of :cpp:func:`xRingbufferReceive` to receive both parts of a split item in a thread safe manner.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag
:caption: Wrap around in byte buffers
:align: center
Byte buffers **store as much data as possible into the free space at the tail of buffer**. The remaining data will then be stored in the free space at the head of the buffer. No overhead is incurred when wrapping around in byte buffers.
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient to completely store the 28 bytes of data. Therefore, the 16 bytes of free space is filled with data, and the remaining 12 bytes are written to the free space at the head of the buffer. The buffer now contains data in two separate continuous parts, and each continuous part is treated as a separate item by the byte buffer.
Retrieving/Returning
^^^^^^^^^^^^^^^^^^^^
The following diagrams illustrate the differences between No-Split and Allow-Split buffers as compared to byte buffers in retrieving and returning data:
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag
:caption: Retrieving/Returning items in No-Split and Allow-Split ring buffers
:align: center
Items in No-Split buffers and Allow-Split buffers are **retrieved in strict FIFO order** and **must be returned** for the occupied space to be freed. Multiple items can be retrieved before returning, and the items do not necessarily need to be returned in the order they were retrieved. However, the freeing of space must occur in FIFO order, therefore not returning the earliest retrieved item prevents the space of subsequent items from being freed.
Referring to the diagram above, the **16, 20, and 8 byte items are retrieved in FIFO order**. However, the items are not returned in the order they were retrieved. First, the 20 byte item is returned followed by the 8 byte and the 16 byte items. The space is not freed until the first item, i.e., the 16 byte item is returned.
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag
:caption: Retrieving/Returning data in byte buffers
:align: center
Byte buffers **do not allow multiple retrievals before returning** (every retrieval must be followed by a return before another retrieval is permitted). When using :cpp:func:`xRingbufferReceive` or :cpp:func:`xRingbufferReceiveFromISR`, all continuous stored data will be retrieved. :cpp:func:`xRingbufferReceiveUpTo` or :cpp:func:`xRingbufferReceiveUpToFromISR` can be used to restrict the maximum number of bytes retrieved. Since every retrieval must be followed by a return, the space is freed as soon as the data is returned.
Referring to the diagram above, the 38 bytes of continuous stored data at the tail of the buffer is retrieved, returned, and freed. The next call to :cpp:func:`xRingbufferReceive` or :cpp:func:`xRingbufferReceiveFromISR` then wraps around and does the same to the 30 bytes of continuous stored data at the head of the buffer.
.. note::
Retrieving items from Allow-Split buffers must be done via :cpp:func:`xRingbufferReceiveSplit` or :cpp:func:`xRingbufferReceiveSplitFromISR` instead of :cpp:func:`xRingbufferReceive` or :cpp:func:`xRingbufferReceiveFromISR`.
Ring Buffers with Queue Sets
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ring buffers can be added to FreeRTOS queue sets using :cpp:func:`xRingbufferAddToQueueSetRead` such that every time a ring buffer receives an item or data, the queue set is notified. Once added to a queue set, every attempt to retrieve an item from a ring buffer should be preceded by a call to :cpp:func:`xQueueSelectFromSet`. To check whether the selected queue set member is the ring buffer, call :cpp:func:`xRingbufferCanRead`.
The following example demonstrates queue set usage with ring buffers:
.. code-block:: c
#include "freertos/queue.h"
#include "freertos/ringbuf.h"
...
//Create ring buffer and queue set
RingbufHandle_t buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
QueueSetHandle_t queue_set = xQueueCreateSet(3);
//Add ring buffer to queue set
if (xRingbufferAddToQueueSetRead(buf_handle, queue_set) != pdTRUE) {
printf("Failed to add to queue set\n");
}
...
//Block on queue set
QueueSetMemberHandle_t member = xQueueSelectFromSet(queue_set, pdMS_TO_TICKS(1000));
//Check if member is ring buffer
if (member != NULL && xRingbufferCanRead(buf_handle, member) == pdTRUE) {
//Member is ring buffer, receive item from ring buffer
size_t item_size;
char *item = (char *)xRingbufferReceive(buf_handle, &item_size, 0);
//Handle item
...
} else {
...
}
Ring Buffers with Static Allocation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :cpp:func:`xRingbufferCreateStatic` can be used to create ring buffers with specific memory requirements (such as a ring buffer being allocated in external RAM). All blocks of memory used by a ring buffer must be manually allocated beforehand, then passed to the :cpp:func:`xRingbufferCreateStatic` to be initialized as a ring buffer. These blocks include the following:
- The ring buffer's data structure of type :cpp:type:`StaticRingbuffer_t`.
- The ring buffer's storage area of size ``xBufferSize``. Note that ``xBufferSize`` must be 32-bit aligned for No-Split and Allow-Split buffers.
The manner in which these blocks are allocated depends on the users requirements (e.g., all blocks being statically declared, or dynamically allocated with specific capabilities such as external RAM).
.. note::
When deleting a ring buffer created via :cpp:func:`xRingbufferCreateStatic`, the function :cpp:func:`vRingbufferDelete` will not free any of the memory blocks. This must be done manually by the user after :cpp:func:`vRingbufferDelete` is called.
The code snippet below demonstrates a ring buffer being allocated entirely in external RAM.
.. code-block:: c
#include "freertos/ringbuf.h"
#include "freertos/semphr.h"
#include "esp_heap_caps.h"
#define BUFFER_SIZE 400 //32-bit aligned size
#define BUFFER_TYPE RINGBUF_TYPE_NOSPLIT
...
//Allocate ring buffer data structure and storage area into external RAM
StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*BUFFER_SIZE, MALLOC_CAP_SPIRAM);
//Create a ring buffer with manually allocated memory
RingbufHandle_t handle = xRingbufferCreateStatic(BUFFER_SIZE, BUFFER_TYPE, buffer_storage, buffer_struct);
...
//Delete the ring buffer after used
vRingbufferDelete(handle);
//Manually free all blocks of memory
free(buffer_struct);
free(buffer_storage);
.. ------------------------------------------- ESP-IDF Tick and Idle Hooks ---------------------------------------------
ESP-IDF Tick and Idle Hooks
---------------------------
FreeRTOS allows applications to provide a tick hook and an idle hook at compile time:
- FreeRTOS tick hook can be enabled via the :ref:`CONFIG_FREERTOS_USE_TICK_HOOK` option. The application must provide the ``void vApplicationTickHook( void )`` callback.
- FreeRTOS idle hook can be enabled via the :ref:`CONFIG_FREERTOS_USE_IDLE_HOOK` option. The application must provide the ``void vApplicationIdleHook( void )`` callback.
However, the FreeRTOS tick hook and idle hook have the following draw backs:
- The FreeRTOS hooks are registered at compile time
- Only one of each hook can be registered
- On multi-core targets, the FreeRTOS hooks are symmetric, meaning each core's tick interrupt and idle tasks ends up calling the same hook
Therefore, ESP-IDF tick and idle hooks are provided to supplement the features of FreeRTOS tick and idle hooks. The ESP-IDF hooks have the following features:
- The hooks can be registered and deregistered at run-time
- Multiple hooks can be registered (with a maximum of 8 hooks of each type per core)
- On multi-core targets, the hooks can be asymmetric, meaning different hooks can be registered to each core
ESP-IDF hooks can be registered and deregistered using the following APIs:
- For tick hooks:
- Register using :cpp:func:`esp_register_freertos_tick_hook` or :cpp:func:`esp_register_freertos_tick_hook_for_cpu`
- Deregister using :cpp:func:`esp_deregister_freertos_tick_hook` or :cpp:func:`esp_deregister_freertos_tick_hook_for_cpu`
- For idle hooks:
- Register using :cpp:func:`esp_register_freertos_idle_hook` or :cpp:func:`esp_register_freertos_idle_hook_for_cpu`
- Deregister using :cpp:func:`esp_deregister_freertos_idle_hook` or :cpp:func:`esp_deregister_freertos_idle_hook_for_cpu`
.. note::
The tick interrupt stays active while the cache is disabled, therefore any tick hook (FreeRTOS or ESP-IDF) functions must be placed in internal RAM. Please refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` for more details.
.. -------------------------------------------------- TLSP Callback ----------------------------------------------------
TLSP Deletion Callbacks
-----------------------
Vanilla FreeRTOS provides a Thread Local Storage Pointers (TLSP) feature. These are pointers stored directly in the Task Control Block (TCB) of a particular task. TLSPs allow each task to have its own unique set of pointers to data structures. Vanilla FreeRTOS expects users to:
- set a task's TLSPs by calling :cpp:func:`vTaskSetThreadLocalStoragePointer` after the task has been created.
- get a task's TLSPs by calling :cpp:func:`pvTaskGetThreadLocalStoragePointer` during the task's lifetime.
- free the memory pointed to by the TLSPs before the task is deleted.
However, there can be instances where users may want the freeing of TLSP memory to be automatic. Therefore, ESP-IDF provides the additional feature of TLSP deletion callbacks. These user-provided deletion callbacks are called automatically when a task is deleted, thus allowing the TLSP memory to be cleaned up without needing to add the cleanup logic explicitly to the code of every task.
The TLSP deletion callbacks are set in a similar fashion to the TLSPs themselves.
- :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback` sets both a particular TLSP and its associated callback.
- Calling the Vanilla FreeRTOS function :cpp:func:`vTaskSetThreadLocalStoragePointer` simply sets the TLSP's associated Deletion Callback to `NULL`, meaning that no callback is called for that TLSP during task deletion.
When implementing TLSP callbacks, users should note the following:
- The callback **must never attempt to block or yield** and critical sections should be kept as short as possible.
- The callback is called shortly before a deleted task's memory is freed. Thus, the callback can either be called from :cpp:func:`vTaskDelete` itself, or from the idle task.
.. --------------------------------------------- ESP-IDF Additional API ------------------------------------------------
.. _freertos-idf-additional-api:
IDF Additional API
------------------
The :component_file:`freertos/esp_additions/include/freertos/idf_additions.h` header contains FreeRTOS-related helper functions added by ESP-IDF. Users can include this header via ``#include "freertos/idf_additions.h"``.
.. ------------------------------------------ Component Specific Properties --------------------------------------------
Component Specific Properties
-----------------------------
Besides standard component variables that are available with basic cmake build properties, FreeRTOS component also provides arguments (only one so far) for simpler integration with other modules:
- `ORIG_INCLUDE_PATH` - contains an absolute path to freertos root include folder. Thus instead of `#include "freertos/FreeRTOS.h"` you can refer to headers directly: `#include "FreeRTOS.h"`.
.. -------------------------------------------------- API Reference ----------------------------------------------------
API Reference
-------------
Ring Buffer API
^^^^^^^^^^^^^^^
.. include-build-file:: inc/ringbuf.inc
Hooks API
^^^^^^^^^
.. include-build-file:: inc/esp_freertos_hooks.inc
Additional API
^^^^^^^^^^^^^^
.. include-build-file:: inc/idf_additions.inc
@@ -0,0 +1,547 @@
FreeRTOS (IDF)
==============
:link_to_translation:`zh_CN:[中文]`
This document provides information regarding the dual-core SMP implementation of FreeRTOS inside ESP-IDF. This document is split into the following sections:
.. contents:: Sections
:depth: 2
.. ---------------------------------------------------- Overview -------------------------------------------------------
Overview
--------
The original FreeRTOS (hereinafter referred to as **Vanilla FreeRTOS**) is a compact and efficient real-time operating system supported on numerous single-core MCUs and SoCs. However, to support dual-core ESP targets, such as ESP32, ESP32-S3, and ESP32-P4, ESP-IDF provides a unique implementation of FreeRTOS with dual-core symmetric multiprocessing (SMP) capabilities (hereinafter referred to as **IDF FreeRTOS**).
IDF FreeRTOS source code is based on Vanilla FreeRTOS v10.5.1 but contains significant modifications to both kernel behavior and API in order to support dual-core SMP. However, IDF FreeRTOS can also be configured for single-core by enabling the :ref:`CONFIG_FREERTOS_UNICORE` option (see :ref:`freertos-idf-single-core` for more details).
.. note::
This document assumes that the reader has a requisite understanding of Vanilla FreeRTOS, i.e., its features, behavior, and API usage. Refer to the `Vanilla FreeRTOS documentation <https://www.freertos.org/index.html>`_ for more details.
.. -------------------------------------------- Symmetric Multiprocessing ----------------------------------------------
Symmetric Multiprocessing
-------------------------
Basic Concepts
^^^^^^^^^^^^^^
Symmetric multiprocessing is a computing architecture where two or more identical CPU cores are connected to a single shared main memory and controlled by a single operating system. In general, an SMP system:
- has multiple cores running independently. Each core has its own register file, interrupts, and interrupt handling.
- presents an identical view of memory to each core. Thus, a piece of code that accesses a particular memory address has the same effect regardless of which core it runs on.
The main advantages of an SMP system compared to single-core or asymmetric multiprocessing systems are that:
- the presence of multiple cores allows for multiple hardware threads, thus increasing overall processing throughput.
- having symmetric memory means that threads can switch cores during execution. This, in general, can lead to better CPU utilization.
Although an SMP system allows threads to switch cores, there are scenarios where a thread must/should only run on a particular core. Therefore, threads in an SMP system also have a core affinity that specifies which particular core the thread is allowed to run on.
- A thread that is pinned to a particular core is only able to run on that core.
- A thread that is unpinned will be allowed to switch between cores during execution instead of being pinned to a particular core.
SMP on an ESP Target
^^^^^^^^^^^^^^^^^^^^
ESP targets such as ESP32, ESP32-S3, ESP32-P4 and ESP32-H4 are dual-core SMP SoCs. These targets have the following hardware features that make them SMP-capable:
- Two identical cores are known as Core 0 and Core 1. This means that the execution of a piece of code is identical regardless of which core it runs on.
- Symmetric memory (with some small exceptions).
- If multiple cores access the same memory address simultaneously, their access will be serialized by the memory bus.
- True atomic access to the same memory address is achieved via an atomic compare-and-swap instruction provided by the ISA.
- Cross-core interrupts that allow one core to trigger an interrupt on the other core. This allows cores to signal events to each other (such as requesting a context switch on the other core).
.. note::
Within ESP-IDF, Core 0 and Core 1 are sometimes referred to as ``PRO_CPU`` and ``APP_CPU`` respectively. The aliases exist in ESP-IDF as they reflect how typical ESP-IDF applications utilize the two cores. Typically, the tasks responsible for handling protocol related processing such as Wi-Fi or Bluetooth are pinned to Core 0 (thus the name ``PRO_CPU``), where as the tasks handling the remainder of the application are pinned to Core 1, (thus the name ``APP_CPU``).
.. ------------------------------------------------------ Tasks --------------------------------------------------------
Tasks
-----
Creation
^^^^^^^^
Vanilla FreeRTOS provides the following functions to create a task:
- :cpp:func:`xTaskCreate` creates a task. The task's memory is dynamically allocated.
- :cpp:func:`xTaskCreateStatic` creates a task. The task's memory is statically allocated, i.e., provided by the user.
However, in an SMP system, tasks need to be assigned a particular affinity. Therefore, ESP-IDF provides a ``...PinnedToCore()`` version of Vanilla FreeRTOS's task creation functions:
- :cpp:func:`xTaskCreatePinnedToCore` creates a task with a particular core affinity. The task's memory is dynamically allocated.
- :cpp:func:`xTaskCreateStaticPinnedToCore` creates a task with a particular core affinity. The task's memory is statically allocated, i.e., provided by the user.
The ``...PinnedToCore()`` versions of the task creation function API differ from their vanilla counterparts by having an extra ``xCoreID`` parameter that is used to specify the created task's core affinity. The valid values for core affinity are:
- ``0``, which pins the created task to Core 0
- ``1``, which pins the created task to Core 1
- ``tskNO_AFFINITY``, which allows the task to be run on both cores
Note that IDF FreeRTOS still supports the vanilla versions of the task creation functions. However, these standard functions have been modified to essentially invoke their respective ``...PinnedToCore()`` counterparts while setting the core affinity to ``tskNO_AFFINITY``.
.. note::
IDF FreeRTOS also changes the units of ``ulStackDepth`` in the task creation functions. Task stack sizes in Vanilla FreeRTOS are specified in a number of words, whereas in IDF FreeRTOS, the task stack sizes are specified in bytes.
Execution
^^^^^^^^^
The anatomy of a task in IDF FreeRTOS is the same as in Vanilla FreeRTOS. More specifically, IDF FreeRTOS tasks:
- Can only be in one of the following states: Running, Ready, Blocked, or Suspended.
- Task functions are typically implemented as an infinite loop.
- Task functions should never return.
Deletion
^^^^^^^^
Task deletion in Vanilla FreeRTOS is called via :cpp:func:`vTaskDelete`. The function allows deletion of another task or the currently running task if the provided task handle is ``NULL``. The actual freeing of the task's memory is sometimes delegated to the idle task if the task being deleted is the currently running task.
IDF FreeRTOS provides the same :cpp:func:`vTaskDelete` function. However, due to the dual-core nature, there are some behavioral differences when calling :cpp:func:`vTaskDelete` in IDF FreeRTOS:
- When deleting a task that is currently running on the other core, a yield is triggered on the other core, and the task's memory is freed by one of the idle tasks.
- A deleted task's memory is freed immediately if it is not running on either core.
Please avoid deleting a task that is running on another core as it is difficult to determine what the task is performing, which may lead to unpredictable behavior such as:
- Deleting a task that is holding a mutex.
- Deleting a task that has yet to free memory it previously allocated.
Where possible, please design your own application so that when calling :cpp:func:`vTaskDelete`, the deleted task is in a known state. For example:
- Tasks self-deleting via ``vTaskDelete(NULL)`` when their execution is complete and have also cleaned up all resources used within the task.
- Tasks placing themselves in the suspend state via :cpp:func:`vTaskSuspend` before being deleted by another task.
.. --------------------------------------------------- Scheduling ------------------------------------------------------
SMP Scheduler
-------------
The Vanilla FreeRTOS scheduler is best described as a **fixed priority preemptive scheduler with time slicing** meaning that:
- Each task is given a constant priority upon creation. The scheduler executes the highest priority ready-state task.
- The scheduler can switch execution to another task without the cooperation of the currently running task.
- The scheduler periodically switches execution between ready-state tasks of the same priority in a round-robin fashion. Time slicing is governed by a tick interrupt.
The IDF FreeRTOS scheduler supports the same scheduling features, i.e., Fixed Priority, Preemption, and Time Slicing, albeit with some small behavioral differences.
Fixed Priority
^^^^^^^^^^^^^^
In Vanilla FreeRTOS, when the scheduler selects a new task to run, it always selects the current highest priority ready-state task. In IDF FreeRTOS, each core independently schedules tasks to run. When a particular core selects a task, the core will select the highest priority ready-state task that can be run by the core. A task can be run by the core if:
- The task has a compatible affinity, i.e., is either pinned to that core or is unpinned.
- The task is not currently being run by another core.
However, please do not assume that the two highest priority ready-state tasks are always run by the scheduler, as a task's core affinity must also be accounted for. For example, given the following tasks:
- Task A of priority 10 pinned to Core 0
- Task B of priority 9 pinned to Core 0
- Task C of priority 8 pinned to Core 1
The resulting schedule will have Task A running on Core 0 and Task C running on Core 1. Task B is not run even though it is the second-highest priority task.
Preemption
^^^^^^^^^^
In Vanilla FreeRTOS, the scheduler can preempt the currently running task if a higher priority task becomes ready to execute. Likewise in IDF FreeRTOS, each core can be individually preempted by the scheduler if the scheduler determines that a higher-priority task can run on that core.
However, there are some instances where a higher-priority task that becomes ready can be run on multiple cores. In this case, the scheduler only preempts one core. The scheduler always gives preference to the current core when multiple cores can be preempted. In other words, if the higher priority ready task is unpinned and has a higher priority than the current priority of both cores, the scheduler will always choose to preempt the current core. For example, given the following tasks:
- Task A of priority 8 currently running on Core 0
- Task B of priority 9 currently running on Core 1
- Task C of priority 10 that is unpinned and was unblocked by Task B
The resulting schedule will have Task A running on Core 0 and Task C preempting Task B given that the scheduler always gives preference to the current core.
Time Slicing
^^^^^^^^^^^^
The Vanilla FreeRTOS scheduler implements time slicing, which means that if the current highest ready priority contains multiple ready tasks, the scheduler will switch between those tasks periodically in a round-robin fashion.
However, in IDF FreeRTOS, it is not possible to implement perfect Round Robin time slicing due to the fact that a particular task may not be able to run on a particular core due to the following reasons:
- The task is pinned to another core.
- For unpinned tasks, the task is already being run by another core.
Therefore, when a core searches the ready-state task list for a task to run, the core may need to skip over a few tasks in the same priority list or drop to a lower priority in order to find a ready-state task that the core can run.
The IDF FreeRTOS scheduler implements a Best Effort Round Robin time slicing for ready-state tasks of the same priority by ensuring that tasks that have been selected to run are placed at the back of the list, thus giving unselected tasks a higher priority on the next scheduling iteration (i.e., the next tick interrupt or yield).
The following example demonstrates the Best Effort Round Robin time slicing in action. Assume that:
- There are four ready-state tasks of the same priority ``AX``, ``B0``, ``C1``, and ``D1`` where:
- The priority is the current highest priority with ready-state .
- The first character represents the task's name, i.e., ``A``, ``B``, ``C``, ``D``.
- The second character represents the task's core pinning, and ``X`` means unpinned.
- The task list is always searched from the head.
1. Starting state. None of the ready-state tasks have been selected to run.
.. code-block:: none
Head [ AX , B0 , C1 , D0 ] Tail
2. Core 0 has a tick interrupt and searches for a task to run. Task A is selected and moved to the back of the list.
.. code-block:: none
Core 0 ─┐
Head [ AX , B0 , C1 , D0 ] Tail
[0]
Head [ B0 , C1 , D0 , AX ] Tail
3. Core 1 has a tick interrupt and searches for a task to run. Task B cannot be run due to incompatible affinity, so Core 1 skips to Task C. Task C is selected and moved to the back of the list.
.. code-block:: none
Core 1 ──────┐
▼ [0]
Head [ B0 , C1 , D0 , AX ] Tail
[0] [1]
Head [ B0 , D0 , AX , C1 ] Tail
4. Core 0 has another tick interrupt and searches for a task to run. Task B is selected and moved to the back of the list.
.. code-block:: none
Core 0 ─┐
▼ [1]
Head [ B0 , D0 , AX , C1 ] Tail
[1] [0]
Head [ D0 , AX , C1 , B0 ] Tail
5. Core 1 has another tick and searches for a task to run. Task D cannot be run due to incompatible affinity, so Core 1 skips to Task A. Task A is selected and moved to the back of the list.
.. code-block:: none
Core 1 ──────┐
▼ [0]
Head [ D0 , AX , C1 , B0 ] Tail
[0] [1]
Head [ D0 , C1 , B0 , AX ] Tail
The implications to users regarding the Best Effort Round Robin time slicing:
- Users cannot expect multiple ready-state tasks of the same priority to run sequentially as is the case in Vanilla FreeRTOS. As demonstrated in the example above, a core may need to skip over tasks.
- However, given enough ticks, a task will eventually be given some processing time.
- If a core cannot find a task runnable task at the highest ready-state priority, it will drop to a lower priority to search for tasks.
- To achieve ideal round-robin time slicing, users should ensure that all tasks of a particular priority are pinned to the same core.
Tick Interrupts
^^^^^^^^^^^^^^^
Vanilla FreeRTOS requires that a periodic tick interrupt occurs. The tick interrupt is responsible for:
- Incrementing the scheduler's tick count
- Unblocking any blocked tasks that have timed out
- Checking if time slicing is required, i.e., triggering a context switch
- Executing the application tick hook
In IDF FreeRTOS, each core receives a periodic interrupt and independently runs the tick interrupt. The tick interrupts on each core are of the same period but can be out of phase. However, the tick responsibilities listed above are not run by all cores:
- Core 0 executes all of the tick interrupt responsibilities listed above
- Core 1 only checks for time slicing and executes the application tick hook
.. note::
Core 0 is solely responsible for keeping time in IDF FreeRTOS. Therefore, anything that prevents Core 0 from incrementing the tick count, such as suspending the scheduler on Core 0, will cause the entire scheduler's timekeeping to lag behind.
Idle Tasks
^^^^^^^^^^
Vanilla FreeRTOS will implicitly create an idle task of priority 0 when the scheduler is started. The idle task runs when no other task is ready to run, and it has the following responsibilities:
- Freeing the memory of deleted tasks
- Executing the application idle hook
In IDF FreeRTOS, a separate pinned idle task is created for each core. The idle tasks on each core have the same responsibilities as their vanilla counterparts.
Scheduler Suspension
^^^^^^^^^^^^^^^^^^^^
Vanilla FreeRTOS allows the scheduler to be suspended/resumed by calling :cpp:func:`vTaskSuspendAll` and :cpp:func:`xTaskResumeAll` respectively. While the scheduler is suspended:
- Task switching is disabled but interrupts are left enabled.
- Calling any blocking/yielding function is forbidden, and time slicing is disabled.
- The tick count is frozen, but the tick interrupt still occurs to execute the application tick hook.
On scheduler resumption, :cpp:func:`xTaskResumeAll` catches up all of the lost ticks and unblock any timed-out tasks.
In IDF FreeRTOS, suspending the scheduler across multiple cores is not possible. Therefore when :cpp:func:`vTaskSuspendAll` is called on a particular core (e.g., core A):
- Task switching is disabled only on core A but interrupts for core A are left enabled.
- Calling any blocking/yielding function on core A is forbidden. Time slicing is disabled on core A.
- If an interrupt on core A unblocks any tasks, tasks with affinity to core A will go into core A's own pending ready task list. Unpinned tasks or tasks with affinity to other cores can be scheduled on cores with the scheduler running.
- If the scheduler is suspended on all cores, tasks unblocked by an interrupt will be directed to the pending ready task lists of their pinned cores. For unpinned tasks, they will be placed in the pending ready list of the core where the interrupt occurred.
- If core A is on Core 0, the tick count is frozen, and a pended tick count is incremented instead. However, the tick interrupt will still occur in order to execute the application tick hook.
When :cpp:func:`xTaskResumeAll` is called on a particular core (e.g., core A):
- Any tasks added to core A's pending ready task list will be resumed.
- If core A is Core 0, the pended tick count is unwound to catch up with the lost ticks.
.. warning::
Given that scheduler suspension on IDF FreeRTOS only suspends scheduling on a particular core, scheduler suspension is **NOT** a valid method of ensuring mutual exclusion between tasks when accessing shared data. Users should use proper locking primitives such as mutexes or spinlocks if they require mutual exclusion.
.. ------------------------------------------------ Critical Sections --------------------------------------------------
Critical Sections
-----------------
Disabling Interrupts
^^^^^^^^^^^^^^^^^^^^
Vanilla FreeRTOS allows interrupts to be disabled and enabled by calling :c:macro:`taskDISABLE_INTERRUPTS` and :c:macro:`taskENABLE_INTERRUPTS` respectively. IDF FreeRTOS provides the same API. However, interrupts are only disabled or enabled on the current core.
Disabling interrupts is a valid method of achieving mutual exclusion in Vanilla FreeRTOS (and single-core systems in general). **However, in an SMP system, disabling interrupts is not a valid method of ensuring mutual exclusion**. Critical sections that utilize a spinlock should be used instead.
API Changes
^^^^^^^^^^^
Vanilla FreeRTOS implements critical sections by disabling interrupts, which prevents preemptive context switches and the servicing of ISRs during a critical section. Thus a task/ISR that enters a critical section is guaranteed to be the sole entity to access a shared resource. Critical sections in Vanilla FreeRTOS have the following API:
- ``taskENTER_CRITICAL()`` enters a critical section by disabling interrupts
- ``taskEXIT_CRITICAL()`` exits a critical section by reenabling interrupts
- ``taskENTER_CRITICAL_FROM_ISR()`` enters a critical section from an ISR by disabling interrupt nesting
- ``taskEXIT_CRITICAL_FROM_ISR()`` exits a critical section from an ISR by reenabling interrupt nesting
However, in an SMP system, merely disabling interrupts does not constitute a critical section as the presence of other cores means that a shared resource can still be concurrently accessed. Therefore, critical sections in IDF FreeRTOS are implemented using spinlocks. To accommodate the spinlocks, the IDF FreeRTOS critical section APIs contain an additional spinlock parameter as shown below:
- Spinlocks are of ``portMUX_TYPE`` (**not to be confused to FreeRTOS mutexes**)
- ``taskENTER_CRITICAL(&spinlock)`` enters a critical from a task context
- ``taskEXIT_CRITICAL(&spinlock)`` exits a critical section from a task context
- ``taskENTER_CRITICAL_ISR(&spinlock)`` enters a critical section from an interrupt context
- ``taskEXIT_CRITICAL_ISR(&spinlock)`` exits a critical section from an interrupt context
.. note::
The critical section API can be called recursively, i.e., nested critical sections. Entering a critical section multiple times recursively is valid so long as the critical section is exited the same number of times it was entered. However, given that critical sections can target different spinlocks, users should take care to avoid deadlocking when entering critical sections recursively.
Spinlocks can be allocated statically or dynamically. As such, macros are provided for both static and dynamic initialization of spinlocks, as demonstrated by the following code snippets.
- Allocating a static spinlock and initializing it using ``portMUX_INITIALIZER_UNLOCKED``:
.. code:: c
// Statically allocate and initialize the spinlock
static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED;
void some_function(void)
{
taskENTER_CRITICAL(&my_spinlock);
// We are now in a critical section
taskEXIT_CRITICAL(&my_spinlock);
}
- Allocating a dynamic spinlock and initializing it using ``portMUX_INITIALIZE()``:
.. code:: c
// Allocate the spinlock dynamically
portMUX_TYPE *my_spinlock = malloc(sizeof(portMUX_TYPE));
// Initialize the spinlock dynamically
portMUX_INITIALIZE(my_spinlock);
...
taskENTER_CRITICAL(my_spinlock);
// Access the resource
taskEXIT_CRITICAL(my_spinlock);
Implementation
^^^^^^^^^^^^^^
In IDF FreeRTOS, the process of a particular core entering and exiting a critical section is as follows:
- For ``taskENTER_CRITICAL(&spinlock)`` or ``taskENTER_CRITICAL_ISR(&spinlock)``
#. The core disables its interrupts or interrupt nesting up to ``configMAX_SYSCALL_INTERRUPT_PRIORITY``.
#. The core then spins on the spinlock using an atomic compare-and-set instruction until it acquires the lock. A lock is acquired when the core is able to set the lock's owner value to the core's ID.
#. Once the spinlock is acquired, the function returns. The remainder of the critical section runs with interrupts or interrupt nesting disabled.
- For ``taskEXIT_CRITICAL(&spinlock)`` or ``taskEXIT_CRITICAL_ISR(&spinlock)``
#. The core releases the spinlock by clearing the spinlock's owner value.
#. The core re-enables interrupts or interrupt nesting.
Thread-Safe Port Critical Bypass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``xPortThreadSafeClaim()`` and ``xPortThreadSafeDisclaim()`` (``portmacro.h``) skip port-layer critical enter/exit on the current core. **Thread safety between Claim and Disclaim must be guaranteed by the caller.**
.. warning::
- Caller guarantees thread safety for the ClaimDisclaim window (all cores).
- Claim only with interrupts disabled on the current core; one active claim system-wide; pair with Disclaim on every path.
- ``pdPASS`` from ``xPortEnterCriticalTimeout()`` does not mean ``mux`` was taken.
Not a substitute for ``taskENTER_CRITICAL(&spinlock)``.
Restrictions and Considerations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Given that interrupts (or interrupt nesting) are disabled during a critical section, there are multiple restrictions regarding what can be done within critical sections. During a critical section, users should keep the following restrictions and considerations in mind:
- Critical sections should be kept as short as possible
- The longer the critical section lasts, the longer a pending interrupt can be delayed.
- A typical critical section should only access a few data structures and/or hardware registers.
- If possible, defer as much processing and/or event handling to the outside of critical sections.
- FreeRTOS API should not be called from within a critical section
- Users should never call any blocking or yielding functions within a critical section
.. ------------------------------------------------------ Misc ---------------------------------------------------------
Misc
----
.. only:: SOC_CPU_HAS_FPU
Floating Point Usage
^^^^^^^^^^^^^^^^^^^^
Usually, when a context switch occurs:
- the current state of a core's registers are saved to the stack of the task being switched out
- the previously saved state of the core's registers is loaded from the stack of the task being switched in
However, IDF FreeRTOS implements Lazy Context Switching for the Floating Point Unit (FPU) registers of a core. In other words, when a context switch occurs on a particular core (e.g., Core 0), the state of the core's FPU registers is not immediately saved to the stack of the task getting switched out (e.g., Task A). The FPU registers are left untouched until:
- A different task (e.g., Task B) runs on the same core and uses FPU. This will trigger an exception that saves the FPU registers to Task A's stack.
- Task A gets scheduled to the same core and continues execution. Saving and restoring the FPU registers is not necessary in this case.
However, given that tasks can be unpinned and thus can be scheduled on different cores (e.g., Task A switches to Core 1), it is unfeasible to copy and restore the FPU registers across cores. Therefore, when a task utilizes FPU by using a ``float`` type in its call flow, IDF FreeRTOS will automatically pin the task to the current core it is running on. This ensures that all tasks that use FPU are always pinned to a particular core.
Furthermore, IDF FreeRTOS by default does not support the usage of FPU within an interrupt context given that the FPU register state is tied to a particular task.
.. only:: esp32
.. note::
Users that require the use of the ``float`` type in an ISR routine should refer to the :ref:`CONFIG_FREERTOS_FPU_IN_ISR` configuration option.
.. note::
ESP targets that contain an FPU do not support hardware acceleration for double precision floating point arithmetic (``double``). Instead, ``double`` is implemented via software, hence the behavioral restrictions regarding the ``float`` type do not apply to ``double``. Note that due to the lack of hardware acceleration, ``double`` operations may consume significantly more CPU time in comparison to ``float``.
.. only:: SOC_CPU_HAS_PIE
PIE/AI Coprocessor Usage
^^^^^^^^^^^^^^^^^^^^^^^^
Like the Floating Point Unit (FPU), IDF FreeRTOS implements **Lazy Context Switching** for the PIE coprocessor. On a context switch, PIE registers remain untouched until a task executes a PIE instruction. Once a task uses the PIE coprocessor, it is **pinned to the current core**.
.. only:: esp32s31
.. note::
On ESP32-S31, the PIE coprocessor is available **only on Core 1**. If a task executes a PIE instruction while running on Core 0, IDF FreeRTOS migrates the task to Core 1 and pins it there. This migration **overrides** any existing core affinity.
Because of this migration, tasks must **not** use the PIE coprocessor within a critical section or ISR, as doing so will cause a runtime abort.
.. only:: SOC_CPU_HAS_HWLOOP
Hardware Loop (HWLP) Usage
^^^^^^^^^^^^^^^^^^^^^^^^^^
In IDF FreeRTOS, the Hardware Loop (HWLP) unit is handled differently from other coprocessors: it does **not** use Lazy Context Switching.
When a task uses the HWLP and a context switch occurs, the HWLP registers are saved immediately during the interrupt entry path. Later, if the same task is switched back in, all HWLP registers are restored immediately.
In practice, this means that any task that has ever used the HWLP will always have an additional overhead on both context switch out and switch in.
.. only:: SOC_CPU_HAS_DSP
DSP Coprocessor Usage
^^^^^^^^^^^^^^^^^^^^^
On targets that feature the DSP coprocessor, context switching follows the same lazy scheme as the FPU: the coprocessor state is not saved until another task on the same core uses it or the task is switched to another core. When a task uses the DSP coprocessor, IDF FreeRTOS will automatically **pin the task to the current core** it is running on. The DSP coprocessor must not be used from within an interrupt context.
.. -------------------------------------------------- Single Core -----------------------------------------------------
.. _freertos-idf-single-core:
Single-Core Mode
----------------
Although IDF FreeRTOS is modified for dual-core SMP, IDF FreeRTOS can also be built for single-core by enabling the :ref:`CONFIG_FREERTOS_UNICORE` option.
For single-core targets (such as ESP32-S2 and ESP32-C3), the :ref:`CONFIG_FREERTOS_UNICORE` option is always enabled. For multi-core targets (such as ESP32 and ESP32-S3), :ref:`CONFIG_FREERTOS_UNICORE` can also be set, but will result in the application only running Core 0.
When building in single-core mode, IDF FreeRTOS is designed to be identical to Vanilla FreeRTOS, thus all aforementioned SMP changes to kernel behavior are removed. As a result, building IDF FreeRTOS in single-core mode has the following characteristics:
- All operations performed by the kernel inside critical sections are now deterministic (i.e., no walking of linked lists inside critical sections).
- Vanilla FreeRTOS scheduling algorithm is restored (including perfect Round Robin time slicing).
- All SMP specific data is removed from single-core builds.
SMP APIs can still be called in single-core mode. These APIs remain exposed to allow source code to be built for single-core and multi-core, without needing to call a different set of APIs. However, SMP APIs will not exhibit any SMP behavior in single-core mode, thus becoming equivalent to their single-core counterparts. For example:
- any ``...ForCore(..., BaseType_t xCoreID)`` SMP API will only accept ``0`` as a valid value for ``xCoreID``.
- ``...PinnedToCore()`` task creation APIs will simply ignore the ``xCoreID`` core affinity argument.
- Critical section APIs will still require a spinlock argument, but no spinlock will be taken and critical sections revert to simply disabling/enabling interrupts.
.. ------------------------------------------------- API References ----------------------------------------------------
API Reference
-------------
This section introduces FreeRTOS types, functions, and macros. It is automatically generated from FreeRTOS header files.
Task API
^^^^^^^^
.. include-build-file:: inc/task.inc
Queue API
^^^^^^^^^
.. include-build-file:: inc/queue.inc
Semaphore API
^^^^^^^^^^^^^
.. include-build-file:: inc/semphr.inc
Timer API
^^^^^^^^^
.. include-build-file:: inc/timers.inc
Event Group API
^^^^^^^^^^^^^^^
.. include-build-file:: inc/event_groups.inc
Stream Buffer API
^^^^^^^^^^^^^^^^^
.. include-build-file:: inc/stream_buffer.inc
Message Buffer API
^^^^^^^^^^^^^^^^^^
.. include-build-file:: inc/message_buffer.inc
+813
View File
@@ -0,0 +1,813 @@
Heap Memory Debugging
=====================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
ESP-IDF integrates tools for requesting :ref:`heap information <heap-information>`, :ref:`heap corruption detection <heap-corruption>`, :ref:`kernel address sanitizer (KASAN) <heap-kasan>`, and :ref:`heap tracing <heap-tracing>`. These can help track down memory-related bugs.
For general information about the heap memory allocator, see :doc:`Heap Memory Allocation </api-reference/system/mem_alloc>`.
.. _heap-information:
Heap Information
----------------
To obtain information about the state of the heap, call the following functions:
- :cpp:func:`heap_caps_get_free_size` can be used to return the current free memory for different memory capabilities.
- :cpp:func:`heap_caps_get_largest_free_block` can be used to return the largest free block in the heap, which is also the largest single allocation currently possible. Tracking this value and comparing it to the total free heap allows you to detect heap fragmentation.
- :cpp:func:`heap_caps_get_minimum_free_size` can be used to track the heap "low watermark" across heaps registered during startup. Heaps added at runtime using :cpp:func:`heap_caps_add_region_with_caps` (i.e., from ``app_main`` onwards) are not taken into account.
- :cpp:func:`heap_caps_get_info` returns a :cpp:class:`multi_heap_info_t` structure, which contains the information from the above functions, plus some additional heap-specific data (number of allocations, etc.).
- :cpp:func:`heap_caps_print_heap_info` prints a summary of the information returned by :cpp:func:`heap_caps_get_info` to stdout.
- :cpp:func:`heap_caps_dump` and :cpp:func:`heap_caps_dump_all` output detailed information about the structure of each block in the heap. Note that this can be a large amount of output.
.. _heap-allocation-free:
Heap Allocation and Free Function Hooks
---------------------------------------
Users can use allocation and free detection hooks to be notified of every successful allocation and free operation:
- Providing a definition of :cpp:func:`esp_heap_trace_alloc_hook` allows you to be notified of every successful memory allocation operation.
- Providing a definition of :cpp:func:`esp_heap_trace_free_hook` allows you to be notified of every successful memory-free operations.
This feature can be enabled by setting the :ref:`CONFIG_HEAP_USE_HOOKS` option. :cpp:func:`esp_heap_trace_alloc_hook` and :cpp:func:`esp_heap_trace_free_hook` have weak declarations (e.g., ``__attribute__((weak))``), thus it is not necessary to provide declarations for both hooks. Given that it is technically possible to allocate and free memory from an ISR (**though strongly discouraged from doing so**), the :cpp:func:`esp_heap_trace_alloc_hook` and :cpp:func:`esp_heap_trace_free_hook` can potentially be called from an ISR.
It is not recommended to perform (or call API functions to perform) blocking operations or memory allocation/free operations in the hook functions. In general, the best practice is to keep the implementation concise and leave the heavy computation outside of the hook functions.
The example below shows how to define the allocation and free function hooks:
.. code-block:: c
#include "esp_heap_caps.h"
void esp_heap_trace_alloc_hook(void* ptr, size_t size, uint32_t caps)
{
...
}
void esp_heap_trace_free_hook(void* ptr)
{
...
}
void app_main()
{
...
}
.. _heap-allocation-failed:
Memory Allocation Failed Hook
-----------------------------
Users can use :cpp:func:`heap_caps_register_failed_alloc_callback` to register a callback that is invoked every time an allocation operation fails.
Additionally, users can enable the :ref:`CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS`, which will automatically trigger a system abort if any allocation operation fails.
The example below shows how to register an allocation failure callback:
.. code-block:: c
#include "esp_heap_caps.h"
void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name)
{
printf("%s was called but failed to allocate %d bytes with 0x%X capabilities. \n",function_name, requested_size, caps);
}
void app_main()
{
...
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
...
void *ptr = heap_caps_malloc(allocation_size, MALLOC_CAP_DEFAULT);
...
}
.. _heap-corruption:
Heap Corruption Detection
-------------------------
Heap corruption detection allows you to detect various types of heap memory errors:
- Out-of-bound writes & buffer overflows
- Writes to freed memory
- Reads from freed or uninitialized memory
Three levels of corruption detection are available. Each one providing a finer level of detection than the previous:
.. list::
- `Basic (No Poisoning)`_
- `Light Impact`_
- `Comprehensive`_
Assertions
^^^^^^^^^^
The heap implementation (:component_file:`heap/multi_heap.c`, etc.) includes numerous assertions that will fail if the heap memory is corrupted. To detect heap corruption most effectively, ensure that assertions are enabled in the project configuration via the :ref:`CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL` option.
If a heap integrity assertion fails, a line will be printed like ``CORRUPT HEAP: multi_heap.c:225 detected at 0x3ffbb71c``. The memory address printed is the address of the heap structure that has corrupt content.
It is also possible to manually check heap integrity by calling :cpp:func:`heap_caps_check_integrity_all` or related functions. This function checks all of the requested heap memory for integrity and can be used even if assertions are disabled. If the integrity checks detects an error, it will print the error along with the address(es) of corrupt heap structures.
Finding Heap Corruption
^^^^^^^^^^^^^^^^^^^^^^^
Memory corruption can be one of the hardest classes of bugs to find and fix, as the source of the corruption could be completely unrelated to the symptoms of the corruption. Here are some tips:
- A crash with a ``CORRUPT HEAP:`` message usually includes a stack trace, but this stack trace is rarely useful. The crash is the symptom of memory corruption when the system realizes the heap is corrupt. But usually, the corruption happens elsewhere and earlier in time.
- Increasing the heap memory debugging `Configuration`_ level to "Light impact" or "Comprehensive" gives you a more accurate message with the first corrupt memory address.
- Adding regular calls to :cpp:func:`heap_caps_check_integrity_all` or :cpp:func:`heap_caps_check_integrity_addr` in your code helps you pin down the exact time that the corruption happened. You can move these checks around to "close in on" the section of code that corrupted the heap.
- Based on the memory address that has been corrupted, you can use :ref:`JTAG debugging <jtag-debugging-introduction>` to set a watchpoint on this address and have the CPU halt when it is written to.
- If you do not have JTAG, but you do know roughly when the corruption happens, set a watchpoint in software just beforehand via :cpp:func:`esp_cpu_set_watchpoint`. A fatal exception will occur when the watchpoint triggers. The following is an example of how to use the function - ``esp_cpu_set_watchpoint(0, (void *)addr, 4, ESP_WATCHPOINT_STORE)``. Note that watchpoints are per-CPU and are set on the current running CPU only. So if you do not know which CPU is corrupting memory, call this function on both CPUs.
- For buffer overflows, `heap tracing`_ in ``HEAP_TRACE_ALL`` mode tells which callers are allocating which addresses from the heap. See `Heap Tracing To Find Heap Corruption`_ for more details. You can try to find the function that allocates memory with an address immediately before the corrupted address, since it is probably the function that overflows the buffer.
- Calling :cpp:func:`heap_caps_dump` or :cpp:func:`heap_caps_dump_all` can give an indication of what heap blocks are surrounding the corrupted region and may have overflowed or underflowed, etc.
Configuration
^^^^^^^^^^^^^
Temporarily increasing the heap corruption detection level can give more detailed information about heap corruption errors.
In the project configuration menu, under ``Component config``, there is a menu ``Heap memory debugging``. The option :ref:`CONFIG_HEAP_CORRUPTION_DETECTION` can be set to one of the following three levels:
Basic (No Poisoning)
++++++++++++++++++++
This is the default level. By default, no special heap corruption features are enabled, but the provided assertions are enabled. A heap corruption error will be printed if any of the heap's internal data structures appear overwritten or corrupted. This usually indicates a buffer overrun or out-of-bounds write.
If assertions are enabled, an assertion will also trigger if a double-free occurs (the same memory is freed twice).
Calling :cpp:func:`heap_caps_check_integrity` in Basic mode checks the integrity of all heap structures, and print errors if any appear to be corrupted.
Light Impact
++++++++++++
This level incorporates the "Basic" detection features. Additionally, each block of memory allocated is "poisoned" with head and tail "canary bytes". If an application writes over the "canary bytes", they will be seen as corrupted and integrity checks will fail.
The head canary word is ``0xABBA1234`` (``3412BAAB`` in byte order), and the tail canary word is ``0xBAAD5678`` (``7856ADBA`` in byte order).
With basic heap corruption checks, most out-of-bound writes can be detected and the number of overrun bytes before a failure is detected depends on the properties of the heap. However, the Light Impact mode is more precise as even a single-byte overrun can be detected.
Enabling light-impact checking increases the memory usage since each individual allocation uses additional bytes of metadata.
Each time :cpp:func:`heap_caps_free` is called in Light Impact mode, the head and tail canary bytes of the buffer being freed are checked against the expected values.
When :cpp:func:`heap_caps_check_integrity` or :cpp:func:`heap_caps_check_integrity_all` is called, all allocated blocks of heap memory have their canary bytes checked against the expected values.
In both cases, the functions involve checking that the first 4 bytes of an allocated block (before the buffer is returned to the user) should be the word ``0xABBA1234``, and the last 4 bytes of the allocated block (after the buffer is returned to the user) should be the word ``0xBAAD5678``.
Different values usually indicate buffer underrun or overrun. Overrun indicates that when writing to memory, the data written exceeds the size of the allocated memory, resulting in writing to an unallocated memory area; underrun indicates that when reading memory, the data read exceeds the allocated memory and reads data from an unallocated memory area.
Comprehensive
+++++++++++++
This level incorporates the "Light Impact" detection features. Additionally, it checks for uninitialized-access and use-after-free bugs. In this mode, all freshly allocated memory is filled with the pattern ``0xCE``, and all freed memory is filled with the pattern ``0xFE``.
Enabling Comprehensive mode has a substantial impact on runtime performance, as all memory needs to be set to the allocation patterns each time a :cpp:func:`heap_caps_malloc` or :cpp:func:`heap_caps_free` completes, and the memory also needs to be checked each time. However, this mode allows easier detection of memory corruptions which are much more subtle to find otherwise. It is recommended to only enable this mode when debugging, not in production.
The checks for allocated and free patterns (``0xCE`` and ``0xFE``, respectively) are also done when calling :cpp:func:`heap_caps_check_integrity` or :cpp:func:`heap_caps_check_integrity_all`.
Crashes in Comprehensive Mode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If an application crashes when reading or writing an address related to ``0xCECECECE`` in Comprehensive mode, it indicates that it has read uninitialized memory. The application should be changed to either use :cpp:func:`heap_caps_calloc` (which zeroes memory), or initialize the memory before using it. The value ``0xCECECECE`` may also be seen in stack-allocated automatic variables, because, in ESP-IDF, most task stacks are originally allocated from the heap, and in C, stack memory is uninitialized by default.
If an application crashes, and the exception register dump indicates that some addresses or values were ``0xFEFEFEFE``, this indicates that it is reading heap memory after it has been freed, i.e., a "use-after-free bug". The application should be changed to not access heap memory after it has been freed.
If a call to :cpp:func:`heap_caps_malloc` or :cpp:func:`heap_caps_realloc` causes a crash because it was expected to find the pattern ``0xFEFEFEFE`` in free memory and a different pattern was found, it indicates that the app has a use-after-free bug where it is writing to memory that has already been freed.
Manual Heap Checks in Comprehensive Mode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Calls to :cpp:func:`heap_caps_check_integrity` or :cpp:func:`heap_caps_check_integrity_all` may print errors relating to ``0xFEFEFEFE``, ``0xABBA1234``, or ``0xBAAD5678``. In each case the checker is expected to find a given pattern, and will error out if not found:
- For free heap blocks, the checker expects to find all bytes set to ``0xFE``. Any other values indicate a use-after-free bug where free memory has been incorrectly overwritten.
- For allocated heap blocks, the behavior is the same as for the Light Impact mode. The canary bytes ``0xABBA1234`` and ``0xBAAD5678`` are checked at the head and tail of each allocated buffer, and any variation indicates a buffer overrun or underrun.
.. _heap-kasan:
Kernel Address Sanitizer (KASAN)
--------------------------------
KASAN is a compiler-assisted heap and DRAM memory safety checker. When enabled, GCC instruments memory loads and stores with runtime checks against a shadow memory region. Violations (buffer overflows, underflows, use-after-free, etc.) are reported at the point of access.
Enable it under ``Component config`` > ``Compiler options`` > ``Enable Kernel Address Sanitizer (KASAN)`` (see :ref:`CONFIG_COMPILER_KASAN`). The option is currently marked experimental: turn on ``Make experimental features visible`` (see :ref:`CONFIG_IDF_EXPERIMENTAL_FEATURES`) first.
KASAN is most useful during development and debugging:
- Detects out-of-bounds heap accesses via configurable allocation redzones (see :ref:`CONFIG_KASAN_HEAP_REDZONE_SIZE`)
- Can catch use-after-free when the freed-block quarantine is enabled (see :ref:`CONFIG_KASAN_QUARANTINE_SIZE`)
- Instruments most application and component code; low-level HAL/ROM/bootloader code is excluded automatically
Trade-offs to keep in mind:
- Code size for instrumented components typically grows by 1.53x
- Shadow memory reserves roughly 4264 KiB of internal DRAM (target-dependent)
- Runtime overhead is significant; do not enable in production firmware
KASAN uses its own heap hooks and redzone scheme. Do not enable heap poisoning at the same time — leave :ref:`CONFIG_HEAP_CORRUPTION_DETECTION` at ``Basic (no poisoning)`` (the default).
For deliberate fault injection and regression testing, see the ``kasan_test`` application under ``tools/test_apps/system/kasan_test``.
.. _heap-task-tracking:
Heap Task Tracking
------------------
The Heap Task Tracking can be enabled via the menuconfig: ``Component config`` > ``Heap memory debugging`` > ``Enable heap task tracking`` (see :ref:`CONFIG_HEAP_TASK_TRACKING`).
The feature allows users to track the heap memory usage of each task created since startup and provides a series of statistics that can be accessed via getter functions or simply dumped into the stream of the user's choosing. This feature is useful for identifying memory usage patterns and potential memory leaks.
An additional configuration can be enabled by the user via the menuconfig: ``Component config`` > ``Heap memory debugging`` > ``Keep information about the memory usage of deleted tasks`` (see :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS`) to keep the statistics collected for a given task even after it is deleted.
.. note::
Note that the Heap Task Tracking cannot detect the deletion of statically allocated tasks. Therefore, users will have to keep in mind while reading the following section that statically allocated tasks will always be considered alive in the scope of the Heap Task Tracking feature.
It is important to mention that its usage is strongly discouraged for other purposes than debugging for the following reasons:
.. list::
- Tracking the allocations and storing the resulting statistics for each task requires a non-negligible RAM usage overhead.
- The overall performance of the heap allocator is severely impacted due to the additional processing required for each allocation and free operation.
.. note::
Note that the memory allocated by the heap task tracking feature will not be visible when dumping or accessing the statistics.
Structure of the Statistics And Information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For a given task, the heap task tracking feature categorizes statistics on three different levels:
.. list::
- The task level statistics
- The heap level statistics
- The allocation level statistics
The task level statistics provides the following information:
.. list::
- Name of the given task
- Task handle of the given task
- Status of the given task (if the task is running or deleted)
- Peak memory usage of the given task (the maximum amount of memory used by the given task during the task lifetime)
- Current memory usage of the given task
- Number of heaps in which the task has allocated memory
The heap level statistics provides the following information for each heap used by the given task:
.. list::
- Name of the given heap
- Capabilities of the given heap (without priority)
- Total size of the given heap
- Current usage of the given task on the given heap
- Peak usage of the given task on the given heap
- Number of allocations done by the given task for on the given heap
The allocation level statistics provides the following information for each allocation done by the given task on the given heap:
.. list::
- Address of the given allocation
- Size of the given allocation
Dumping the Statistics And Information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :cpp:func:`heap_caps_print_single_task_stat_overview` API prints an overview of heap usage for a specific task to the provided output stream.
.. code-block:: text
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ task_name │ ALIVE │ 0 │ 7152 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
:cpp:func:`heap_caps_print_all_task_stat_overview` prints an overview of heap usage for all tasks (including the deleted tasks if :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS` is enabled).
.. code-block:: text
┌────────────────────┬─────────┬──────────────────────┬───────────────────┬─────────────────┐
│ TASK │ STATUS │ CURRENT MEMORY USAGE │ PEAK MEMORY USAGE │ TOTAL HEAP USED │
├────────────────────┼─────────┼──────────────────────┼───────────────────┼─────────────────┤
│ task_name │ DELETED │ 11392 │ 11616 │ 1 │
│ other_task_name │ ALIVE │ 0 │ 9408 │ 2 │
│ main │ ALIVE │ 3860 │ 7412 │ 2 │
│ ipc1 │ ALIVE │ 32 │ 44 │ 1 │
│ ipc0 │ ALIVE │ 10080 │ 10092 │ 1 │
│ Pre-scheduler │ ALIVE │ 2236 │ 2236 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
.. note::
Note that the task named "Pre-scheduler" represents allocations that occurred before the scheduler was started. It is not an actual task, so the "status" field (which is shown as "ALIVE") is not meaningful and should be ignored.
Use :cpp:func:`heap_caps_print_single_task_stat` to dump the complete set of statistics for a specific task, or :cpp:func:`heap_caps_print_all_task_stat` to dump statistics for all tasks:
.. code-block:: text
[...]
├ ALIVE: main, CURRENT MEMORY USAGE 308, PEAK MEMORY USAGE 7412, TOTAL HEAP USED 2:
│ ├ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 220 (0%), PEAK 220 (0%), ALLOC COUNT: 2
│ │ ├ ALLOC 0x3fc99024, SIZE 88
│ │ ├ ALLOC 0x3fc99124, SIZE 132
│ └ HEAP: RAM, CAPS: 0x0010580e, SIZE: 22308, USAGE: CURRENT 88 (0%), PEAK 7192 (32%), ALLOC COUNT: 5
│ ├ ALLOC 0x3fce99f8, SIZE 20
│ ├ ALLOC 0x3fce9a10, SIZE 12
│ ├ ALLOC 0x3fce9a20, SIZE 16
│ ├ ALLOC 0x3fce9a34, SIZE 20
│ ├ ALLOC 0x3fce9a4c, SIZE 20
[...]
└ ALIVE: Pre-scheduler, CURRENT MEMORY USAGE 2236, PEAK MEMORY USAGE 2236, TOTAL HEAP USED 1:
└ HEAP: RAM, CAPS: 0x0010580e, SIZE: 344400, USAGE: CURRENT 2236 (0%), PEAK 2236 (0%), ALLOC COUNT: 11
├ ALLOC 0x3fc95cb0, SIZE 164
├ ALLOC 0x3fc95dd8, SIZE 12
├ ALLOC 0x3fc95dfc, SIZE 12
├ ALLOC 0x3fc95e20, SIZE 16
├ ALLOC 0x3fc95e48, SIZE 24
├ ALLOC 0x3fc95e78, SIZE 88
├ ALLOC 0x3fc95ee8, SIZE 88
├ ALLOC 0x3fc95f58, SIZE 88
├ ALLOC 0x3fc95fc8, SIZE 88
├ ALLOC 0x3fc96038, SIZE 1312
├ ALLOC 0x3fc96570, SIZE 344
.. note::
The dump shown above has been truncated (see "[...]") for readability reasons and only displays the statistics and information of the **main** task and the **Pre-scheduler**. The goal here is only to demonstrate the information displayed when calling the :cpp:func:`heap_caps_print_all_task_stat` (resp. :cpp:func:`heap_caps_print_single_task_stat`) API functions.
.. note::
Detailed use of the API functions described in this section can be found in :example:`system/heap_task_tracking/basic`.
Getting the Statistics And Information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:cpp:func:`heap_caps_get_single_task_stat` allows the user to access information of a specific task. The information retrieved by calling this API is identical to the one dumped using :cpp:func:`heap_caps_print_single_task_stat`.
:cpp:func:`heap_caps_get_all_task_stat` allows the user to access an overview of the information of all tasks (including the deleted tasks if :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS` is enabled). The information retrieved by calling this API is identical to the one dumped using :cpp:func:`heap_caps_print_all_task_stat`.
Each getter function requires a pointer to the data structure that will be used by the heap task tracking to gather the statistics and information of a given task (or all tasks). This data structure contains pointers to arrays that the user can allocate statically or dynamically.
The size of the arrays used to store information is difficult to estimate. Examples include the number of allocations per task, the number of heaps used by each task, and the number of tasks created since startup. Therefore, the heap task tracking also provides :cpp:func:`heap_caps_alloc_single_task_stat_arrays` (resp. :cpp:func:`heap_caps_alloc_all_task_stat_arrays`) to dynamically allocate the required amount of memory for those arrays.
Similarly, the heap task tracking also provides :cpp:func:`heap_caps_free_single_task_stat_arrays` (resp. :cpp:func:`heap_caps_free_all_task_stat_arrays`) to free the memory dynamically allocated when calling :cpp:func:`heap_caps_alloc_single_task_stat_arrays` (resp. :cpp:func:`heap_caps_alloc_all_task_stat_arrays`).
.. note::
Detailed use of the API functions described in this section can be found in :example:`system/heap_task_tracking/advanced`.
.. _heap-tracing:
Heap Tracing
------------
Heap Tracing allows the tracing of code which allocates or frees memory. Two tracing modes are supported:
- Standalone. In this mode, traced data are kept on-board, so the size of the gathered information is limited by the buffer assigned for that purpose, and the analysis is done by the on-board code. There are a couple of APIs available for accessing and dumping collected info.
- Host-based. This mode does not have the limitation of the standalone mode, because traced data are sent to the host over JTAG connection using app_trace library. Later on, they can be analyzed using special tools.
Heap tracing can perform two functions:
- Leak checking: find memory that is allocated and never freed.
- Heap use analysis: show all functions that are allocating or freeing memory while the trace is running.
How to Diagnose Memory Leaks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you suspect a memory leak, the first step is to figure out which part of the program is leaking memory. Use the :cpp:func:`heap_caps_get_free_size` or related functions in :ref:`heap information <heap-information>` to track memory use over the life of the application. Try to narrow the leak down to a single function or sequence of functions where free memory always decreases and never recovers.
Standalone Mode
^^^^^^^^^^^^^^^
Once you have identified the code which you think is leaking:
- Enable the :ref:`CONFIG_HEAP_TRACING_DEST` option.
- Call the function :cpp:func:`heap_trace_init_standalone` early in the program, to register a buffer that can be used to record the memory trace.
- Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs or frees in the system. Call this immediately before the piece of code which you suspect is leaking memory.
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing. This state will stop the tracing of both allocations and frees.
- Call the function :cpp:func:`heap_trace_alloc_pause` to pause the tracing of new allocations while continuing to trace the frees. Call this immediately after the piece of code which you suspect is leaking memory to prevent any new allocations to be recorded.
- Call the function :cpp:func:`heap_trace_dump` to dump the results of the heap trace.
The following code snippet demonstrates how application code would typically initialize, start, and stop heap tracing:
.. code-block:: c
#include "esp_heap_trace.h"
#define NUM_RECORDS 100
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
...
void app_main()
{
...
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
...
}
void some_function()
{
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
do_something_you_suspect_is_leaking();
ESP_ERROR_CHECK( heap_trace_stop() );
heap_trace_dump();
...
}
The output from the heap trace has a similar format to the following example:
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
.. code-block:: none
====== Heap Trace: 8 records (8 capacity) ======
3 bytes (@ 0x3fcb26f8, Internal) allocated CPU 0 ccount 0x1e7af728 freed
6 bytes (@ 0x3fcb4ff0, Internal) allocated CPU 0 ccount 0x1e7afc38 freed
9 bytes (@ 0x3fcb5000, Internal) allocated CPU 0 ccount 0x1e7b01d4 freed
12 bytes (@ 0x3fcb5010, Internal) allocated CPU 0 ccount 0x1e7b0778 freed
15 bytes (@ 0x3fcb5020, Internal) allocated CPU 0 ccount 0x1e7b0d18 freed
18 bytes (@ 0x3fcb5034, Internal) allocated CPU 0 ccount 0x1e7b12b8 freed
21 bytes (@ 0x3fcb504c, Internal) allocated CPU 0 ccount 0x1e7b1858 freed
24 bytes (@ 0x3fcb5068, Internal) allocated CPU 0 ccount 0x1e7b1dfc freed
====== Heap Trace Summary ======
Mode: Heap Trace All
0 bytes alive in trace (0/8 allocations)
records: 8 (8 capacity, 8 high water mark)
total allocations: 8
total frees: 8
================================
Or the following example, when the ``CONFIG_ESP_SYSTEM_USE_FRAME_POINTER`` option is enabled and the stack depth is configured properly:
.. code-block:: none
====== Heap Trace: 8 records (8 capacity) ======
6 bytes (@ 0x3fc9f620, Internal) allocated CPU 0 ccount 0x1a31ac84 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
9 bytes (@ 0x3fc9f630, Internal) allocated CPU 0 ccount 0x1a31b618 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
12 bytes (@ 0x3fc9f640, Internal) allocated CPU 0 ccount 0x1a31bfac caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
15 bytes (@ 0x3fc9f650, Internal) allocated CPU 0 ccount 0x1a31c940 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
18 bytes (@ 0x3fc9f664, Internal) allocated CPU 0 ccount 0x1a31d2d4 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
21 bytes (@ 0x3fc9f67c, Internal) allocated CPU 0 ccount 0x1a31dc68 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
24 bytes (@ 0x3fc9f698, Internal) allocated CPU 0 ccount 0x1a31e600 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
freed by 0x403839e4:0x42008096
0x403839e4: free at /path/to/idf/examples/components/newlib/heap.c:40
0x42008096: test_func_74 at /path/to/idf/examples/components/heap/test_apps/heap_tests/main/test_heap_trace.c:104 (discriminator 3)
6 bytes (@ 0x3fc9f6b4, Internal) allocated CPU 0 ccount 0x1a320698 caller 0x40376321:0x40376379
0x40376321: heap_caps_malloc at /path/to/idf/examples/components/heap/heap_caps.c:84
0x40376379: heap_caps_malloc_default at /path/to/idf/examples/components/heap/heap_caps.c:110
====== Heap Trace Summary ======
Mode: Heap Trace All
6 bytes alive in trace (1/8 allocations)
records: 8 (8 capacity, 8 high water mark)
total allocations: 9
total frees: 8
================================
.. note::
The above example output uses :doc:`IDF Monitor </api-guides/tools/idf-monitor>` to automatically decode PC addresses to their source files and line numbers.
``(NB: Internal Buffer has overflowed, so trace data is incomplete.)`` will be logged if the list of records overflow. If you see this log, consider either shortening the tracing period or increasing the number of records in the trace buffer.
``(NB: New entries were traced while dumping, so trace dump may have duplicate entries.)`` will be logged in the summary if new entries are traced while calling :cpp:func:`heap_trace_dump` or :cpp:func:`heap_trace_dump_caps`.
In ``HEAP_TRACE_LEAKS`` or ``HEAP_TRACE_ALL`` mode, for each traced memory allocation that has not already been freed, a line is printed with:
.. list::
- ``XX bytes`` is the number of bytes allocated.
- ``@ 0x...`` is the heap address returned from :cpp:func:`heap_caps_malloc` or :cpp:func:`heap_caps_calloc` .
- ``Internal`` or ``PSRAM`` is the general location of the allocated memory.
- ``CPU x`` is the CPU (0 or 1) running when the allocation was made.
- ``ccount 0x...`` is the CCOUNT (CPU cycle count) register value the allocation was made. The value is different for CPU 0 vs CPU 1.
:CONFIG_IDF_TARGET_ARCH_XTENSA: - ``caller 0x...`` gives the call stack of the call to :cpp:func:`heap_caps_malloc`, as a list of PC addresses. These can be decoded to source files and line numbers, as shown above.
In ``HEAP_TRACE_LEAKS`` mode, when memory is freed, the associated record is dropped.
In ``HEAP_TRACE_ALL``:
.. list::
:CONFIG_IDF_TARGET_ARCH_RISCV: - when memory is freed, the associated record is kept in the list and its field ``freed`` is set to true.
:CONFIG_IDF_TARGET_ARCH_XTENSA: - when memory is freed, the associated record field ``freed by`` is filled with the call stack of the call to :cpp:func:`heap_caps_free`, as a list of PC addresses. These can be decoded to source files and line numbers, as shown above.
- After the maximum number of records is reached, old records are dropped and replaced with new records.
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
The depth of the call stack recorded for each trace entry can be configured in the project configuration menu, under ``Heap Memory Debugging`` > ``Enable heap tracing`` > :ref:`CONFIG_HEAP_TRACING_STACK_DEPTH`. Up to 32 stack frames can be recorded for each allocation (the default is 2). Each additional stack frame increases the memory usage of each ``heap_trace_record_t`` record by eight bytes.
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
By default, the depth of the call stack recorded for each trace entry is 0, which means that only the direct caller of the memory allocation function can be retrieve. However, when the ``CONFIG_ESP_SYSTEM_USE_FRAME_POINTER`` option is enabled, this call stack depth can be configured in the project configuration menu, under ``Heap Memory Debugging`` > ``Enable heap tracing`` > :ref:`CONFIG_HEAP_TRACING_STACK_DEPTH`. Up to 32 stack frames can be recorded for each allocation (the default is 2). Each additional stack frame increases the memory usage of each ``heap_trace_record_t`` record by eight bytes.
Finally, the total number of the 'leaked' bytes (bytes allocated but not freed while the trace is running) is printed together with the total number of allocations it represents.
Using hashmap for increased performance
+++++++++++++++++++++++++++++++++++++++
By default, the heap tracing uses a statically allocated doubly-linked list to store the trace records. This has the disadvantage of causing runtime performance issues as the list gets fuller since the more items are in the list, the more time consuming it is to find a given item. This problem makes the use of the doubly linked list particularly inefficient if the user wishes to store a very large amount of records (to the point where the feature is simply no longer usable as the time it takes to retrieve an item in the list prevents the user application from executing properly).
For this reason, the option to use a hashmap mechanism to store records is available by enabling ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACE_HASH_MAP` in the project configuration menu, allowing users to track significant amounts of records without suffering from drastic performance loss.
Each hashmap entry is a singly linked list of records sharing the same hash ID.
Each record hash ID is calculated based on the pointer to the memory they track. The hash function used is based on the Fowler-Noll-Vo hash function modified to ensure an even spread of all records in the range [0, hashmap size[ where hashmap size can be defined by setting ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` in the project configuration menu.
.. note::
.. list::
- The option :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` defines the number of entries in the hashmap. The total number of records that can be stored is still defined by the user when calling :cpp:func:`heap_trace_init_standalone`. If ``N`` is the maximum number of records and ``H`` the number of entries in the hashmap, Then each entry will contain at max ``N / H`` records.
- The hashmap complements the doubly-linked list and does not replace it. This means that the hashmap usage can create a significant memory overhead.
:SOC_SPIRAM_SUPPORTED: - The memory used to store the hashmap is dynamically allocated (in internal memory by default) but by setting ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM`, the user can force the hashmap in external memory (this option is available under the condition that :ref:`CONFIG_SPIRAM` is enabled).
Host-Based Mode
^^^^^^^^^^^^^^^
Once you have identified the code which you think is leaking:
- In the project configuration menu, navigate to ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` and select ``Host-Based``.
- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` and select ``JTAG``.
- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` and select ``SEGGER SystemView``.
- Call the function :cpp:func:`heap_trace_init_tohost` early in the program, to initialize the JTAG heap tracing module.
- Call the function :cpp:func:`heap_trace_start` to begin recording all memory allocation and free calls in the system. Call this immediately before the piece of code which you suspect is leaking memory.
In host-based mode, the argument to this function is ignored, and the heap tracing module behaves like ``HEAP_TRACE_ALL`` is passed, i.e., all allocations and deallocations are sent to the host.
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing.
The following code snippet demonstrates how application code would typically initialize, start, and stop host-based mode heap tracing:
.. code-block:: c
#include "esp_heap_trace.h"
...
void app_main()
{
...
ESP_ERROR_CHECK( heap_trace_init_tohost() );
...
}
void some_function()
{
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
do_something_you_suspect_is_leaking();
ESP_ERROR_CHECK( heap_trace_stop() );
...
}
To gather and analyze heap trace, do the following on the host:
1. Build the program and download it to the target as described in :ref:`Step 5. First Steps on ESP-IDF <get-started-build>`.
2. Run OpenOCD (see :doc:`JTAG Debugging </api-guides/jtag-debugging/index>`).
.. note::
In order to use this feature, you need OpenOCD version ``v0.10.0-esp32-20181105`` or later.
3. You can use GDB to start and/or stop tracing automatically. To do this you need to prepare a special ``gdbinit`` file:
.. code-block:: c
target remote :3333
mon reset halt
maintenance flush register-cache
tb heap_trace_start
commands
mon esp sysview start file:///tmp/heap.svdat
c
end
tb heap_trace_stop
commands
mon esp sysview stop
end
c
Using this file GDB can connect to the target, reset it, and start tracing when the program hits breakpoint at :cpp:func:`heap_trace_start`. Tracing will be stopped when the program hits breakpoint at :cpp:func:`heap_trace_stop`. Traced data will be saved to ``/tmp/heap_log.svdat``.
4. Run GDB using ``{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb -x gdbinit </path/to/program/elf>``.
5. Quit GDB when the program stops at :cpp:func:`heap_trace_stop`. Traced data are saved in ``/tmp/heap.svdat``.
6. Run processing script ``$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -p -b </path/to/program/elf> /tmp/heap_log.svdat``.
The output from the heap trace has a similar format to the following example:
.. code-block::
Parse trace from '/tmp/heap.svdat'...
Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!)
Process events from '['/tmp/heap.svdat']'...
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.002258425] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.002563725] HEAP: Freed bytes @ 0x3ffaffe0 from task "free" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.002782950] HEAP: Freed bytes @ 0x3ffb40b8 from task "main" on core 0 by:
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
[0.002798700] HEAP: Freed bytes @ 0x3ffb50bc from task "main" on core 0 by:
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.102449800] HEAP: Allocated 4 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.102666150] HEAP: Freed bytes @ 0x3ffaffe8 from task "free" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.202451725] HEAP: Allocated 6 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.202667075] HEAP: Freed bytes @ 0x3ffafff0 from task "free" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.302451475] HEAP: Allocated 8 bytes @ 0x3ffb40b8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.302667500] HEAP: Freed bytes @ 0x3ffb40b8 from task "free" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
Processing completed.
Processed 1019 events
=============== HEAP TRACE REPORT ===============
Processed 14 heap events.
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
Found 10 leaked bytes in 4 blocks.
Heap Tracing To Find Heap Corruption
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Heap tracing can also be used to help track down heap corruption. When a region in the heap is corrupted, it may be from some other part of the program that allocated memory at a nearby address.
If you have an approximate idea of when the corruption occurred, enabling heap tracing in ``HEAP_TRACE_ALL`` mode allows you to record all the memory allocation functions used and the corresponding allocation addresses.
Using heap tracing in this way is very similar to memory leak detection as described above. For memories that are allocated and not freed, the output is the same. However, records will also be shown for memory that has been freed.
Performance Impact
^^^^^^^^^^^^^^^^^^
Enabling heap tracing in menuconfig increases the code size of your program, and has a very small negative impact on the performance of heap allocation or free operations even when heap tracing is not running.
When heap tracing is running, heap allocation or free operations are substantially slower than when heap tracing is stopped. Increasing the depth of stack frames recorded for each allocation (see above) also increases this performance impact.
To mitigate the performance loss when the heap tracing is enabled and active, enable :ref:`CONFIG_HEAP_TRACE_HASH_MAP`. With this configuration enabled, a hash map mechanism will be used to handle the heap trace records, thus considerably decreasing the heap allocation or free execution time. The size of the hash map can be modified by setting the value of :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE`.
.. only:: SOC_SPIRAM_SUPPORTED
By default, the hash map is placed into internal RAM. It can also be placed into external RAM if :ref:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM` is enabled. In order to enable this configuration, make sure to enable :ref:`CONFIG_SPIRAM` and :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`.
False-Positive Memory Leaks
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Not everything printed by :cpp:func:`heap_trace_dump` is necessarily a memory leak. The following cases may also be printed:
- Any memory that is allocated after :cpp:func:`heap_trace_start` but freed after :cpp:func:`heap_trace_stop` appears in the leaked dump.
- Allocations may be made by other tasks in the system. Depending on the timing of these tasks, it is quite possible that this memory is freed after :cpp:func:`heap_trace_stop` is called.
- The first time a task uses stdio - e.g., when it calls :cpp:func:`heap_caps_printf` - a lock, i.e., RTOS mutex semaphore, is allocated by the libc. This allocation lasts until the task is deleted.
- Certain uses of :cpp:func:`heap_caps_printf`, such as printing floating point numbers and allocating some memory from the heap on demand. These allocations last until the task is deleted.
- The Bluetooth, Wi-Fi, and TCP/IP libraries allocate heap memory buffers to handle incoming or outgoing data. These memory buffers are usually short-lived, but some may be shown in the heap leak trace if the data has been received or transmitted by the lower levels of the network during the heap tracing.
- TCP connections retain some memory even after they are closed due to the ``TIME_WAIT`` state. Once the ``TIME_WAIT`` period is completed, this memory will be freed.
One way to differentiate between "real" and "false positive" memory leaks is to call the suspect code multiple times while tracing is running, and look for patterns (multiple matching allocations) in the heap trace output.
Application Examples
--------------------
- :example:`system/heap_task_tracking/basic` demonstrates the use of the overview feature of the heap task tracking, dumping per-task summary statistics on heap memory usage.
- :example:`system/heap_task_tracking/advanced` demonstrates the use of the statistics getter functions of the heap task tracking, accessing per-task complete statistic on the heap memory usage.
API ReferenceHeap Task Tracking
----------------------------------
.. include-build-file:: inc/esp_heap_task_info.inc
API ReferenceHeap Tracing
----------------------------
.. include-build-file:: inc/esp_heap_trace.inc
+28
View File
@@ -0,0 +1,28 @@
Himem
=====
:link_to_translation:`zh_CN:[中文]`
Overview
--------
For external memories that are <= 4 MiB, the MMU is configured to use a "unity mapping", meaning that each CPU address is mapped 1-to-1 to the external SPI RAM address, thus allowing external memory to be accessed transparently. However, because the address space for external memory is limited to 4 MiB, only SPI RAM chips that are <= 4 MiB in size can be used fully transparently.
It is still possible for ESP32 to use SPI RAM chips >= 4 MiB in size. However, the memory on these chips needs to be accessed using a bank switching scheme. ESP-IDF provides the **Himem API** to control this bank switching. More specifically, the Himem API allows particular 32 K banks within 4 MiB address switch mappings at run time, thus allowing access to more than 4 MiB of external memory.
Usage
-----
In order to use the Himem API, you have to enable it in the menuconfig using :ref:`CONFIG_SPIRAM_BANKSWITCH_ENABLE`, as well as set the amount of banks reserved for this in :ref:`CONFIG_SPIRAM_BANKSWITCH_RESERVE`. This decreases the amount of external memory allocated by functions like ``malloc()``, but it allows you to use the Himem API to map any of the remaining memory into the reserved banks.
The Himem API is more-or-less an abstraction of the bank switching scheme: it allows you to claim one or more banks of address space (called 'regions' in the API) as well as one or more of banks of memory to map into the ranges.
Application Examples
--------------------
- :example:`system/himem` demonstrates how to use the Himem API on {IDF_TARGET_NAME} to run a memory test of the upper 4 MiB of an 8 MiB PSRAM chip, illustrating how to allocate address space, allocate the physical memory, and switch it in or out of the allocated address space.
API Reference
-------------
.. include-build-file:: inc/himem.inc
@@ -0,0 +1,84 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
OCODE (BLOCK2) OCode = 78 R/W (0b1001110)
TEMP_CALIB (BLOCK2) Temperature calibration data = -7.4 R/W (0b101001010)
ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 28 R/W (0x07)
ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = 0 R/W (0b10000)
ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = -44 R/W (0x8b)
ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = 16 R/W (0b000100)
DIG_DBIAS_HVT (BLOCK2) BLOCK2 digital dbias when hvt = -16 R/W (0b10100)
DIG_LDO_SLP_DBIAS2 (BLOCK2) BLOCK2 DIG_LDO_DBG0_DBIAS2 = -8 R/W (0b1000010)
DIG_LDO_SLP_DBIAS26 (BLOCK2) BLOCK2 DIG_LDO_DBG0_DBIAS26 = 24 R/W (0x06)
DIG_LDO_ACT_DBIAS26 (BLOCK2) BLOCK2 DIG_LDO_ACT_DBIAS26 = 16 R/W (0b000100)
DIG_LDO_ACT_STEPD10 (BLOCK2) BLOCK2 DIG_LDO_ACT_STEPD10 = 12 R/W (0x3)
RTC_LDO_SLP_DBIAS13 (BLOCK2) BLOCK2 DIG_LDO_SLP_DBIAS13 = 88 R/W (0b0010110)
RTC_LDO_SLP_DBIAS29 (BLOCK2) BLOCK2 DIG_LDO_SLP_DBIAS29 = 96 R/W (0b000011000)
RTC_LDO_SLP_DBIAS31 (BLOCK2) BLOCK2 DIG_LDO_SLP_DBIAS31 = 4 R/W (0b000001)
RTC_LDO_ACT_DBIAS31 (BLOCK2) BLOCK2 DIG_LDO_ACT_DBIAS31 = 24 R/W (0b000110)
RTC_LDO_ACT_DBIAS13 (BLOCK2) BLOCK2 DIG_LDO_ACT_DBIAS13 = 72 R/W (0x12)
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00)
RD_DIS (BLOCK0) Disable reading from BlOCK3 = 0 R/W (0b00)
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
DIS_DIRECT_BOOT (BLOCK0) This bit set means disable direct_boot mode = False R/W (0b0)
Flash fuses:
FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0)
mmand during SPI boot
FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0)
nit of ms. If the value is less than 15; the waiti
ng time is the configurable value. Otherwise; the
waiting time is twice the configurable value
Identity fuses:
DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0)
WAFER_VERSION_MINOR (BLOCK2) WAFER_VERSION_MINOR = 2 R/W (0x2)
WAFER_VERSION_MAJOR (BLOCK2) WAFER_VERSION_MAJOR = 1 R/W (0b01)
PKG_VERSION (BLOCK2) EFUSE_PKG_VERSION = 1 R/W (0b001)
BLK_VERSION_MINOR (BLOCK2) Minor version of BLOCK2 = With calib R/W (0b001)
BLK_VERSION_MAJOR (BLOCK2) Major version of BLOCK2 = 0 R/W (0b00)
Jtag fuses:
DIS_PAD_JTAG (BLOCK0) Set this bit to disable pad jtag = False R/W (0b0)
Mac fuses:
CUSTOM_MAC_USED (BLOCK0) True if MAC_CUSTOM is burned = False R/W (0b0)
CUSTOM_MAC (BLOCK1) Custom MAC address
= 00:00:00:00:00:00 (OK) R/W
MAC (BLOCK2) MAC address
= 08:3a:8d:5c:4b:94 (OK) R/W
Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0) The bit be set to disable icache in download mode = False R/W (0b0)
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) The bit be set to disable manual encryption = False R/W (0b0)
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
XTS_KEY_LENGTH_256 (BLOCK0) Flash encryption key length = 128 bits key R/W (0b0)
DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0)
:0] = 0; 1; 2; 4; 5; 6; 7)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0)
SECURE_BOOT_EN (BLOCK0) The bit be set to enable secure boot = False R/W (0b0)
SECURE_VERSION (BLOCK0) Secure version for anti-rollback = 0 R/W (0x0)
BLOCK_KEY0 (BLOCK3) BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryp
= 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
tion
BLOCK_KEY0_LOW_128 (BLOCK3) BLOCK_KEY0 - lower 128-bits. 128-bit key of Flash
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Encryption
BLOCK_KEY0_HI_128 (BLOCK3) BLOCK_KEY0 - higher 128-bits. 128-bits key of Secu
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
re Boot
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00)
ock cycle
@@ -0,0 +1,18 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32c2"...
espefuse v5.0.2
Connecting...
=== Run "dump" command ===
BLOCK0 (BLOCK0 ) [0 ] read_regs: 00000000 00000000
BLOCK1 (BLOCK1 ) [1 ] read_regs: 00000000 00000000 00000000
BLOCK2 (BLOCK2 ) [2 ] read_regs: 8d5c4b94 8252083a 5c01e953 80d0a824 c0860b18 00006890 00000000 4b000000
BLOCK_KEY0 (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 (BLOCK0 ) [0 ] err__regs: 00000000 00000000
EFUSE_RD_RS_ERR_REG 0x00000000
@@ -0,0 +1,153 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = -36 R/W (0b1001001)
K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = -64 R/W (0b1010000)
V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = -40 R/W (0x8a)
V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = -76 R/W (0x93)
DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = -28 R/W (0b10111)
THRES_HVT (BLOCK1) BLOCK1 pvt threshold when hvt = 2000 R/W (0b0111110100)
TEMP_CALIB (BLOCK2) Temperature calibration data = -7.2 R/W (0b101001000)
OCODE (BLOCK2) ADC OCode = 78 R/W (0x4e)
ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 1560 R/W (0b0110000110)
ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = -108 R/W (0b1000011011)
ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = -232 R/W (0b1000111010)
ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = -696 R/W (0b1010101110)
ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = -212 R/W (0b1000110101)
ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = 52 R/W (0b0000001101)
ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = -152 R/W (0b1000100110)
ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = -284 R/W (0b1001000111)
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0)
DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0)
DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = False R/W (0b0)
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
ERR_RST_ENABLE (BLOCK0) Use BLOCK0 to check error record registers = with check R/W (0b1)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0)
nit of ms. If the value is less than 15; the waiti
ng time is the configurable value; Otherwise; the
waiting time is twice the configurable value
FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0)
mmand during SPI boot
Identity fuses:
DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0)
WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 3 R/W (0b011)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 2 R/W (0b010)
WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0)
WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 25 60 04 96 c3 fd 41 6f be ed 2c 51 1d e3 7e 21 R/W
BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = With calibration R/W (0b01)
WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 3 R/W (0x3)
<< 3 + WAFER_VERSION_MINOR_LO (read only)
Jtag fuses:
SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000)
d number 1 means disable ). JTAG can be enabled in
HMAC module
DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = False R/W (0b0)
is disabled permanently
Mac fuses:
MAC (BLOCK1) MAC address
= 58:cf:79:0f:96:8c (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC address
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = False R/W (0b0)
oot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0)
hip into download mode
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in = False R/W (0b0)
download boot modes
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0)
SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0)
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0)
boot
DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0)
:0] = 0; 1; 2; 3; 6; 7)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0)
SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback = 0 R/W (0x0000)
feature)
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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_CLK (BLOCK1) SPI PAD CLK = 0 R/W (0b000000)
SPI_PAD_CONFIG_Q (BLOCK1) SPI PAD Q(D1) = 0 R/W (0b000000)
SPI_PAD_CONFIG_D (BLOCK1) SPI PAD D(D0) = 0 R/W (0b000000)
SPI_PAD_CONFIG_CS (BLOCK1) SPI PAD CS = 0 R/W (0b000000)
SPI_PAD_CONFIG_HD (BLOCK1) SPI PAD HD(D3) = 0 R/W (0b000000)
SPI_PAD_CONFIG_WP (BLOCK1) SPI PAD WP(D2) = 0 R/W (0b000000)
SPI_PAD_CONFIG_DQS (BLOCK1) SPI PAD DQS = 0 R/W (0b000000)
SPI_PAD_CONFIG_D4 (BLOCK1) SPI PAD D4 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D5 (BLOCK1) SPI PAD D5 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D6 (BLOCK1) SPI PAD D6 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D7 (BLOCK1) SPI PAD D7 = 0 R/W (0b000000)
Usb fuses:
DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = False R/W (0b0)
jtag in module of usb device
DIS_USB_SERIAL_JTAG (BLOCK0) USB-Serial-JTAG = Enable R/W (0b0)
USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0)
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0)
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disable UART download mode through USB-Serial-JTAG = False R/W (0b0)
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Set this bit to vdd spi pin function as gpio = False R/W (0b0)
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00)
ock cycle
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32c3"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 80000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: 790f968c 000058cf 00000000 020c0000 715424e0 0047d2f2
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 96046025 6f41fdc3 512cedbe 217ee31d d864ea41 5aba3a86 1e260363 00000009
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,178 @@
.. code-block:: none
idf.py -p PORT efuse-summary
Executing action: efuse-summary
(...)
=== Run "summary" command ===
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled.\ = False R/W (0b0)
\ 1: disabled\\ 0: enabled\\
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled.\\ 1: disabled\\ 0: enabled\\
KM_DISABLE_DEPLOY_MODE (BLOCK0) Represents whether the deploy mode of key manager = 0 R/W (0x0)
is disable or not. \\ 1: disabled \\ 0: enabled.\\
KM_RND_SWITCH_CYCLE (BLOCK0) Set the bits to control key manager random number = 0 R/W (0b00)
switch cycle. 0: control by register. 1: 8 km clk
cycles. 2: 16 km cycles. 3: 32 km cycles
KM_DEPLOY_ONLY_ONCE (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0)
can only be deployed once. 1 is true; 0 is false.
bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled.\\ 1: disabled\\ 0: enabled
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
HYS_EN_PAD (BLOCK0) Represents whether the hysteresis function of = False R/W (0b0)
corresponding PAD is enabled.\\ 1: enabled\\ 0:disabled
HUK_GEN_STATE (BLOCK0) Set the bits to control validation of HUK generate = 0 R/W (0b000000000)
mode.\\ Odd of 1 is invalid.\\ Even of 1 is valid
XTAL_48M_SEL (BLOCK0) Represents whether XTAL frequency is 48MHz or not. = 0 R/W (0b000)
If not; 40MHz XTAL will be used. If this field co
ntains Odd number bit 1: Enable 48MHz XTAL\ Even n
umber bit 1: Enable 40MHz XTAL
XTAL_48M_SEL_MODE (BLOCK0) Specify the XTAL frequency selection is decided by = False R/W (0b0)
eFuse or strapping-PAD-state. 1: eFuse\\ 0: strap
ping-PAD-state
ECC_FORCE_CONST_TIME (BLOCK0) Represents whether to force ecc to use const-time = False R/W (0b0)
calculation mode. \\ 1: Enable. \\ 0: Disable
BLOCK_SYS_DATA1 (BLOCK2) System data part 1 (reserved)
= 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
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot.\\ 1: forced\\ 0:not
forced\\
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled.\\ 1: enabled\\
0: disabled\\
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way.\\ = 0 R/W (0b000)
Odd number: disabled\\ Even number: enabled\\
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently).\\ 1: disabled\\ 0: enabled\\
Mac fuses:
MAC (BLOCK1) MAC address
= 00:00:00:00:00:00 (OK) R/W
MAC_EXT (BLOCK1) Represents the extended bits of MAC address = 00:00 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
MAC_EUI64 (BLOCK1) calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:M
= 00:00:00:00:00:00:00:00 (OK) R/W
AC_EXT[1]:MAC[3]:MAC[4]:MAC[5]
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled.\\ 1: dis
abled\\ 0: enabled\\
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0)
e_download is disabled or enabled.\\ 1: disabled\\
0: enabled\\
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode).\\ 1: disa
bled\\ 0: enabled\\
FORCE_USE_KEY_MANAGER_KEY (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0)
must come from key manager. 1 is true; 0 is false.
bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds
FORCE_DISABLE_SW_INIT_KEY (BLOCK0) Set this bit to disable software written init key; = False R/W (0b0)
and force use efuse_init_key
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led.\\ 1: enabled\\ 0: disabled\\
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled.\\ 1: enabled.\\ 0: disabled
KM_XTS_KEY_LENGTH_256 (BLOCK0) Set this bitto configure flash encryption use xts- = False R/W (0b0)
128 key. else use xts-256 key
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled.\\ 1: disabled\\ 0: enabled\\
LOCK_KM_KEY (BLOCK0) Represetns whether to lock the efuse xts key.\\ 1. = False R/W (0b0)
Lock\\ 0: Unlock\\
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled.\\ 1: enabled\\ 0: disabled\\
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled.\\ 1: disa
bled\\ 0: enabled\\
XTS_DPA_PSEUDO_LEVEL (BLOCK0) Represents the pseudo round level of xts-aes anti- = 0 R/W (0b00)
dpa attack.\\ 3: High.\\ 2: Moderate 1. Low\\ 0: D
isabled\\
XTS_DPA_CLK_ENABLE (BLOCK0) Represents whether xts-aes anti-dpa attack clock i = False R/W (0b0)
s enabled.\\ 1. Enable.\\ 0: Disable.\\
ECDSA_DISABLE_P192 (BLOCK0) Represents whether to disable P192 curve in ECDSA. = False R/W (0b0)
\\ 1: Disabled.\\ 0: Not disable
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled.\\ 1: disabled\\ 0: ena
bled\\
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0)
.\\ 1: exchanged\\ 0: not exchanged\\
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled.\\ 1: disabled\\ 0: enabled\\
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled.\\ 1: Disable\\ 0: E
nable\\
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0)
io.\\ 1: functioned\\ 0: not functioned\\
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents the threshold level of the RTC watchdog = 0 R/W (0b00)
STG0 timeout.\\ 0: Original threshold configurati
on value of STG0 *2 \\1: Original threshold config
uration value of STG0 *4 \\2: Original threshold c
onfiguration value of STG0 *8 \\3: Original thresh
old configuration value of STG0 *16 \\
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32c5"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: f9f95440 fffe6055 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,154 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
SWAP_UART_SDIO_EN (BLOCK0) Represents whether pad of uart and sdio is swapped = False R/W (0b0)
or not. 1: swapped. 0: not swapped
DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled. = False R/W (0b0)
1: disabled. 0: enabled
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot. 1: forced. 0:not for
ced
FLASH_CAP (BLOCK1) = 0 R/W (0b000)
FLASH_TEMP (BLOCK1) = 0 R/W (0b00)
FLASH_VENDOR (BLOCK1) = 0 R/W (0b000)
Identity fuses:
DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0)
WAFER_VERSION_MINOR (BLOCK1) = 1 R/W (0x1)
WAFER_VERSION_MAJOR (BLOCK1) = 0 R/W (0b00)
PKG_VERSION (BLOCK1) Package version = 1 R/W (0b001)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled. 1: enabled. 0:
disabled
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000)
dd number: disabled. Even number: enabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled. 0: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 60:55:f9:f7:52:9c (OK) R/W
MAC_EXT (BLOCK1) Stores the extended bits of MAC address = 00:00 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0) Represents whether icache is disabled or enabled i = False R/W (0b0)
n Download mode. 1: disabled. 0: enabled
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led. 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0)
e_download is disabled or enabled. 1: disabled. 0:
enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disable
ed. 0: enabled
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0)
nabled. 0: disabled
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled. 1: disable
ed. 0: enabled
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled. 0: enable
d
DIS_USB_SERIAL_JTAG (BLOCK0) Represents whether USB-Serial-JTAG is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0)
. 1: exchanged. 0: not exchanged
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: disabled. 0: ena
bled
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0)
io. 1: functioned. 0: not functioned
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00)
is selected at startup. 1: selected. 0: not select
ed
@@ -0,0 +1,164 @@
.. code-block:: none
idf.py -p /dev/ttyUSB0 efuse-summary
Executing action: efuse-summary
(...)
=== Run "summary" command ===
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Represents whether cache is disabled. 1: Disabled = False R/W (0b0)
0: Enabled.
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1. Disable 0: Enable
UART_PRINT_CONTROL (BLOCK0) Represents the types of UART printing = 0 R/W (0b00)
HYS_EN_PAD (BLOCK0) Set bits to enable hysteresis function of PAD0~27 = False R/W (0b0)
DIS_WIFI6 (BLOCK0) Represents whether the WIFI6 feature is enable or = False R/W (0b0)
disabled. 1: WIFI6 is disable; 0: WIFI6 is enabled
ECC_FORCE_CONST_TIME (BLOCK0) Represents whether to force ecc to use const-time = False R/W (0b0)
calculation mode. 1: Enable. 0: Disable
BOOTLOADER_ANTI_ROLLBACK_EN (BLOCK0) Represents whether the ani-rollback check for the = False R/W (0b0)
2nd stage bootloader is enabled.1: Enabled0: Disab
led
BOOTLOADER_ANTI_ROLLBACK_UPDATE_IN_ROM (BLOCK0) Represents whether the ani-rollback SECURE_VERSION = False R/W (0b0)
will be updated from the ROM bootloader.1: Enable
0: Disable
REPEAT_DATA4 (BLOCK0) Reserved = 0 R/W (0x000000)
PSRAM_CAP (BLOCK1) PSRAM capacity = 0 R/W (0b000)
PSRAM_VENDOR (BLOCK1) PSRAM vendor = 0 R/W (0b00)
TEMP (BLOCK1) Temperature = 0 R/W (0b00)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is programmed value. Otherwise; the wai
ting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot
RECOVERY_BOOTLOADER_FLASH_SECTOR (BLOCK0) Represents the starting flash sector (flash sector = 1008 R/W (0x3f0)
size is 0x1000) of the recovery bootloader used b
y the ROM bootloader If the primary bootloader fai
ls. 0 and 0xFFF - this feature is disabled
FLASH_CAP (BLOCK1) Flash capacity = 0 R/W (0b000)
FLASH_VENDOR (BLOCK1) Flash vendor = 0 R/W (0b000)
Identity fuses:
WAFER_VERSION_MINOR (BLOCK1) Minor chip version = 0 R/W (0x0)
WAFER_VERSION_MAJOR (BLOCK1) Major chip version = 1 R/W (0b01)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK1) Disables check of blk version major = False R/W (0b0)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled. 1: enabled 0: d
isabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled 0: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 30:ed:a0:e5:25:20 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0)
e_download is disabled or enabled. 1: disabled 0:
enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disabled
0: enabled
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1. Enable 0: Disable
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1. Enable 0: Disable
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disable or ena = False R/W (0b0)
ble. 1. Disable 0: Enable
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: Enable 0: Disable
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST_VERIFY_ON_WAKE is disable = False R/W (0b0)
or enable when Secure Boot is enable
XTS_DPA_CLK_ENABLE (BLOCK0) Represents whether xts-aes anti-dpa attack clock i = False R/W (0b0)
s enabled. 1. Enable. 0: Disable.
XTS_DPA_PSEUDO_LEVEL (BLOCK0) Represents the pseudo round level of xts-aes anti- = 0 R/W (0b00)
dpa attack. 3: High. 2: Moderate 1. Low 0: Disabled
ECDSA_DISABLE_P192 (BLOCK0) Represents whether to disable P192 curve in ECDSA. = False R/W (0b0)
1: Disabled. 0: Not disabled
BOOTLOADER_ANTI_ROLLBACK_SECURE_VERSION (BLOCK0) Represents the anti-rollback secure version of the = 0 R/W (0x0)
2nd stage bootloader used by the ROM bootloader
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled 0: enabled
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins of USB_SERIA = False R/W (0b0)
L_JTAG PHY is exchanged. 1: exchanged 0: not excha
nged
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled. 1. Disable 0: Enable
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: Disable 0: Enable
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0)
io. 1: functioned 0: not functioned
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) lp wdt timeout threshold at startup = initial time = 0 R/W (0b00)
out value * (2 ^ (EFUSE_WDT_DELAY_SEL + 1))
@@ -0,0 +1,22 @@
.. code-block:: none
idf.py -p /dev/ttyUSB0 efuse-dump
espefuse v5.0.2
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32c61"...
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] dump: 00000000 00000000 00000000 00000000 0000fc00 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] dump: a0e52520 000030ed 00000010 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32c6"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: f9f7529c 00006055 00000000 01040000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,154 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled. = False R/W (0b0)
1: disabled. 0: enabled
POWERGLITCH_EN (BLOCK0) Represents whether power glitch function is enable = False R/W (0b0)
d. 1: enabled. 0: disabled
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
HYS_EN_PAD0 (BLOCK0) Set bits to enable hysteresis function of PAD0~5 = 0 R/W (0b000000)
HYS_EN_PAD1 (BLOCK0) Set bits to enable hysteresis function of PAD6~27 = 0 R/W (0b0000000000000000000000)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot. 1: forced. 0:not for
ced
FLASH_CAP (BLOCK1) = 0 R/W (0b000)
FLASH_TEMP (BLOCK1) = 0 R/W (0b00)
FLASH_VENDOR (BLOCK1) = 0 R/W (0b000)
Identity fuses:
WAFER_VERSION_MINOR (BLOCK1) = 0 R/W (0b000)
WAFER_VERSION_MAJOR (BLOCK1) = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK_VERSION_MINOR (BLOCK2) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
DISABLE_BLK_VERSION_MAJOR (BLOCK2) Disables check of blk version major = False R/W (0b0)
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Set this bit to enable selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio25 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000)
dd number: disabled. Even number: enabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled. 0: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 60:55:f9:f7:2c:a2:ff:fe (OK) R/W
MAC_EXT (BLOCK1) Stores the extended bits of MAC address = ff:fe (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00:ff:fe (OK) R/W
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led. 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0)
e_download is disabled or enabled. 1: disabled. 0:
enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disable
ed. 0: enabled
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
ECDSA_FORCE_USE_HARDWARE_K (BLOCK0) Represents whether hardware random number k is for = False R/W (0b0)
ced used in ESDCA. 1: force used. 0: not force use
d
CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0)
nabled. 0: disabled
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled. 1: disable
ed. 0: enabled
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled. 0: enable
d
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0)
. 1: exchanged. 0: not exchanged
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Set this bit to disable USB-Serial-JTAG print duri = False R/W (0b0)
ng rom boot
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: disabled. 0: ena
bled
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0)
io. 1: functioned. 0: not functioned
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00)
is selected at startup. 1: selected. 0: not select
ed
@@ -0,0 +1,164 @@
.. code-block:: none
idf.py -p PORT efuse-summary
Executing action: efuse-summary
(...)
=== Run "summary" command ===
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled. = False R/W (0b0)
1: disabled. 0: enabled
POWERGLITCH_EN (BLOCK0) Represents whether power glitch function is = False R/W (0b0)
enabled. 1: enabled. 0: disabled
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
RPT4_RESERVED0_2 (BLOCK0) Reserved = 0 R/W (0b00)
RPT4_RESERVED0_1 (BLOCK0) Reserved = False R/W (0b0)
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00)
HYS_EN_PAD0 (BLOCK0) Set bits to enable hysteresis function of PAD0~5 = 0 R/W (0b000000)
HYS_EN_PAD1 (BLOCK0) Set bits to enable hysteresis function of PAD6~27 = 0 R/W (0b0000000000000000000000)
RXIQ_0 (BLOCK1) Stores RF Calibration data. RXIQ data 0 = 0 R/W (0b0000000)
RXIQ_1 (BLOCK1) Stores RF Calibration data. RXIQ data 1 = 0 R/W (0b0000000)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the
waiting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a = False R/W (0b0)
resume command during SPI boot. 1: forced. 0:not
forced
FLASH_CAP (BLOCK1) Stores the flash cap = 0 R/W (0b000)
FLASH_TEMP (BLOCK1) Stores the flash temp = 0 R/W (0b00)
FLASH_VENDOR (BLOCK1) Stores the flash vendor = 0 R/W (0b000)
Identity fuses:
RXIQ_VERSION (BLOCK1) Stores RF Calibration data. RXIQ version = 0 R/W (0b000)
WAFER_VERSION_MINOR (BLOCK1) Stores the wafer version minor = 0 R/W (0b000)
WAFER_VERSION_MAJOR (BLOCK1) Stores the wafer version major = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK_VERSION_MINOR (BLOCK2) BLK_VERSION_MINOR of BLOCK2. 1: RF Calibration = 0 R/W (0b000)
data in BLOCK1
BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
DISABLE_BLK_VERSION_MAJOR (BLOCK2) Disables check of blk version major = False R/W (0b0)
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Set this bit to enable selection between = False R/W (0b0)
usb_to_jtag and pad_to_jtag through strapping
gpio25 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. = 0 R/W (0b000)
Odd number: disabled. Even number: enabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the = False R/W (0b0)
hard way(permanently). 1: disabled. 0: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 00:00:00:00:00:00 (OK) R/W
MAC_EXT (BLOCK1) Stores the extended bits of MAC address = 00:00 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
MAC_EUI64 (BLOCK1) calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:M
= 00:00:00:00:00:00:00:00 (OK) R/W
AC_EXT[1]:MAC[3]:MAC[4]:MAC[5]
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip = False R/W (0b0)
into download mode is disabled or enabled. 1:
disabled. 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during = False R/W (0b0)
boot_mode_download is disabled or enabled. 1: disabled. 0:
enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is = False R/W (0b0)
disabled or enabled(except in SPI boot mode). 1:
disabled. 0: enabled
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
ECDSA_FORCE_USE_HARDWARE_K (BLOCK0) Represents whether hardware random number k is = False R/W (0b0)
forced used in ESDCA. 1: force used. 0: not force
used
CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. = False R/W (0b0)
1:enabled. 0: disabled
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF = 0 R/W (0x0000)
anti-rollback feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled. 1:
disabled. 0: enabled
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to = False R/W (0b0)
jtag is disabled or enabled. 1: disabled. 0:
enabled
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0)
1: exchanged. 0: not exchanged
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Set this bit to disable USB-Serial-JTAG print = False R/W (0b0)
during rom boot
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download = False R/W (0b0)
function is disabled or enabled. 1: disabled. 0:
enabled
Vdd fuses:
VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as = False R/W (0b0)
gpio. 1: functioned. 0: not functioned
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00)
is selected at startup. 1: selected. 0: not
selected
@@ -0,0 +1,21 @@
.. code-block:: none
idf.py -p PORT efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32h21"...
espefuse v5.3.dev3
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32h2"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: f9f72ca2 fffe6055 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,248 @@
.. code-block:: none
idf.py -p PORT efuse-summary
Executing action: efuse-summary
(...)
=== Run "summary" command ===
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled. 1: disabled 0: enabled
PVT_GLITCH_EN (BLOCK0) Represents whether to enable PVT power glitch moni = False R/W (0b0)
tor function.1:Enable. 0:Disable
PVT_GLITCH_MODE (BLOCK0) Use to configure glitch mode = 0 R/W (0b00)
DIS_CORE1 (BLOCK0) Represents whether the CPU-Core1 is disabled. 1: = False R/W (0b0)
Disabled. 0: Not disable
ECC_FORCE_CONST_TIME (BLOCK0) Represents whether to force ecc to use const-time = False R/W (0b0)
calculation mode. 1: Enable. 0: Disable
KM_DISABLE_DEPLOY_MODE (BLOCK0) Represents whether the new key deployment of key m = 0 R/W (0b00000)
anager is disabled. Bit0: Represents whether the n
ew ECDSA key deployment is disabled0: Enabled1: Di
sabledBit1: Represents whether the new XTS-AES (fl
ash and PSRAM) key deployment is disabled0: Enable
d1: DisabledBit2: Represents whether the new HMAC
key deployment is disabled0: Enabled1: DisabledBit
3: Represents whether the new DS key deployment is
disabled0: Enabled1: Disabled
KM_RND_SWITCH_CYCLE (BLOCK0) Represents the cycle at which the Key Manager swit = 0 R/W (0b00)
ches random numbers.0: Controlled by the \hyperref
[fielddesc:KEYMNGRNDSWITCHCYCLE]{KEYMNG\_RND\_SWIT
CH\_CYCLE} register. For more information; please
refer to Chapter \ref{mod:keymng} \textit{\nameref
{mod:keymng}}1: 8 Key Manager clock cycles2: 16 Ke
y Manager clock cycles3: 32 Key Manager clock cycl
es
KM_DEPLOY_ONLY_ONCE (BLOCK0) Represents whether the corresponding key can be de = 0 R/W (0b00000)
ployed only once.Bit0: Represents whether the ECDS
A key can be deployed only once0: The key can be d
eployed multiple times1: The key can be deployed o
nly onceBit1: Represents whether the XTS-AES (flas
h and PSRAM) key can be deployed only once0: The k
ey can be deployed multiple times1: The key can be
deployed only onceBit2: Represents whether the HM
AC key can be deployed only once0: The key can be
deployed multiple times1: The key can be deployed
only onceBit3: Represents whether the DS key can b
e deployed only once0: The key can be deployed
multiple times1: The key can be deployed only once
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled 0: enabled
UART_PRINT_CONTROL (BLOCK0) Represents the type of UART printing. 00: force en = 0 R/W (0b00)
able printing 01: enable printing when GPIO8 is re
set at low level 10: enable printing when GPIO8 is
reset at high level 11: force disable printing
HUK_GEN_STATE (BLOCK0) Represents whether the HUK generate mode is valid. = 0 R/W (0b00000)
Odd count of bits with a value of 1: InvalidEven c
ount of bits with a value of 1: Valid
DCDC_CCM_EN (BLOCK0) Represents whether change DCDC to CCM mode = False R/W (0b0)
PVT_LIMIT (BLOCK1) Power glitch monitor threthold = 0 R/W (0x0000)
PVT_CELL_SELECT (BLOCK1) Power glitch monitor PVT cell select = 0 R/W (0b0000000)
PVT_PUMP_LIMIT (BLOCK1) Use to configure voltage monitor limit for charge = 0 R/W (0x00)
pump
PUMP_DRV (BLOCK1) Use to configure charge pump voltage gain = 0 R/W (0x0)
HYS_EN_PAD (BLOCK1) Represents whether the hysteresis function of = False R/W (0b0)
corresponding PAD is enabled. 1: enabled 0:disabled
PVT_GLITCH_CHARGE_RESET (BLOCK1) Represents whether to trigger reset or charge pump = False R/W (0b0)
when PVT power glitch happened.1:Trigger charge p
ump. 0:Trigger reset
PSRAM_CAP (BLOCK1) Psram capacity = 0 R/W (0b000)
PSRAM_VENDOR (BLOCK1) Psram vendor = 0 R/W (0b00)
TEMP (BLOCK1) Temp (die embedded inside) = 0 R/W (0b00)
ADJUST_1V2 (BLOCK1) SPI LDO adjust of 1.2v = 0 R/W (0x0)
ADJUST_1V8 (BLOCK1) SPI LDO adjust of 1.8v = 0 R/W (0x0)
ACTIVE_DCDC_1V25 (BLOCK1) DCDC-DCDC DBIAS of 1.25v = 0 R/W (0x0)
ACTIVE_DCDC_1V35 (BLOCK1) DCDC-DCDC DBIAS of 1.35v = 0 R/W (0x0)
SLP_DCDC (BLOCK1) DCDC DBIAS in sleep = 0 R/W (0b00000)
VDD_3V4_DOUT (BLOCK2) ADC dout of vdd 3.4v = 0 R/W (0b0000000000)
INITCODE_DIFF_1P8_3P3 (BLOCK2) Initcode diff between IO LDO 1.8v and 3.3v = 0 R/W (0b00000)
HI_DOUT_DIFF_1P8_3P3 (BLOCK2) HI dout diff between IO LDO 1.8v and 3.3v = 0 R/W (0b00000)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0b000)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot. 1: forced 0:not forc
ed
FLASH_LDO_EFUSE_SEL (BLOCK0) Represents whether to select efuse control flash l = False R/W (0b0)
do default voltage. 1 : efuse 0 : strapping
FLASH_LDO_POWER_SEL (BLOCK1) Represents which flash ldo be select: 1: FLASH LDO = False R/W (0b0)
1P2 0 : FLASH LDO 1P8
FLASH_CAP (BLOCK1) Flash capacity = 0 R/W (0b000)
FLASH_VENDOR (BLOCK1) Flash vendor = 0 R/W (0b000)
Identity fuses:
WAFER_VERSION_MINOR (BLOCK1) Minor chip version = 1 R/W (0x1)
WAFER_VERSION_MAJOR (BLOCK1) Major chip version = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK1) Disables check of blk version major = False R/W (0b0)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled. 1: enabled 0: d
isabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled 0: enabled
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000)
dd number: disabled Even number: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 30:ed:a0:ed:57:cc (OK) R/W
MAC_EXT (BLOCK1) Represents the extended bits of MAC address = 00:00 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
MAC_EUI64 (BLOCK1) calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:M
= 30:ed:a0:00:00:ed:57:cc (OK) R/W
AC_EXT[1]:MAC[3]:MAC[4]:MAC[5]
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0)
e_download is disabled or enabled. 1: disabled 0:
enabled
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disabled
0: enabled
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0b00000)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0b00000)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0b00000)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0b00000)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0b00000)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0b00000)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
XTS_DPA_PSEUDO_LEVEL (BLOCK0) Represents the pseudo round level of xts-aes anti- = 0 R/W (0b00)
dpa attack. 3: High. 2: Moderate 1. Low 0: Disabled
XTS_DPA_CLK_ENABLE (BLOCK0) Represents whether xts-aes anti-dpa attack clock i = False R/W (0b0)
s enabled. 1. Enable. 0: Disable.
SECURE_BOOT_SHA384_EN (BLOCK0) Represents if the chip supports Secure Boot using = False R/W (0b0)
SHA-384
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
FORCE_USE_KEY_MANAGER_KEY (BLOCK0) Represents whether the corresponding key must come = 0 R/W (0b00000)
from Key Manager. Bit0: Represents whether the EC
DSA key must come from Key Manager.0: The key does
not need to come from Key Manager1: The key must
come from Key ManagerBit1: Represents whether the
XTS-AES (flash and PSRAM) key must come from Key M
anager.0: The key does not need to come from Key M
anager1: The key must come from Key ManagerBit2: R
epresents whether the HMAC key must come from Key
Manager.0: The key does not need to come from Key
Manager1: The key must come from Key ManagerBit3:
Represents whether the DS key must come from Key M
anager.0: The key does not need to come from Key M
anager1: The key must come from Key Manager
FORCE_DISABLE_SW_INIT_KEY (BLOCK0) Represents whether to disable the use of the initi = False R/W (0b0)
alization key written by software and instead forc
e use efuse\_init\_key.0: Enable1: Disable
KM_XTS_KEY_LENGTH_256 (BLOCK0) Represents which key flash encryption uses.0: XTS- = False R/W (0b0)
AES-256 key1: XTS-AES-128 key
LOCK_KM_KEY (BLOCK0) Represents whether the keys in the Key Manager are = False R/W (0b0)
locked after deployment.0: Not locked1: Locked
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled. 1: disabled 0: enabled
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled 0: enabled
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled. 1: disabled 0: enabled
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: Disable 0: Enabl
e
USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins of USB_SERIA = False R/W (0b0)
L_JTAG PHY is exchanged. 1: exchanged 0: not excha
nged
USB_OTG_FS_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins of USB_OTG_F = False R/W (0b0)
S PHY is exchanged. 1: exchanged 0: not exchanged
USB_PHY_SEL (BLOCK0) Represents whether to exchange the USB_SERIAL_JTAG = False R/W (0b0)
PHY with USB_OTG_FS PHY. 1: exchanged. 0: not e
xchanged
Vdd fuses:
VDD_SPI_LDO_ADJUST (BLOCK1) Represents configuration of FLASH LDO mode and = 0 R/W (0x00)
voltage.
Wdt fuses:
WDT_DELAY_SEL (BLOCK1) Represents the threshold level of the RTC watchdog = 0 R/W (0b00)
STG0 timeout. 0: Original threshold configuration
value of STG0 *2 1: Original threshold configurat
ion value of STG0 *4 2: Original threshold configu
ration value of STG0 *8 3: Original threshold conf
iguration value of STG0 *16
@@ -0,0 +1,21 @@
.. code-block:: none
idf.py -p PORT efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32h4"...
espefuse v5.3.dev3
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] dump: a0ed57cc 000030ed 00000000 00040000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
@@ -0,0 +1,185 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
POWERGLITCH_EN (BLOCK0) Represents whether power glitch function is enable = False R/W (0b0)
d. 1: enabled. 0: disabled
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
KM_HUK_GEN_STATE (BLOCK0) Set this bit to control validation of HUK generate = 0 R/W (0b000000000)
mode. Odd of 1 is invalid; even of 1 is valid
KM_RND_SWITCH_CYCLE (BLOCK0) Set bits to control key manager random number swit = 0 R/W (0b00)
ch cycle. 0: control by register. 1: 8 km clk cycl
es. 2: 16 km cycles. 3: 32 km cycles
KM_DEPLOY_ONLY_ONCE (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0)
can only be deployed once. 1 is true; 0 is false.
Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
UART_PRINT_CONTROL (BLOCK0) Represents the type of UART printing. 00: force en = 0 R/W (0b00)
able printing. 01: enable printing when GPIO8 is r
eset at low level. 10: enable printing when GPIO8
is reset at high level. 11: force disable printing
HYS_EN_PAD (BLOCK0) Represents whether the hysteresis function of corr = False R/W (0b0)
corresponding PAD is enabled. 1: enabled. 0:disabled
DCDC_VSET (BLOCK0) Set the dcdc voltage default = 0 R/W (0b00000)
PXA0_TIEH_SEL_0 (BLOCK0) TBD = 0 R/W (0b00)
PXA0_TIEH_SEL_1 (BLOCK0) TBD = 0 R/W (0b00)
PXA0_TIEH_SEL_2 (BLOCK0) TBD = 0 R/W (0b00)
PXA0_TIEH_SEL_3 (BLOCK0) TBD = 0 R/W (0b00)
KM_DISABLE_DEPLOY_MODE (BLOCK0) TBD = 0 R/W (0x0)
HP_PWR_SRC_SEL (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
DCDC_VSET_EN (BLOCK0) Select dcdc vset use efuse_dcdc_vset = False R/W (0b0)
DIS_SWD (BLOCK0) Set this bit to disable super-watchdog = False R/W (0b0)
PSRAM_CAP (BLOCK1) PSRAM capacity = 0 R/W (0b00)
PSRAM_TEMP (BLOCK1) PSRAM temperature = 0 R/W (0b00)
PSRAM_VENDOR (BLOCK1) PSRAM vendor = 0 R/W (0b00)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TYPE (BLOCK0) The type of interfaced flash. 0: four data lines; = False R/W (0b0)
1: eight data lines
FLASH_PAGE_SIZE (BLOCK0) Set flash page size = 0 R/W (0b00)
FLASH_ECC_EN (BLOCK0) Set this bit to enable ecc for flash boot = False R/W (0b0)
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot. 1: forced. 0:not for
ced
FLASH_CAP (BLOCK1) Flash capacity = 0 R/W (0b000)
FLASH_TEMP (BLOCK1) Flash temperature = 0 R/W (0b00)
FLASH_VENDOR (BLOCK1) Flash vendor = 0 R/W (0b000)
Identity fuses:
WAFER_VERSION_MINOR (BLOCK1) Minor chip version = 0 R/W (0x0)
WAFER_VERSION_MAJOR (BLOCK1) Major chip version = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK1) Disables check of blk version major = False R/W (0b0)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled. 1: enabled. 0:
disabled
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000)
dd number: disabled. Even number: enabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled. 0: enabled
Mac fuses:
MAC (BLOCK1) MAC address
= 60:55:f9:f8:80:40 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led. 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Set this bit to disable accessing MSPI flash/MSPI = False R/W (0b0)
ram by SYS AXI matrix during boot_mode_download
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disable
ed. 0: enabled
FORCE_USE_KEY_MANAGER_KEY (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0)
must come from key manager.. 1 is true; 0 is false
. Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds
FORCE_DISABLE_SW_INIT_KEY (BLOCK0) Set this bit to disable software written init key; = False R/W (0b0)
and force use efuse_init_key
XTS_KEY_LENGTH_256 (BLOCK0) Set this bit to configure flash encryption use xts = False R/W (0b0)
-128 key; else use xts-256 key
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0)
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
ECDSA_ENABLE_SOFT_K (BLOCK0) Represents whether hardware random number k is for = False R/W (0b0)
ced used in ESDCA. 1: force used. 0: not force use
d
CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0)
nabled. 0: disabled
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
LOCK_KM_KEY (BLOCK0) TBD = False R/W (0b0)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled. 1: disable
ed. 0: enabled
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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
Usb fuses:
USB_DEVICE_EXCHG_PINS (BLOCK0) Enable usb device exchange pins of D+ and D- = False R/W (0b0)
USB_OTG11_EXCHG_PINS (BLOCK0) Enable usb otg11 exchange pins of D+ and D- = False R/W (0b0)
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled. 0: enable
d
USB_PHY_SEL (BLOCK0) TBD = False R/W (0b0)
DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download via USB-OTG = False R/W (0b0)
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: disabled. 0: ena
bled
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00)
is selected at startup. 1: selected. 0: not select
ed
DIS_WDT (BLOCK0) Set this bit to disable watch dog = False R/W (0b0)
@@ -0,0 +1,25 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32p4"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,153 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
"ninja efuse-summary"...
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0)
DIS_DCACHE (BLOCK0) Set this bit to disable Dcache = False R/W (0b0)
DIS_TWAI (BLOCK0) Set this bit to disable the TWAI Controller functi = False R/W (0b0)
on
DIS_BOOT_REMAP (BLOCK0) Disables capability to Remap RAM to ROM address sp = False R/W (0b0)
ace
DIS_LEGACY_SPI_BOOT (BLOCK0) Set this bit to disable Legacy SPI boot mode = False R/W (0b0)
UART_PRINT_CHANNEL (BLOCK0) Selects the default UART for printing boot message = UART0 R/W (0b0)
s
UART_PRINT_CONTROL (BLOCK0) Set the default UART boot message output mode = Enable R/W (0b00)
PIN_POWER_SELECTION (BLOCK0) Set default power supply for GPIO33-GPIO37; set wh = VDD3P3_CPU R/W (0b0)
en SPI flash is initialized
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up; = 0 R/W (0x0)
in unit of (ms/2). When the value is 15; delay is
7.5 ms
FLASH_TYPE (BLOCK0) SPI flash type = 4 data lines R/W (0b0)
FORCE_SEND_RESUME (BLOCK0) If set; forces ROM code to send an SPI flash resum = False R/W (0b0)
e command during SPI boot
FLASH_VERSION (BLOCK1) Flash version = 2 R/W (0x2)
Identity fuses:
BLOCK0_VERSION (BLOCK0) BLOCK0 efuse version = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0)
WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 1 R/W (0b01)
WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR = 0 R/W (0b00)
PSRAM_VERSION (BLOCK1) PSRAM version = 1 R/W (0x1)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0x0)
WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= ea 0e c6 f1 01 f2 38 82 e9 98 5b 59 81 fe 00 02 R/W
BLK_VERSION_MINOR (BLOCK2) BLK_VERSION_MINOR of BLOCK2 = ADC calib V2 R/W (0b010)
WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 0 R/W (0x0)
<< 3 + WAFER_VERSION_MINOR_LO (read only)
Jtag fuses:
SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled; JT = False R/W (0b0)
AG can be activated temporarily by HMAC peripheral
HARD_DIS_JTAG (BLOCK0) Hardware disables JTAG permanently = False R/W (0b0)
Mac fuses:
MAC (BLOCK1) MAC address
= 58:cf:79:b3:b9:54 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0)
DIS_DOWNLOAD_DCACHE (BLOCK0) Disables Dcache when SoC is in Download mode = False R/W (0b0)
DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0)
hip into download mode
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption when in download boot mo = False R/W (0b0)
des
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disabled otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Purpose of KEY0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Purpose of KEY1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Purpose of KEY2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Purpose of KEY3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Purpose of KEY4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Purpose of KEY5 = USER R/W (0x0)
SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0)
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable aggressive secure boot key = False R/W (0b0)
revocation mode
DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable all download boot modes = False R/W (0b0)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode ( = False R/W (0b0)
read/write flash only)
SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback = 0 R/W (0x0000)
feature)
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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_CLK (BLOCK1) SPI_PAD_configure CLK = 0 R/W (0b000000)
SPI_PAD_CONFIG_Q (BLOCK1) SPI_PAD_configure Q(D1) = 0 R/W (0b000000)
SPI_PAD_CONFIG_D (BLOCK1) SPI_PAD_configure D(D0) = 0 R/W (0b000000)
SPI_PAD_CONFIG_CS (BLOCK1) SPI_PAD_configure CS = 0 R/W (0b000000)
SPI_PAD_CONFIG_HD (BLOCK1) SPI_PAD_configure HD(D3) = 0 R/W (0b000000)
SPI_PAD_CONFIG_WP (BLOCK1) SPI_PAD_configure WP(D2) = 0 R/W (0b000000)
SPI_PAD_CONFIG_DQS (BLOCK1) SPI_PAD_configure DQS = 0 R/W (0b000000)
SPI_PAD_CONFIG_D4 (BLOCK1) SPI_PAD_configure D4 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D5 (BLOCK1) SPI_PAD_configure D5 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D6 (BLOCK1) SPI_PAD_configure D6 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D7 (BLOCK1) SPI_PAD_configure D7 = 0 R/W (0b000000)
Usb fuses:
DIS_USB (BLOCK0) Set this bit to disable USB OTG function = False R/W (0b0)
USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0)
USB_EXT_PHY_ENABLE (BLOCK0) Set this bit to enable external USB PHY = False R/W (0b0)
USB_FORCE_NOPERSIST (BLOCK0) If set; forces USB BVALID to 1 = False R/W (0b0)
DIS_USB_DOWNLOAD_MODE (BLOCK0) Set this bit to disable use of USB OTG in UART dow = False R/W (0b0)
nload boot mode
Vdd fuses:
VDD_SPI_XPD (BLOCK0) If VDD_SPI_FORCE is 1; this value determines if th = False R/W (0b0)
e VDD_SPI regulator is powered on
VDD_SPI_TIEH (BLOCK0) If VDD_SPI_FORCE is 1; determines VDD_SPI voltage
= VDD_SPI connects to 1.8 V LDO R/W (0b0)
VDD_SPI_FORCE (BLOCK0) Set this bit to use XPD_VDD_PSI_REG and VDD_SPI_TI = False R/W (0b0)
EH to configure VDD_SPI LDO
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00)
ock cycle
Flash voltage (VDD_SPI) determined by GPIO45 on reset (GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO
GPIO45=Low or NC: VDD_SPI pin is powered directly from VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V).
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32s2"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: 79b3b954 000058cf 00000000 10440000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: f1c60eea 8238f201 595b98e9 0200fe81 1c549f24 88491102 06461421 070c2083
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,187 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = 12 R/W (0b0000011)
K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = -28 R/W (0b1000111)
V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = 20 R/W (0x05)
V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = -44 R/W (0x8b)
DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = -36 R/W (0b11001)
ADC2_CAL_VOL_ATTEN3 (BLOCK1) ADC2 calibration voltage at atten3 = -24 R/W (0b100110)
TEMP_CALIB (BLOCK2) Temperature calibration data = -10.9 R/W (0b101101101)
OCODE (BLOCK2) ADC OCode = 88 R/W (0x58)
ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 432 R/W (0x6c)
ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = -16 R/W (0b100100)
ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = 88 R/W (0b010110)
ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = 0 R/W (0b100000)
ADC2_INIT_CODE_ATTEN0 (BLOCK2) ADC2 init code at atten0 = -72 R/W (0x92)
ADC2_INIT_CODE_ATTEN1 (BLOCK2) ADC2 init code at atten1 = -16 R/W (0b100100)
ADC2_INIT_CODE_ATTEN2 (BLOCK2) ADC2 init code at atten2 = 48 R/W (0b001100)
ADC2_INIT_CODE_ATTEN3 (BLOCK2) ADC2 init code at atten3 = 112 R/W (0b011100)
ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = 412 R/W (0x67)
ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = 392 R/W (0x62)
ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = 356 R/W (0x59)
ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = 412 R/W (0x67)
ADC2_CAL_VOL_ATTEN0 (BLOCK2) ADC2 calibration voltage at atten0 = -116 R/W (0x9d)
ADC2_CAL_VOL_ATTEN1 (BLOCK2) ADC2 calibration voltage at atten1 = -72 R/W (0b1010010)
ADC2_CAL_VOL_ATTEN2 (BLOCK2) ADC2 calibration voltage at atten2 = -64 R/W (0b1010000)
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0)
DIS_DCACHE (BLOCK0) Set this bit to disable Dcache = False R/W (0b0)
DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0)
DIS_APP_CPU (BLOCK0) Disable app cpu = False R/W (0b0)
DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = False R/W (0b0)
UART_PRINT_CONTROL (BLOCK0) Set the default UART boot message output mode = Enable R/W (0b00)
PIN_POWER_SELECTION (BLOCK0) Set default power supply for GPIO33-GPIO37; set wh = VDD3P3_CPU R/W (0b0)
en SPI flash is initialized
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0)
nit of ms. If the value is less than 15; the waiti
ng time is the configurable value. Otherwise; the
waiting time is twice the configurable value
FLASH_ECC_MODE (BLOCK0) Flash ECC mode in ROM = 16to18 byte R/W (0b0)
FLASH_TYPE (BLOCK0) SPI flash type = 4 data lines R/W (0b0)
FLASH_PAGE_SIZE (BLOCK0) Set Flash page size = 0 R/W (0b00)
FLASH_ECC_EN (BLOCK0) Set 1 to enable ECC for flash boot = False R/W (0b0)
FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0)
mmand during SPI boot
Identity fuses:
DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0)
WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 3 R/W (0b011)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 3 R/W (0b011)
WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0)
WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= cb 3a c9 b8 88 2b c3 bc 5e f4 00 60 ac 25 be 4b R/W
BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = ADC calib V1 R/W (0b01)
WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 3 R/W (0x3)
<< 3 + WAFER_VERSION_MINOR_LO (read only)
Jtag fuses:
SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000)
d number 1 means disable ). JTAG can be enabled in
HMAC module
DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = False R/W (0b0)
is disabled permanently
STRAP_JTAG_SEL (BLOCK0) Set this bit to enable selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio10 when b
oth reg_dis_usb_jtag and reg_dis_pad_jtag are equa
l to 0
Mac fuses:
MAC (BLOCK1) MAC address
= ec:da:3b:41:f2:70 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode ( = False R/W (0b0)
boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_DOWNLOAD_DCACHE (BLOCK0) Set this bit to disable Dcache in download mode ( = False R/W (0b0)
boot_mode[3:0] is 0; 1; 2; 3; 6; 7)
DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces = False R/W (0b0)
chip into download mode
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in = False R/W (0b0)
download boot modes
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disabled otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = USER R/W (0x0)
KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0)
KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0)
KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0)
KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0)
KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0)
SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0)
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0)
boot
DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0)
:0] = 0; 1; 2; 3; 6; 7)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0)
SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback = 0 R/W (0x0000)
feature)
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
BLOCK_KEY5 (BLOCK9)
Purpose: USER
Key5 or user data
= 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_CLK (BLOCK1) SPI_PAD_configure CLK = 0 R/W (0b000000)
SPI_PAD_CONFIG_Q (BLOCK1) SPI_PAD_configure Q(D1) = 0 R/W (0b000000)
SPI_PAD_CONFIG_D (BLOCK1) SPI_PAD_configure D(D0) = 0 R/W (0b000000)
SPI_PAD_CONFIG_CS (BLOCK1) SPI_PAD_configure CS = 0 R/W (0b000000)
SPI_PAD_CONFIG_HD (BLOCK1) SPI_PAD_configure HD(D3) = 0 R/W (0b000000)
SPI_PAD_CONFIG_WP (BLOCK1) SPI_PAD_configure WP(D2) = 0 R/W (0b000000)
SPI_PAD_CONFIG_DQS (BLOCK1) SPI_PAD_configure DQS = 0 R/W (0b000000)
SPI_PAD_CONFIG_D4 (BLOCK1) SPI_PAD_configure D4 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D5 (BLOCK1) SPI_PAD_configure D5 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D6 (BLOCK1) SPI_PAD_configure D6 = 0 R/W (0b000000)
SPI_PAD_CONFIG_D7 (BLOCK1) SPI_PAD_configure D7 = 0 R/W (0b000000)
Usb fuses:
DIS_USB_OTG (BLOCK0) Set this bit to disable USB function = False R/W (0b0)
USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0)
USB_EXT_PHY_ENABLE (BLOCK0) Set this bit to enable external PHY = False R/W (0b0)
DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = False R/W (0b0)
jtag in module of usb device
DIS_USB_SERIAL_JTAG (BLOCK0) Set this bit to disable usb device = False R/W (0b0)
USB_PHY_SEL (BLOCK0) This bit is used to switch internal PHY and extern
= internal PHY is assigned to USB Device while external PHY is assigned to USB OTG R/W (0b0)
al PHY for USB OTG and USB Device
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0)
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable UART download mode through = False R/W (0b0)
USB
DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download through USB-OTG = False R/W (0b0)
Vdd fuses:
VDD_SPI_XPD (BLOCK0) SPI regulator power up signal = False R/W (0b0)
VDD_SPI_TIEH (BLOCK0) If VDD_SPI_FORCE is 1; determines VDD_SPI voltage
= VDD_SPI connects to 1.8 V LDO R/W (0b0)
VDD_SPI_FORCE (BLOCK0) Set this bit and force to use the configuration of = False R/W (0b0)
eFuse to configure VDD_SPI
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00)
ock cycle
Flash voltage (VDD_SPI) determined by GPIO45 on reset (GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO
GPIO45=Low or NC: VDD_SPI pin is powered directly from VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V).
@@ -0,0 +1,194 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Config fuses:
WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000)
RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000)
RESERVED_0_39 (BLOCK0) Enable usb device exchange pins of D+ and D- = 0 R/W (0b000)
DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
EFUSE_DIS_WIFI6 (BLOCK0) USB intphy of usb device signle-end input high thr = False R/W (0b0)
eshold; 1.76V to 2V. Step by 80mV
KM_HUK_GEN_STATE (BLOCK0) Set this bit to control validation of HUK generate = 0 R/W (0b00000)
mode. Odd of 1 is invalid; even of 1 is valid
KM_RND_SWITCH_CYCLE (BLOCK0) Set bits to control key manager random number swit = False R/W (0b0)
ch cycle. 0: control by register. 1: 8 km clk cycl
es. 2: 16 km cycles. 3: 32 km cycles
KM_DISABLE_DEPLOY_MODE (BLOCK0) Set bits to control key manager random number swit = 0 R/W (0b00000)
ch cycle. 0: control by register. 1: 8 km clk cycl
es. 2: 16 km cycles. 3: 32 km cycles
KM_DEPLOY_ONLY_ONCE (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0b00000)
can only be deployed once. 1 is true; 0 is false.
Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds
ECC_FORCE_CONST_TIME (BLOCK0) Represents the spa secure level by configuring the = False R/W (0b0)
clock random divide mode
DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0)
enabled. 1: disabled. 0: enabled
UART_PRINT_CONTROL (BLOCK0) Represents the type of UART printing. 00: force en = 0 R/W (0b00)
able printing. 01: enable printing when GPIO8 is r
eset at low level. 10: enable printing when GPIO8
is reset at high level. 11: force disable printing
HYS_EN_PAD (BLOCK0) Represents whether the hysteresis function of = False R/W (0b0)
corresponding PAD is enabled. 1: enabled. 0:disabled
DCDC_VSET_EN (BLOCK0) Select dcdc vset use efuse_dcdc_vset = False R/W (0b0)
DIS_SWD (BLOCK0) Set this bit to disable super-watchdog = False R/W (0b0)
BOOTLOADER_ANTI_ROLLBACK_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
BOOTLOADER_ANTI_ROLLBACK_UPDATE (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
RMA_ENA (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0b00)
RMA_SESSION_COUNTER (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0b000)
RMA_NONCE_ENA (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0b00)
RMA_CHIP_INFO_SOURCE (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
RMA_DISABLE_FAST_VEF (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
PVT_0_GLITCH_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
PVT_0_GLITCH_MODE (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0b00)
PVT_1_GLITCH_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
PVT_1_GLITCH_MODE (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0b00)
POWER_GLITCH_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0x0)
XTS_SHADOW_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
SPI_BOOT_CRYPT_SCRAMBLER_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
PSRAM_CAP (BLOCK1) PSRAM capacity = 0 R/W (0b000)
TEMP (BLOCK1) Operating temperature of the ESP chip = 0 R/W (0b00)
PSRAM_VENDOR (BLOCK1) PSRAM vendor = 0 R/W (0b00)
BLOCK_USR_DATA (BLOCK3) User data
= 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
BLOCK_SYS_DATA2 (BLOCK9) System data part 2 (reserved)
= 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
Flash fuses:
FLASH_TYPE (BLOCK0) The type of interfaced flash. 0: four data lines; = False R/W (0b0)
1: eight data lines
FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0)
in unit of ms. When the value less than 15; the wa
iting time is the programmed value. Otherwise; the
waiting time is 2 times the programmed value
FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0)
sume command during SPI boot. 1: forced. 0:not for
ced
RECOVERY_BOOTLOADER_FLASH_SECTOR (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0x000)
PMU_FLASH_POWEL_SEL (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
PMU_FLASH_POWEL_SEL_EN (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
Identity fuses:
BOOTLOADER_ANTI_ROLLBACK_VERSION (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = 0 R/W (0x0)
WAFER_VERSION_MINOR (BLOCK1) Minor chip version = 0 R/W (0x0)
WAFER_VERSION_MAJOR (BLOCK1) Major chip version = 0 R/W (0b00)
DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0)
DISABLE_BLK_VERSION_MAJOR (BLOCK1) Disables check of blk version major = False R/W (0b0)
BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000)
BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00)
PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000)
OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Jtag fuses:
JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0)
ag and pad_to_jtag through strapping gpio15 when b
oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are
equal to 0 is enabled or disabled. 1: enabled. 0:
disabled
SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000)
dd number: disabled. Even number: enabled
DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0)
y(permanently). 1: disabled. 0: enabled
RE_ENABLE_JTAG_SOURCE (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0)
Mac fuses:
MAC (BLOCK1) MAC address
= 00:00:00:00:00:00 (OK) R/W
CUSTOM_MAC (BLOCK3) Custom MAC
= 00:00:00:00:00:00 (OK) R/W
Security fuses:
DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0)
nto download mode is disabled or enabled. 1: disab
led. 0: enabled
SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Set this bit to disable accessing MSPI flash/MSPI = False R/W (0b0)
ram by SYS AXI matrix during boot_mode_download
DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0)
led or enabled(except in SPI boot mode). 1: disable
ed. 0: enabled
FORCE_USE_KEY_MANAGER_KEY (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0b00000)
must come from key manager.. 1 is true; 0 is false
. Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds
FORCE_DISABLE_SW_INIT_KEY (BLOCK0) Set this bit to disable software written init key; = False R/W (0b0)
and force use efuse_init_key
KM_XTS_KEY_LENGTH_256 (BLOCK0) Set this bit to configure flash encryption use xts = False R/W (0b0)
-128 key; else use xts-256 key
SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000)
and disables otherwise
SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0)
SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0)
KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0b00000)
KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0b00000)
KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0b00000)
KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0b00000)
KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0b00000)
ECDSA_ENABLE_SOFT_K (BLOCK0) Represents whether hardware random number k is for = False R/W (0b0)
ced used in ESDCA. 1: force used. 0: not force use
d
SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00)
clock random divide mode
XTS_DPA_CLK_ENABLE (BLOCK0) Represents the spa secure level by configuring the = False R/W (0b0)
clock random divide mode
XTS_DPA_PSEUDO_LEVEL (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = 0 R/W (0b00)
nabled. 0: disabled
SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled. 0: disabled
SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0)
is enabled or disabled. 1: enabled. 0: disabled
DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0)
abled. 1: disabled. 0: enabled
LOCK_KM_KEY (BLOCK0) TBD = False R/W (0b0)
ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0)
disabled. 1: enabled. 0: disabled
SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000)
ck feature
SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0)
or enabled when Secure Boot is enabled. 1: disable
ed. 0: enabled
SECURE_BOOT_SHA384_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0)
led. 1: enabled. 0: disabled
BLOCK_KEY0 (BLOCK4)
Purpose: USER
Key0 or user data
= 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
BLOCK_KEY1 (BLOCK5)
Purpose: USER
Key1 or user data
= 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
BLOCK_KEY2 (BLOCK6)
Purpose: USER
Key2 or user data
= 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
BLOCK_KEY3 (BLOCK7)
Purpose: USER
Key3 or user data
= 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
BLOCK_KEY4 (BLOCK8)
Purpose: USER
Key4 or user data
= 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
Usb fuses:
DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0)
tag is disabled or enabled. 1: disabled. 0: enable
d
DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download via USB-OTG = False R/W (0b0)
DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0)
isabled or enabled. 1: disabled. 0: enabled
DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0)
nction is disabled or enabled. 1: disabled. 0: ena
bled
Wdt fuses:
WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b0)
is selected at startup. 1: selected. 0: not select
ed
DIS_WDT (BLOCK0) Set this bit to disable watch dog = False R/W (0b0)
@@ -0,0 +1,20 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32s31"...
espefuse v5.3.dev2
=== Run "dump" command ===
BLOCK0 ( ) [0 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA (BLOCK2 ) [2 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_USR_DATA (BLOCK3 ) [3 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK9 ) [9 ] dump: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
@@ -0,0 +1,26 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32s3"...
espefuse v5.0.2
=== Run "dump" command ===
Connecting....
BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000
MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: 3b41f270 0000ecda 00000000 030c0000 2c707800 9800cc58
BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: b8c93acb bcc32b88 6000f45e 4bbe25ac 8d8b16d1 924940b4 b2c4cee1 50a53ace
BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_RD_RS_ERR0_REG 0x00000000
EFUSE_RD_RS_ERR1_REG 0x00000000
@@ -0,0 +1,89 @@
.. code-block:: none
idf.py efuse-summary
Executing action: efuse-summary
(...)
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:i
level 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)
@@ -0,0 +1,17 @@
.. code-block:: none
idf.py efuse-dump
Executing action: efuse-dump
Running espefuse in directory <project-directory>
Executing "espefuse dump --chip esp32"...
espefuse v5.0.2
Connecting....
=== Run "dump" command ===
BLOCK0 ( ) [0 ] read_regs: 00000000 7e5a6e58 00e294b9 0000a200 00000333 00100000 00000004
BLOCK1 (flash_encryption) [1 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK2 (secure_boot_v1 s) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
BLOCK3 ( ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
EFUSE_REG_DEC_STATUS 0x00000000
@@ -0,0 +1,32 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`1` 240
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 240 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,25 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 120
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 120 MHz
- APB: 40 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 40 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 40 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,25 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,25 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 240
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 240 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,25 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,25 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,40 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 96
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 96 MHz
- APB: 32 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 32 MHz
- APB: 32 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`2` 64
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 64 MHz
- APB: 32 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 32 MHz
- APB: 32 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`2` 48
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 48 MHz
- APB: 32 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 32 MHz
- APB: 32 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,7 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
@@ -0,0 +1,7 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
@@ -0,0 +1,13 @@
+---------------+---------------------------------------+-------------------------------------+
| Max CPU | Lock Acquisition | CPU and APB Frequencies |
| Frequency Set | | |
+---------------+---------------------------------------+-------------------------------------+
| 360 | ``ESP_PM_CPU_FREQ_MAX`` acquired | | CPU: 360 MHz |
| | | | APB: 90 MHz |
+ +---------------------------------------+-------------------------------------+
| | ``ESP_PM_APB_FREQ_MAX`` acquired, | | CPU: 90 MHz |
| | ``ESP_PM_CPU_FREQ_MAX`` not acquired | | APB: 90 MHz |
+ +---------------------------------------+-------------------------------------+
| | None | Min values for both frequencies set |
| | | with :cpp:func:`esp_pm_configure` |
+---------------+---------------------------------------+-------------------------------------+
@@ -0,0 +1,36 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 240
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 240 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX``or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,36 @@
.. flat-table::
:widths: 1 3 3
* - Max CPU Frequency Set
- Lock Acquisition
- CPU and APB Frequencies
* - :rspan:`2` 240
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 240 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`2` 160
- ``ESP_PM_CPU_FREQ_MAX`` acquired
-
- CPU: 160 MHz
- APB: 80 MHz
* - ``ESP_PM_APB_FREQ_MAX`` acquired, ``ESP_PM_CPU_FREQ_MAX`` not acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
* - :rspan:`1` 80
- Any of ``ESP_PM_CPU_FREQ_MAX``or ``ESP_PM_APB_FREQ_MAX`` acquired
-
- CPU: 80 MHz
- APB: 80 MHz
* - None
- Min values for both frequencies set with :cpp:func:`esp_pm_configure`
@@ -0,0 +1,3 @@
.. note::
To be updated.
@@ -0,0 +1,120 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Parsing efuse CSV input file $IDF_PATH/components/efuse/esp32c2/esp_efuse_table.csv ...
Verifying efuse table...
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 8
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 1 1
4 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 1 1
5 WR_DIS.DIS_DOWNLOAD_ICACHE EFUSE_BLK0 1 1
6 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
7 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 2 1
8 WR_DIS.XTS_KEY_LENGTH_256 EFUSE_BLK0 2 1
9 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 2 1
10 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 3 1
11 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 3 1
12 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 3 1
13 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 3 1
14 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 3 1
15 WR_DIS.FLASH_TPUW EFUSE_BLK0 3 1
16 WR_DIS.SECURE_VERSION EFUSE_BLK0 4 1
17 WR_DIS.CUSTOM_MAC_USED EFUSE_BLK0 4 1
18 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 4 1
19 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 4 1
20 WR_DIS.CUSTOM_MAC EFUSE_BLK0 5 1
21 WR_DIS.MAC EFUSE_BLK0 6 1
22 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 6 1
23 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 6 1
24 WR_DIS.PKG_VERSION EFUSE_BLK0 6 1
25 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 6 1
26 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 6 1
27 WR_DIS.OCODE EFUSE_BLK0 6 1
28 WR_DIS.TEMP_CALIB EFUSE_BLK0 6 1
29 WR_DIS.ADC1_INIT_CODE_ATTEN0 EFUSE_BLK0 6 1
30 WR_DIS.ADC1_INIT_CODE_ATTEN3 EFUSE_BLK0 6 1
31 WR_DIS.ADC1_CAL_VOL_ATTEN0 EFUSE_BLK0 6 1
32 WR_DIS.ADC1_CAL_VOL_ATTEN3 EFUSE_BLK0 6 1
33 WR_DIS.DIG_DBIAS_HVT EFUSE_BLK0 6 1
34 WR_DIS.DIG_LDO_SLP_DBIAS2 EFUSE_BLK0 6 1
35 WR_DIS.DIG_LDO_SLP_DBIAS26 EFUSE_BLK0 6 1
36 WR_DIS.DIG_LDO_ACT_DBIAS26 EFUSE_BLK0 6 1
37 WR_DIS.DIG_LDO_ACT_STEPD10 EFUSE_BLK0 6 1
38 WR_DIS.RTC_LDO_SLP_DBIAS13 EFUSE_BLK0 6 1
39 WR_DIS.RTC_LDO_SLP_DBIAS29 EFUSE_BLK0 6 1
40 WR_DIS.RTC_LDO_SLP_DBIAS31 EFUSE_BLK0 6 1
41 WR_DIS.RTC_LDO_ACT_DBIAS31 EFUSE_BLK0 6 1
42 WR_DIS.RTC_LDO_ACT_DBIAS13 EFUSE_BLK0 6 1
43 WR_DIS.ADC_CALIBRATION_3 EFUSE_BLK0 6 1
44 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 7 1
45 RD_DIS EFUSE_BLK0 32 2
46 RD_DIS.KEY0 EFUSE_BLK0 32 2
47 RD_DIS.KEY0.LOW EFUSE_BLK0 32 1
48 RD_DIS.KEY0.HI EFUSE_BLK0 33 1
49 WDT_DELAY_SEL EFUSE_BLK0 34 2
50 DIS_PAD_JTAG EFUSE_BLK0 36 1
51 DIS_DOWNLOAD_ICACHE EFUSE_BLK0 37 1
52 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 38 1
53 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 39 3
54 XTS_KEY_LENGTH_256 EFUSE_BLK0 42 1
55 UART_PRINT_CONTROL EFUSE_BLK0 43 2
56 FORCE_SEND_RESUME EFUSE_BLK0 45 1
57 DIS_DOWNLOAD_MODE EFUSE_BLK0 46 1
58 DIS_DIRECT_BOOT EFUSE_BLK0 47 1
59 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 48 1
60 FLASH_TPUW EFUSE_BLK0 49 4
61 SECURE_BOOT_EN EFUSE_BLK0 53 1
62 SECURE_VERSION EFUSE_BLK0 54 4
63 CUSTOM_MAC_USED EFUSE_BLK0 58 1
64 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 59 1
65 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 60 1
66 USER_DATA EFUSE_BLK1 0 88
67 USER_DATA.MAC_CUSTOM EFUSE_BLK1 0 48
68 MAC EFUSE_BLK2 0 8
69 MAC EFUSE_BLK2 8 8
70 MAC EFUSE_BLK2 16 8
71 MAC EFUSE_BLK2 24 8
72 MAC EFUSE_BLK2 32 8
73 MAC EFUSE_BLK2 40 8
74 WAFER_VERSION_MINOR EFUSE_BLK2 48 4
75 WAFER_VERSION_MAJOR EFUSE_BLK2 52 2
76 PKG_VERSION EFUSE_BLK2 54 3
77 BLK_VERSION_MINOR EFUSE_BLK2 57 3
78 BLK_VERSION_MAJOR EFUSE_BLK2 60 2
79 OCODE EFUSE_BLK2 62 7
80 TEMP_CALIB EFUSE_BLK2 69 9
81 ADC1_INIT_CODE_ATTEN0 EFUSE_BLK2 78 8
82 ADC1_INIT_CODE_ATTEN3 EFUSE_BLK2 86 5
83 ADC1_CAL_VOL_ATTEN0 EFUSE_BLK2 91 8
84 ADC1_CAL_VOL_ATTEN3 EFUSE_BLK2 99 6
85 DIG_DBIAS_HVT EFUSE_BLK2 105 5
86 DIG_LDO_SLP_DBIAS2 EFUSE_BLK2 110 7
87 DIG_LDO_SLP_DBIAS26 EFUSE_BLK2 117 8
88 DIG_LDO_ACT_DBIAS26 EFUSE_BLK2 125 6
89 DIG_LDO_ACT_STEPD10 EFUSE_BLK2 131 4
90 RTC_LDO_SLP_DBIAS13 EFUSE_BLK2 135 7
91 RTC_LDO_SLP_DBIAS29 EFUSE_BLK2 142 9
92 RTC_LDO_SLP_DBIAS31 EFUSE_BLK2 151 6
93 RTC_LDO_ACT_DBIAS31 EFUSE_BLK2 157 6
94 RTC_LDO_ACT_DBIAS13 EFUSE_BLK2 163 8
95 ADC_CALIBRATION_3 EFUSE_BLK2 192 11
96 KEY0 EFUSE_BLK3 0 256
97 KEY0.FE_256BIT EFUSE_BLK3 0 256
98 KEY0.FE_128BIT EFUSE_BLK3 0 128
99 KEY0.SB_128BIT EFUSE_BLK3 128 128
Used bits in efuse table:
EFUSE_BLK0
[0 7] [0 1] [1 1] [1 2] [2 2] ... [6 6] [6 6] [6 6] [6 6] [6 6] [6 6] [6 6] [6 6] [6 6] [6 7] [32 33] [32 33] [32 60]
EFUSE_BLK1
[0 87] [0 47]
EFUSE_BLK2
[0 170] [192 202]
EFUSE_BLK3
[0 255] [0 255] [0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,212 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
5 WR_DIS.DIS_DOWNLOAD_ICACHE EFUSE_BLK0 2 1
6 WR_DIS.DIS_USB_SERIAL_JTAG EFUSE_BLK0 2 1
7 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
8 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
9 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
10 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
11 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
12 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
13 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
14 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
15 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
16 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
17 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
18 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
19 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
20 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
21 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
22 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
23 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
24 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
25 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
26 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
27 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
28 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
29 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
30 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
31 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
32 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
33 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
34 WR_DIS.ERR_RST_ENABLE EFUSE_BLK0 19 1
35 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 19 1
36 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 19 1
37 WR_DIS.BLK1 EFUSE_BLK0 20 1
38 WR_DIS.MAC EFUSE_BLK0 20 1
39 WR_DIS.SPI_PAD_CONFIG_CLK EFUSE_BLK0 20 1
40 WR_DIS.SPI_PAD_CONFIG_Q EFUSE_BLK0 20 1
41 WR_DIS.SPI_PAD_CONFIG_D EFUSE_BLK0 20 1
42 WR_DIS.SPI_PAD_CONFIG_CS EFUSE_BLK0 20 1
43 WR_DIS.SPI_PAD_CONFIG_HD EFUSE_BLK0 20 1
44 WR_DIS.SPI_PAD_CONFIG_WP EFUSE_BLK0 20 1
45 WR_DIS.SPI_PAD_CONFIG_DQS EFUSE_BLK0 20 1
46 WR_DIS.SPI_PAD_CONFIG_D4 EFUSE_BLK0 20 1
47 WR_DIS.SPI_PAD_CONFIG_D5 EFUSE_BLK0 20 1
48 WR_DIS.SPI_PAD_CONFIG_D6 EFUSE_BLK0 20 1
49 WR_DIS.SPI_PAD_CONFIG_D7 EFUSE_BLK0 20 1
50 WR_DIS.WAFER_VERSION_MINOR_LO EFUSE_BLK0 20 1
51 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
52 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
53 WR_DIS.K_RTC_LDO EFUSE_BLK0 20 1
54 WR_DIS.K_DIG_LDO EFUSE_BLK0 20 1
55 WR_DIS.V_RTC_DBIAS20 EFUSE_BLK0 20 1
56 WR_DIS.V_DIG_DBIAS20 EFUSE_BLK0 20 1
57 WR_DIS.DIG_DBIAS_HVT EFUSE_BLK0 20 1
58 WR_DIS.THRES_HVT EFUSE_BLK0 20 1
59 WR_DIS.WAFER_VERSION_MINOR_HI EFUSE_BLK0 20 1
60 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
61 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
62 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
63 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 21 1
64 WR_DIS.TEMP_CALIB EFUSE_BLK0 21 1
65 WR_DIS.OCODE EFUSE_BLK0 21 1
66 WR_DIS.ADC1_INIT_CODE_ATTEN0 EFUSE_BLK0 21 1
67 WR_DIS.ADC1_INIT_CODE_ATTEN1 EFUSE_BLK0 21 1
68 WR_DIS.ADC1_INIT_CODE_ATTEN2 EFUSE_BLK0 21 1
69 WR_DIS.ADC1_INIT_CODE_ATTEN3 EFUSE_BLK0 21 1
70 WR_DIS.ADC1_CAL_VOL_ATTEN0 EFUSE_BLK0 21 1
71 WR_DIS.ADC1_CAL_VOL_ATTEN1 EFUSE_BLK0 21 1
72 WR_DIS.ADC1_CAL_VOL_ATTEN2 EFUSE_BLK0 21 1
73 WR_DIS.ADC1_CAL_VOL_ATTEN3 EFUSE_BLK0 21 1
74 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
75 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
76 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
77 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
78 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
79 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
80 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
81 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
82 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
83 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
84 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
85 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
86 RD_DIS EFUSE_BLK0 32 7
87 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
88 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
89 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
90 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
91 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
92 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
93 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
94 DIS_ICACHE EFUSE_BLK0 40 1
95 DIS_USB_JTAG EFUSE_BLK0 41 1
96 DIS_DOWNLOAD_ICACHE EFUSE_BLK0 42 1
97 DIS_USB_SERIAL_JTAG EFUSE_BLK0 43 1
98 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
99 DIS_TWAI EFUSE_BLK0 46 1
100 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
101 SOFT_DIS_JTAG EFUSE_BLK0 48 3
102 DIS_PAD_JTAG EFUSE_BLK0 51 1
103 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
104 USB_EXCHG_PINS EFUSE_BLK0 57 1
105 VDD_SPI_AS_GPIO EFUSE_BLK0 58 1
106 WDT_DELAY_SEL EFUSE_BLK0 80 2
107 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
108 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
109 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
110 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
111 KEY_PURPOSE_0 EFUSE_BLK0 88 4
112 KEY_PURPOSE_1 EFUSE_BLK0 92 4
113 KEY_PURPOSE_2 EFUSE_BLK0 96 4
114 KEY_PURPOSE_3 EFUSE_BLK0 100 4
115 KEY_PURPOSE_4 EFUSE_BLK0 104 4
116 KEY_PURPOSE_5 EFUSE_BLK0 108 4
117 SECURE_BOOT_EN EFUSE_BLK0 116 1
118 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
119 FLASH_TPUW EFUSE_BLK0 124 4
120 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
121 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
122 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
123 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
124 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
125 UART_PRINT_CONTROL EFUSE_BLK0 134 2
126 FORCE_SEND_RESUME EFUSE_BLK0 141 1
127 SECURE_VERSION EFUSE_BLK0 142 16
128 ERR_RST_ENABLE EFUSE_BLK0 159 1
129 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 160 1
130 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 161 1
131 MAC EFUSE_BLK1 0 8
132 MAC EFUSE_BLK1 8 8
133 MAC EFUSE_BLK1 16 8
134 MAC EFUSE_BLK1 24 8
135 MAC EFUSE_BLK1 32 8
136 MAC EFUSE_BLK1 40 8
137 SPI_PAD_CONFIG_CLK EFUSE_BLK1 48 6
138 SPI_PAD_CONFIG_Q EFUSE_BLK1 54 6
139 SPI_PAD_CONFIG_D EFUSE_BLK1 60 6
140 SPI_PAD_CONFIG_CS EFUSE_BLK1 66 6
141 SPI_PAD_CONFIG_HD EFUSE_BLK1 72 6
142 SPI_PAD_CONFIG_WP EFUSE_BLK1 78 6
143 SPI_PAD_CONFIG_DQS EFUSE_BLK1 84 6
144 SPI_PAD_CONFIG_D4 EFUSE_BLK1 90 6
145 SPI_PAD_CONFIG_D5 EFUSE_BLK1 96 6
146 SPI_PAD_CONFIG_D6 EFUSE_BLK1 102 6
147 SPI_PAD_CONFIG_D7 EFUSE_BLK1 108 6
148 WAFER_VERSION_MINOR_LO EFUSE_BLK1 114 3
149 PKG_VERSION EFUSE_BLK1 117 3
150 BLK_VERSION_MINOR EFUSE_BLK1 120 3
151 K_RTC_LDO EFUSE_BLK1 135 7
152 K_DIG_LDO EFUSE_BLK1 142 7
153 V_RTC_DBIAS20 EFUSE_BLK1 149 8
154 V_DIG_DBIAS20 EFUSE_BLK1 157 8
155 DIG_DBIAS_HVT EFUSE_BLK1 165 5
156 THRES_HVT EFUSE_BLK1 170 10
157 WAFER_VERSION_MINOR_HI EFUSE_BLK1 183 1
158 WAFER_VERSION_MAJOR EFUSE_BLK1 184 2
159 SYS_DATA_PART2 EFUSE_BLK10 0 256
160 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
161 BLK_VERSION_MAJOR EFUSE_BLK2 128 2
162 TEMP_CALIB EFUSE_BLK2 131 9
163 OCODE EFUSE_BLK2 140 8
164 ADC1_INIT_CODE_ATTEN0 EFUSE_BLK2 148 10
165 ADC1_INIT_CODE_ATTEN1 EFUSE_BLK2 158 10
166 ADC1_INIT_CODE_ATTEN2 EFUSE_BLK2 168 10
167 ADC1_INIT_CODE_ATTEN3 EFUSE_BLK2 178 10
168 ADC1_CAL_VOL_ATTEN0 EFUSE_BLK2 188 10
169 ADC1_CAL_VOL_ATTEN1 EFUSE_BLK2 198 10
170 ADC1_CAL_VOL_ATTEN2 EFUSE_BLK2 208 10
171 ADC1_CAL_VOL_ATTEN3 EFUSE_BLK2 218 10
172 USER_DATA EFUSE_BLK3 0 256
173 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
174 KEY0 EFUSE_BLK4 0 256
175 KEY1 EFUSE_BLK5 0 256
176 KEY2 EFUSE_BLK6 0 256
177 KEY3 EFUSE_BLK7 0 256
178 KEY4 EFUSE_BLK8 0 256
179 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [40 44] [46 52] [57 58] [80 111] [116 117] [124 130] [132 135] [141 157] [159 161]
EFUSE_BLK1
[0 122] [135 179] [183 185]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 129] [131 227]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,170 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Verifying efuse table...
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
5 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
6 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
7 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
8 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
9 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
10 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
11 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
12 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
13 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
14 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
15 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
16 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
17 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
18 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
19 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
20 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
21 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
22 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
23 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
24 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 17 1
25 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
26 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
27 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
28 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
29 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
30 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
31 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
32 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
33 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
34 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 19 1
35 WR_DIS.BLK1 EFUSE_BLK0 20 1
36 WR_DIS.MAC EFUSE_BLK0 20 1
37 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
38 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
39 WR_DIS.BLOCK_SYS_DATA1 EFUSE_BLK0 21 1
40 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
41 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
42 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
43 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
44 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
45 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
46 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
47 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
48 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
49 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
50 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
51 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
52 RD_DIS EFUSE_BLK0 32 7
53 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
54 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
55 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
56 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
57 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
58 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
59 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
60 DIS_ICACHE EFUSE_BLK0 40 1
61 DIS_USB_JTAG EFUSE_BLK0 41 1
62 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
63 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
64 DIS_TWAI EFUSE_BLK0 46 1
65 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
66 SOFT_DIS_JTAG EFUSE_BLK0 48 3
67 DIS_PAD_JTAG EFUSE_BLK0 51 1
68 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
69 USB_EXCHG_PINS EFUSE_BLK0 57 1
70 VDD_SPI_AS_GPIO EFUSE_BLK0 58 1
71 KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 64 4
72 KM_RND_SWITCH_CYCLE EFUSE_BLK0 68 2
73 KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 70 4
74 FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 74 4
75 FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 78 1
76 WDT_DELAY_SEL EFUSE_BLK0 80 2
77 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
78 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
79 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
80 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
81 KEY_PURPOSE_0 EFUSE_BLK0 88 4
82 KEY_PURPOSE_1 EFUSE_BLK0 92 4
83 KEY_PURPOSE_2 EFUSE_BLK0 96 4
84 KEY_PURPOSE_3 EFUSE_BLK0 100 4
85 KEY_PURPOSE_4 EFUSE_BLK0 104 4
86 KEY_PURPOSE_5 EFUSE_BLK0 108 4
87 SEC_DPA_LEVEL EFUSE_BLK0 112 2
88 SECURE_BOOT_EN EFUSE_BLK0 116 1
89 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
90 KM_XTS_KEY_LENGTH_256 EFUSE_BLK0 123 1
91 FLASH_TPUW EFUSE_BLK0 124 4
92 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
93 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
94 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
95 LOCK_KM_KEY EFUSE_BLK0 131 1
96 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
97 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
98 UART_PRINT_CONTROL EFUSE_BLK0 134 2
99 FORCE_SEND_RESUME EFUSE_BLK0 136 1
100 SECURE_VERSION EFUSE_BLK0 137 16
101 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 153 1
102 HYS_EN_PAD EFUSE_BLK0 154 1
103 XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 155 2
104 XTS_DPA_CLK_ENABLE EFUSE_BLK0 157 1
105 HUK_GEN_STATE EFUSE_BLK0 160 9
106 XTAL_48M_SEL EFUSE_BLK0 169 3
107 XTAL_48M_SEL_MODE EFUSE_BLK0 172 1
108 ECDSA_DISABLE_P192 EFUSE_BLK0 173 1
109 ECC_FORCE_CONST_TIME EFUSE_BLK0 174 1
110 MAC EFUSE_BLK1 0 8
111 MAC EFUSE_BLK1 8 8
112 MAC EFUSE_BLK1 16 8
113 MAC EFUSE_BLK1 24 8
114 MAC EFUSE_BLK1 32 8
115 MAC EFUSE_BLK1 40 8
116 MAC_EXT EFUSE_BLK1 48 16
117 SYS_DATA_PART2 EFUSE_BLK10 0 256
118 BLOCK_SYS_DATA1 EFUSE_BLK2 0 256
119 USER_DATA EFUSE_BLK3 0 256
120 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
121 KEY0 EFUSE_BLK4 0 256
122 KEY1 EFUSE_BLK5 0 256
123 KEY2 EFUSE_BLK6 0 256
124 KEY3 EFUSE_BLK7 0 256
125 KEY4 EFUSE_BLK8 0 256
126 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [40 41] [44 52] [57 58] [64 78] [80 113] [116 117] [123 157] [160 174]
EFUSE_BLK1
[0 63]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 255]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,174 @@
.. code-block:: none
$ ./efuse_table_gen.py -t IDF_TARGET_PATH_NAME {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Parsing efuse CSV input file esp32c6/esp_efuse_table.csv ...
Verifying efuse table...
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.CRYPT_DPA_ENABLE EFUSE_BLK0 1 1
4 WR_DIS.SWAP_UART_SDIO_EN EFUSE_BLK0 2 1
5 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
6 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
7 WR_DIS.DIS_DOWNLOAD_ICACHE EFUSE_BLK0 2 1
8 WR_DIS.DIS_USB_SERIAL_JTAG EFUSE_BLK0 2 1
9 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
10 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
11 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
12 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
13 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
14 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
15 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
16 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
17 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
18 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
19 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
20 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
21 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
22 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
23 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
24 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
25 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
26 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
27 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
28 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 17 1
29 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
30 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
31 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
32 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
33 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
34 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
35 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
36 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
37 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
38 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 19 1
39 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 19 1
40 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 19 1
41 WR_DIS.BLK1 EFUSE_BLK0 20 1
42 WR_DIS.MAC EFUSE_BLK0 20 1
43 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
44 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
45 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
46 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
47 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
48 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
49 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
50 WR_DIS.FLASH_TEMP EFUSE_BLK0 20 1
51 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
52 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
53 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
54 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
55 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
56 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
57 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
58 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
59 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
60 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
61 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
62 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
63 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
64 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
65 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
66 RD_DIS EFUSE_BLK0 32 7
67 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
68 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
69 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
70 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
71 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
72 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
73 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
74 SWAP_UART_SDIO_EN EFUSE_BLK0 39 1
75 DIS_ICACHE EFUSE_BLK0 40 1
76 DIS_USB_JTAG EFUSE_BLK0 41 1
77 DIS_DOWNLOAD_ICACHE EFUSE_BLK0 42 1
78 DIS_USB_SERIAL_JTAG EFUSE_BLK0 43 1
79 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
80 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
81 DIS_TWAI EFUSE_BLK0 46 1
82 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
83 SOFT_DIS_JTAG EFUSE_BLK0 48 3
84 DIS_PAD_JTAG EFUSE_BLK0 51 1
85 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
86 USB_EXCHG_PINS EFUSE_BLK0 57 1
87 VDD_SPI_AS_GPIO EFUSE_BLK0 58 1
88 WDT_DELAY_SEL EFUSE_BLK0 80 2
89 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
90 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
91 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
92 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
93 KEY_PURPOSE_0 EFUSE_BLK0 88 4
94 KEY_PURPOSE_1 EFUSE_BLK0 92 4
95 KEY_PURPOSE_2 EFUSE_BLK0 96 4
96 KEY_PURPOSE_3 EFUSE_BLK0 100 4
97 KEY_PURPOSE_4 EFUSE_BLK0 104 4
98 KEY_PURPOSE_5 EFUSE_BLK0 108 4
99 SEC_DPA_LEVEL EFUSE_BLK0 112 2
100 CRYPT_DPA_ENABLE EFUSE_BLK0 114 1
101 SECURE_BOOT_EN EFUSE_BLK0 116 1
102 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
103 FLASH_TPUW EFUSE_BLK0 124 4
104 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
105 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
106 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
107 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
108 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
109 UART_PRINT_CONTROL EFUSE_BLK0 134 2
110 FORCE_SEND_RESUME EFUSE_BLK0 141 1
111 SECURE_VERSION EFUSE_BLK0 142 16
112 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 158 1
113 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 160 1
114 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 161 1
115 MAC EFUSE_BLK1 0 8
116 MAC EFUSE_BLK1 8 8
117 MAC EFUSE_BLK1 16 8
118 MAC EFUSE_BLK1 24 8
119 MAC EFUSE_BLK1 32 8
120 MAC EFUSE_BLK1 40 8
121 MAC_EXT EFUSE_BLK1 48 16
122 WAFER_VERSION_MINOR EFUSE_BLK1 114 4
123 WAFER_VERSION_MAJOR EFUSE_BLK1 118 2
124 PKG_VERSION EFUSE_BLK1 120 3
125 BLK_VERSION_MINOR EFUSE_BLK1 123 3
126 BLK_VERSION_MAJOR EFUSE_BLK1 126 2
127 FLASH_CAP EFUSE_BLK1 128 3
128 FLASH_TEMP EFUSE_BLK1 131 2
129 FLASH_VENDOR EFUSE_BLK1 133 3
130 SYS_DATA_PART2 EFUSE_BLK10 0 256
131 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
132 USER_DATA EFUSE_BLK3 0 256
133 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
134 KEY0 EFUSE_BLK4 0 256
135 KEY1 EFUSE_BLK5 0 256
136 KEY2 EFUSE_BLK6 0 256
137 KEY3 EFUSE_BLK7 0 256
138 KEY4 EFUSE_BLK8 0 256
139 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 2] [2 2] ... [30 38] [32 52] [57 58] [80 114] [116 117] [124 130] [132 135] [141 158] [160 161]
EFUSE_BLK1
[0 63] [114 135]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 127]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,233 @@
.. code-block:: none
$ ./efuse_table_gen.py -t IDF_TARGET_PATH_NAME {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Parsing efuse CSV input file esp32c61/esp_efuse_table.csv ...
Verifying efuse table...
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
5 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
6 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 2 1
7 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
8 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
9 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
10 WR_DIS.HYS_EN_PAD EFUSE_BLK0 2 1
11 WR_DIS.DIS_WIFI6 EFUSE_BLK0 2 1
12 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
13 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
14 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
15 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
16 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
17 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
18 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
19 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
20 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
21 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
22 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
23 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
24 WR_DIS.XTS_DPA_CLK_ENABLE EFUSE_BLK0 14 1
25 WR_DIS.XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 14 1
26 WR_DIS.ECDSA_DISABLE_P192 EFUSE_BLK0 14 1
27 WR_DIS.ECC_FORCE_CONST_TIME EFUSE_BLK0 14 1
28 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
29 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
30 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
31 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
32 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
33 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
34 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
35 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
36 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
37 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
38 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
39 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 18 1
40 WR_DIS.BLK1 EFUSE_BLK0 20 1
41 WR_DIS.MAC EFUSE_BLK0 20 1
42 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
43 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
44 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
45 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 20 1
46 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
47 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
48 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
49 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
50 WR_DIS.PSRAM_CAP EFUSE_BLK0 20 1
51 WR_DIS.PSRAM_VENDOR EFUSE_BLK0 20 1
52 WR_DIS.TEMP EFUSE_BLK0 20 1
53 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
54 WR_DIS.ACTIVE_HP_DBIAS EFUSE_BLK0 20 1
55 WR_DIS.ACTIVE_LP_DBIAS EFUSE_BLK0 20 1
56 WR_DIS.LSLP_HP_DBG EFUSE_BLK0 20 1
57 WR_DIS.LSLP_HP_DBIAS EFUSE_BLK0 20 1
58 WR_DIS.DSLP_LP_DBG EFUSE_BLK0 20 1
59 WR_DIS.DSLP_LP_DBIAS EFUSE_BLK0 20 1
60 WR_DIS.LP_HP_DBIAS_VOL_GAP EFUSE_BLK0 20 1
61 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
62 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
63 WR_DIS.TEMPERATURE_SENSOR EFUSE_BLK0 21 1
64 WR_DIS.OCODE EFUSE_BLK0 21 1
65 WR_DIS.ADC1_AVE_INIT_CODE_ATTEN0 EFUSE_BLK0 21 1
66 WR_DIS.ADC1_AVE_INIT_CODE_ATTEN1 EFUSE_BLK0 21 1
67 WR_DIS.ADC1_AVE_INIT_CODE_ATTEN2 EFUSE_BLK0 21 1
68 WR_DIS.ADC1_AVE_INIT_CODE_ATTEN3 EFUSE_BLK0 21 1
69 WR_DIS.ADC1_HI_DOUT_ATTEN0 EFUSE_BLK0 21 1
70 WR_DIS.ADC1_HI_DOUT_ATTEN1 EFUSE_BLK0 21 1
71 WR_DIS.ADC1_HI_DOUT_ATTEN2 EFUSE_BLK0 21 1
72 WR_DIS.ADC1_HI_DOUT_ATTEN3 EFUSE_BLK0 21 1
73 WR_DIS.ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
74 WR_DIS.ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
75 WR_DIS.ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
76 WR_DIS.ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
77 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
78 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
79 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
80 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
81 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
82 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
83 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
84 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
85 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
86 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
87 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
88 RD_DIS EFUSE_BLK0 32 7
89 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
90 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
91 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
92 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
93 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
94 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
95 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
96 DIS_ICACHE EFUSE_BLK0 39 1
97 DIS_USB_JTAG EFUSE_BLK0 40 1
98 DIS_FORCE_DOWNLOAD EFUSE_BLK0 42 1
99 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 43 1
100 JTAG_SEL_ENABLE EFUSE_BLK0 44 1
101 DIS_PAD_JTAG EFUSE_BLK0 45 1
102 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 46 1
103 USB_EXCHG_PINS EFUSE_BLK0 51 1
104 VDD_SPI_AS_GPIO EFUSE_BLK0 52 1
105 WDT_DELAY_SEL EFUSE_BLK0 53 2
106 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 55 3
107 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 58 1
108 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 59 1
109 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 60 1
110 KEY_PURPOSE_0 EFUSE_BLK0 64 4
111 KEY_PURPOSE_1 EFUSE_BLK0 68 4
112 KEY_PURPOSE_2 EFUSE_BLK0 72 4
113 KEY_PURPOSE_3 EFUSE_BLK0 76 4
114 KEY_PURPOSE_4 EFUSE_BLK0 80 4
115 KEY_PURPOSE_5 EFUSE_BLK0 84 4
116 SEC_DPA_LEVEL EFUSE_BLK0 88 2
117 SECURE_BOOT_EN EFUSE_BLK0 90 1
118 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 91 1
119 FLASH_TPUW EFUSE_BLK0 92 4
120 DIS_DOWNLOAD_MODE EFUSE_BLK0 96 1
121 DIS_DIRECT_BOOT EFUSE_BLK0 97 1
122 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 98 1
123 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 99 1
124 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 100 1
125 UART_PRINT_CONTROL EFUSE_BLK0 101 2
126 FORCE_SEND_RESUME EFUSE_BLK0 103 1
127 SECURE_VERSION EFUSE_BLK0 104 16
128 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 120 1
129 HYS_EN_PAD EFUSE_BLK0 121 1
130 XTS_DPA_CLK_ENABLE EFUSE_BLK0 122 1
131 XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 123 2
132 DIS_WIFI6 EFUSE_BLK0 125 1
133 ECDSA_DISABLE_P192 EFUSE_BLK0 126 1
134 ECC_FORCE_CONST_TIME EFUSE_BLK0 127 1
135 BOOTLOADER_ANTI_ROLLBACK_SECURE_VERSION EFUSE_BLK0 128 4
136 BOOTLOADER_ANTI_ROLLBACK_EN EFUSE_BLK0 132 1
137 BOOTLOADER_ANTI_ROLLBACK_UPDATE_IN_ROM EFUSE_BLK0 133 1
138 RECOVERY_BOOTLOADER_FLASH_SECTOR EFUSE_BLK0 134 12
139 REPEAT_DATA4 EFUSE_BLK0 160 24
140 MAC EFUSE_BLK1 0 8
141 MAC EFUSE_BLK1 8 8
142 MAC EFUSE_BLK1 16 8
143 MAC EFUSE_BLK1 24 8
144 MAC EFUSE_BLK1 32 8
145 MAC EFUSE_BLK1 40 8
146 WAFER_VERSION_MINOR EFUSE_BLK1 64 4
147 WAFER_VERSION_MAJOR EFUSE_BLK1 68 2
148 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 70 1
149 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK1 71 1
150 BLK_VERSION_MINOR EFUSE_BLK1 72 3
151 BLK_VERSION_MAJOR EFUSE_BLK1 75 2
152 FLASH_CAP EFUSE_BLK1 77 3
153 FLASH_VENDOR EFUSE_BLK1 80 3
154 PSRAM_CAP EFUSE_BLK1 83 3
155 PSRAM_VENDOR EFUSE_BLK1 86 2
156 TEMP EFUSE_BLK1 88 2
157 PKG_VERSION EFUSE_BLK1 90 3
158 ACTIVE_HP_DBIAS EFUSE_BLK1 93 4
159 ACTIVE_LP_DBIAS EFUSE_BLK1 97 4
160 LSLP_HP_DBG EFUSE_BLK1 101 2
161 LSLP_HP_DBIAS EFUSE_BLK1 103 4
162 DSLP_LP_DBG EFUSE_BLK1 107 4
163 DSLP_LP_DBIAS EFUSE_BLK1 111 5
164 LP_HP_DBIAS_VOL_GAP EFUSE_BLK1 116 5
165 SYS_DATA_PART2 EFUSE_BLK10 0 256
166 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
167 TEMPERATURE_SENSOR EFUSE_BLK2 128 9
168 OCODE EFUSE_BLK2 137 8
169 ADC1_AVE_INIT_CODE_ATTEN0 EFUSE_BLK2 145 10
170 ADC1_AVE_INIT_CODE_ATTEN1 EFUSE_BLK2 155 10
171 ADC1_AVE_INIT_CODE_ATTEN2 EFUSE_BLK2 165 10
172 ADC1_AVE_INIT_CODE_ATTEN3 EFUSE_BLK2 175 10
173 ADC1_HI_DOUT_ATTEN0 EFUSE_BLK2 185 10
174 ADC1_HI_DOUT_ATTEN1 EFUSE_BLK2 195 10
175 ADC1_HI_DOUT_ATTEN2 EFUSE_BLK2 205 10
176 ADC1_HI_DOUT_ATTEN3 EFUSE_BLK2 215 10
177 ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK2 225 4
178 ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK2 229 4
179 ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK2 233 4
180 ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK2 237 4
181 USER_DATA EFUSE_BLK3 0 256
182 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
183 KEY0 EFUSE_BLK4 0 256
184 KEY1 EFUSE_BLK5 0 256
185 KEY2 EFUSE_BLK6 0 256
186 KEY3 EFUSE_BLK7 0 256
187 KEY4 EFUSE_BLK8 0 256
188 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [64 145] [160 183]
EFUSE_BLK1
[0 47] [64 120]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 240]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,177 @@
.. code-block:: none
$ ./efuse_table_gen.py -t IDF_TARGET_PATH_NAME {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Parsing efuse CSV input file esp32c6/esp_efuse_table.csv ...
Verifying efuse table...
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
5 WR_DIS.POWERGLITCH_EN EFUSE_BLK0 2 1
6 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
7 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 2 1
8 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
9 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
10 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
11 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
12 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
13 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
14 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
15 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
16 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
17 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
18 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
19 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
20 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
21 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
22 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
23 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
24 WR_DIS.CRYPT_DPA_ENABLE EFUSE_BLK0 14 1
25 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
26 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
27 WR_DIS.ECDSA_FORCE_USE_HARDWARE_K EFUSE_BLK0 17 1
28 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
29 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
30 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
31 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
32 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
33 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
34 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
35 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
36 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
37 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 18 1
38 WR_DIS.HYS_EN_PAD0 EFUSE_BLK0 19 1
39 WR_DIS.HYS_EN_PAD1 EFUSE_BLK0 19 1
40 WR_DIS.BLK1 EFUSE_BLK0 20 1
41 WR_DIS.MAC EFUSE_BLK0 20 1
42 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
43 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
44 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
45 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
46 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
47 WR_DIS.FLASH_TEMP EFUSE_BLK0 20 1
48 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
49 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
50 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
51 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
52 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 21 1
53 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 21 1
54 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 21 1
55 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
56 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
57 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
58 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
59 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
60 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
61 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
62 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
63 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
64 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
65 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
66 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
67 RD_DIS EFUSE_BLK0 32 7
68 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
69 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
70 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
71 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
72 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
73 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
74 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
75 DIS_ICACHE EFUSE_BLK0 40 1
76 DIS_USB_JTAG EFUSE_BLK0 41 1
77 POWERGLITCH_EN EFUSE_BLK0 42 1
78 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
79 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
80 DIS_TWAI EFUSE_BLK0 46 1
81 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
82 SOFT_DIS_JTAG EFUSE_BLK0 48 3
83 DIS_PAD_JTAG EFUSE_BLK0 51 1
84 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
85 USB_EXCHG_PINS EFUSE_BLK0 57 1
86 VDD_SPI_AS_GPIO EFUSE_BLK0 58 1
87 WDT_DELAY_SEL EFUSE_BLK0 80 2
88 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
89 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
90 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
91 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
92 KEY_PURPOSE_0 EFUSE_BLK0 88 4
93 KEY_PURPOSE_1 EFUSE_BLK0 92 4
94 KEY_PURPOSE_2 EFUSE_BLK0 96 4
95 KEY_PURPOSE_3 EFUSE_BLK0 100 4
96 KEY_PURPOSE_4 EFUSE_BLK0 104 4
97 KEY_PURPOSE_5 EFUSE_BLK0 108 4
98 SEC_DPA_LEVEL EFUSE_BLK0 112 2
99 ECDSA_FORCE_USE_HARDWARE_K EFUSE_BLK0 114 1
100 CRYPT_DPA_ENABLE EFUSE_BLK0 115 1
101 SECURE_BOOT_EN EFUSE_BLK0 116 1
102 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
103 FLASH_TPUW EFUSE_BLK0 124 4
104 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
105 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
106 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
107 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
108 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
109 UART_PRINT_CONTROL EFUSE_BLK0 134 2
110 FORCE_SEND_RESUME EFUSE_BLK0 136 1
111 SECURE_VERSION EFUSE_BLK0 137 16
112 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 153 1
113 HYS_EN_PAD0 EFUSE_BLK0 154 6
114 HYS_EN_PAD1 EFUSE_BLK0 160 22
115 MAC EFUSE_BLK1 0 8
116 MAC EFUSE_BLK1 8 8
117 MAC EFUSE_BLK1 16 8
118 MAC EFUSE_BLK1 24 8
119 MAC EFUSE_BLK1 32 8
120 MAC EFUSE_BLK1 40 8
121 MAC_EXT EFUSE_BLK1 48 16
122 WAFER_VERSION_MINOR EFUSE_BLK1 114 3
123 WAFER_VERSION_MAJOR EFUSE_BLK1 117 2
124 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 119 1
125 FLASH_CAP EFUSE_BLK1 120 3
126 FLASH_TEMP EFUSE_BLK1 123 2
127 FLASH_VENDOR EFUSE_BLK1 125 3
128 PKG_VERSION EFUSE_BLK1 128 3
129 SYS_DATA_PART2 EFUSE_BLK10 0 256
130 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
131 BLK_VERSION_MINOR EFUSE_BLK2 130 3
132 BLK_VERSION_MAJOR EFUSE_BLK2 133 2
133 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK2 135 1
134 USER_DATA EFUSE_BLK3 0 256
135 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
136 KEY0 EFUSE_BLK4 0 256
137 KEY1 EFUSE_BLK5 0 256
138 KEY2 EFUSE_BLK6 0 256
139 KEY3 EFUSE_BLK7 0 256
140 KEY4 EFUSE_BLK8 0 256
141 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [21 22] [22 30] [30 38] [32 38] [40 42] [44 52] [57 58] [80 117] [124 130] [132 181]
EFUSE_BLK1
[0 63] [114 130]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 127] [130 135]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,240 @@
.. code-block:: none
$ ./efuse_table_gen.py --idf_target {IDF_TARGET_PATH_NAME} {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Parsing efuse CSV input file esp32h21/esp_efuse_table.csv ...
Verifying efuse table...
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
5 WR_DIS.POWERGLITCH_EN EFUSE_BLK0 2 1
6 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
7 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 2 1
8 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
9 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
10 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
11 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
12 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
13 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
14 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
15 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
16 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
17 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
18 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
19 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
20 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
21 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
22 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
23 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
24 WR_DIS.CRYPT_DPA_ENABLE EFUSE_BLK0 14 1
25 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
26 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
27 WR_DIS.ECDSA_CURVE_MODE EFUSE_BLK0 17 1
28 WR_DIS.ECC_FORCE_CONST_TIME EFUSE_BLK0 17 1
29 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
30 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
31 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
32 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
33 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
34 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
35 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
36 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
37 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
38 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 18 1
39 WR_DIS.HYS_EN_PAD0 EFUSE_BLK0 19 1
40 WR_DIS.HYS_EN_PAD1 EFUSE_BLK0 19 1
41 WR_DIS.BLK1 EFUSE_BLK0 20 1
42 WR_DIS.MAC EFUSE_BLK0 20 1
43 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
44 WR_DIS.RXIQ_VERSION EFUSE_BLK0 20 1
45 WR_DIS.RXIQ_0 EFUSE_BLK0 20 1
46 WR_DIS.RXIQ_1 EFUSE_BLK0 20 1
47 WR_DIS.ACTIVE_HP_DBIAS EFUSE_BLK0 20 1
48 WR_DIS.ACTIVE_LP_DBIAS EFUSE_BLK0 20 1
49 WR_DIS.DSLP_DBIAS EFUSE_BLK0 20 1
50 WR_DIS.DBIAS_VOL_GAP EFUSE_BLK0 20 1
51 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
52 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
53 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
54 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
55 WR_DIS.FLASH_TEMP EFUSE_BLK0 20 1
56 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
57 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
58 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
59 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
60 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 21 1
61 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 21 1
62 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 21 1
63 WR_DIS.TEMP_CALIB EFUSE_BLK0 21 1
64 WR_DIS.ADC1_AVE_INITCODE_ATTEN0 EFUSE_BLK0 21 1
65 WR_DIS.ADC1_AVE_INITCODE_ATTEN1 EFUSE_BLK0 21 1
66 WR_DIS.ADC1_AVE_INITCODE_ATTEN2 EFUSE_BLK0 21 1
67 WR_DIS.ADC1_AVE_INITCODE_ATTEN3 EFUSE_BLK0 21 1
68 WR_DIS.ADC1_HI_DOUT_ATTEN0 EFUSE_BLK0 21 1
69 WR_DIS.ADC1_HI_DOUT_ATTEN1 EFUSE_BLK0 21 1
70 WR_DIS.ADC1_HI_DOUT_ATTEN2 EFUSE_BLK0 21 1
71 WR_DIS.ADC1_HI_DOUT_ATTEN3 EFUSE_BLK0 21 1
72 WR_DIS.ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
73 WR_DIS.ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
74 WR_DIS.ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
75 WR_DIS.ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
76 WR_DIS.ADC1_CH4_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
77 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
78 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
79 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
80 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
81 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
82 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
83 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
84 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
85 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
86 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
87 WR_DIS.VDD_SPI_AS_GPIO EFUSE_BLK0 30 1
88 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
89 RD_DIS EFUSE_BLK0 32 7
90 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
91 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
92 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
93 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
94 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
95 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
96 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
97 PVT_GLITCH_EN EFUSE_BLK0 39 1
98 DIS_ICACHE EFUSE_BLK0 40 1
99 DIS_USB_JTAG EFUSE_BLK0 41 1
100 POWERGLITCH_EN EFUSE_BLK0 42 1
101 DIS_USJ EFUSE_BLK0 43 1
102 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
103 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
104 DIS_TWAI EFUSE_BLK0 46 1
105 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
106 SOFT_DIS_JTAG EFUSE_BLK0 48 3
107 DIS_PAD_JTAG EFUSE_BLK0 51 1
108 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
109 USB_DREFH EFUSE_BLK0 53 2
110 USB_DREFL EFUSE_BLK0 55 2
111 USB_EXCHG_PINS EFUSE_BLK0 57 1
112 VDD_SPI_AS_GPIO EFUSE_BLK0 58 1
113 ECDSA_CURVE_MODE EFUSE_BLK0 59 2
114 ECC_FORCE_CONST_TIME EFUSE_BLK0 61 1
115 XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 62 2
116 IO_LDO_ADJUST EFUSE_BLK0 64 8
117 VDD_SPI_LDO_ADJUST EFUSE_BLK0 72 8
118 WDT_DELAY_SEL EFUSE_BLK0 80 2
119 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
120 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
121 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
122 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
123 KEY_PURPOSE_0 EFUSE_BLK0 88 4
124 KEY_PURPOSE_1 EFUSE_BLK0 92 4
125 KEY_PURPOSE_2 EFUSE_BLK0 96 4
126 KEY_PURPOSE_3 EFUSE_BLK0 100 4
127 KEY_PURPOSE_4 EFUSE_BLK0 104 4
128 KEY_PURPOSE_5 EFUSE_BLK0 108 4
129 SEC_DPA_LEVEL EFUSE_BLK0 112 2
130 IO_LDO_1P8 EFUSE_BLK0 114 1
131 CRYPT_DPA_ENABLE EFUSE_BLK0 115 1
132 SECURE_BOOT_EN EFUSE_BLK0 116 1
133 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
134 POWERGLITCH_EN1 EFUSE_BLK0 118 5
135 FLASH_TPUW EFUSE_BLK0 124 4
136 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
137 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
138 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
139 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
140 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
141 UART_PRINT_CONTROL EFUSE_BLK0 134 2
142 FORCE_SEND_RESUME EFUSE_BLK0 136 1
143 SECURE_VERSION EFUSE_BLK0 137 16
144 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 153 1
145 HYS_EN_PAD0 EFUSE_BLK0 154 6
146 HYS_EN_PAD1 EFUSE_BLK0 160 22
147 MAC EFUSE_BLK1 0 8
148 MAC EFUSE_BLK1 8 8
149 MAC EFUSE_BLK1 16 8
150 MAC EFUSE_BLK1 24 8
151 MAC EFUSE_BLK1 32 8
152 MAC EFUSE_BLK1 40 8
153 MAC_EXT EFUSE_BLK1 48 8
154 MAC_EXT EFUSE_BLK1 56 8
155 RXIQ_VERSION EFUSE_BLK1 64 3
156 RXIQ_0 EFUSE_BLK1 67 7
157 RXIQ_1 EFUSE_BLK1 74 7
158 ACTIVE_HP_DBIAS EFUSE_BLK1 81 5
159 ACTIVE_LP_DBIAS EFUSE_BLK1 86 5
160 DSLP_DBIAS EFUSE_BLK1 91 4
161 DBIAS_VOL_GAP EFUSE_BLK1 95 5
162 WAFER_VERSION_MINOR EFUSE_BLK1 114 3
163 WAFER_VERSION_MAJOR EFUSE_BLK1 117 2
164 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 119 1
165 FLASH_CAP EFUSE_BLK1 120 3
166 FLASH_TEMP EFUSE_BLK1 123 2
167 FLASH_VENDOR EFUSE_BLK1 125 3
168 PKG_VERSION EFUSE_BLK1 128 3
169 SYS_DATA_PART2 EFUSE_BLK10 0 256
170 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
171 BLK_VERSION_MINOR EFUSE_BLK2 130 3
172 BLK_VERSION_MAJOR EFUSE_BLK2 133 2
173 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK2 135 1
174 TEMP_CALIB EFUSE_BLK2 136 9
175 ADC1_AVE_INITCODE_ATTEN0 EFUSE_BLK2 145 10
176 ADC1_AVE_INITCODE_ATTEN1 EFUSE_BLK2 155 10
177 ADC1_AVE_INITCODE_ATTEN2 EFUSE_BLK2 165 10
178 ADC1_AVE_INITCODE_ATTEN3 EFUSE_BLK2 175 10
179 ADC1_HI_DOUT_ATTEN0 EFUSE_BLK2 185 10
180 ADC1_HI_DOUT_ATTEN1 EFUSE_BLK2 195 10
181 ADC1_HI_DOUT_ATTEN2 EFUSE_BLK2 205 10
182 ADC1_HI_DOUT_ATTEN3 EFUSE_BLK2 215 10
183 ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK2 225 4
184 ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK2 229 4
185 ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK2 233 4
186 ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK2 237 4
187 ADC1_CH4_ATTEN0_INITCODE_DIFF EFUSE_BLK2 241 4
188 USER_DATA EFUSE_BLK3 0 256
189 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
190 KEY0 EFUSE_BLK4 0 256
191 KEY1 EFUSE_BLK5 0 256
192 KEY2 EFUSE_BLK6 0 256
193 KEY3 EFUSE_BLK7 0 256
194 KEY4 EFUSE_BLK8 0 256
195 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [21 21] [21 22] [22 30] [30 38] [32 122] [124 130] [132 181]
EFUSE_BLK1
[0 99] [114 130]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 127] [130 244]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,282 @@
.. code-block:: none
$ ./efuse_table_gen.py --idf_target {IDF_TARGET_PATH_NAME} {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Parsing efuse CSV input file esp32h4/esp_efuse_table.csv ...
Verifying efuse table...
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 1 1
4 WR_DIS.KM_RND_SWITCH_CYCLE EFUSE_BLK0 1 1
5 WR_DIS.KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 1 1
6 WR_DIS.FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 1 1
7 WR_DIS.FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 1 1
8 WR_DIS.KM_XTS_KEY_LENGTH_256 EFUSE_BLK0 1 1
9 WR_DIS.LOCK_KM_KEY EFUSE_BLK0 1 1
10 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
11 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
12 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 2 1
13 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
14 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
15 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
16 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
17 WR_DIS.PVT_GLITCH_EN EFUSE_BLK0 2 1
18 WR_DIS.PVT_GLITCH_MODE EFUSE_BLK0 2 1
19 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
20 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
21 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
22 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
23 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
24 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
25 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
26 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
27 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
28 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
29 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
30 WR_DIS.XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 14 1
31 WR_DIS.XTS_DPA_CLK_ENABLE EFUSE_BLK0 14 1
32 WR_DIS.ECC_FORCE_CONST_TIME EFUSE_BLK0 14 1
33 WR_DIS.SECURE_BOOT_SHA384_EN EFUSE_BLK0 14 1
34 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
35 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
36 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
37 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
38 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
39 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
40 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
41 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
42 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
43 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
44 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
45 WR_DIS.HUK_GEN_STATE EFUSE_BLK0 19 1
46 WR_DIS.BLK1 EFUSE_BLK0 20 1
47 WR_DIS.MAC EFUSE_BLK0 20 1
48 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
49 WR_DIS.PVT_LIMIT EFUSE_BLK0 20 1
50 WR_DIS.PVT_CELL_SELECT EFUSE_BLK0 20 1
51 WR_DIS.PVT_PUMP_LIMIT EFUSE_BLK0 20 1
52 WR_DIS.PUMP_DRV EFUSE_BLK0 20 1
53 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 20 1
54 WR_DIS.HYS_EN_PAD EFUSE_BLK0 20 1
55 WR_DIS.PVT_GLITCH_CHARGE_RESET EFUSE_BLK0 20 1
56 WR_DIS.VDD_SPI_LDO_ADJUST EFUSE_BLK0 20 1
57 WR_DIS.FLASH_LDO_POWER_SEL EFUSE_BLK0 20 1
58 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
59 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
60 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
61 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 20 1
62 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
63 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
64 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
65 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
66 WR_DIS.PSRAM_CAP EFUSE_BLK0 20 1
67 WR_DIS.PSRAM_VENDOR EFUSE_BLK0 20 1
68 WR_DIS.TEMP EFUSE_BLK0 20 1
69 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
70 WR_DIS.PVT_DBIAS EFUSE_BLK0 20 1
71 WR_DIS.ADJUST_1V2 EFUSE_BLK0 20 1
72 WR_DIS.ADJUST_1V8 EFUSE_BLK0 20 1
73 WR_DIS.ACTIVE_DCDC_1V25 EFUSE_BLK0 20 1
74 WR_DIS.ACTIVE_DCDC_1V35 EFUSE_BLK0 20 1
75 WR_DIS.SLP_DCDC EFUSE_BLK0 20 1
76 WR_DIS.LSLP_HP_DRVB EFUSE_BLK0 20 1
77 WR_DIS.DSLP_LP_DBIAS EFUSE_BLK0 20 1
78 WR_DIS.TEMP_CALIB EFUSE_BLK0 20 1
79 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
80 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
81 WR_DIS.OCODE EFUSE_BLK0 21 1
82 WR_DIS.DCDC_OCODE EFUSE_BLK0 21 1
83 WR_DIS.VDD_3V4_DOUT EFUSE_BLK0 21 1
84 WR_DIS.ADC1_AVE_INITCODE_ATTEN0 EFUSE_BLK0 21 1
85 WR_DIS.ADC1_AVE_INITCODE_ATTEN1 EFUSE_BLK0 21 1
86 WR_DIS.ADC1_AVE_INITCODE_ATTEN2 EFUSE_BLK0 21 1
87 WR_DIS.ADC1_AVE_INITCODE_ATTEN3 EFUSE_BLK0 21 1
88 WR_DIS.ADC1_HI_DOUT_ATTEN0 EFUSE_BLK0 21 1
89 WR_DIS.ADC1_HI_DOUT_ATTEN1 EFUSE_BLK0 21 1
90 WR_DIS.ADC1_HI_DOUT_ATTEN2 EFUSE_BLK0 21 1
91 WR_DIS.ADC1_HI_DOUT_ATTEN3 EFUSE_BLK0 21 1
92 WR_DIS.ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
93 WR_DIS.ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
94 WR_DIS.ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
95 WR_DIS.ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
96 WR_DIS.ADC1_CH4_ATTEN0_INITCODE_DIFF EFUSE_BLK0 21 1
97 WR_DIS.INITCODE_DIFF_1P8_3P3 EFUSE_BLK0 21 1
98 WR_DIS.HI_DOUT_DIFF_1P8_3P3 EFUSE_BLK0 21 1
99 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
100 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
101 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
102 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
103 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
104 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
105 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
106 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
107 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
108 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
109 WR_DIS.USB_OTG_FS_EXCHG_PINS EFUSE_BLK0 30 1
110 WR_DIS.USB_PHY_SEL EFUSE_BLK0 30 1
111 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
112 RD_DIS EFUSE_BLK0 32 7
113 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
114 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
115 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
116 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
117 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
118 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
119 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
120 DIS_USB_JTAG EFUSE_BLK0 39 1
121 DIS_FORCE_DOWNLOAD EFUSE_BLK0 41 1
122 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 42 1
123 DIS_TWAI EFUSE_BLK0 43 1
124 JTAG_SEL_ENABLE EFUSE_BLK0 44 1
125 DIS_PAD_JTAG EFUSE_BLK0 45 1
126 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 46 1
127 PVT_GLITCH_EN EFUSE_BLK0 50 1
128 PVT_GLITCH_MODE EFUSE_BLK0 52 2
129 DIS_CORE1 EFUSE_BLK0 54 1
130 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 55 3
131 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 58 1
132 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 59 1
133 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 60 1
134 KEY_PURPOSE_0 EFUSE_BLK0 64 5
135 KEY_PURPOSE_1 EFUSE_BLK0 69 5
136 KEY_PURPOSE_2 EFUSE_BLK0 74 5
137 KEY_PURPOSE_3 EFUSE_BLK0 79 5
138 KEY_PURPOSE_4 EFUSE_BLK0 84 5
139 KEY_PURPOSE_5 EFUSE_BLK0 89 5
140 SEC_DPA_LEVEL EFUSE_BLK0 94 2
141 XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 96 2
142 XTS_DPA_CLK_ENABLE EFUSE_BLK0 98 1
143 ECC_FORCE_CONST_TIME EFUSE_BLK0 99 1
144 SECURE_BOOT_SHA384_EN EFUSE_BLK0 100 1
145 SECURE_BOOT_EN EFUSE_BLK0 101 1
146 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 102 1
147 KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 103 5
148 KM_RND_SWITCH_CYCLE EFUSE_BLK0 108 2
149 KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 110 5
150 FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 115 5
151 FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 120 1
152 KM_XTS_KEY_LENGTH_256 EFUSE_BLK0 121 1
153 LOCK_KM_KEY EFUSE_BLK0 122 1
154 FLASH_TPUW EFUSE_BLK0 123 3
155 DIS_DOWNLOAD_MODE EFUSE_BLK0 127 1
156 DIS_DIRECT_BOOT EFUSE_BLK0 128 1
157 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 129 1
158 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 130 1
159 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 131 1
160 UART_PRINT_CONTROL EFUSE_BLK0 132 2
161 FORCE_SEND_RESUME EFUSE_BLK0 134 1
162 SECURE_VERSION EFUSE_BLK0 135 16
163 HUK_GEN_STATE EFUSE_BLK0 151 5
164 FLASH_LDO_EFUSE_SEL EFUSE_BLK0 156 1
165 USB_EXCHG_PINS EFUSE_BLK0 168 1
166 USB_OTG_FS_EXCHG_PINS EFUSE_BLK0 169 1
167 USB_PHY_SEL EFUSE_BLK0 170 1
168 SOFT_DIS_JTAG EFUSE_BLK0 171 3
169 IO_LDO_ADJUST EFUSE_BLK0 174 8
170 IO_LDO_1P8 EFUSE_BLK0 182 1
171 DCDC_CCM_EN EFUSE_BLK0 183 1
172 MAC EFUSE_BLK1 0 8
173 MAC EFUSE_BLK1 8 8
174 MAC EFUSE_BLK1 16 8
175 MAC EFUSE_BLK1 24 8
176 MAC EFUSE_BLK1 32 8
177 MAC EFUSE_BLK1 40 8
178 MAC_EXT EFUSE_BLK1 48 8
179 MAC_EXT EFUSE_BLK1 56 8
180 PVT_LIMIT EFUSE_BLK1 64 16
181 PVT_CELL_SELECT EFUSE_BLK1 80 7
182 PVT_PUMP_LIMIT EFUSE_BLK1 87 8
183 PUMP_DRV EFUSE_BLK1 96 4
184 WDT_DELAY_SEL EFUSE_BLK1 100 2
185 HYS_EN_PAD EFUSE_BLK1 102 1
186 PVT_GLITCH_CHARGE_RESET EFUSE_BLK1 103 1
187 VDD_SPI_LDO_ADJUST EFUSE_BLK1 105 8
188 FLASH_LDO_POWER_SEL EFUSE_BLK1 113 1
189 WAFER_VERSION_MINOR EFUSE_BLK1 114 4
190 WAFER_VERSION_MAJOR EFUSE_BLK1 118 2
191 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 120 1
192 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK1 121 1
193 BLK_VERSION_MINOR EFUSE_BLK1 122 3
194 BLK_VERSION_MAJOR EFUSE_BLK1 125 2
195 FLASH_CAP EFUSE_BLK1 127 3
196 FLASH_VENDOR EFUSE_BLK1 130 3
197 PSRAM_CAP EFUSE_BLK1 133 3
198 PSRAM_VENDOR EFUSE_BLK1 136 2
199 TEMP EFUSE_BLK1 138 2
200 PKG_VERSION EFUSE_BLK1 140 3
201 PVT_DBIAS EFUSE_BLK1 143 5
202 ADJUST_1V2 EFUSE_BLK1 148 4
203 ADJUST_1V8 EFUSE_BLK1 152 4
204 ACTIVE_DCDC_1V25 EFUSE_BLK1 156 4
205 ACTIVE_DCDC_1V35 EFUSE_BLK1 160 4
206 SLP_DCDC EFUSE_BLK1 164 5
207 LSLP_HP_DRVB EFUSE_BLK1 169 5
208 DSLP_LP_DBIAS EFUSE_BLK1 174 2
209 TEMP_CALIB EFUSE_BLK1 176 10
210 SYS_DATA_PART2 EFUSE_BLK10 0 256
211 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
212 OCODE EFUSE_BLK2 128 8
213 DCDC_OCODE EFUSE_BLK2 136 8
214 VDD_3V4_DOUT EFUSE_BLK2 144 10
215 ADC1_AVE_INITCODE_ATTEN0 EFUSE_BLK2 154 9
216 ADC1_AVE_INITCODE_ATTEN1 EFUSE_BLK2 163 9
217 ADC1_AVE_INITCODE_ATTEN2 EFUSE_BLK2 172 9
218 ADC1_AVE_INITCODE_ATTEN3 EFUSE_BLK2 181 9
219 ADC1_HI_DOUT_ATTEN0 EFUSE_BLK2 190 9
220 ADC1_HI_DOUT_ATTEN1 EFUSE_BLK2 199 9
221 ADC1_HI_DOUT_ATTEN2 EFUSE_BLK2 208 9
222 ADC1_HI_DOUT_ATTEN3 EFUSE_BLK2 217 9
223 ADC1_CH0_ATTEN0_INITCODE_DIFF EFUSE_BLK2 226 3
224 ADC1_CH1_ATTEN0_INITCODE_DIFF EFUSE_BLK2 229 3
225 ADC1_CH2_ATTEN0_INITCODE_DIFF EFUSE_BLK2 232 3
226 ADC1_CH3_ATTEN0_INITCODE_DIFF EFUSE_BLK2 235 3
227 ADC1_CH4_ATTEN0_INITCODE_DIFF EFUSE_BLK2 238 3
228 INITCODE_DIFF_1P8_3P3 EFUSE_BLK2 241 5
229 HI_DOUT_DIFF_1P8_3P3 EFUSE_BLK2 246 5
230 USER_DATA EFUSE_BLK3 0 256
231 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
232 KEY0 EFUSE_BLK4 0 256
233 KEY1 EFUSE_BLK5 0 256
234 KEY2 EFUSE_BLK6 0 256
235 KEY3 EFUSE_BLK7 0 256
236 KEY4 EFUSE_BLK8 0 256
237 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 1] [1 1] ... [50 50] [52 60] [64 125] [127 156] [168 183]
EFUSE_BLK1
[0 94] [96 103] [105 185]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 250]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,180 @@
.. code-block:: none
$ ./efuse_table_gen.py -t IDF_TARGET_PATH_NAME {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Parsing efuse CSV input file ../esp32p4/esp_efuse_table.csv ...
Verifying efuse table...
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
4 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
5 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
6 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
7 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
8 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
9 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
10 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
11 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
12 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
13 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
14 WR_DIS.BLK1 EFUSE_BLK0 20 1
15 WR_DIS.MAC EFUSE_BLK0 20 1
16 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
17 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
18 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
19 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 20 1
20 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
21 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
22 WR_DIS.FLASH_CAP EFUSE_BLK0 20 1
23 WR_DIS.FLASH_TEMP EFUSE_BLK0 20 1
24 WR_DIS.FLASH_VENDOR EFUSE_BLK0 20 1
25 WR_DIS.PSRAM_CAP EFUSE_BLK0 20 1
26 WR_DIS.PSRAM_TEMP EFUSE_BLK0 20 1
27 WR_DIS.PSRAM_VENDOR EFUSE_BLK0 20 1
28 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
29 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
30 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
31 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
32 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
33 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
34 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
35 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
36 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
37 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
38 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
39 RD_DIS EFUSE_BLK0 32 7
40 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
41 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
42 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
43 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
44 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
45 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
46 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
47 USB_DEVICE_EXCHG_PINS EFUSE_BLK0 39 1
48 USB_OTG11_EXCHG_PINS EFUSE_BLK0 40 1
49 DIS_USB_JTAG EFUSE_BLK0 41 1
50 POWERGLITCH_EN EFUSE_BLK0 42 1
51 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
52 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
53 DIS_TWAI EFUSE_BLK0 46 1
54 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
55 SOFT_DIS_JTAG EFUSE_BLK0 48 3
56 DIS_PAD_JTAG EFUSE_BLK0 51 1
57 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
58 USB_PHY_SEL EFUSE_BLK0 57 1
59 KM_HUK_GEN_STATE EFUSE_BLK0 58 9
60 KM_RND_SWITCH_CYCLE EFUSE_BLK0 67 2
61 KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 69 4
62 FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 73 4
63 FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 77 1
64 XTS_KEY_LENGTH_256 EFUSE_BLK0 78 1
65 WDT_DELAY_SEL EFUSE_BLK0 80 2
66 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
67 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
68 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
69 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
70 KEY_PURPOSE_0 EFUSE_BLK0 88 4
71 KEY_PURPOSE_1 EFUSE_BLK0 92 4
72 KEY_PURPOSE_2 EFUSE_BLK0 96 4
73 KEY_PURPOSE_3 EFUSE_BLK0 100 4
74 KEY_PURPOSE_4 EFUSE_BLK0 104 4
75 KEY_PURPOSE_5 EFUSE_BLK0 108 4
76 SEC_DPA_LEVEL EFUSE_BLK0 112 2
77 ECDSA_ENABLE_SOFT_K EFUSE_BLK0 114 1
78 CRYPT_DPA_ENABLE EFUSE_BLK0 115 1
79 SECURE_BOOT_EN EFUSE_BLK0 116 1
80 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
81 FLASH_TYPE EFUSE_BLK0 119 1
82 FLASH_PAGE_SIZE EFUSE_BLK0 120 2
83 FLASH_ECC_EN EFUSE_BLK0 122 1
84 DIS_USB_OTG_DOWNLOAD_MODE EFUSE_BLK0 123 1
85 FLASH_TPUW EFUSE_BLK0 124 4
86 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
87 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
88 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
89 LOCK_KM_KEY EFUSE_BLK0 131 1
90 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
91 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
92 UART_PRINT_CONTROL EFUSE_BLK0 134 2
93 FORCE_SEND_RESUME EFUSE_BLK0 136 1
94 SECURE_VERSION EFUSE_BLK0 137 16
95 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 153 1
96 HYS_EN_PAD EFUSE_BLK0 154 1
97 DCDC_VSET EFUSE_BLK0 155 5
98 PXA0_TIEH_SEL_0 EFUSE_BLK0 160 2
99 PXA0_TIEH_SEL_1 EFUSE_BLK0 162 2
100 PXA0_TIEH_SEL_2 EFUSE_BLK0 164 2
101 PXA0_TIEH_SEL_3 EFUSE_BLK0 166 2
102 KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 168 4
103 HP_PWR_SRC_SEL EFUSE_BLK0 178 1
104 DCDC_VSET_EN EFUSE_BLK0 179 1
105 DIS_WDT EFUSE_BLK0 180 1
106 DIS_SWD EFUSE_BLK0 181 1
107 MAC EFUSE_BLK1 0 8
108 MAC EFUSE_BLK1 8 8
109 MAC EFUSE_BLK1 16 8
110 MAC EFUSE_BLK1 24 8
111 MAC EFUSE_BLK1 32 8
112 MAC EFUSE_BLK1 40 8
113 WAFER_VERSION_MINOR EFUSE_BLK1 64 4
114 WAFER_VERSION_MAJOR EFUSE_BLK1 68 2
115 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 70 1
116 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK1 71 1
117 BLK_VERSION_MINOR EFUSE_BLK1 72 3
118 BLK_VERSION_MAJOR EFUSE_BLK1 75 2
119 FLASH_CAP EFUSE_BLK1 77 3
120 FLASH_TEMP EFUSE_BLK1 80 2
121 FLASH_VENDOR EFUSE_BLK1 82 3
122 PSRAM_CAP EFUSE_BLK1 85 2
123 PSRAM_TEMP EFUSE_BLK1 87 2
124 PSRAM_VENDOR EFUSE_BLK1 89 2
125 PKG_VERSION EFUSE_BLK1 91 3
126 SYS_DATA_PART2 EFUSE_BLK10 0 256
127 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
128 USER_DATA EFUSE_BLK3 0 256
129 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
130 KEY0 EFUSE_BLK4 0 256
131 KEY1 EFUSE_BLK5 0 256
132 KEY2 EFUSE_BLK6 0 256
133 KEY3 EFUSE_BLK7 0 256
134 KEY4 EFUSE_BLK8 0 256
135 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [4 13] [15 15] [20 20] [20 20] [20 29] [32 38] [32 42] [44 52] [57 78] [80 117] [119 171] [178 181]
EFUSE_BLK1
[0 47] [64 93]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 127]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,234 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Parsing efuse CSV input file $IDF_PATH/components/efuse/esp32s2/esp_efuse_table.csv ...
Verifying efuse table...
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_DCACHE EFUSE_BLK0 2 1
5 WR_DIS.DIS_DOWNLOAD_ICACHE EFUSE_BLK0 2 1
6 WR_DIS.DIS_DOWNLOAD_DCACHE EFUSE_BLK0 2 1
7 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
8 WR_DIS.DIS_USB EFUSE_BLK0 2 1
9 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
10 WR_DIS.DIS_BOOT_REMAP EFUSE_BLK0 2 1
11 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 2 1
12 WR_DIS.HARD_DIS_JTAG EFUSE_BLK0 2 1
13 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
14 WR_DIS.VDD_SPI_XPD EFUSE_BLK0 3 1
15 WR_DIS.VDD_SPI_TIEH EFUSE_BLK0 3 1
16 WR_DIS.VDD_SPI_FORCE EFUSE_BLK0 3 1
17 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
18 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
19 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
20 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
21 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
22 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
23 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
24 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
25 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
26 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
27 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
28 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
29 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
30 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
31 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
32 WR_DIS.DIS_LEGACY_SPI_BOOT EFUSE_BLK0 18 1
33 WR_DIS.UART_PRINT_CHANNEL EFUSE_BLK0 18 1
34 WR_DIS.DIS_USB_DOWNLOAD_MODE EFUSE_BLK0 18 1
35 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
36 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
37 WR_DIS.PIN_POWER_SELECTION EFUSE_BLK0 18 1
38 WR_DIS.FLASH_TYPE EFUSE_BLK0 18 1
39 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
40 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
41 WR_DIS.BLK1 EFUSE_BLK0 20 1
42 WR_DIS.MAC EFUSE_BLK0 20 1
43 WR_DIS.SPI_PAD_CONFIG_CLK EFUSE_BLK0 20 1
44 WR_DIS.SPI_PAD_CONFIG_Q EFUSE_BLK0 20 1
45 WR_DIS.SPI_PAD_CONFIG_D EFUSE_BLK0 20 1
46 WR_DIS.SPI_PAD_CONFIG_CS EFUSE_BLK0 20 1
47 WR_DIS.SPI_PAD_CONFIG_HD EFUSE_BLK0 20 1
48 WR_DIS.SPI_PAD_CONFIG_WP EFUSE_BLK0 20 1
49 WR_DIS.SPI_PAD_CONFIG_DQS EFUSE_BLK0 20 1
50 WR_DIS.SPI_PAD_CONFIG_D4 EFUSE_BLK0 20 1
51 WR_DIS.SPI_PAD_CONFIG_D5 EFUSE_BLK0 20 1
52 WR_DIS.SPI_PAD_CONFIG_D6 EFUSE_BLK0 20 1
53 WR_DIS.SPI_PAD_CONFIG_D7 EFUSE_BLK0 20 1
54 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
55 WR_DIS.WAFER_VERSION_MINOR_HI EFUSE_BLK0 20 1
56 WR_DIS.FLASH_VERSION EFUSE_BLK0 20 1
57 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
58 WR_DIS.PSRAM_VERSION EFUSE_BLK0 20 1
59 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
60 WR_DIS.WAFER_VERSION_MINOR_LO EFUSE_BLK0 20 1
61 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
62 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
63 WR_DIS.ADC_CALIB EFUSE_BLK0 21 1
64 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 21 1
65 WR_DIS.TEMP_CALIB EFUSE_BLK0 21 1
66 WR_DIS.RTCCALIB_V1IDX_A10H EFUSE_BLK0 21 1
67 WR_DIS.RTCCALIB_V1IDX_A11H EFUSE_BLK0 21 1
68 WR_DIS.RTCCALIB_V1IDX_A12H EFUSE_BLK0 21 1
69 WR_DIS.RTCCALIB_V1IDX_A13H EFUSE_BLK0 21 1
70 WR_DIS.RTCCALIB_V1IDX_A20H EFUSE_BLK0 21 1
71 WR_DIS.RTCCALIB_V1IDX_A21H EFUSE_BLK0 21 1
72 WR_DIS.RTCCALIB_V1IDX_A22H EFUSE_BLK0 21 1
73 WR_DIS.RTCCALIB_V1IDX_A23H EFUSE_BLK0 21 1
74 WR_DIS.RTCCALIB_V1IDX_A10L EFUSE_BLK0 21 1
75 WR_DIS.RTCCALIB_V1IDX_A11L EFUSE_BLK0 21 1
76 WR_DIS.RTCCALIB_V1IDX_A12L EFUSE_BLK0 21 1
77 WR_DIS.RTCCALIB_V1IDX_A13L EFUSE_BLK0 21 1
78 WR_DIS.RTCCALIB_V1IDX_A20L EFUSE_BLK0 21 1
79 WR_DIS.RTCCALIB_V1IDX_A21L EFUSE_BLK0 21 1
80 WR_DIS.RTCCALIB_V1IDX_A22L EFUSE_BLK0 21 1
81 WR_DIS.RTCCALIB_V1IDX_A23L EFUSE_BLK0 21 1
82 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
83 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
84 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
85 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
86 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
87 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
88 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
89 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
90 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
91 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
92 WR_DIS.USB_EXT_PHY_ENABLE EFUSE_BLK0 30 1
93 WR_DIS.USB_FORCE_NOPERSIST EFUSE_BLK0 30 1
94 WR_DIS.BLOCK0_VERSION EFUSE_BLK0 30 1
95 RD_DIS EFUSE_BLK0 32 7
96 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
97 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
98 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
99 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
100 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
101 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
102 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
103 DIS_ICACHE EFUSE_BLK0 40 1
104 DIS_DCACHE EFUSE_BLK0 41 1
105 DIS_DOWNLOAD_ICACHE EFUSE_BLK0 42 1
106 DIS_DOWNLOAD_DCACHE EFUSE_BLK0 43 1
107 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
108 DIS_USB EFUSE_BLK0 45 1
109 DIS_TWAI EFUSE_BLK0 46 1
110 DIS_BOOT_REMAP EFUSE_BLK0 47 1
111 SOFT_DIS_JTAG EFUSE_BLK0 49 1
112 HARD_DIS_JTAG EFUSE_BLK0 50 1
113 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 51 1
114 USB_EXCHG_PINS EFUSE_BLK0 56 1
115 USB_EXT_PHY_ENABLE EFUSE_BLK0 57 1
116 USB_FORCE_NOPERSIST EFUSE_BLK0 58 1
117 BLOCK0_VERSION EFUSE_BLK0 59 2
118 VDD_SPI_XPD EFUSE_BLK0 68 1
119 VDD_SPI_TIEH EFUSE_BLK0 69 1
120 VDD_SPI_FORCE EFUSE_BLK0 70 1
121 WDT_DELAY_SEL EFUSE_BLK0 80 2
122 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
123 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
124 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
125 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
126 KEY_PURPOSE_0 EFUSE_BLK0 88 4
127 KEY_PURPOSE_1 EFUSE_BLK0 92 4
128 KEY_PURPOSE_2 EFUSE_BLK0 96 4
129 KEY_PURPOSE_3 EFUSE_BLK0 100 4
130 KEY_PURPOSE_4 EFUSE_BLK0 104 4
131 KEY_PURPOSE_5 EFUSE_BLK0 108 4
132 SECURE_BOOT_EN EFUSE_BLK0 116 1
133 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
134 FLASH_TPUW EFUSE_BLK0 124 4
135 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
136 DIS_LEGACY_SPI_BOOT EFUSE_BLK0 129 1
137 UART_PRINT_CHANNEL EFUSE_BLK0 130 1
138 DIS_USB_DOWNLOAD_MODE EFUSE_BLK0 132 1
139 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
140 UART_PRINT_CONTROL EFUSE_BLK0 134 2
141 PIN_POWER_SELECTION EFUSE_BLK0 136 1
142 FLASH_TYPE EFUSE_BLK0 137 1
143 FORCE_SEND_RESUME EFUSE_BLK0 138 1
144 SECURE_VERSION EFUSE_BLK0 139 16
145 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 160 1
146 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 161 1
147 MAC EFUSE_BLK1 0 8
148 MAC EFUSE_BLK1 8 8
149 MAC EFUSE_BLK1 16 8
150 MAC EFUSE_BLK1 24 8
151 MAC EFUSE_BLK1 32 8
152 MAC EFUSE_BLK1 40 8
153 SPI_PAD_CONFIG_CLK EFUSE_BLK1 48 6
154 SPI_PAD_CONFIG_Q EFUSE_BLK1 54 6
155 SPI_PAD_CONFIG_D EFUSE_BLK1 60 6
156 SPI_PAD_CONFIG_CS EFUSE_BLK1 66 6
157 SPI_PAD_CONFIG_HD EFUSE_BLK1 72 6
158 SPI_PAD_CONFIG_WP EFUSE_BLK1 78 6
159 SPI_PAD_CONFIG_DQS EFUSE_BLK1 84 6
160 SPI_PAD_CONFIG_D4 EFUSE_BLK1 90 6
161 SPI_PAD_CONFIG_D5 EFUSE_BLK1 96 6
162 SPI_PAD_CONFIG_D6 EFUSE_BLK1 102 6
163 SPI_PAD_CONFIG_D7 EFUSE_BLK1 108 6
164 WAFER_VERSION_MAJOR EFUSE_BLK1 114 2
165 WAFER_VERSION_MINOR_HI EFUSE_BLK1 116 1
166 FLASH_VERSION EFUSE_BLK1 117 4
167 BLK_VERSION_MAJOR EFUSE_BLK1 121 2
168 PSRAM_VERSION EFUSE_BLK1 124 4
169 PKG_VERSION EFUSE_BLK1 128 4
170 WAFER_VERSION_MINOR_LO EFUSE_BLK1 132 3
171 SYS_DATA_PART2 EFUSE_BLK10 0 256
172 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
173 ADC_CALIB EFUSE_BLK2 128 4
174 BLK_VERSION_MINOR EFUSE_BLK2 132 3
175 TEMP_CALIB EFUSE_BLK2 135 9
176 RTCCALIB_V1IDX_A10H EFUSE_BLK2 144 8
177 RTCCALIB_V1IDX_A11H EFUSE_BLK2 152 8
178 RTCCALIB_V1IDX_A12H EFUSE_BLK2 160 8
179 RTCCALIB_V1IDX_A13H EFUSE_BLK2 168 8
180 RTCCALIB_V1IDX_A20H EFUSE_BLK2 176 8
181 RTCCALIB_V1IDX_A21H EFUSE_BLK2 184 8
182 RTCCALIB_V1IDX_A22H EFUSE_BLK2 192 8
183 RTCCALIB_V1IDX_A23H EFUSE_BLK2 200 8
184 RTCCALIB_V1IDX_A10L EFUSE_BLK2 208 6
185 RTCCALIB_V1IDX_A11L EFUSE_BLK2 214 6
186 RTCCALIB_V1IDX_A12L EFUSE_BLK2 220 6
187 RTCCALIB_V1IDX_A13L EFUSE_BLK2 226 6
188 RTCCALIB_V1IDX_A20L EFUSE_BLK2 232 6
189 RTCCALIB_V1IDX_A21L EFUSE_BLK2 238 6
190 RTCCALIB_V1IDX_A22L EFUSE_BLK2 244 6
191 RTCCALIB_V1IDX_A23L EFUSE_BLK2 250 6
192 USER_DATA EFUSE_BLK3 0 256
193 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
194 KEY0 EFUSE_BLK4 0 256
195 KEY1 EFUSE_BLK5 0 256
196 KEY2 EFUSE_BLK6 0 256
197 KEY3 EFUSE_BLK7 0 256
198 KEY4 EFUSE_BLK8 0 256
199 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [32 38] [40 47] [49 51] [56 60] [68 70] [80 111] [116 117] [124 130] [132 154] [160 161]
EFUSE_BLK1
[0 122] [124 134]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 255]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,252 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.DIS_ICACHE EFUSE_BLK0 2 1
4 WR_DIS.DIS_DCACHE EFUSE_BLK0 2 1
5 WR_DIS.DIS_DOWNLOAD_ICACHE EFUSE_BLK0 2 1
6 WR_DIS.DIS_DOWNLOAD_DCACHE EFUSE_BLK0 2 1
7 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
8 WR_DIS.DIS_USB_OTG EFUSE_BLK0 2 1
9 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
10 WR_DIS.DIS_APP_CPU EFUSE_BLK0 2 1
11 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
12 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
13 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
14 WR_DIS.DIS_USB_SERIAL_JTAG EFUSE_BLK0 2 1
15 WR_DIS.STRAP_JTAG_SEL EFUSE_BLK0 2 1
16 WR_DIS.USB_PHY_SEL EFUSE_BLK0 2 1
17 WR_DIS.VDD_SPI_XPD EFUSE_BLK0 3 1
18 WR_DIS.VDD_SPI_TIEH EFUSE_BLK0 3 1
19 WR_DIS.VDD_SPI_FORCE EFUSE_BLK0 3 1
20 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 3 1
21 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
22 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
23 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
24 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
25 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
26 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
27 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
28 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
29 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
30 WR_DIS.KEY_PURPOSE_5 EFUSE_BLK0 13 1
31 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
32 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
33 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
34 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
35 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
36 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
37 WR_DIS.FLASH_ECC_MODE EFUSE_BLK0 18 1
38 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
39 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
40 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
41 WR_DIS.PIN_POWER_SELECTION EFUSE_BLK0 18 1
42 WR_DIS.FLASH_TYPE EFUSE_BLK0 18 1
43 WR_DIS.FLASH_PAGE_SIZE EFUSE_BLK0 18 1
44 WR_DIS.FLASH_ECC_EN EFUSE_BLK0 18 1
45 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
46 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
47 WR_DIS.DIS_USB_OTG_DOWNLOAD_MODE EFUSE_BLK0 19 1
48 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 19 1
49 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 19 1
50 WR_DIS.BLK1 EFUSE_BLK0 20 1
51 WR_DIS.MAC EFUSE_BLK0 20 1
52 WR_DIS.SPI_PAD_CONFIG_CLK EFUSE_BLK0 20 1
53 WR_DIS.SPI_PAD_CONFIG_Q EFUSE_BLK0 20 1
54 WR_DIS.SPI_PAD_CONFIG_D EFUSE_BLK0 20 1
55 WR_DIS.SPI_PAD_CONFIG_CS EFUSE_BLK0 20 1
56 WR_DIS.SPI_PAD_CONFIG_HD EFUSE_BLK0 20 1
57 WR_DIS.SPI_PAD_CONFIG_WP EFUSE_BLK0 20 1
58 WR_DIS.SPI_PAD_CONFIG_DQS EFUSE_BLK0 20 1
59 WR_DIS.SPI_PAD_CONFIG_D4 EFUSE_BLK0 20 1
60 WR_DIS.SPI_PAD_CONFIG_D5 EFUSE_BLK0 20 1
61 WR_DIS.SPI_PAD_CONFIG_D6 EFUSE_BLK0 20 1
62 WR_DIS.SPI_PAD_CONFIG_D7 EFUSE_BLK0 20 1
63 WR_DIS.WAFER_VERSION_MINOR_LO EFUSE_BLK0 20 1
64 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
65 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
66 WR_DIS.K_RTC_LDO EFUSE_BLK0 20 1
67 WR_DIS.K_DIG_LDO EFUSE_BLK0 20 1
68 WR_DIS.V_RTC_DBIAS20 EFUSE_BLK0 20 1
69 WR_DIS.V_DIG_DBIAS20 EFUSE_BLK0 20 1
70 WR_DIS.DIG_DBIAS_HVT EFUSE_BLK0 20 1
71 WR_DIS.WAFER_VERSION_MINOR_HI EFUSE_BLK0 20 1
72 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
73 WR_DIS.ADC2_CAL_VOL_ATTEN3 EFUSE_BLK0 20 1
74 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
75 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
76 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 21 1
77 WR_DIS.TEMP_CALIB EFUSE_BLK0 21 1
78 WR_DIS.OCODE EFUSE_BLK0 21 1
79 WR_DIS.ADC1_INIT_CODE_ATTEN0 EFUSE_BLK0 21 1
80 WR_DIS.ADC1_INIT_CODE_ATTEN1 EFUSE_BLK0 21 1
81 WR_DIS.ADC1_INIT_CODE_ATTEN2 EFUSE_BLK0 21 1
82 WR_DIS.ADC1_INIT_CODE_ATTEN3 EFUSE_BLK0 21 1
83 WR_DIS.ADC2_INIT_CODE_ATTEN0 EFUSE_BLK0 21 1
84 WR_DIS.ADC2_INIT_CODE_ATTEN1 EFUSE_BLK0 21 1
85 WR_DIS.ADC2_INIT_CODE_ATTEN2 EFUSE_BLK0 21 1
86 WR_DIS.ADC2_INIT_CODE_ATTEN3 EFUSE_BLK0 21 1
87 WR_DIS.ADC1_CAL_VOL_ATTEN0 EFUSE_BLK0 21 1
88 WR_DIS.ADC1_CAL_VOL_ATTEN1 EFUSE_BLK0 21 1
89 WR_DIS.ADC1_CAL_VOL_ATTEN2 EFUSE_BLK0 21 1
90 WR_DIS.ADC1_CAL_VOL_ATTEN3 EFUSE_BLK0 21 1
91 WR_DIS.ADC2_CAL_VOL_ATTEN0 EFUSE_BLK0 21 1
92 WR_DIS.ADC2_CAL_VOL_ATTEN1 EFUSE_BLK0 21 1
93 WR_DIS.ADC2_CAL_VOL_ATTEN2 EFUSE_BLK0 21 1
94 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
95 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
96 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
97 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
98 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
99 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
100 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
101 WR_DIS.BLOCK_KEY5 EFUSE_BLK0 28 1
102 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 29 1
103 WR_DIS.USB_EXCHG_PINS EFUSE_BLK0 30 1
104 WR_DIS.USB_EXT_PHY_ENABLE EFUSE_BLK0 30 1
105 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
106 RD_DIS EFUSE_BLK0 32 7
107 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
108 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
109 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
110 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
111 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
112 RD_DIS.BLOCK_KEY5 EFUSE_BLK0 37 1
113 RD_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 38 1
114 DIS_ICACHE EFUSE_BLK0 40 1
115 DIS_DCACHE EFUSE_BLK0 41 1
116 DIS_DOWNLOAD_ICACHE EFUSE_BLK0 42 1
117 DIS_DOWNLOAD_DCACHE EFUSE_BLK0 43 1
118 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
119 DIS_USB_OTG EFUSE_BLK0 45 1
120 DIS_TWAI EFUSE_BLK0 46 1
121 DIS_APP_CPU EFUSE_BLK0 47 1
122 SOFT_DIS_JTAG EFUSE_BLK0 48 3
123 DIS_PAD_JTAG EFUSE_BLK0 51 1
124 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
125 USB_EXCHG_PINS EFUSE_BLK0 57 1
126 USB_EXT_PHY_ENABLE EFUSE_BLK0 58 1
127 VDD_SPI_XPD EFUSE_BLK0 68 1
128 VDD_SPI_TIEH EFUSE_BLK0 69 1
129 VDD_SPI_FORCE EFUSE_BLK0 70 1
130 WDT_DELAY_SEL EFUSE_BLK0 80 2
131 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 82 3
132 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 85 1
133 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 86 1
134 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 87 1
135 KEY_PURPOSE_0 EFUSE_BLK0 88 4
136 KEY_PURPOSE_1 EFUSE_BLK0 92 4
137 KEY_PURPOSE_2 EFUSE_BLK0 96 4
138 KEY_PURPOSE_3 EFUSE_BLK0 100 4
139 KEY_PURPOSE_4 EFUSE_BLK0 104 4
140 KEY_PURPOSE_5 EFUSE_BLK0 108 4
141 SECURE_BOOT_EN EFUSE_BLK0 116 1
142 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 117 1
143 DIS_USB_JTAG EFUSE_BLK0 118 1
144 DIS_USB_SERIAL_JTAG EFUSE_BLK0 119 1
145 STRAP_JTAG_SEL EFUSE_BLK0 120 1
146 USB_PHY_SEL EFUSE_BLK0 121 1
147 FLASH_TPUW EFUSE_BLK0 124 4
148 DIS_DOWNLOAD_MODE EFUSE_BLK0 128 1
149 DIS_DIRECT_BOOT EFUSE_BLK0 129 1
150 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 130 1
151 FLASH_ECC_MODE EFUSE_BLK0 131 1
152 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 132 1
153 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 133 1
154 UART_PRINT_CONTROL EFUSE_BLK0 134 2
155 PIN_POWER_SELECTION EFUSE_BLK0 136 1
156 FLASH_TYPE EFUSE_BLK0 137 1
157 FLASH_PAGE_SIZE EFUSE_BLK0 138 2
158 FLASH_ECC_EN EFUSE_BLK0 140 1
159 FORCE_SEND_RESUME EFUSE_BLK0 141 1
160 SECURE_VERSION EFUSE_BLK0 142 16
161 DIS_USB_OTG_DOWNLOAD_MODE EFUSE_BLK0 159 1
162 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 160 1
163 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 161 1
164 MAC EFUSE_BLK1 0 8
165 MAC EFUSE_BLK1 8 8
166 MAC EFUSE_BLK1 16 8
167 MAC EFUSE_BLK1 24 8
168 MAC EFUSE_BLK1 32 8
169 MAC EFUSE_BLK1 40 8
170 SPI_PAD_CONFIG_CLK EFUSE_BLK1 48 6
171 SPI_PAD_CONFIG_Q EFUSE_BLK1 54 6
172 SPI_PAD_CONFIG_D EFUSE_BLK1 60 6
173 SPI_PAD_CONFIG_CS EFUSE_BLK1 66 6
174 SPI_PAD_CONFIG_HD EFUSE_BLK1 72 6
175 SPI_PAD_CONFIG_WP EFUSE_BLK1 78 6
176 SPI_PAD_CONFIG_DQS EFUSE_BLK1 84 6
177 SPI_PAD_CONFIG_D4 EFUSE_BLK1 90 6
178 SPI_PAD_CONFIG_D5 EFUSE_BLK1 96 6
179 SPI_PAD_CONFIG_D6 EFUSE_BLK1 102 6
180 SPI_PAD_CONFIG_D7 EFUSE_BLK1 108 6
181 WAFER_VERSION_MINOR_LO EFUSE_BLK1 114 3
182 PKG_VERSION EFUSE_BLK1 117 3
183 BLK_VERSION_MINOR EFUSE_BLK1 120 3
184 K_RTC_LDO EFUSE_BLK1 141 7
185 K_DIG_LDO EFUSE_BLK1 148 7
186 V_RTC_DBIAS20 EFUSE_BLK1 155 8
187 V_DIG_DBIAS20 EFUSE_BLK1 163 8
188 DIG_DBIAS_HVT EFUSE_BLK1 171 5
189 WAFER_VERSION_MINOR_HI EFUSE_BLK1 183 1
190 WAFER_VERSION_MAJOR EFUSE_BLK1 184 2
191 ADC2_CAL_VOL_ATTEN3 EFUSE_BLK1 186 6
192 SYS_DATA_PART2 EFUSE_BLK10 0 256
193 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
194 BLK_VERSION_MAJOR EFUSE_BLK2 128 2
195 TEMP_CALIB EFUSE_BLK2 132 9
196 OCODE EFUSE_BLK2 141 8
197 ADC1_INIT_CODE_ATTEN0 EFUSE_BLK2 149 8
198 ADC1_INIT_CODE_ATTEN1 EFUSE_BLK2 157 6
199 ADC1_INIT_CODE_ATTEN2 EFUSE_BLK2 163 6
200 ADC1_INIT_CODE_ATTEN3 EFUSE_BLK2 169 6
201 ADC2_INIT_CODE_ATTEN0 EFUSE_BLK2 175 8
202 ADC2_INIT_CODE_ATTEN1 EFUSE_BLK2 183 6
203 ADC2_INIT_CODE_ATTEN2 EFUSE_BLK2 189 6
204 ADC2_INIT_CODE_ATTEN3 EFUSE_BLK2 195 6
205 ADC1_CAL_VOL_ATTEN0 EFUSE_BLK2 201 8
206 ADC1_CAL_VOL_ATTEN1 EFUSE_BLK2 209 8
207 ADC1_CAL_VOL_ATTEN2 EFUSE_BLK2 217 8
208 ADC1_CAL_VOL_ATTEN3 EFUSE_BLK2 225 8
209 ADC2_CAL_VOL_ATTEN0 EFUSE_BLK2 233 8
210 ADC2_CAL_VOL_ATTEN1 EFUSE_BLK2 241 7
211 ADC2_CAL_VOL_ATTEN2 EFUSE_BLK2 248 7
212 USER_DATA EFUSE_BLK3 0 256
213 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
214 KEY0 EFUSE_BLK4 0 256
215 KEY1 EFUSE_BLK5 0 256
216 KEY2 EFUSE_BLK6 0 256
217 KEY3 EFUSE_BLK7 0 256
218 KEY4 EFUSE_BLK8 0 256
219 KEY5 EFUSE_BLK9 0 256
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 0] [2 2] ... [22 30] [30 38] [32 38] [40 52] [57 58] [68 70] [80 111] [116 121] [124 157] [159 161]
EFUSE_BLK1
[0 122] [141 175] [183 191]
EFUSE_BLK10
[0 255]
EFUSE_BLK2
[0 129] [132 254]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 255]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,231 @@
.. code-block:: none
$ ./efuse_table_gen.py -t {IDF_TARGET_PATH_NAME} {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Max number of bits in BLK 256
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 32
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.KM_RND_SWITCH_CYCLE EFUSE_BLK0 1 1
4 WR_DIS.KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 1 1
5 WR_DIS.KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 1 1
6 WR_DIS.FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 1 1
7 WR_DIS.FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 1 1
8 WR_DIS.KM_XTS_KEY_LENGTH_256 EFUSE_BLK0 1 1
9 WR_DIS.LOCK_KM_KEY EFUSE_BLK0 1 1
10 WR_DIS.DIS_USB_JTAG EFUSE_BLK0 2 1
11 WR_DIS.DIS_FORCE_DOWNLOAD EFUSE_BLK0 2 1
12 WR_DIS.SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 2 1
13 WR_DIS.DIS_TWAI EFUSE_BLK0 2 1
14 WR_DIS.JTAG_SEL_ENABLE EFUSE_BLK0 2 1
15 WR_DIS.DIS_PAD_JTAG EFUSE_BLK0 2 1
16 WR_DIS.DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 2 1
17 WR_DIS.WDT_DELAY_SEL EFUSE_BLK0 2 1
18 WR_DIS.SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 2 1
19 WR_DIS.DIS_WDT EFUSE_BLK0 2 1
20 WR_DIS.DIS_SWD EFUSE_BLK0 2 1
21 WR_DIS.PMU_FLASH_POWER_SEL EFUSE_BLK0 2 1
22 WR_DIS.PMU_FLASH_POWER_SEL_EN EFUSE_BLK0 2 1
23 WR_DIS.POWER_GLITCH_EN EFUSE_BLK0 2 1
24 WR_DIS.PVT_0_GLITCH_EN EFUSE_BLK0 3 1
25 WR_DIS.PVT_0_GLITCH_MODE EFUSE_BLK0 3 1
26 WR_DIS.PVT_1_GLITCH_EN EFUSE_BLK0 3 1
27 WR_DIS.PVT_1_GLITCH_MODE EFUSE_BLK0 3 1
28 WR_DIS.SPI_BOOT_CRYPT_CNT EFUSE_BLK0 4 1
29 WR_DIS.SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 5 1
30 WR_DIS.SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 6 1
31 WR_DIS.SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 7 1
32 WR_DIS.KEY_PURPOSE_0 EFUSE_BLK0 8 1
33 WR_DIS.KEY_PURPOSE_1 EFUSE_BLK0 9 1
34 WR_DIS.KEY_PURPOSE_2 EFUSE_BLK0 10 1
35 WR_DIS.KEY_PURPOSE_3 EFUSE_BLK0 11 1
36 WR_DIS.KEY_PURPOSE_4 EFUSE_BLK0 12 1
37 WR_DIS.DIS_SM_CRYPT EFUSE_BLK0 14 1
38 WR_DIS.ECC_FORCE_CONST_TIME EFUSE_BLK0 14 1
39 WR_DIS.ECDSA_DISABLE_SOFT_K EFUSE_BLK0 14 1
40 WR_DIS.SEC_DPA_LEVEL EFUSE_BLK0 14 1
41 WR_DIS.XTS_DPA_CLK_ENABLE EFUSE_BLK0 14 1
42 WR_DIS.XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 14 1
43 WR_DIS.RMA_NONCE_ENA EFUSE_BLK0 14 1
44 WR_DIS.RMA_CHIP_INFO_SOURCE EFUSE_BLK0 14 1
45 WR_DIS.RMA_DISABLE_FAST_VEF EFUSE_BLK0 14 1
46 WR_DIS.ENA_XTS_SHADOW EFUSE_BLK0 14 1
47 WR_DIS.ENA_SPI_BOOT_CRYPT_SCRAMBLER EFUSE_BLK0 14 1
48 WR_DIS.RE_ENABLE_JTAG_SOURCE EFUSE_BLK0 14 1
49 WR_DIS.SECURE_BOOT_EN EFUSE_BLK0 15 1
50 WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 16 1
51 WR_DIS.FLASH_TYPE EFUSE_BLK0 18 1
52 WR_DIS.DIS_USB_OTG_DOWNLOAD_MODE EFUSE_BLK0 18 1
53 WR_DIS.FLASH_TPUW EFUSE_BLK0 18 1
54 WR_DIS.DIS_DOWNLOAD_MODE EFUSE_BLK0 18 1
55 WR_DIS.DIS_DIRECT_BOOT EFUSE_BLK0 18 1
56 WR_DIS.DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 18 1
57 WR_DIS.DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 18 1
58 WR_DIS.ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 18 1
59 WR_DIS.UART_PRINT_CONTROL EFUSE_BLK0 18 1
60 WR_DIS.FORCE_SEND_RESUME EFUSE_BLK0 18 1
61 WR_DIS.SECURE_VERSION EFUSE_BLK0 18 1
62 WR_DIS.HUK_GEN_STATE EFUSE_BLK0 19 1
63 WR_DIS.BLK1 EFUSE_BLK0 20 1
64 WR_DIS.MAC EFUSE_BLK0 20 1
65 WR_DIS.MAC_EXT EFUSE_BLK0 20 1
66 WR_DIS.WAFER_VERSION_MINOR EFUSE_BLK0 20 1
67 WR_DIS.WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
68 WR_DIS.DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK0 20 1
69 WR_DIS.DISABLE_BLK_VERSION_MAJOR EFUSE_BLK0 20 1
70 WR_DIS.BLK_VERSION_MINOR EFUSE_BLK0 20 1
71 WR_DIS.BLK_VERSION_MAJOR EFUSE_BLK0 20 1
72 WR_DIS.PSRAM_CAP EFUSE_BLK0 20 1
73 WR_DIS.TEMP EFUSE_BLK0 20 1
74 WR_DIS.PSRAM_VENDOR EFUSE_BLK0 20 1
75 WR_DIS.PKG_VERSION EFUSE_BLK0 20 1
76 WR_DIS.SYS_DATA_PART1 EFUSE_BLK0 21 1
77 WR_DIS.OPTIONAL_UNIQUE_ID EFUSE_BLK0 21 1
78 WR_DIS.BLOCK_USR_DATA EFUSE_BLK0 22 1
79 WR_DIS.CUSTOM_MAC EFUSE_BLK0 22 1
80 WR_DIS.BLOCK_KEY0 EFUSE_BLK0 23 1
81 WR_DIS.BLOCK_KEY1 EFUSE_BLK0 24 1
82 WR_DIS.BLOCK_KEY2 EFUSE_BLK0 25 1
83 WR_DIS.BLOCK_KEY3 EFUSE_BLK0 26 1
84 WR_DIS.BLOCK_KEY4 EFUSE_BLK0 27 1
85 WR_DIS.BLOCK_SYS_DATA2 EFUSE_BLK0 28 1
86 WR_DIS.USB_DEVICE_EXCHG_PINS EFUSE_BLK0 28 1
87 WR_DIS.SOFT_DIS_JTAG EFUSE_BLK0 31 1
88 RD_DIS EFUSE_BLK0 32 7
89 RD_DIS.BLOCK_KEY0 EFUSE_BLK0 32 1
90 RD_DIS.BLOCK_KEY1 EFUSE_BLK0 33 1
91 RD_DIS.BLOCK_KEY2 EFUSE_BLK0 34 1
92 RD_DIS.BLOCK_KEY3 EFUSE_BLK0 35 1
93 RD_DIS.BLOCK_KEY4 EFUSE_BLK0 36 1
94 DIS_USB_JTAG EFUSE_BLK0 42 1
95 DIS_FORCE_DOWNLOAD EFUSE_BLK0 44 1
96 SPI_DOWNLOAD_MSPI_DIS EFUSE_BLK0 45 1
97 DIS_TWAI EFUSE_BLK0 46 1
98 JTAG_SEL_ENABLE EFUSE_BLK0 47 1
99 SOFT_DIS_JTAG EFUSE_BLK0 48 3
100 DIS_PAD_JTAG EFUSE_BLK0 51 1
101 DIS_DOWNLOAD_MANUAL_ENCRYPT EFUSE_BLK0 52 1
102 HUK_GEN_STATE EFUSE_BLK0 55 5
103 KM_RND_SWITCH_CYCLE EFUSE_BLK0 64 1
104 KM_DISABLE_DEPLOY_MODE EFUSE_BLK0 66 5
105 KM_DEPLOY_ONLY_ONCE EFUSE_BLK0 71 5
106 FORCE_USE_KEY_MANAGER_KEY EFUSE_BLK0 76 5
107 FORCE_DISABLE_SW_INIT_KEY EFUSE_BLK0 81 1
108 KM_XTS_KEY_LENGTH_256 EFUSE_BLK0 82 1
109 WDT_DELAY_SEL EFUSE_BLK0 83 1
110 DIS_SM_CRYPT EFUSE_BLK0 84 1
111 SPI_BOOT_CRYPT_CNT EFUSE_BLK0 85 3
112 SECURE_BOOT_KEY_REVOKE0 EFUSE_BLK0 88 1
113 SECURE_BOOT_KEY_REVOKE1 EFUSE_BLK0 89 1
114 SECURE_BOOT_KEY_REVOKE2 EFUSE_BLK0 90 1
115 KEY_PURPOSE_0 EFUSE_BLK0 96 5
116 KEY_PURPOSE_1 EFUSE_BLK0 101 5
117 KEY_PURPOSE_2 EFUSE_BLK0 106 5
118 KEY_PURPOSE_3 EFUSE_BLK0 111 5
119 KEY_PURPOSE_4 EFUSE_BLK0 116 5
120 ECC_FORCE_CONST_TIME EFUSE_BLK0 121 1
121 ECDSA_DISABLE_SOFT_K EFUSE_BLK0 122 1
122 SEC_DPA_LEVEL EFUSE_BLK0 123 2
123 XTS_DPA_CLK_ENABLE EFUSE_BLK0 125 1
124 XTS_DPA_PSEUDO_LEVEL EFUSE_BLK0 128 2
125 SECURE_BOOT_EN EFUSE_BLK0 130 1
126 SECURE_BOOT_AGGRESSIVE_REVOKE EFUSE_BLK0 131 1
127 FLASH_TYPE EFUSE_BLK0 133 1
128 DIS_USB_OTG_DOWNLOAD_MODE EFUSE_BLK0 137 1
129 FLASH_TPUW EFUSE_BLK0 140 4
130 DIS_DOWNLOAD_MODE EFUSE_BLK0 144 1
131 DIS_DIRECT_BOOT EFUSE_BLK0 145 1
132 DIS_USB_SERIAL_JTAG_ROM_PRINT EFUSE_BLK0 146 1
133 LOCK_KM_KEY EFUSE_BLK0 147 1
134 DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE EFUSE_BLK0 148 1
135 ENABLE_SECURITY_DOWNLOAD EFUSE_BLK0 149 1
136 UART_PRINT_CONTROL EFUSE_BLK0 150 2
137 FORCE_SEND_RESUME EFUSE_BLK0 152 1
138 SECURE_VERSION EFUSE_BLK0 160 16
139 SECURE_BOOT_DISABLE_FAST_WAKE EFUSE_BLK0 176 1
140 HYS_EN_PAD EFUSE_BLK0 177 1
141 DCDC_VSET_EN EFUSE_BLK0 194 1
142 DIS_WDT EFUSE_BLK0 195 1
143 DIS_SWD EFUSE_BLK0 196 1
144 SECURE_BOOT_SHA384_EN EFUSE_BLK0 203 1
145 BOOTLOADER_ANTI_ROLLBACK_SECURE_VERSION EFUSE_BLK0 204 4
146 BOOTLOADER_ANTI_ROLLBACK_EN EFUSE_BLK0 208 1
147 BOOTLOADER_ANTI_ROLLBACK_UPDATE_IN_ROM EFUSE_BLK0 209 1
148 RECOVERY_BOOTLOADER_FLASH_SECTOR EFUSE_BLK0 210 12
149 RMA_ENA EFUSE_BLK0 222 2
150 RMA_SESSION_COUNTER EFUSE_BLK0 224 3
151 RMA_NONCE_ENA EFUSE_BLK0 227 2
152 RMA_CHIP_INFO_SOURCE EFUSE_BLK0 229 1
153 RMA_DISABLE_FAST_VEF EFUSE_BLK0 230 1
154 PVT_0_GLITCH_EN EFUSE_BLK0 231 1
155 PVT_0_GLITCH_MODE EFUSE_BLK0 232 2
156 PVT_1_GLITCH_EN EFUSE_BLK0 234 1
157 PVT_1_GLITCH_MODE EFUSE_BLK0 235 2
158 PMU_FLASH_POWER_SEL EFUSE_BLK0 237 1
159 PMU_FLASH_POWER_SEL_EN EFUSE_BLK0 238 1
160 POWER_GLITCH_EN EFUSE_BLK0 239 4
161 ENA_XTS_SHADOW EFUSE_BLK0 243 1
162 ENA_SPI_BOOT_CRYPT_SCRAMBLER EFUSE_BLK0 244 1
163 RE_ENABLE_JTAG_SOURCE EFUSE_BLK0 245 1
164 MAC EFUSE_BLK1 0 8
165 MAC EFUSE_BLK1 8 8
166 MAC EFUSE_BLK1 16 8
167 MAC EFUSE_BLK1 24 8
168 MAC EFUSE_BLK1 32 8
169 MAC EFUSE_BLK1 40 8
170 MAC_EXT EFUSE_BLK1 48 8
171 MAC_EXT EFUSE_BLK1 56 8
172 WAFER_VERSION_MINOR EFUSE_BLK1 114 4
173 WAFER_VERSION_MAJOR EFUSE_BLK1 118 2
174 DISABLE_WAFER_VERSION_MAJOR EFUSE_BLK1 120 1
175 DISABLE_BLK_VERSION_MAJOR EFUSE_BLK1 121 1
176 BLK_VERSION_MINOR EFUSE_BLK1 122 3
177 BLK_VERSION_MAJOR EFUSE_BLK1 125 2
178 PSRAM_CAP EFUSE_BLK1 127 3
179 TEMP EFUSE_BLK1 130 2
180 PSRAM_VENDOR EFUSE_BLK1 132 2
181 PKG_VERSION EFUSE_BLK1 134 2
182 OPTIONAL_UNIQUE_ID EFUSE_BLK2 0 128
183 USER_DATA EFUSE_BLK3 0 256
184 USER_DATA.MAC_CUSTOM EFUSE_BLK3 200 48
185 KEY0 EFUSE_BLK4 0 256
186 KEY1 EFUSE_BLK5 0 256
187 KEY2 EFUSE_BLK6 0 256
188 KEY3 EFUSE_BLK7 0 256
189 KEY4 EFUSE_BLK8 0 256
190 SYS_DATA_PART2 EFUSE_BLK9 0 32
191 USB_DEVICE_EXCHG_PINS EFUSE_BLK9 192 1
Used bits in efuse table:
EFUSE_BLK0
[0 31] [0 1] [1 1] [1 1] ... [140 152] [160 177] [194 196] [203 245]
EFUSE_BLK1
[0 63] [114 135]
EFUSE_BLK2
[0 127]
EFUSE_BLK3
[0 255] [200 247]
EFUSE_BLK4
[0 255]
EFUSE_BLK5
[0 255]
EFUSE_BLK6
[0 255]
EFUSE_BLK7
[0 255]
EFUSE_BLK8
[0 255]
EFUSE_BLK9
[0 31] [192 192]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
@@ -0,0 +1,131 @@
.. code-block:: none
$ ./efuse_table_gen.py {IDF_TARGET_PATH_NAME}/esp_efuse_table.csv --info
Parsing efuse CSV input file $IDF_PATH/components/efuse/esp32/esp_efuse_table.csv ...
Verifying efuse table...
Max number of bits in BLK 192
Sorted efuse table:
# field_name efuse_block bit_start bit_count
1 WR_DIS EFUSE_BLK0 0 16
2 WR_DIS.RD_DIS EFUSE_BLK0 0 1
3 WR_DIS.WR_DIS EFUSE_BLK0 1 1
4 WR_DIS.FLASH_CRYPT_CNT EFUSE_BLK0 2 1
5 WR_DIS.UART_DOWNLOAD_DIS EFUSE_BLK0 2 1
6 WR_DIS.MAC EFUSE_BLK0 3 1
7 WR_DIS.MAC_CRC EFUSE_BLK0 3 1
8 WR_DIS.DISABLE_APP_CPU EFUSE_BLK0 3 1
9 WR_DIS.DISABLE_BT EFUSE_BLK0 3 1
10 WR_DIS.DIS_CACHE EFUSE_BLK0 3 1
11 WR_DIS.VOL_LEVEL_HP_INV EFUSE_BLK0 3 1
12 WR_DIS.CLK8M_FREQ EFUSE_BLK0 4 1
13 WR_DIS.ADC_VREF EFUSE_BLK0 4 1
14 WR_DIS.XPD_SDIO_REG EFUSE_BLK0 5 1
15 WR_DIS.XPD_SDIO_TIEH EFUSE_BLK0 5 1
16 WR_DIS.XPD_SDIO_FORCE EFUSE_BLK0 5 1
17 WR_DIS.SPI_PAD_CONFIG_CLK EFUSE_BLK0 6 1
18 WR_DIS.SPI_PAD_CONFIG_Q EFUSE_BLK0 6 1
19 WR_DIS.SPI_PAD_CONFIG_D EFUSE_BLK0 6 1
20 WR_DIS.SPI_PAD_CONFIG_CS0 EFUSE_BLK0 6 1
21 WR_DIS.BLOCK1 EFUSE_BLK0 7 1
22 WR_DIS.BLOCK2 EFUSE_BLK0 8 1
23 WR_DIS.BLOCK3 EFUSE_BLK0 9 1
24 WR_DIS.CUSTOM_MAC_CRC EFUSE_BLK0 9 1
25 WR_DIS.CUSTOM_MAC EFUSE_BLK0 9 1
26 WR_DIS.ADC1_TP_LOW EFUSE_BLK0 9 1
27 WR_DIS.ADC1_TP_HIGH EFUSE_BLK0 9 1
28 WR_DIS.ADC2_TP_LOW EFUSE_BLK0 9 1
29 WR_DIS.ADC2_TP_HIGH EFUSE_BLK0 9 1
30 WR_DIS.SECURE_VERSION EFUSE_BLK0 9 1
31 WR_DIS.MAC_VERSION EFUSE_BLK0 9 1
32 WR_DIS.BLK3_PART_RESERVE EFUSE_BLK0 10 1
33 WR_DIS.FLASH_CRYPT_CONFIG EFUSE_BLK0 10 1
34 WR_DIS.CODING_SCHEME EFUSE_BLK0 10 1
35 WR_DIS.KEY_STATUS EFUSE_BLK0 10 1
36 WR_DIS.ABS_DONE_0 EFUSE_BLK0 12 1
37 WR_DIS.ABS_DONE_1 EFUSE_BLK0 13 1
38 WR_DIS.JTAG_DISABLE EFUSE_BLK0 14 1
39 WR_DIS.CONSOLE_DEBUG_DISABLE EFUSE_BLK0 15 1
40 WR_DIS.DISABLE_DL_ENCRYPT EFUSE_BLK0 15 1
41 WR_DIS.DISABLE_DL_DECRYPT EFUSE_BLK0 15 1
42 WR_DIS.DISABLE_DL_CACHE EFUSE_BLK0 15 1
43 RD_DIS EFUSE_BLK0 16 4
44 RD_DIS.BLOCK1 EFUSE_BLK0 16 1
45 RD_DIS.BLOCK2 EFUSE_BLK0 17 1
46 RD_DIS.BLOCK3 EFUSE_BLK0 18 1
47 RD_DIS.CUSTOM_MAC_CRC EFUSE_BLK0 18 1
48 RD_DIS.CUSTOM_MAC EFUSE_BLK0 18 1
49 RD_DIS.ADC1_TP_LOW EFUSE_BLK0 18 1
50 RD_DIS.ADC1_TP_HIGH EFUSE_BLK0 18 1
51 RD_DIS.ADC2_TP_LOW EFUSE_BLK0 18 1
52 RD_DIS.ADC2_TP_HIGH EFUSE_BLK0 18 1
53 RD_DIS.SECURE_VERSION EFUSE_BLK0 18 1
54 RD_DIS.MAC_VERSION EFUSE_BLK0 18 1
55 RD_DIS.BLK3_PART_RESERVE EFUSE_BLK0 19 1
56 RD_DIS.FLASH_CRYPT_CONFIG EFUSE_BLK0 19 1
57 RD_DIS.CODING_SCHEME EFUSE_BLK0 19 1
58 RD_DIS.KEY_STATUS EFUSE_BLK0 19 1
59 FLASH_CRYPT_CNT EFUSE_BLK0 20 7
60 UART_DOWNLOAD_DIS EFUSE_BLK0 27 1
61 MAC EFUSE_BLK0 32 8
62 MAC EFUSE_BLK0 40 8
63 MAC EFUSE_BLK0 48 8
64 MAC EFUSE_BLK0 56 8
65 MAC EFUSE_BLK0 64 8
66 MAC EFUSE_BLK0 72 8
67 MAC_CRC EFUSE_BLK0 80 8
68 DISABLE_APP_CPU EFUSE_BLK0 96 1
69 DISABLE_BT EFUSE_BLK0 97 1
70 CHIP_PACKAGE_4BIT EFUSE_BLK0 98 1
71 DIS_CACHE EFUSE_BLK0 99 1
72 SPI_PAD_CONFIG_HD EFUSE_BLK0 100 5
73 CHIP_PACKAGE EFUSE_BLK0 105 3
74 CHIP_CPU_FREQ_LOW EFUSE_BLK0 108 1
75 CHIP_CPU_FREQ_RATED EFUSE_BLK0 109 1
76 BLK3_PART_RESERVE EFUSE_BLK0 110 1
77 CHIP_VER_REV1 EFUSE_BLK0 111 1
78 CLK8M_FREQ EFUSE_BLK0 128 8
79 ADC_VREF EFUSE_BLK0 136 5
80 XPD_SDIO_REG EFUSE_BLK0 142 1
81 XPD_SDIO_TIEH EFUSE_BLK0 143 1
82 XPD_SDIO_FORCE EFUSE_BLK0 144 1
83 SPI_PAD_CONFIG_CLK EFUSE_BLK0 160 5
84 SPI_PAD_CONFIG_Q EFUSE_BLK0 165 5
85 SPI_PAD_CONFIG_D EFUSE_BLK0 170 5
86 SPI_PAD_CONFIG_CS0 EFUSE_BLK0 175 5
87 CHIP_VER_REV2 EFUSE_BLK0 180 1
88 VOL_LEVEL_HP_INV EFUSE_BLK0 182 2
89 WAFER_VERSION_MINOR EFUSE_BLK0 184 2
90 FLASH_CRYPT_CONFIG EFUSE_BLK0 188 4
91 CODING_SCHEME EFUSE_BLK0 192 2
92 CONSOLE_DEBUG_DISABLE EFUSE_BLK0 194 1
93 DISABLE_SDIO_HOST EFUSE_BLK0 195 1
94 ABS_DONE_0 EFUSE_BLK0 196 1
95 ABS_DONE_1 EFUSE_BLK0 197 1
96 JTAG_DISABLE EFUSE_BLK0 198 1
97 DISABLE_DL_ENCRYPT EFUSE_BLK0 199 1
98 DISABLE_DL_DECRYPT EFUSE_BLK0 200 1
99 DISABLE_DL_CACHE EFUSE_BLK0 201 1
100 KEY_STATUS EFUSE_BLK0 202 1
101 BLOCK1 EFUSE_BLK1 0 192
102 BLOCK2 EFUSE_BLK2 0 192
103 CUSTOM_MAC_CRC EFUSE_BLK3 0 8
104 MAC_CUSTOM EFUSE_BLK3 8 48
105 ADC1_TP_LOW EFUSE_BLK3 96 7
106 ADC1_TP_HIGH EFUSE_BLK3 103 9
107 ADC2_TP_LOW EFUSE_BLK3 112 7
108 ADC2_TP_HIGH EFUSE_BLK3 119 9
109 SECURE_VERSION EFUSE_BLK3 128 32
110 MAC_VERSION EFUSE_BLK3 184 8
Used bits in efuse table:
EFUSE_BLK0
[0 15] [0 2] [2 3] ... [19 19] [19 27] [32 87] [96 111] [128 140] [142 144] [160 180] [182 185] [188 202]
EFUSE_BLK1
[0 191]
EFUSE_BLK2
[0 191]
EFUSE_BLK3
[0 55] [96 159] [184 191]
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
+45
View File
@@ -0,0 +1,45 @@
System API
**********
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 1
app_image_format
bootloader_image_format
app_trace
esp_function_with_shared_stack
chip_revision
console
efuse
esp_err
esp_https_ota
esp_event
freertos
freertos_idf
freertos_additions
mem_alloc
mm
:SOC_PSRAM_DMA_CAPABLE or SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE: mm_sync
heap_debug
esp_timer
internal-unstable
:SOC_HP_CPU_HAS_MULTIPLE_CORES: ipc
intr_alloc
log
misc_system_api
ota
:CONFIG_IDF_TARGET_ARCH_XTENSA: perfmon
power_management
pthread
random
sleep_modes
soc_caps
system_time
:esp32: himem
ulp
wdts
Code examples for this API section are provided in the :example:`system` directory of ESP-IDF examples.
@@ -0,0 +1,12 @@
Internal and Unstable APIs
==========================
:link_to_translation:`zh_CN:[中文]`
This section is listing some APIs that are internal or likely to be changed or removed in the next releases of ESP-IDF.
API Reference
-------------
.. include-build-file:: inc/esp_rom_sys.inc
+214
View File
@@ -0,0 +1,214 @@
Interrupt Allocation
====================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
.. only:: esp32 or esp32s3
The {IDF_TARGET_NAME} has two cores, with 32 interrupts each. Each interrupt has a fixed priority, most (but not all) interrupts are connected to the interrupt matrix.
.. only:: esp32s2
The {IDF_TARGET_NAME} has one core, with 32 interrupts. Each interrupt has a fixed priority, most (but not all) interrupts are connected to the interrupt matrix.
.. only:: esp32c2 or esp32c3
The {IDF_TARGET_NAME} has one core, with 31 interrupts. Each interrupt's priority is independently programmable.
.. only:: esp32c6 or esp32h2
The {IDF_TARGET_NAME} has one core, with 28 external asynchronous interrupts. Each interrupt's priority is independently programmable. In addition, there are also 4 core local interrupt sources (CLINT). See **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#riscvcpu>`__] for more details.
.. only:: esp32p4 or esp32h4
The {IDF_TARGET_NAME} has two cores, with 32 external asynchronous interrupts each. Each interrupt's priority is independently programmable. In addition, there are also 3 core local interrupt sources (CLINT) on each core. See **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#riscvcpu>`__] for more details.
.. only:: esp32c5 or esp32c61
The {IDF_TARGET_NAME} has one core, with 32 external asynchronous interrupts. Each interrupt's priority is independently programmable. In addition, there are also 3 core local interrupt sources (CLINT). For details, see **{IDF_TARGET_NAME} Technical Reference Manual** > **High-Performance CPU** [`PDF <{IDF_TARGET_TRM_EN_URL}#riscvcpu>`__].
Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in multiple drivers. The :cpp:func:`esp_intr_alloc` abstraction exists to hide all these implementation details.
A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc`, :cpp:func:`esp_intr_alloc_bind`, :cpp:func:`esp_intr_alloc_intrstatus`, :cpp:func:`esp_intr_alloc_intrstatus_bind`, or :cpp:func:`esp_intr_alloc_info`. It can use the flags passed to this function to specify the type, priority, and trigger method of the interrupt to allocate. The interrupt allocation code will then find an applicable interrupt, use the interrupt matrix to hook it up to the peripheral, and install the given interrupt handler and ISR to it.
The interrupt allocator presents two different types of interrupts, namely shared interrupts and non-shared interrupts, both of which require different handling. Non-shared interrupts will allocate a separate interrupt for every :cpp:func:`esp_intr_alloc` call, and this interrupt is use solely for the peripheral attached to it, with only one ISR that will get called. Shared interrupts can have multiple peripherals triggering them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared interrupts should check the interrupt status of the peripheral they service in order to check if any action is required.
Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can only be level interrupts due to the chance of missed interrupts when edge interrupts are used.
To illustrate why shared interrupts can only be level-triggered, take the scenario where peripheral A and peripheral B share the same edge-triggered interrupt. Peripheral B triggers an interrupt and sets its interrupt signal high, causing a low-to-high edge, which in turn latches the CPU's interrupt bit and triggers the ISR. The ISR executes, checks that peripheral A did not trigger an interrupt, and proceeds to handle and clear peripheral B's interrupt signal. Before the ISR returns, the CPU clears its interrupt bit latch. Thus, during the entire interrupt handling process, if peripheral A triggers an interrupt, it will be missed due the CPU clearing the interrupt bit latch.
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES and CONFIG_IDF_TARGET_ARCH_XTENSA
Multicore Issues
----------------
Peripherals that can generate interrupts can be divided in two types:
- External peripherals, within the {IDF_TARGET_NAME} but outside the Xtensa cores themselves. Most {IDF_TARGET_NAME} peripherals are of this type.
- Internal peripherals, part of the Xtensa CPU cores themselves.
Interrupt handling differs slightly between these two types of peripherals.
Internal Peripheral Interrupts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Each Xtensa CPU core has its own set of six internal peripherals:
- Three timer comparators
- A performance monitor
- Two software interrupts
Internal interrupt sources are defined in ``esp_intr_alloc.h`` as ``ETS_INTERNAL_*_INTR_SOURCE``.
These peripherals can only be configured from the core they are associated with. When generating an interrupt, the interrupt they generate is hard-wired to their associated core; it is not possible to have, for example, an internal timer comparator of one core generate an interrupt on another core. That is why these sources can only be managed using a task running on that specific core. Internal interrupt sources are still allocatable using :cpp:func:`esp_intr_alloc` as normal, but they cannot be shared and will always have a fixed interrupt level (namely, the one associated in hardware with the peripheral).
External Peripheral Interrupts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The remaining interrupt sources are from external peripherals.
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES and CONFIG_IDF_TARGET_ARCH_RISCV
Multicore Considerations
------------------------
Each core on {IDF_TARGET_NAME} provides internal interrupts that are triggered by the core itself and external interrupts that are triggered by peripherals. However, ESP-IDF only makes use of the external interrupts on {IDF_TARGET_NAME}. Most {IDF_TARGET_NAME} interrupt sources are external interrupts.
Each external interrupt slot of each core is wired to the interrupt matrix. The interrupt matrix allows any interrupt slot to be connected to any external interrupt source. Mapping multiple external interrupts sources to a single slot is also supported. These external interrupt sources are defined in ``soc/interrupts.h`` as ``ETS_*_INTR_SOURCE``.
.. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES
- Allocating an external interrupt will always allocate it on the core that does the allocation.
- Freeing an external interrupt must always happen on the same core it was allocated on.
- Disabling and enabling external interrupts from another core is allowed.
- Multiple external interrupt sources can share an interrupt slot by passing ``ESP_INTR_FLAG_SHARED`` as a flag to :cpp:func:`esp_intr_alloc`.
Care should be taken when calling :cpp:func:`esp_intr_alloc` from a task which is not pinned to a core. During task switching, these tasks can migrate between cores. Therefore it is impossible to tell which CPU the interrupt is allocated on, which makes it difficult to free the interrupt handle and may also cause debugging difficulties. It is advised to use :cpp:func:`xTaskCreatePinnedToCore` with a specific CoreID argument to create tasks that allocate interrupts. In the case of internal interrupt sources, this is required.
.. _iram_safe_interrupts_handlers:
IRAM-Safe Interrupt Handlers
----------------------------
When performing write and erase operations on SPI flash, {IDF_TARGET_NAME} will disable the cache, making SPI flash and SPIRAM inaccessible for interrupt handlers. This is why there are two types of interrupt handlers in ESP-IDF, which have their advantages and disadvantages:
**IRAM-safe interrupt handlers** - only access code and data in internal memory (IRAM for code, DRAM for data).
.. list::
- **+** **Latency**: They execute relatively fast and with low latency, since they are not blocked by slow flash write and erase operations (erases can take tens or hundreds of milliseconds to complete). This is useful for interrupts which need a guaranteed minimum execution latency.
- **-** **Internal memory use**: They consume precious internal memory that could otherwise be used for something else.
- **+** **Cache misses**: They do not rely on the cache with potential cache misses since the code and data are in internal memory already.
- **Usage**: To register such an interrupt via the interrupt allocator API, use the :c:macro:`ESP_INTR_FLAG_IRAM` flag.
**Non-IRAM-safe interrupt handlers** - may access code and (read-only) data in flash.
.. list::
- **-** **Latency**: In case of flash operations, these interrupt handlers are postponed, which makes their average latency longer and less predictable.
- **+** **Internal memory use**: They do not use any or not as much memory in internal RAM as IRAM-safe interrupts.
- **Usage**: To register such an interrupt via the interrupt allocator API, do *not* use the :c:macro:`ESP_INTR_FLAG_IRAM` flag.
*Note that there is nothing that explicitly marks an interrupt handler as IRAM-safe.* An interrupt handler is IRAM-safe implicitly if and only if the code and data it may access are placed in internal memory. The term "IRAM-safe" is actually a bit misleading, since there are more requirements than just placing the handler's code in IRAM memory. Examples of interrupt handlers that are **not** IRAM-safe include:
.. list::
- A handler that has some of its code placed in flash memory.
- A handler that is placed in IRAM but calls functions placed in flash memory.
- A handler that accesses a read-only variable placed in flash, even though the handler's code is actually placed in IRAM.
For details on placing code and data in IRAM or DRAM, see :ref:`how-to-place-code-in-iram`.
For more details about SPI flash operations and their interactions with interrupt handlers, see the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>`.
.. note::
Never register an interrupt handler with ``ESP_INTR_FLAG_IRAM`` flag if you are not 100% sure that all the code and data that the interrupt ever accesses are in IRAM (code) or DRAM (data). Disregarding this will lead to (sometimes spurious) :ref:`cache errors <cache_error>`. This must also be true for code and data accessed indirectly through function calls.
.. _intr-alloc-shared-interrupts:
Multiple Handlers Sharing A Source
----------------------------------
Several handlers can be assigned to a same source, given that all handlers are allocated using the ``ESP_INTR_FLAG_SHARED`` flag. They will all be allocated to the interrupt, which the source is attached to, and called sequentially when the source is active. The handlers can be disabled and freed individually. The source is attached to the interrupt (enabled), if one or more handlers are enabled, otherwise detached. A handler will never be called when disabled, while **its source may still be triggered** if any one of its handler enabled.
Sources attached to non-shared interrupt do not support this feature.
By default, when ``ESP_INTR_FLAG_SHARED`` flag is specified, the interrupt allocator will allocate only priority level 1 interrupts. Use ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` to also allow allocating shared interrupts at priority levels 2 and 3.
**Private shared interrupts** (``ESP_INTR_FLAG_SHARED_PRIVATE``) behave like ``ESP_INTR_FLAG_SHARED`` in that they allow multiple sources to share the same CPU interrupt line. However, unlike regular shared interrupts, these lines are never selected automatically by the interrupt allocator.
In other words, even when using ``ESP_INTR_FLAG_SHARED``, no allocation function will ever choose an interrupt line that was created with ``ESP_INTR_FLAG_SHARED_PRIVATE``. These lines are effectively reserved and can only be used by explicitly binding new sources to them (e.g., via ``esp_intr_alloc_bind()`` or related APIs).
This allows you to define a fixed set of interrupt sources sharing a single CPU line (for example, multiple GPIO sources) without the risk of the allocator reusing that line for unrelated interrupts.
Though the framework supports this feature, you have to use it **very carefully**. There usually exist two ways to stop an interrupt from being triggered: **disable the source** or **mask peripheral interrupt status**. ESP-IDF only handles enabling and disabling of the source itself, leaving status and mask bits to be handled by users.
**Status bits shall either be masked before the handler responsible for it is disabled, or be masked and then properly handled in another enabled interrupt**.
.. note::
Leaving some status bits unhandled without masking them, while disabling the handlers for them, will cause the interrupt(s) to be triggered indefinitely, resulting therefore in a system crash.
When calling :cpp:func:`esp_intr_alloc` or :cpp:func:`esp_intr_alloc_intrstatus`, the interrupt allocator selects the first interrupt that meets the level requirements for mapping the specified source, without considering other sources already mapped to the shared interrupt line. However, by using the functions :cpp:func:`esp_intr_alloc_bind` or :cpp:func:`esp_intr_alloc_intrstatus_bind`, you can explicitly specify the interrupt handler to be shared with the given interrupt source.
For private shared interrupts, the first allocation uses ``ESP_INTR_FLAG_SHARED_PRIVATE`` (with :cpp:func:`esp_intr_alloc` or :cpp:func:`esp_intr_alloc_intrstatus`), and subsequent sources are attached via the same functions, still with ``ESP_INTR_FLAG_SHARED_PRIVATE`` flag and the returned handle.
Named Groups
^^^^^^^^^^^^
Shared interrupts groups, public or private, can be defined by name. This is done via the ``bind_by.name`` field of the :cpp:type:`esp_intr_alloc_info_t` structure. If a shared interrupt group with the specified name already exists (created by an earlier call using the same name), the new source is attached to that group. Otherwise, a new shared interrupt group is allocated and tagged with that name. Only one of ``bind_by.handle`` or ``bind_by.name`` may be set. The usual flag rules (e.g., interrupt level, SHARED vs SHARED_PRIVATE) still apply. This does not affect the behavior of public shared interrupts: interrupt allocation functions can still attach new sources to existing public shared lines without specifying a name or handle.
Troubleshooting Interrupt Allocation
------------------------------------
On most Espressif SoCs, CPU interrupts are a limited resource. Therefore it is possible for a program to run out of CPU interrupts, for example by initializing several peripheral drivers. Typically, this will result in the driver initialization function returning ``ESP_ERR_NOT_FOUND`` error code.
If this happens, you can use :cpp:func:`esp_intr_dump` function to print the list of interrupts along with their status. The output of this function typically looks like this:
.. code-block::
CPU 0 interrupt status:
Int Level Type Status
0 1 Level Reserved
1 1 Level Reserved
2 1 Level Used: RTC_CORE
3 1 Level Used: TG0_LACT_LEVEL
...
The columns of the output have the following meaning:
.. list::
- ``Int``: CPU interrupt input number. This is typically not used in software directly, and is provided for reference only.
:not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: Interrupt priority (1-7) of the CPU interrupt. This priority is fixed in hardware, and cannot be changed.
:SOC_CPU_HAS_FLEXIBLE_INTC: - ``Level``: For interrupts which have been allocated, the priority of the interrupt. For free interrupts ``*`` is printed.
:not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``: Interrupt type (Level or Edge) of the CPU interrupt. This type is fixed in hardware, and cannot be changed.
:SOC_CPU_HAS_FLEXIBLE_INTC: - ``Type``: For interrupts which have been allocated, the type (Level or Edge) of the interrupt. For free interrupts ``*`` is printed.
- ``Status``: One of the possible statuses of the interrupt:
- ``Reserved``: The interrupt is reserved either at hardware level, or by one of the parts of ESP-IDF. It can not be allocated using :cpp:func:`esp_intr_alloc`.
- ``Used: <source>``: The interrupt is allocated and connected to a single peripheral.
- ``Shared: <source1> <source2> ...``: The interrupt is allocated and connected to multiple peripherals. See :ref:`intr-alloc-shared-interrupts` above.
- ``Free``: The interrupt is not allocated and can be used by :cpp:func:`esp_intr_alloc`.
:not SOC_CPU_HAS_FLEXIBLE_INTC: - ``Free (not general-use)``: The interrupt is not allocated, but is either a high-priority interrupt (priority 4-7) or an edge-triggered interrupt. High-priority interrupts can be allocated using :cpp:func:`esp_intr_alloc` but requires the handlers to be written in Assembly, see :doc:`../../api-guides/hlinterrupts`. Edge-triggered low- and medium-priority interrupts can also be allocated using :cpp:func:`esp_intr_alloc`, but are not used often since most peripheral interrupts are level-triggered.
If you have confirmed that the application is indeed running out of interrupts, a combination of the following suggestions can help resolve the issue:
.. list::
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - On multi-core targets, try initializing some of the peripheral drivers from a task pinned to the second core. Interrupts are typically allocated on the same core where the peripheral driver initialization function runs. Therefore by running the initialization function on the second core, more interrupt inputs can be used.
- Determine the interrupts which can tolerate higher latency, and allocate them using ``ESP_INTR_FLAG_SHARED`` flag (optionally ORed with ``ESP_INTR_FLAG_LOWMED``). Using this flag for two or more peripherals will let them use a single interrupt input, and therefore save interrupt inputs for other peripherals. See :ref:`intr-alloc-shared-interrupts` above.
:not SOC_CPU_HAS_FLEXIBLE_INTC: - Some peripheral driver may default to allocating interrupts with ``ESP_INTR_FLAG_LEVEL1`` flag, so priority 2 and 3 interrupts do not get used by default. If :cpp:func:`esp_intr_dump` shows that some priority 2 or 3 interrupts are available, try changing the interrupt allocation flags when initializing the driver to ``ESP_INTR_FLAG_LEVEL2`` or ``ESP_INTR_FLAG_LEVEL3``.
- Check if some of the peripheral drivers do not need to be used all the time, and initialize or deinitialize them on demand. This can reduce the number of simultaneously allocated interrupts.
API Reference
-------------
.. include-build-file:: inc/esp_intr_types.inc
.. include-build-file:: inc/esp_intr_alloc.inc
+184
View File
@@ -0,0 +1,184 @@
Inter-Processor Call (IPC)
==========================
:link_to_translation:`zh_CN:[中文]`
.. note::
IPC stands for an **"Inter-Processor Call"** and **NOT** "Inter-Process Communication" as found on other operating systems.
Overview
--------
Due to the dual core nature of the {IDF_TARGET_NAME}, there are some scenarios where a certain callback must be executed from a particular core such as:
- When allocating an ISR to an interrupt source of a particular core (applies to freeing a particular core's interrupt source as well)
- On particular chips (such as the ESP32), accessing memory that is exclusive to a particular core (such as RTC Fast Memory)
- Reading the registers/state of another core
The IPC (Inter-Processor Call) feature allows a particular core (the calling core) to trigger the execution of a callback function on another core (the target core). The IPC feature allows execution of a callback function on the target core in either a task context, or an interrupt context. Depending on the context that the callback function is executed in, different restrictions apply to the implementation of the callback function.
IPC in Task Context
-------------------
The IPC feature implements callback execution in a task context by creating an IPC task for each core during application startup. When the calling core needs to execute a callback on the target core, the callback will execute in the context of the target core's IPC task.
When using IPCs in a task context, users need to consider the following:
- IPC callbacks should ideally be simple and short. An IPC callback **must never block or yield**.
- The IPC tasks are created at the highest possible priority (i.e., ``configMAX_PRIORITIES - 1``).
- If :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY` is enabled, the target core's IPC task will be lowered to the current priority of the target core before executing the callback.
- If :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY` is disabled, the target core will always execute the callback at the highest possible priority.
- Depending on the complexity of the callback, users may need to configure the stack size of the IPC task via :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE`.
- The IPC feature is internally protected by a mutex. Therefore, simultaneous IPC calls from two or more calling core's are serialized on a first come first serve basis.
API Usage
^^^^^^^^^
Task Context IPC callbacks have the following restrictions:
- The callback must be of the :cpp:type:`esp_ipc_func_t` type.
- The callback **must never block or yield** as this will result in the target core's IPC task blocking or yielding.
- The callback must avoid changing any aspect of the IPC task's state, e.g., by calling ``vTaskPrioritySet(NULL, x)``.
The IPC feature offers the API listed below to execute a callback in a task context on a target core. The API allows the calling core to block until the callback's execution has completed, or return immediately once the callback's execution has started.
- :cpp:func:`esp_ipc_call` triggers an IPC call on the target core. This function will block until the target core's IPC task **begins** execution of the callback.
- :cpp:func:`esp_ipc_call_blocking` triggers an IPC on the target core. This function will block until the target core's IPC task **completes** execution of the callback.
IPC in Interrupt Context
------------------------
In some cases, we need to quickly obtain the state of another core such as in a core dump, GDB stub, various unit tests, and hardware errata workarounds. The IPC ISR feature implements callback execution from a High Priority Interrupt context by reserving a High Priority Interrupt on each core for IPC usage. When a calling core needs to execute a callback on the target core, the callback will execute in the context of the High Priority Interrupt of the target core.
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
For such scenarios, the IPC ISR feature supports execution of callbacks in a :doc:`High Priority Interrupt </api-guides/hlinterrupts>` context.
When using IPCs in High Priority Interrupt context, users need to consider the following:
.. list::
:CONFIG_IDF_TARGET_ARCH_XTENSA: - Since the callback is executed in a High Priority Interrupt context, the callback must be written entirely in assembly. See the API Usage below for more details regarding writing assembly callbacks.
- The priority of the reserved High Priority Interrupt is dependent on the :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` option.
When the callback executes, users need to consider the following:
.. list::
- The calling core will disable interrupts of priority level 3 and lower.
:CONFIG_IDF_TARGET_ARCH_XTENSA: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution of IPC ISR callback, the target core will disable interrupts of priority level 5 and lower regardless of what :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` is set to.
:CONFIG_IDF_TARGET_ARCH_RISCV: - Although the priority of the reserved interrupt depends on :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`, during the execution of IPC ISR callback, the target core will disable all interrupts.
API Usage
^^^^^^^^^
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
High Priority Interrupt IPC callbacks have the following restrictions:
- The callback must be of type :cpp:type:`esp_ipc_isr_func_t` but implemented entirely in assembly.
- The callback is invoked via the ``CALLX0`` instruction with register windowing disabled, thus the callback:
- must not call any register window related instructions, e.g., ``entry`` and ``retw``.
- must not call other C functions as register windowing is disabled.
- The callback should be placed in IRAM at a 4-byte aligned address.
- On invocation of, or after returning from the callback, the registers ``a2, a3, a4`` are saved/restored automatically, thus can be used in the callback. The callback should **ONLY** use those registers.
- ``a2`` contains the ``void *arg`` of the callback.
- ``a3/a4`` are free to use as scratch registers.
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
High Priority Interrupt IPC callbacks must be of type :cpp:type:`esp_ipc_isr_func_t` and have the same restrictions as for regular interrupt handlers. The callback function can be written in C.
The IPC feature offers the API listed below to execute a callback in a High Priority Interrupt context:
- :cpp:func:`esp_ipc_isr_call` triggers an IPC call on the target core. This function will busy-wait until the target core **begins** execution of the callback.
- :cpp:func:`esp_ipc_isr_call_blocking` triggers an IPC call on the target core. This function will busy-wait until the target core **completes** execution of the callback.
These functions interrupt the other CPU and execute the callback in the context of a High Priority Interrupt. There are two common usage patterns:
- For simple callbacks that do not enter critical sections shared with the other CPU, call :cpp:func:`esp_ipc_isr_call` or :cpp:func:`esp_ipc_isr_call_blocking` directly.
- If the calling CPU may enter critical sections used by the other CPU, or if several callbacks must run while the other CPU remains stopped, first stall the other CPU using :cpp:func:`esp_ipc_isr_stall_other_cpu` or :cpp:func:`esp_ipc_isr_stall_other_cpu_safe`. Then use :cpp:func:`esp_ipc_isr_call` or :cpp:func:`esp_ipc_isr_call_blocking` to execute callbacks. After the operation is complete, release the other CPU with :cpp:func:`esp_ipc_isr_release_other_cpu`.
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
The following code-blocks demonstrates a High Priority Interrupt IPC callback written in assembly that simply reads the target core's cycle count:
.. code-block:: asm
/* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) */
// this function reads CCOUNT of the target core and stores it in arg.
// use only a2, a3 and a4 regs here.
.section .iram1, "ax"
.align 4
.global esp_test_ipc_isr_get_cycle_count_other_cpu
.type esp_test_ipc_isr_get_cycle_count_other_cpu, @function
// Args:
// a2 - void* arg
esp_test_ipc_isr_get_cycle_count_other_cpu:
rsr.ccount a3
s32i a3, a2, 0
ret
The callback can be called directly when no shared critical section can deadlock:
.. code-block:: c
uint32_t cycle_count;
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
Alternatively, safely stall the other CPU before making one or more IPC calls:
.. code-block:: c
while (esp_ipc_isr_stall_other_cpu_safe() != ESP_OK) {
// Optionally, add a timeout or yield to avoid infinite loop
}
uint32_t cycle_count;
esp_ipc_isr_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, (void *)&cycle_count);
esp_ipc_isr_release_other_cpu();
.. note::
The number of scratch registers available for use is sufficient for most simple use cases. But if your callback requires more scratch registers, ``void *arg`` can point to a buffer that is used as a register save area. The callback can then save and restore more registers. See the :example:`system/ipc/ipc_isr`.
.. note::
For more examples of High Priority Interrupt IPC callbacks, you can refer to :idf_file:`components/esp_system/port/arch/xtensa/esp_ipc_isr_routines.S` and :idf_file:`components/esp_system/test_apps/esp_system_unity_tests/main/port/arch/xtensa/test_ipc_isr.S`.
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
See :idf_file:`examples/system/ipc/ipc_isr/riscv/main/main.c` for an example of its use.
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
See :idf_file:`examples/system/ipc/ipc_isr/xtensa/main/main.c` for an example of its use.
The High Priority Interrupt IPC API also provides the following convenience functions that can stall/resume the target core. These APIs utilize the High Priority Interrupt IPC, but supply their own internal callbacks:
.. list::
:CONFIG_IDF_TARGET_ARCH_RISCV: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target core. The calling core disables interrupts of level 3 and lower, while the target core will busy-wait with all interrupts disabled. The target core will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
:CONFIG_IDF_TARGET_ARCH_XTENSA: - :cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the target core. The calling core disables interrupts of level 3 and lower while the target core will busy-wait with interrupts of level 5 and lower disabled. The target core will busy-wait until :cpp:func:`esp_ipc_isr_release_other_cpu` is called.
- :cpp:func:`esp_ipc_isr_stall_other_cpu_safe` attempts to stall the other core only if it is not in a critical section or ISR context. If the other core is in such a state, the function considers it unsafe to stall, releases the core, and returns an error.
- :cpp:func:`esp_ipc_isr_release_other_cpu` resumes the target core.
Application Examples
--------------------
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
- :example:`system/ipc/ipc_isr/xtensa` demonstrates how to use the IPC ISR feature to run an IPC in the context of a High Priority Interrupt, allowing users to quickly get the state of the other CPU, with two assembly callbacks that return the PS register of the other core and save/restore registers while performing tasks based on input arguments.
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
- :example:`system/ipc/ipc_isr/riscv` demonstrates how to use the IPC ISR feature on {IDF_TARGET_NAME} to run an IPC in the context of a High Priority Interrupt, including how to quickly get the state of the other CPU and how to return multiple values from the callback function.
API Reference
-------------
.. include-build-file:: inc/esp_ipc.inc
.. include-build-file:: inc/esp_ipc_isr.inc
+707
View File
@@ -0,0 +1,707 @@
Logging library
===============
:link_to_translation:`zh_CN:[中文]`
Overview
--------
ESP-IDF provides a flexible logging system with two configurable versions, **Log V1** and **Log V2**, selectable via :ref:`CONFIG_LOG_VERSION`. This document outlines their features, configurations, usage guidelines, and performance comparisons.
- **Log V1** (default): The original implementation designed for simplicity. It is optimized for early and DRAM logging but has higher flash usage and lacks flexibility.
- **Log V2**: The enhanced implementation improves flexibility, reduces flash usage, and centralizes log formatting but requires a bit more stack.
**Log V2** is backward-compatible with **Log V1**, meaning projects written using **Log V1** can switch to **Log V2** without modification. However, projects utilizing Log V2-specific features cannot revert to **Log V1** due to compatibility constraints.
Features of **Log V1**
^^^^^^^^^^^^^^^^^^^^^^
- Formatting is included in the ``format`` argument and compiled into Flash.
- Fast early and DRAM logging compared to ESP_LOG.
- Simple implementation but has limitations:
- Larger binary size due to redundant formatting items.
- Inflexible due to the lack of support for custom log formatting.
- Build errors point to the wrong argument number in macros.
Features of **Log V2**
^^^^^^^^^^^^^^^^^^^^^^
- Centralized formatting via a single function, :cpp:func:`esp_log`.
- Reduces binary size by only storing the user-defined format string.
- The timestamp is captured only when it is required for output and the log level permits logging.
- Allows customization for log output:
- Disable/enable color, timestamps, or tags globally, per file or per message log.
- Output logs without formatting (useful for binary logging).
- Apply different log settings for bootloader and app.
- The format argument can be dynamic and set as a variable, allowing greater flexibility in constructing log messages.
- Unified handler for logs across bootloader, ISR, startup code, and constrained environments.
- Drawbacks:
- Consumes more stack and memory.
- The log handler is slightly slower than **Log V1**, but the difference is negligible compared to the time spent transferring the data, e.g. over UART.
Log Levels
----------
Log levels are configured separately for application and bootloader. This separation allows developers to apply different logging settings via Kconfig options for each. For example, concise logs can be enabled for the bootloader while detailed debugging is enabled for the application. Use the bootloader-specific Kconfig options to configure log levels for the bootloader independently of the main application.
There are six verbosity levels:
- **Verbose** - Highly detailed and frequent debugging messages, often including internal states, that may overwhelm the output. (highest)
- **Debug** - Detailed diagnostic messages intended to aid in debugging (e.g., variable values, pointer addresses).
- **Info** - General information messages that describe the normal operation of the system.
- **Warning** - Events that could potentially cause issues but have been handled or mitigated.
- **Error** - Critical errors indicating that the software cannot recover without intervention.
- **None** - No log output. Used to completely disable logging. (lowest)
Log Level Settings
------------------
Log level settings control which logs are included in the binary and their visibility at runtime. There are two types of log level settings:
- **Log level**: Specifies which log levels are displayed at runtime. The bootloader's **log level** is configured via :ref:`CONFIG_BOOTLOADER_LOG_LEVEL`, while the application's **log level** is set via :ref:`CONFIG_LOG_DEFAULT_LEVEL`. The current log level can be retrieved using the function ``esp_log_get_default_level``.
- **Maximum log level**: Determines which log levels are included in the binary. Logs above this level are discarded at compile time and excluded from the final image. It can be set higher than the **log level**, allowing additional logs to be included in the binary and enabling them for debugging later if needed via :cpp:func:`esp_log_level_set`. The :ref:`CONFIG_LOG_MAXIMUM_LEVEL` option enables this feature for the application, but the bootloader does not support it. For the bootloader, the **maximum log level** is always the same as the **log level**.
Example for the application: if the **log level** is set to **Warning** and the **maximum log level** is set to **Debug**, the binary will include log messages of levels **Error**, **Warning**, **Info**, and **Debug**. However, at runtime, only log messages of levels **Error** and **Warning** will be outputted unless the log level is explicitly changed using :cpp:func:`esp_log_level_set`. The log level can be adjusted, increased or decreased, depending on the user's needs.
``Maximum Log Level`` Setting
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``LOG_LOCAL_LEVEL`` definition allows you to override the **maximum log level** for a specific source file or component without modifying the Kconfig options. It effectively sets the **maximum log level** locally, enabling or excluding specific logs in the binary.
This approach is especially useful when you need more detailed logs for specific areas of the code without globally increasing the **maximum log level**, thereby avoiding unnecessary impacts on the binary size.
- Change the **maximum log level** for a source file (do not add it in header files, as it may not work due to the single-inclusion approach used by header files). Define ``LOG_LOCAL_LEVEL`` with one of the values from :cpp:type:`esp_log_level_t` before including ``esp_log.h``. This allows you to control which log messages are included in the binary for that specific source file.
.. code-block:: c
// in a my_file.c file
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
- Change the **maximum log level** for an entire component by defining ``LOG_LOCAL_LEVEL`` in the component's `CMakeLists.txt`. This ensures that the specified log level is applied across all source files within the component, controlling which log messages are included in the binary:
.. code-block:: cmake
# in a component's CMakeLists.txt file
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE")
Runtime **Log Level** Setting
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Only the application supports changing the log level at runtime. The bootloader does not support this feature.
By default, all log levels up to the **log level** are enabled at the startup. The function :cpp:func:`esp_log_level_set` can be used to set the **log level** globally or on a per-module basis. Modules are identified by their tags, which are human-readable ASCII zero-terminated strings. This functionality depends on :ref:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`, which is enabled by default. If this feature is not required, you can disable it to reduce code size and improve performance.
Example: Set the log level to ``ERROR`` for all components (global setting):
.. code-block:: c
esp_log_level_set("*", ESP_LOG_ERROR);
Adjusting log output per module (tag) depends on :ref:`CONFIG_LOG_TAG_LEVEL_IMPL`, which is enabled by default. If this feature is not required, you can disable it to reduce code size and improve performance:
Example: Set the log level to ``WARNING`` only for the Wi-Fi component (module-specific setting):
.. code-block:: c
esp_log_level_set("wifi", ESP_LOG_WARN);
Use Logging Library
---------------------
In each C file that uses the logging functionality, define the ``TAG`` variable.
.. code-block:: c
// #define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE // Optional: Increase log level that will be included in binary (only for this file)
#include "esp_log.h"
static const char* TAG = "MyModule";
// ...
ESP_LOGI(TAG, "Baud rate error %.1f%%. Requested: %d baud, actual: %d baud", error * 100, baud_req, baud_real);
ESP_EARLY_LOGW(TAG, "Early log message %d", i++);
ESP_DRAM_LOGE(DRAM_STR("TAG_IN_DRAM"), "DRAM log message %d", i++); // Use DRAM_STR macro to put in DRAM if needed
.. code-block:: bash
I (112500) MyModule: Baud rate error 1.5%. Requested: 115200 baud, actual: 116928 baud
W (112500) MyModule: Early log message 1
E TAG_IN_DRAM: DRAM log message 2
.. note::
The ``TAG`` variable points to a string literal stored in flash memory. If the same ``TAG`` string is used multiple times within a single build unit (translation unit), the compiler and linker typically optimize it to a single copy in flash through a process called **string pooling**. However, if the same ``TAG`` string is used across different components or translation units, each component or unit will have its own copy in flash unless global linker optimizations are applied.
The logging library provides a wide range of macros to accommodate various use cases, from general-purpose logging to early startup and constrained environments. Choosing the right macro and structuring your program accordingly can help optimize performance and ensure reliable operation. However, it is recommended to structure your program to avoid logging in constrained environments whenever possible.
- Verbose: :c:macro:`ESP_LOGV`, :c:macro:`ESP_EARLY_LOGV`, :c:macro:`ESP_DRAM_LOGV`.
- Debug: :c:macro:`ESP_LOGD`, :c:macro:`ESP_EARLY_LOGD`, :c:macro:`ESP_DRAM_LOGD`.
- Info: :c:macro:`ESP_LOGI`, :c:macro:`ESP_EARLY_LOGI`, :c:macro:`ESP_DRAM_LOGI`.
- Warning: :c:macro:`ESP_LOGW`, :c:macro:`ESP_EARLY_LOGW`, :c:macro:`ESP_DRAM_LOGW`.
- Error: :c:macro:`ESP_LOGE`, :c:macro:`ESP_EARLY_LOGE`, :c:macro:`ESP_DRAM_LOGE`.
There are three groups of macros available:
- **ESP_LOGx**: Standard logging macros suitable for most use cases during normal operation. Use these in your application code for logging in non-constrained environments, avoiding use in ISRs, early startup, or when the flash cache is disabled. A key characteristic of these macros is that they use the `vprintf` function from the Newlib library for formatting and outputting logs.
- **ESP_EARLY_LOGx**: Designed for use in constrained environments during early startup, before the heap allocator or syscalls are initialized. These macros are commonly used in critical startup code or in critical sections where interrupts are disabled. A key characteristic of these macros is that they use the ROM `printf` function, always output timestamps in microseconds, and do not support per-module log verbosity settings.
- **ESP_DRAM_LOGx**: Designed for use in constrained environments where logging occurs with interrupts disabled or when the flash cache is inaccessible. These macros should be used sparingly, as they can impact performance. They are suitable for critical sections or interrupt routines where other logging macros may not work reliably. A key characteristic of these macros is that they use the ROM `printf` function, do not output timestamps, allocate the format argument in DRAM to ensure accessibility when the cache is disabled, and do not support per-module log verbosity settings.
.. Note::
Use the **DRAM_STR("my_tag")** macro to allocate the tag in DRAM. This is necessary to ensure access to the tag when the flash cache is disabled.
The difference between **Log V1** and **Log V2** is that in **Log V2**, all logs from these macros are routed through a single handler. This handler can automatically detect constrained environments (e.g., early startup, disabled interrupts, or flash cache inaccessible) and dynamically selects the appropriate printing function, ensuring efficient logging across various runtime contexts.
Log Format
----------
- **Log V1**: Only supports disabling color formatting globally. Other formatting options, such as timestamp and tag, are always enabled.
- **Log V2**:
- Allows complete customization of formatting, including the ability to disable color, tag, and timestamp formatting globally, per file, per module, or even for individual log messages.
- Provides finer control over log output, making it more adaptable to specific use cases and environments.
.. code-block:: c
// #define ESP_LOG_COLOR_DISABLED (1) /* For Log v2 only */
// #define ESP_LOG_TIMESTAMP_DISABLED (1) /* For Log v2 only */
#include "esp_log.h"
static const char* TAG = "boot";
// ...
ESP_LOGI(TAG, "chip revision: v%d.%d", major, minor);
.. code-block:: none
I (56) boot: chip revision: v3.0
level name |end of line
| |
[0;32mI (56) boot: chip revision: v3.0[0m
|_____| |___||____||_________________||_|
|start | |tag | |end color
|color | |user string
|timestamp
The logging system supports the following formatting options, applicable for both the application and bootloader:
- **Color**: Adds color codes to enhance log visibility globally. Controlled by :ref:`CONFIG_LOG_COLORS`, which is disabled by default because the ESP-IDF monitor tool (`idf.py monitor`) can detect the log level by its **level name** and apply the standard IDF color scheme.
- For **Log V2**, the :ref:`CONFIG_LOG_COLORS_SUPPORT` option enables runtime support for adding color output to specific logs, files, or components, even if global color is disabled. To enable color for a specific context use ``ESP_LOG_COLOR_DISABLED``.
.. note::
Please note that IDF Monitor requires the log message format described above in order to apply color highlighting automatically. The minimum required format is a log level name followed by a timestamp, and each log message must end with a newline character. For example, ``I (56): Log message\n``. If this format is not followed, such as when the timestamp is disabled, automatic log coloring will not work. In these cases, it is recommended to enable :ref:`CONFIG_LOG_COLORS` in the menuconfig. Another limitation is that for multi-line log messages, only the first line will be colored correctly.
- **Level Name**: A single letter (I, W, E, D, V) indicating log verbosity, displayed at the start of each message. Useful for identifying log levels, especially when color is disabled, as utilized by the ESP-IDF monitor tool.
- **Timestamp**: Adds a timestamp to log messages globally. Controlled by :ref:`CONFIG_LOG_TIMESTAMP_SOURCE`.
- **None**: No timestamp. Useful for log analysis or debugging where timing is not critical. Saves processing power and memory. Available only for **Log V2**.
- **Milliseconds since boot** `(18532)` (default): Derived from the RTOS tick count multiplied by the tick period.
- **System time (HH:MM:SS.sss)** `(14:31:18.532)`: Displays time in hours, minutes, seconds, and milliseconds.
- **System time (YY-MM-DD HH:MM:SS.sss)** `(2023-08-15 14:31:18.532)`: Similar to the above, but also includes the date.
- **Unix time in milliseconds** `(1692099078532)`: Displays Unix time in milliseconds.
- For **Log V2**, the :ref:`CONFIG_LOG_TIMESTAMP_SUPPORT` option enables runtime support for adding timestamp output to specific logs, files, or components, even if global timestamp is disabled. To enable the **Milliseconds since boot** timestamp for a specific context, use ``ESP_LOG_TIMESTAMP_DISABLED``.
- **Tag**: Displays a user-defined identifier for the source module.
- For **Log V2**, the tag can be passed to the macros as ``NULL``, in which case it will not be printed, and per-component log level check will not work.
- **End Line**: Adds a newline character at the end of the log messages.
The following options are applicable only for **Log V2** and are used alongside the provided log macros. These definitions can be set in the same manner as ``LOG_LOCAL_LEVEL``. Their scope depends on where they are defined (e.g., file, component, or globally):
- **ESP_LOG_CONSTRAINED_ENV**:
- Define as ``1`` to force the log handler :cpp:func:`esp_log` to use a safe printf function suitable for the specified scope.
- **ESP_LOG_FORMATTING_DISABLED**:
- Default: ``0`` (enables all formatting items such as color, timestamps, tags, and end line).
- Define as ``1`` to disable all formatting items for the specified scope.
- **ESP_LOG_COLOR_DISABLED**: Requires :ref:`CONFIG_LOG_COLORS_SUPPORT` to be enabled.
- If global color (:ref:`CONFIG_LOG_COLORS`) is disabled, define as ``0`` to enable color output for the specified scope.
- If global color (:ref:`CONFIG_LOG_COLORS`) is enabled, define as ``1`` to disable color output for the specified scope.
- **ESP_LOG_TIMESTAMP_DISABLED**: Requires :ref:`CONFIG_LOG_TIMESTAMP_SUPPORT` to be enabled.
- If global timestamping (:ref:`CONFIG_LOG_TIMESTAMP_SOURCE`) is disabled, define as ``0`` to enable tick timestamp output for the specified scope.
- If global timestamping (:ref:`CONFIG_LOG_TIMESTAMP_SOURCE`) is enabled, define as ``1`` to disable tick timestamp output for the specified scope.
- **ESP_LOG_MODE_BINARY_EN**: Requires ``CONFIG_LOG_MODE_BINARY`` or ``CONFIG_BOOTLOADER_LOG_MODE_BINARY`` to be enabled.
- Setting ``ESP_LOG_MODE_BINARY_EN`` to ``0`` does not make sense for regular use because logs will still be sent in binary mode. However, the format string will not be removed from flash, and argument analysis will be performed at runtime. This setting may be useful for specific scenarios such as debugging or testing.
- Setting ``ESP_LOG_MODE_BINARY_EN`` to ``1`` when text logging mode is enabled will have no effect. In this case, ``ESP_LOG_MODE_BINARY_EN`` will be suppressed and automatically defined as ``0``.
Per-Log Formatting
^^^^^^^^^^^^^^^^^^
The above definition works seamlessly with the provided log macros. However, if you require more flexibility or the ability to change settings at runtime, such as adjusting the log level based on a value (for example, temperature), this can be done using alternative macros. Note that in this case, the logs cannot be discarded from the binary, as they bypass compile-time log level checks.
The example below demonstrates how to adjust formatting for individual log messages:
.. code-block:: c
#include "esp_log.h"
esp_log_config_t configs = {
.opts = {
.log_level = ESP_LOG_INFO, // Set log level
.constrained_env = false, // Specify constrained environment
.require_formatting = true, // Enable formatting
.dis_color = ESP_LOG_COLOR_DISABLED, // Use global color setting
.dis_timestamp = ESP_LOG_TIMESTAMP_DISABLED, // Use global timestamp setting
.reserved = 0, // Reserved for future use
}
};
// ...
if (temperature > 55) {
configs.opts.log_level = ESP_LOG_WARN;
}
// Similar to ESP_LOGx macros but allows applying custom configurations
// If the configs var is constant, the compiler can exclude the log during compilation
// if it is below the maximum log level, otherwise not.
ESP_LOG_LEVEL_LOCAL(configs, TAG, "Temp = %dC", temperature);
// Note: The following calls bypass compile-time log level checks,
// they cannot be discarded from the binary
esp_log(configs, TAG, "Temp = %dC", temperature);
ESP_LOG_LEVEL(configs, TAG, "Temp = %dC", temperature);
Log Level Control
-----------------
Only the application supports changing the log level at runtime. The bootloader does not support this feature.
The logging library allows adjusting log output per module (tag) at runtime using the function :cpp:func:`esp_log_level_set`. This feature applies only to non-constrained environments (**ESP_LOGx** macros). Constrained environments (e.g., **ESP_EARLY_LOGx** or **ESP_DRAM_LOGx**) do not support dynamic log levels due to the absence of locks and lightweight requirements in their log handlers.
.. code-block:: c
// Set log level to ERROR for all components (global setting)
esp_log_level_set("*", ESP_LOG_ERROR);
// Set log level to WARNING for the WiFi component (module-specific setting)
esp_log_level_set("wifi", ESP_LOG_WARN);
// Set log level to INFO for the DHCP client (module-specific setting)
esp_log_level_set("dhcpc", ESP_LOG_INFO);
There are three settings that control the ability to change the log level at runtime globally or per module (tag):
- **Dynamic Log Level Control** (:ref:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`, enabled by default): Enables runtime log level changes via :cpp:func:`esp_log_level_set`. This feature increases flexibility but adds memory and performance overhead. If binary size is a concern and dynamic log level changes are unnecessary, consider disabling this option, especially when :ref:`CONFIG_LOG_TAG_LEVEL_IMPL` is set to **None**, to minimize program size.
If your application does not require dynamic log level adjustments, disabling this option can improve efficiency by:
- Reducing memory consumption:
- **IRAM**: about 260 bytes
- **DRAM**: about 264 bytes
- **Flash**: about 1 KB
- Boosting log operation performance by up to 10 times.
- **Tag-Level Checks** (:ref:`CONFIG_LOG_TAG_LEVEL_IMPL`, default **Cache + Linked List**): Determines how per-tag log level checks are performed, affecting memory usage and lookup speed:
- **None**: Disables per-tag log level checks entirely, reducing overhead but removing runtime flexibility.
- **Linked List**: Enables per-tag log level settings using a linked list-only implementation (no cache). This method searches through all tags in the linked list to determine the log level, which may result in slower lookups for a large number of tags but consumes less memory compared to the **Cache** approach. The linked list approach performs full string comparisons of log tags to identify the appropriate log level. Unlike **Cache**, it does not rely on tag pointer comparisons, making it suitable for dynamic tag definitions. Select this option if you prioritize memory savings, need to enable or disable logs for specific modules, or want to use tags defined as variables. Selecting this option automatically enables **Dynamic Log Level Control**. The linked list entries are allocated on the heap during the execution of ``ESP_LOGx`` macros when a new tag is encountered.
- **Cache + Linked List** (Default): It is a hybrid mode that combines caching with a **linked list** for log tag level checks. This hybrid approach offers a balance between speed and memory usage. The cache stores recently accessed log tags and their corresponding log levels, providing faster lookups for frequently used tags. The cache approach compares the tag pointers, which is faster than performing full string comparisons. For less frequently used tags, the **linked list** is utilized to search for the log level. This option may not work properly when dynamic tag definitions are used, as it relies on tag pointer comparisons in the cache, which are not suitable for dynamically defined tags. This hybrid approach improves the efficiency of log level retrieval by leveraging the speed of caching for common tags and the memory efficiency of a linked list for less frequently used tags. Selecting this option automatically enables **Dynamic Log Level Control**.
There are some cache configurations to balance memory usage and lookup performance. These settings determine how log tag levels are stored and accessed: :ref:`CONFIG_LOG_TAG_LEVEL_CACHE_IMPL`.
- **Array**: A simple implementation without reordering, suitable for low-memory applications that prioritize simplicity.
- **Binary Min-Heap** (default): An optimized implementation for fast lookups with automatic reordering. Ideal for high-performance applications with sufficient memory. The **Cache Size** (:ref:`CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE`) defines the capacity, which defaults to 31 entries.
A larger cache size enhances lookup performance for frequently accessed log tags but increases memory consumption. In contrast, a smaller cache size conserves memory but may result in more frequent evictions of less commonly used log tags.
- **Master Log Level** (:ref:`CONFIG_LOG_MASTER_LEVEL`, disabled by default): It is an optional setting designed for specific debugging scenarios. It enables a global "master" log level check that occurs before timestamps and tag cache lookups. This is useful for compiling numerous logs that can be selectively enabled or disabled at runtime while minimizing performance impact when log output is unnecessary.
Common use cases include temporarily disabling logs during time-critical or CPU-intensive operations and re-enabling them later.
.. note:: For **Log V1**, this feature may significantly increase program size based on the number of compiled logs. For **Log V2**, the impact is minimal as the check is integrated within the log handler.
If enabled, the master log level defaults to :ref:`CONFIG_LOG_DEFAULT_LEVEL` and can be adjusted at runtime using :cpp:func:`esp_log_set_level_master`. This global check takes precedence over ``esp_log_get_default_level``.
The snippet below shows how it works. Setting the **Master log level** to ``ESP_LOG_NONE`` disables all logging globally. :cpp:func:`esp_log_level_set` does not currently affect logging. However, after the **Master log level** is adjusted to a higher level, logs will be printed as configured by :cpp:func:`esp_log_level_set`:
.. code-block:: c
// Master logging level is CONFIG_LOG_DEFAULT_LEVEL at start-up and = ESP_LOG_INFO
ESP_LOGI("lib_name", "Message for print"); // Prints an INFO message
esp_log_level_set("lib_name", ESP_LOG_WARN); // Enables WARN logs for lib_name
// Disables all logs globally. esp_log_level_set has no effect at the moment
esp_log_set_level_master(ESP_LOG_NONE);
ESP_LOGW("lib_name", "Message for print"); // No print, Master logging level blocks it
esp_log_level_set("lib_name", ESP_LOG_INFO); // Enables INFO logs for lib_name
ESP_LOGI("lib_name", "Message for print"); // No print, Master logging level blocks it
// Enables all INFO logs globally
esp_log_set_level_master(ESP_LOG_INFO);
ESP_LOGI("lib_name", "Message for print"); // Prints an INFO message
.. note::
Even when logs are disabled by tag, processing still takes approximately 10.9 microseconds. To reduce this overhead, consider using the **Master Log Level** or disabling **Tag-Level Checks** functionality.
Logging of Buffers
------------------
The logging system provides macros for logging buffer data. These macros can be used in both bootloader and application, and they are independent of the log version. Available macros:
- :c:macro:`ESP_LOG_BUFFER_HEX` and :c:macro:`ESP_LOG_BUFFER_HEX_LEVEL`: Logs a buffer of hexadecimal bytes. The data is split into lines with 16 bytes per line. :c:macro:`ESP_LOG_BUFFER_HEX` is only for the ``Info`` log level.
.. code-block:: c
#include "esp_log_buffer.h"
uint8_t buffer[] = {
0x54, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20,
0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x73,
0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69,
0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66
};
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, sizeof(buffer), ESP_LOG_DEBUG);
.. code-block:: none
I (954) MyModule: 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73
I (964) MyModule: 74 61 72 74 65 64 20 69 73 20 61 6e 64 20 66
- :c:macro:`ESP_LOG_BUFFER_CHAR` and :c:macro:`ESP_LOG_BUFFER_CHAR_LEVEL`: Logs a buffer of printable characters. Each line contains up to 16 characters. :c:macro:`ESP_LOG_BUFFER_CHAR` is only for the ``Info`` log level.
.. code-block:: c
#include "esp_log_buffer.h"
char buffer[] = "The quick brown fox jumps over the lazy dog.";
ESP_LOG_BUFFER_CHAR_LEVEL(TAG, buffer, sizeof(buffer), ESP_LOG_WARN);
.. code-block:: none
I (980) MyModule: The quick brown
I (985) MyModule: fox jumps over
I (990) MyModule: the lazy dog.
- :c:macro:`ESP_LOG_BUFFER_HEXDUMP`: Dumps a buffer in a formatted hex dump style, displaying both the memory address and corresponding ASCII values. This is especially useful for debugging raw memory content.
.. code-block:: c
#include "esp_log_buffer.h"
uint8_t buffer[] = {
0x54, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20,
0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x73,
0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69
};
ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, sizeof(buffer), ESP_LOG_INFO);
.. code-block:: none
I (1013) MyModule: 0x3ffb5bc0 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73 |The way to get s|
I (1024) MyModule: 0x3ffb5bd0 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69 |tarted is to qui|
The number of lines in the output depends on the size of the buffer.
Binary Logging
--------------
Binary logging is a feature available only in **Log V2**, enabling logs to be transmitted in binary format instead of text. This is configured separately for the **bootloader** (``CONFIG_BOOTLOADER_LOG_MODE_BINARY``) and **application** (``CONFIG_LOG_MODE_BINARY``) via Kconfig options.
By default, when **Log V2** is enabled, the logging system uses **text mode**. Enabling binary logging reduces flash memory usage by removing log format strings from flash and sending only their addresses instead. Additionally, ``printf`` functions are not used, which reduces both stack usage and flash consumption.
This feature introduces the :c:macro:`ESP_LOG_ATTR_STR` macro, which relocates format strings to a ``.noload`` section, effectively removing them from the final binary image. You can also use this mechanism for assertions or user-defined logging messages to further minimize flash usage.
Summary of Benefits:
- Reduces **flash size** by approximately **10% 35%**, depending on the application. The more extensive the logging in a program, the greater the potential savings.
- Minimizes **stack usage** by eliminating the need for the ``vprintf``-like function for log formatting.
- Reduces **log transmission overhead** by transmitting compact binary data.
Binary logging is especially beneficial in **resource-constrained** environments where flash size optimization and efficient logging are critical.
Binary Logging Workflow
-----------------------
Binary logging consists of two main components:
1. :ref:`Chip Side <chip-side>`: Encodes and transmits log data.
- Encoding process
- Argument type encoding
- Runtime argument type encoding
2. :ref:`Host Side <host-side>`: Receives and decodes data using the `esp-idf-monitor tool <https://github.com/espressif/esp-idf-monitor>`_. The ``idf.py monitor`` command automatically decodes binary logs.
- Detects binary log packets.
- Extracts packet fields (log level, format, tag, timestamp, arguments).
- Determines whether addresses reference:
- **ELF file** (requires lookup)
- **Embedded string** (contained in the packet)
- Decodes arguments using the format string and the given array of arguments.
- Reconstructs the final log message by coupling the format string with the decoded arguments.
- Applies terminal colorization.
.. _chip-side:
Chip Side
^^^^^^^^^
Encoding Process
""""""""""""""""
Binary logs are transmitted as structured packets. Strings are sent as addresses if they exist in the ELF file. For runtime-generated strings, an embedded string format is used to transmit the string to the host.
Packet structure:
.. code-block:: none
[0] - Message Type (1: bootloader, 2: application, ...)
[1] - Control Byte (log level, version, time_64bits flag)
[2] - Length (10-bit, max 1023 bytes)
[3-6] - Format Address (if present in ELF) or embedded string
[7-10] - Tag Address (if present in ELF) or embedded string
[11-14] - Timestamp (32-bit if timestamp does not exceed 32 bits. [11-18] - occupied if timestamp takes 64 bits, time_64bits flag is set in Control Byte)
[...] - Arguments (optional). It is an array of arguments: 32-bit, 64-bit, pointers, and embedded string/data.
[15] - CRC8 checksum
The embedded string format is used if string is not present in ELF file, it follows this structure:
.. code-block:: none
[0] - Embedded Identifier (0xFF - 0xFC)
[0,1] - (10-bit) Negative Length of the string = 1 - len(str)
[...] - String Content
.. note::
All multi-byte fields in the packet structure use big-endian encoding.
Argument Type Encoding
""""""""""""""""""""""
Since the format string is removed from the final binary, the chip must still identify argument types to correctly transmit them to the host. This is achieved using the :c:macro:`ESP_LOG_ARGS_TYPE` macro, which leverages the `_Generic` feature to classify user arguments at compile time into three categories: **32-bit**, **64-bit**, and **pointers**. This macro generates an **argument type array** at runtime and passes it to ``esp_log`` before the user arguments, ensuring that:
- The chip transmits data with the correct size and offset.
- The host tool reconstructs the log message accurately.
Runtime Behavior
""""""""""""""""
The ``esp_log`` function first checks if **binary logging** is enabled in the given configuration. If enabled, it extracts the **argument type array** from ``va_list``. However, if the binary log flag is **not** set, no preprocessed argument type array is available. In this case, the binary log handler **extracts argument types** from the format string at runtime.
This runtime extraction is less efficient than explicitly using ``ESP_LOG_ATTR_STR(format) ESP_LOG_ARGS(__VA_ARGS__)``, which generates the argument type array at compile time and removes the format string from flash. Nevertheless, this mechanism ensures that even if a **third-party library does not support binary logging**, logs will still be output correctly.
Special Handling for Buffer Logs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Binary logging supports buffer log functions such as:
- :c:macro:`ESP_LOG_BUFFER_HEX_LEVEL`
- :c:macro:`ESP_LOG_BUFFER_CHAR_LEVEL`
- :c:macro:`ESP_LOG_BUFFER_HEXDUMP`
In such cases, the binary log handler checks whether the format address matches any predefined constants (e.g., ``ESP_BUFFER_HEX_FORMAT``). If it does, the handler skips sending a format string and instead **transmits the raw buffer data directly**.
.. _host-side:
Host Side (Monitor Tool)
^^^^^^^^^^^^^^^^^^^^^^^^
On the **host side**, the `esp-idf-monitor tool <https://github.com/espressif/esp-idf-monitor>`_ decodes binary logs automatically. It is important that the monitor tool operates with the correct version of ELF files. The **bootloader** and **application** each have their own ELF files, which the tool automatically selects when ``idf.py monitor`` is calling.
If an **ELF address** is received, the monitor tool **retrieves the string from the ELF file** using the corresponding ``message type`` byte. If the **address starts with 0xFF** (range: ``0xFF - 0xFC``), it indicates an **embedded string**, with its length encoded in **10 bits**.
Once all components are retrieved, they are formatted and output to the terminal.
Performance and Measurements
----------------------------
When logging is used in a task, the task stack must be configured with at least 2 KB of space to ensure sufficient memory for logging operations.
The following measurements were performed using tests inside the log component with default settings (the maximum and default log levels were set to INFO, color support was disabled, without master log and timestamps were enabled) across different chips:
- Performance measurements for log APIs
- Stack usage for log APIs
``esp_rom_printf`` and ``esp_rom_vprintf`` produce similar results. Similarly, ``vprintf`` and ``printf`` yield comparable outcomes. Hence, only one of each pair is included in the tables below.
.. list-table:: Stack Usage (bytes)
:header-rows: 1
* - Function
- ESP32
- ESP32C2
- ESP32C3
* - esp_rom_printf
- 128
- 192
- 192
* - ESP_EARLY_LOGI V1
- 128
- 192
- 192
* - ESP_EARLY_LOGI V2
- 336
- 324
- 324
* - ESP_DRAM_LOGI V1
- 128
- 192
- 192
* - ESP_DRAM_LOGI V2
- 336
- 324
- 324
* - vprintf
- 1168
- 384
- 1344
* - ESP_LOGI V1
- 1184
- 384
- 1344
* - ESP_LOGI V2
- 1152
- 592
- 1504
The stack usage differences between **Log V1** and **Log V2** are negligible.
.. list-table:: Performance (without output in microseconds)
:header-rows: 1
* - Function
- ESP32
- ESP32C2
- ESP32C3
* - esp_rom_printf
- 1
- 2
- 1
* - ESP_EARLY_LOGI V1
- 15
- 24
- 14
* - ESP_EARLY_LOGI V2
- 28
- 36
- 25
* - ESP_DRAM_LOGI V1
- 6
- 9
- 5
* - ESP_DRAM_LOGI V2
- 19
- 22
- 14
* - vprintf
- 15
- 9
- 7
* - ESP_LOGI V1
- 27
- 16
- 12
* - ESP_LOGI V2
- 77
- 54
- 40
If logging to UART is measured, the performance numbers for **Log V1** and **Log V2** are nearly identical. The slight differences in processing overhead introduced by **Log V2** become negligible compared to the time it takes to send logs over UART. Thus, in most practical use cases, the performance impact of switching to **Log V2** will be unnoticeable.
**Memory Usage (bytes)**
The following measurements were performed using the ``esp_timer`` example with default settings for ESP32: the maximum and default log levels were set to INFO, color support was disabled, and timestamps were enabled. After enabling the **Log V2** option, the example was rebuilt, and the memory usage differences were compared using the command:
.. code-block:: bash
idf.py size --diff ~/esp/logv2/build_v1
.. list-table::
:header-rows: 1
* - Version
- IRAM
- DRAM
- Flash Code
- Flash Data
- App binary size
* - Log V2
- +1772
- 36
- 956
- 1172
- 181104 (384)
.. list-table::
:header-rows: 1
:align: center
* - Version
- Bootloader binary size
* - Log V2
- 26272 (+160)
Enabling **Log V2** increases IRAM usage while reducing the overall application binary size, Flash code, and data usage.
.. only:: not CONFIG_ESP_ROM_HAS_VPRINTF_FUNC
Reducing IRAM Usage in Log V2
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The IRAM increase in **Log V2** is primarily caused by ``esp_rom_vprintf``, which is compiled into IRAM (about 1.2 KB) on {IDF_TARGET_NAME}. This function is referenced as the fallback formatter for constrained environments (ISR, cache disabled) in the ``esp_log_vprintf()`` inline function.
On chips where IRAM and DRAM share the same memory pool, this also reduces available heap by the same amount (about 1.2 KB).
To eliminate this cost, disable :ref:`CONFIG_LOG_API_CONSTRAINED_ENV_SAFE` (enabled by default). When disabled:
- ``ESP_DRAM_LOGx`` and ``ESP_EARLY_LOGx`` expand directly to ``esp_rom_printf()`` (a true ROM function, zero IRAM cost), bypassing the ``esp_log()`` pipeline entirely.
- Normal ``ESP_LOGx`` calls in constrained environments will use the standard ``vprintf`` function. If ``vprintf`` resides in flash, such calls may crash. Use ``ESP_DRAM_LOGx`` for any logging that must work with cache disabled or from an ISR.
- ``esp_rom_vprintf`` is never referenced, so the linker excludes it from the binary.
When enabled, the original **Log V2** behavior is preserved: all constrained-environment logs route through ``esp_log()`` and use ``esp_rom_vprintf`` as the formatter for early/DRAM logs.
Logging to Host via JTAG
------------------------
By default, the logging library uses the vprintf-like function to write formatted output to the dedicated UART. By calling a simple API, all log output may be routed to JTAG instead, making logging several times faster. For details, please refer to Section :ref:`app_trace-logging-to-host`.
Thread Safety
-------------
Logging from constrained environments (or for **ESP_EARLY_LOGx** and **ESP_DRAM_LOGx**) does not use locking mechanisms, which can lead to rare cases of log corruption if other tasks are logging in parallel. To minimize such risks, it is recommended to use general-purpose macros whenever possible.
General-purpose macros (**ESP_LOGx**) ensure thread safety by acquiring locks during log output. In **Log V2**, additional protection is provided by ``flockfile`` during multiple ``vprintf`` calls for formatting.
Logs are first written to a memory buffer before being sent to the UART, ensuring thread-safe operations across different tasks. Avoid logging from constrained environments unless necessary to maintain reliable log output.
Application Example
-------------------
The logging library is commonly used by most ESP-IDF components and examples. For demonstration of log functionality, check ESP-IDF's :idf:`examples` directory. The most relevant examples that deal with logging are the following:
* :example:`system/ota`
* :example:`storage/sd_card`
* :example:`protocols/https_request`
API Reference
-------------
.. include-build-file:: inc/esp_log.inc
.. include-build-file:: inc/esp_log_level.inc
.. include-build-file:: inc/esp_log_buffer.inc
.. include-build-file:: inc/esp_log_timestamp.inc
.. include-build-file:: inc/esp_log_color.inc
.. include-build-file:: inc/esp_log_write.inc
+225
View File
@@ -0,0 +1,225 @@
Heap Memory Allocation
======================
{IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT: default="16", esp32s3="16", esp32p4="16"}
:link_to_translation:`zh_CN:[中文]`
Stack and Heap
--------------
ESP-IDF applications use the common computer architecture patterns of **stack** (dynamic memory allocated by program control flow), **heap** (dynamic memory allocated by function calls), and **static memory** (memory allocated at compile time).
Because ESP-IDF is a multi-threaded RTOS environment, each RTOS task has its own stack. By default, each of these stacks is allocated from the heap when the task is created. See :cpp:func:`xTaskCreateStatic` for the alternative where stacks are statically allocated.
Because {IDF_TARGET_NAME} uses multiple types of RAM, it also contains multiple heaps with different capabilities. A capabilities-based memory allocator allows apps to make heap allocations for different purposes.
For most purposes, the C Standard Library's ``malloc()`` and ``free()`` functions can be used for heap allocation without any special consideration. However, in order to fully make use of all of the memory types and their characteristics, ESP-IDF also has a capabilities-based heap memory allocator. If you want to have a memory with certain properties (e.g., :ref:`dma-capable-memory` or executable-memory), you can create an OR-mask of the required capabilities and pass that to :cpp:func:`heap_caps_malloc`.
.. _memory_capabilities:
Memory Capabilities
-------------------
The {IDF_TARGET_NAME} contains multiple types of RAM:
- DRAM (Data RAM) is memory that is connected to CPU's data bus and is used to hold data. This is the most common kind of memory accessed as a heap.
- IRAM (Instruction RAM) is memory that is connected to the CPU's instruction bus and usually holds executable data only (i.e., instructions). If accessed as generic memory, all accesses must be aligned to :ref:`32-Bit Accessible Memory <32-Bit Accessible Memory>`.
- D/IRAM is RAM that is connected to CPU's data bus and instruction bus, thus can be used either Instruction or Data RAM.
For more details on these internal memory types, see :ref:`memory-layout`.
.. only:: SOC_SPIRAM_SUPPORTED
It is also possible to connect external SPI RAM to the {IDF_TARGET_NAME}. The :doc:`external RAM </api-guides/external-ram>` is integrated into the {IDF_TARGET_NAME}'s memory map via the cache, and accessed similarly to DRAM.
All DRAM memory is single-byte accessible, thus all DRAM heaps possess the ``MALLOC_CAP_8BIT`` capability. Users can call ``heap_caps_get_free_size(MALLOC_CAP_8BIT)`` to get the free size of all DRAM heaps.
.. only:: esp32
If users run out of ``MALLOC_CAP_8BIT``, they can use ``MALLOC_CAP_IRAM_8BIT`` instead. In that case, IRAM can still be used as a "reserve" pool of internal memory if the users only access it in a 32-bit aligned manner, or if they enable ``CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY``.
.. note::
This option is available only on single-core ESP32 configuration (``CONFIG_FREERTOS_UNICORE=y``). The ``CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY`` option has a significant disadvantage compared to regular memory: every byte, half-word, and arbitrary unaligned access to ``MALLOC_CAP_IRAM_8BIT`` memory triggers a ``LoadStore`` or ``Alignment`` exception. Although these exceptions are handled in software to ensure correct values are read or written, each access incurs approximately 167 CPU cycles of overhead and can cause significant performance degradation if accessed frequently. Therefore, it should be avoided in performance-critical sections of code such as ISRs or tight loops. Consider refactoring the code to use 32-bit aligned (``uint32_t``) accesses.
When calling ``malloc()``, the ESP-IDF ``malloc()`` internally calls ``heap_caps_malloc_default(size)``. This will allocate memory with the capability ``MALLOC_CAP_DEFAULT``, which is byte-addressable.
``MALLOC_CAP_DEFAULT`` describes the memory capability, not the exact allocation policy. In particular, ``heap_caps_malloc(size, MALLOC_CAP_DEFAULT)`` is not required to follow the same placement strategy as ``malloc()``.
.. only:: SOC_SPIRAM_SUPPORTED
For example, when :doc:`external RAM </api-guides/external-ram>` is added to the capability allocator, ``heap_caps_malloc(size, MALLOC_CAP_DEFAULT)`` may return external RAM, while ``malloc()`` may still prefer or require internal RAM depending on the configuration.
Because ``malloc()`` uses the capabilities-based allocation system, memory allocated using :cpp:func:`heap_caps_malloc` can be freed by calling the standard ``free()`` function.
Available Heap
--------------
.. _dram-definition:
DRAM
^^^^
At startup, the DRAM heap contains all data memory that is not statically allocated by the app. Reducing statically-allocated buffers increases the amount of available free heap.
To find the amount of statically allocated memory, use the :ref:`idf.py size <idf.py-size>` command.
.. only:: esp32
.. note::
See the :ref:`dram` section for more details about the DRAM usage limitations.
.. note::
At runtime, the available heap DRAM may be less than calculated at compile time, because, at startup, some memory is allocated from the heap before the FreeRTOS scheduler is started (including memory for the stacks of initial FreeRTOS tasks).
IRAM
^^^^
At startup, the IRAM heap contains all instruction memory that is not used by the app executable code.
The :ref:`idf.py size <idf.py-size>` command can be used to find the amount of IRAM used by the app.
D/IRAM
^^^^^^
Some memory in the {IDF_TARGET_NAME} is available as either DRAM or IRAM. If memory is allocated from a D/IRAM region, the free heap size for both types of memory will decrease.
Heap Sizes
^^^^^^^^^^
At startup, all ESP-IDF apps log a summary of all heap addresses (and sizes) at level Info:
.. code-block:: none
I (252) heap_init: Initializing. RAM available for dynamic allocation:
I (259) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (265) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM
I (272) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (278) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (284) heap_init: At 4008944C len 00016BB4 (90 KiB): IRAM
Finding Available Heap
^^^^^^^^^^^^^^^^^^^^^^
See :ref:`heap-information`.
Special Capabilities
--------------------
.. _dma-capable-memory:
DMA-Capable Memory
^^^^^^^^^^^^^^^^^^
Use the ``MALLOC_CAP_DMA`` flag to allocate memory which is suitable for use with hardware DMA engines (for example SPI and I2S). This capability flag excludes any external PSRAM.
.. only:: SOC_SPIRAM_SUPPORTED and not esp32
The EDMA hardware feature allows DMA buffers to be placed in external PSRAM, but there may be additional alignment constraints. Consult the {IDF_TARGET_NAME} Technical Reference Manual for details. To allocate a DMA-capable external memory buffer, use the ``MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA`` capabilities flags; the heap allocator will take care of alignment requirements imposed by the cache and DMA subsystems. If a peripheral has additional alignment requirements, you can use :cpp:func:`heap_caps_aligned_alloc` with the necessary alignment specified.
.. _32-bit accessible memory:
32-Bit Accessible Memory
^^^^^^^^^^^^^^^^^^^^^^^^
If a certain memory structure is only addressed in 32-bit units, for example, an array of ints or pointers, it can be useful to allocate it with the ``MALLOC_CAP_32BIT`` flag. This also allows the allocator to give out IRAM memory, which is sometimes unavailable for a normal ``malloc()`` call. This can help to use all the available memory in the {IDF_TARGET_NAME}.
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA and SOC_CPU_HAS_FPU
Please note that on {IDF_TARGET_NAME} series chips, ``MALLOC_CAP_32BIT`` cannot be used for storing floating-point variables. This is because ``MALLOC_CAP_32BIT`` may return instruction RAM and the floating-point assembly instructions on {IDF_TARGET_NAME} cannot access instruction RAM.
Memory allocated with ``MALLOC_CAP_32BIT`` can **only** be accessed via 32-bit reads and writes, any other type of access will generate a fatal LoadStoreError exception.
.. only:: SOC_SPIRAM_SUPPORTED
External SPI Memory
^^^^^^^^^^^^^^^^^^^
When :doc:`external RAM </api-guides/external-ram>` is enabled, external SPI RAM can be allocated using standard ``malloc`` calls, or via ``heap_caps_malloc(MALLOC_CAP_SPIRAM)``, depending on the configuration. See :ref:`external_ram_config` for more details.
.. only:: esp32
On ESP32 only external SPI RAM under 4 MiB in size can be allocated this way. To use the region above the 4 MiB limit, you can use the :doc:`himem API </api-reference/system/himem>`.
.. only:: SOC_SIMD_INSTRUCTION_SUPPORTED
SIMD-Instruction-Capable Memory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``MALLOC_CAP_SIMD`` flag can be used to allocate memory which is accessible by SIMD (Single Instruction Multiple Data) instructions. The use of this flag also aligns the memory to a SIMD preferred data alignment size ({IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT}-byte) for a better performance.
Thread Safety
-------------
Heap functions are thread-safe, meaning they can be called from different tasks simultaneously without any limitations.
It is technically possible to call ``malloc``, ``free``, and related functions from interrupt handler (ISR) context (see :ref:`calling-heap-related-functions-from-isr`). However, this is not recommended, as heap function calls may delay other interrupts. It is strongly recommended to refactor applications so that any buffers used by an ISR are pre-allocated outside of the ISR. Support for calling heap functions from ISRs may be removed in a future update.
.. _calling-heap-related-functions-from-isr:
Calling Heap-Related Functions from ISR
---------------------------------------
The following functions from the heap component can be called from the interrupt handler (ISR):
* :cpp:func:`heap_caps_malloc`
* :cpp:func:`heap_caps_malloc_default`
* :cpp:func:`heap_caps_realloc_default`
* :cpp:func:`heap_caps_malloc_prefer`
* :cpp:func:`heap_caps_realloc_prefer`
* :cpp:func:`heap_caps_calloc_prefer`
* :cpp:func:`heap_caps_free`
* :cpp:func:`heap_caps_realloc`
* :cpp:func:`heap_caps_calloc`
* :cpp:func:`heap_caps_aligned_alloc`
* :cpp:func:`heap_caps_aligned_free`
.. note::
However, this practice is strongly discouraged.
Heap Tracing & Debugging
------------------------
The following features are documented on the :doc:`Heap Memory Debugging </api-reference/system/heap_debug>` page:
- :ref:`Heap Information <heap-information>` (free space, etc.)
- :ref:`Heap Allocation and Free Function Hooks <heap-allocation-free>`
- :ref:`Heap Corruption Detection <heap-corruption>`
- :ref:`Heap Tracing <heap-tracing>` (memory leak detection, monitoring, etc.)
Implementation Notes
--------------------
Knowledge about the regions of memory in the chip comes from the "SoC" component, which contains memory layout information for the chip, and the different capabilities of each region. Each region's capabilities are prioritized, so that (for example) dedicated DRAM and IRAM regions are used for allocations ahead of the more versatile D/IRAM regions.
Each contiguous region of memory contains its own memory heap. The heaps are created using the :ref:`multi_heap <multi-heap>` functionality. ``multi_heap`` allows any contiguous region of memory to be used as a heap.
The heap capabilities allocator uses knowledge of the memory regions to initialize each individual heap. Allocation functions in the heap capabilities API will find the most appropriate heap for the allocation based on desired capabilities, available space, and preferences for each region's use, and then calling :cpp:func:`multi_heap_malloc` for the heap situated in that particular region.
Calling ``free()`` involves finding the particular heap corresponding to the freed address, and then call :cpp:func:`multi_heap_free` on that particular ``multi_heap`` instance.
API Reference - Heap Allocation
-------------------------------
.. include-build-file:: inc/esp_heap_caps.inc
API Reference - Initialisation
------------------------------
.. include-build-file:: inc/esp_heap_caps_init.inc
.. _multi-heap:
API Reference - Multi-Heap API
------------------------------
(Note: The multi-heap API is used internally by the heap capabilities allocator. Most ESP-IDF programs never need to call this API directly.)
.. include-build-file:: inc/multi_heap.inc
@@ -0,0 +1,311 @@
Miscellaneous System APIs
=========================
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_BASE_MAC_BLOCK: default="BLK1", esp32="BLK0"}
{IDF_TARGET_CPU_RESET_DES: default="the CPU is reset", esp32="both CPUs are reset", esp32s3="both CPUs are reset", esp32p4="both CPUs are reset", esp32h4="both CPUs are reset"}
Software Reset
--------------
To perform software reset of the chip, the :cpp:func:`esp_restart` function is provided. When the function is called, execution of the program stops, {IDF_TARGET_CPU_RESET_DES}, the application is loaded by the bootloader and starts execution again.
Additionally, the :cpp:func:`esp_register_shutdown_handler` function can register a routine that will be automatically called before a restart (that is triggered by :cpp:func:`esp_restart`) occurs. This is similar to the functionality of ``atexit`` POSIX function.
Reset Reason
------------
ESP-IDF applications can be started or restarted due to a variety of reasons. To get the last reset reason, call :cpp:func:`esp_reset_reason` function. See description of :cpp:type:`esp_reset_reason_t` for the list of possible reset reasons.
Heap Memory
-----------
Two heap-memory-related functions are provided:
* :cpp:func:`esp_get_free_heap_size` returns the current size of free heap memory.
* :cpp:func:`esp_get_minimum_free_heap_size` returns the minimum size of free heap memory that has ever been available (i.e., the smallest size of free heap memory in the application's lifetime).
Note that ESP-IDF supports multiple heaps with different capabilities. The functions mentioned in this section return the size of heap memory that can be allocated using the ``malloc`` family of functions. For further information about heap memory, see :doc:`Heap Memory Allocation <mem_alloc>`.
.. _MAC-Address-Allocation:
MAC Address
-----------
These APIs allow querying and customizing MAC addresses for different supported network interfaces (e.g., Wi-Fi, Bluetooth, Ethernet).
To fetch the MAC address for a specific network interface (e.g., Wi-Fi, Bluetooth, Ethernet), call the function :cpp:func:`esp_read_mac`.
In ESP-IDF, the MAC addresses for the various network interfaces are calculated from a single **base MAC address**. By default, the Espressif base MAC address is used. This base MAC address is pre-programmed into the {IDF_TARGET_NAME} eFuse in the factory during production.
.. only:: esp32p4
.. list-table::
:widths: 20 80
:header-rows: 1
* - Interface
- MAC Address (1 universally administered, default)
* - Ethernet
- base_mac
.. note::
On ESP32-P4, :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` is fixed to one universally administered MAC address.
.. only:: (not esp32s2) and (not esp32p4) and (not esp32h2) and (not esp32h21) and (not esp32h4) and (not esp32s31)
.. list-table::
:widths: 20 40 40
:header-rows: 1
* - Interface
- MAC Address (4 universally administered, default)
- MAC Address (2 universally administered)
* - Wi-Fi Station
- base_mac
- base_mac
* - Wi-Fi SoftAP
- base_mac, +1 to the last octet
- :ref:`Local MAC <local-mac-addresses>` (derived from Wi-Fi Station MAC)
* - Bluetooth
- base_mac, +2 to the last octet
- base_mac, +1 to the last octet
* - Ethernet
- base_mac, +3 to the last octet
- :ref:`Local MAC <local-mac-addresses>` (derived from Bluetooth MAC)
.. note::
The :ref:`configuration <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` configures the number of universally administered MAC addresses that are provided by Espressif.
.. only:: esp32s31
.. list-table::
:widths: 20 40 40
:header-rows: 1
* - Interface
- MAC Address (2 universally administered, default)
- MAC Address (4 universally administered)
* - Wi-Fi Station
- base_mac
- base_mac
* - Wi-Fi SoftAP
- :ref:`Local MAC <local-mac-addresses>` (derived from Wi-Fi Station MAC)
- base_mac, +1 to the last octet
* - Bluetooth
- base_mac, +1 to the last octet
- base_mac, +2 to the last octet
* - Ethernet
- :ref:`Local MAC <local-mac-addresses>` (derived from Bluetooth MAC)
- base_mac, +3 to the last octet
.. note::
{IDF_TARGET_NAME} only provides two universally administered MAC addresses in eFuse, so :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` defaults to two. The "Four" option may only be used when a customer-provided custom base MAC range is used (see :ref:`Custom Base MAC <MAC-Address-Allocation>`), where four universally administered MAC addresses are allocated per device. Using "Four" with the default Espressif eFuse base MAC leads to SoftAP and Ethernet consuming global MAC slots (base+1/+3) that are not allocated on this chip and may collide with the Bluetooth MAC.
.. only:: esp32h2 or esp32h21 or esp32h4
.. list-table::
:widths: 20 80
:header-rows: 1
* - Interface
- MAC Address (1 universally administered, default)
* - IEEE 802.15.4
- EUI-64 derived from base_mac and MAC_EXT (base_mac[0:2] ‖ MAC_EXT ‖ base_mac[3:5], MAC_EXT defaults to ff:fe)
* - Bluetooth
- base_mac
.. note::
{IDF_TARGET_NAME} provides a single universally administered MAC address in eFuse (MAC_FACTORY) plus the MAC_EXT field used to build the IEEE 802.15.4 EUI-64. :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` is fixed to one. Bluetooth reuses the base MAC as-is — the BT offset is not applied because {IDF_TARGET_NAME} has no Wi-Fi, so no second universal MAC slot is required.
.. only:: esp32s2
.. list-table::
:widths: 20 40 40
:header-rows: 1
* - Interface
- MAC Address (2 universally administered, default)
- MAC Address (1 universally administered)
* - Wi-Fi Station
- base_mac
- base_mac
* - Wi-Fi SoftAP
- base_mac, +1 to the last octet
- :ref:`Local MAC <local-mac-addresses>` (derived from Wi-Fi Station MAC)
* - Ethernet
- :ref:`Local MAC <local-mac-addresses>` (derived from Wi-Fi SoftAP MAC)
- :ref:`Local MAC <local-mac-addresses>` (derived from base_mac with +1 to last octet. Not recommended.)
.. note::
The :ref:`configuration <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` configures the number of universally administered MAC addresses that are provided by Espressif.
.. only:: not SOC_EMAC_SUPPORTED
.. note::
Although {IDF_TARGET_NAME} has no integrated Ethernet MAC, it is still possible to calculate an Ethernet MAC address. However, this MAC address can only be used with an external ethernet interface such as an SPI-Ethernet device. See :doc:`/api-reference/network/esp_eth`.
Custom Interface MAC
^^^^^^^^^^^^^^^^^^^^
Sometimes you may need to define custom MAC addresses that are not generated from the base MAC address. To set a custom interface MAC address, use the :cpp:func:`esp_iface_mac_addr_set` function. This function allows you to overwrite the MAC addresses of interfaces set (or not yet set) by the base MAC address. Once a MAC address has been set for a particular interface, it will not be affected when the base MAC address is changed.
Custom Base MAC
^^^^^^^^^^^^^^^
The default base MAC is pre-programmed by Espressif in eFuse {IDF_TARGET_BASE_MAC_BLOCK}. To set a custom base MAC instead, call the function :cpp:func:`esp_iface_mac_addr_set` with the ``ESP_MAC_BASE`` argument (or :cpp:func:`esp_base_mac_addr_set`) before initializing any network interfaces or calling the :cpp:func:`esp_read_mac` function. The custom MAC address can be stored in any supported storage device (e.g., flash, NVS).
The custom base MAC addresses should be allocated such that derived MAC addresses will not overlap. Based on the table above, users can configure the option :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` to set the number of valid universal MAC addresses that can be derived from the custom base MAC.
.. note::
It is also possible to call the function :cpp:func:`esp_netif_set_mac` to set the specific MAC used by a network interface after network initialization. But it is recommended to use the base MAC approach documented here to avoid the possibility of the original MAC address briefly appearing on the network before being changed.
Custom MAC Address in eFuse
@@@@@@@@@@@@@@@@@@@@@@@@@@@
When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function :cpp:func:`esp_efuse_mac_get_custom`. Users can also use :cpp:func:`esp_read_mac` with the ``ESP_MAC_EFUSE_CUSTOM`` argument. This loads the MAC address from eFuse BLK3. The :cpp:func:`esp_efuse_mac_get_custom` function assumes that the custom base MAC address is stored in the following format:
.. only:: esp32
.. list-table::
:widths: 20 15 20 45
:header-rows: 1
* - Field
- # of bits
- Range of bits
- Notes
* - Version
- 8
- 191:184
- 0: invalid, others — valid
* - Reserved
- 128
- 183:56
-
* - MAC address
- 48
- 55:8
-
* - MAC address CRC
- 8
- 7:0
- CRC-8-CCITT, polynomial 0x07
.. note::
If the 3/4 coding scheme is enabled, all eFuse fields in this block must be burnt at the same time.
.. only:: not esp32
.. list-table::
:widths: 30 30 30
:header-rows: 1
* - Field
- # of bits
- Range of bits
* - MAC address
- 48
- 200:248
.. note::
The eFuse BLK3 uses RS-coding during burning, which means that all eFuse fields in this block must be burnt at the same time.
Once custom eFuse MAC address has been obtained (using :cpp:func:`esp_efuse_mac_get_custom` or :cpp:func:`esp_read_mac`), you need to set it as the base MAC address. There are two ways to do it:
1. Use an old API: call :cpp:func:`esp_base_mac_addr_set`.
2. Use a new API: call :cpp:func:`esp_iface_mac_addr_set` with the ``ESP_MAC_BASE`` argument.
.. _local-mac-addresses:
Local Versus Universal MAC Addresses
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{IDF_TARGET_NAME} comes pre-programmed with enough valid Espressif universally administered MAC addresses for all internal interfaces. The table above shows how to calculate and derive the MAC address for a specific interface according to the base MAC address.
When using a custom MAC address scheme, it is possible that not all interfaces can be assigned with a universally administered MAC address. In these cases, a locally administered MAC address is assigned. Note that these addresses are intended for use on a single local network only.
See `this article <https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local_(U/L_bit)>`_ for the definition of locally and universally administered MAC addresses.
Function :cpp:func:`esp_derive_local_mac` is called internally to derive a local MAC address from a universal MAC address. The process is as follows:
1. The U/L bit (bit value 0x2) is set in the first octet of the universal MAC address, creating a local MAC address.
2. If this bit is already set in the supplied universal MAC address (i.e., the supplied "universal" MAC address was in fact already a local MAC address), then the first octet of the local MAC address is XORed with 0x4.
Chip Version
------------
:cpp:func:`esp_chip_info` function fills :cpp:class:`esp_chip_info_t` structure with information about the chip. This includes the chip revision, number of CPU cores, and a bit mask of features enabled in the chip.
.. _idf-version-h:
SDK Version
-----------
:cpp:func:`esp_get_idf_version` returns a string describing the ESP-IDF version which is used to compile the application. This is the same value as the one available through ``IDF_VER`` variable of the build system. The version string generally has the format of ``git describe`` output.
To get the version at build time, additional version macros are provided. They can be used to enable or disable parts of the program depending on the ESP-IDF version.
* :c:macro:`ESP_IDF_VERSION_MAJOR`, :c:macro:`ESP_IDF_VERSION_MINOR`, :c:macro:`ESP_IDF_VERSION_PATCH` are defined to integers representing major, minor, and patch version.
* :c:macro:`ESP_IDF_VERSION_VAL` and :c:macro:`ESP_IDF_VERSION` can be used when implementing version checks:
.. code-block:: c
#include "esp_idf_version.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
// enable functionality present in ESP-IDF v4.0
#endif
Debug Helpers
-------------
The debug helper APIs in ``esp_debug_helpers.h`` provide utilities for run-time debugging and stack backtrace output.
- :cpp:func:`esp_backtrace_print` prints the current stack backtrace.
- :cpp:func:`esp_backtrace_print_all_tasks` prints backtraces for all tasks.
- :cpp:func:`esp_backtrace_get_start` and :cpp:func:`esp_backtrace_get_next_frame` allow manual iteration over backtrace frames.
These APIs are useful when diagnosing crashes, watchdog timeouts, or unexpected control flow.
.. _app-version:
App Version
-----------
The application version is stored in :cpp:class:`esp_app_desc_t` structure. It is located in DROM sector and has a fixed offset from the beginning of the binary file. The structure is located after :cpp:class:`esp_image_header_t` and :cpp:class:`esp_image_segment_header_t` structures. The type of the field version is string and it has a maximum length of 32 chars.
To set the version in your project manually, you need to set the ``PROJECT_VER`` variable in the ``CMakeLists.txt`` of your project. In application ``CMakeLists.txt``, put ``set(PROJECT_VER "0.1.0.1")`` before including ``project.cmake``.
If the :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise, if the ``PROJECT_VER`` variable is not set in the project, it will be retrieved either from the ``$(PROJECT_PATH)/version.txt`` file (if present) or using git command ``git describe``. If neither is available, ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_app_get_description` or :cpp:func:`esp_ota_get_partition_description` functions.
Application Examples
--------------------
- :example:`system/base_mac_address` demonstrates how to retrieve, set, and derive the base MAC address for each network interface on {IDF_TARGET_NAME} from non-volatile memory, using either the eFuse blocks or external storage.
API Reference
-------------
.. include-build-file:: inc/esp_system.inc
.. include-build-file:: inc/esp_idf_version.inc
.. include-build-file:: inc/esp_mac.inc
.. include-build-file:: inc/esp_chip_info.inc
.. include-build-file:: inc/esp_cpu.inc
.. include-build-file:: inc/esp_debug_helpers.inc
.. include-build-file:: inc/esp_app_desc.inc
+191
View File
@@ -0,0 +1,191 @@
Memory Management for MMU Supported Memory
******************************************
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 1
Introduction
============
{IDF_TARGET_NAME} Memory Management Unit (MMU) is relatively simple. It can do memory address translation between physical memory addresses and virtual memory addresses. So CPU can access physical memories via virtual addresses. There are multiple types of virtual memory addresses, which have different capabilities.
ESP-IDF provides a memory mapping driver that manages the relation between these physical memory addresses and virtual memory addresses, so as to achieve some features such as reading from SPI flash via a pointer.
Memory mapping driver is actually a capabilities-based virtual memory address allocator that allows applications to make virtual memory address allocations for different purposes. In the following chapters, we call this driver ``esp_mmap`` driver.
ESP-IDF also provides a memory synchronization driver which can be used for potential memory desynchronization scenarios.
Physical Memory Types
=====================
Memory mapping driver currently supports mapping to following physical memory type(s):
.. list::
- SPI flash
:SOC_SPIRAM_SUPPORTED and not esp32: - PSRAM
Virtual Memory Capabilities
===========================
.. list::
- :cpp:enumerator:`MMU_MEM_CAP_EXEC`: This capability indicates that the virtual memory address has the execute permission. Note this permission scope is within the MMU hardware.
- :cpp:enumerator:`MMU_MEM_CAP_READ`: This capability indicates that the virtual memory address has the read permission. Note this permission scope is within the MMU hardware.
- :cpp:enumerator:`MMU_MEM_CAP_WRITE`: This capability indicates that the virtual memory address has the write permission. Note this permission scope is within the MMU hardware.
- :cpp:enumerator:`MMU_MEM_CAP_32BIT`: This capability indicates that the virtual memory address allows for 32 bits or multiples of 32 bits access.
- :cpp:enumerator:`MMU_MEM_CAP_8BIT`: This capability indicates that the virtual memory address allows for 8 bits or multiples of 8 bits access.
.. only:: esp32
8 MB external memory addresses (from 0x40400000 to 0x40C00000) which have the :cpp:enumerator:`MMU_MEM_CAP_EXEC` and :cpp:enumerator:`MMU_MEM_CAP_READ` capabilities are not available for users to allocate, due to hardware limitations.
.. only:: esp32s2
4 MB external memory addresses (from 0x40400000 to 0x40800000) which have the :cpp:enumerator:`MMU_MEM_CAP_EXEC` and :cpp:enumerator:`MMU_MEM_CAP_READ` capabilities are not available for users to allocate, due to hardware limitations.
You can call :cpp:func:`esp_mmu_map_get_max_consecutive_free_block_size` to know the largest consecutive mappable block size with certain capabilities.
Memory Management Drivers
=========================
Driver Concept
--------------
Terminology
^^^^^^^^^^^
The virtual memory pool consists of one or more virtual memory regions, as shown in the figure below:
.. image:: /../_static/diagrams/mmu/mem_pool.png
:scale: 80 %
:align: center
- A virtual memory pool stands for the whole virtual address range that can be mapped to physical memory.
- A virtual memory region is a range of virtual addresses with same attributes.
- A virtual memory block is a piece of virtual address range that is dynamically mapped.
- A slot is the virtual address range between two virtual memory blocks.
- A physical memory block is a piece of physical address range that is to-be-mapped or already mapped to a virtual memory block.
- Dynamical mapping is done by calling ``esp_mmap`` driver API :cpp:func:`esp_mmu_map` or :cpp:func:`esp_mmu_map_virt`. These map the given physical memory block to a virtual memory block, either automatically chosen or requested by a specific virtual start address.
Relation Between Memory Blocks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When mapping a physical memory block A, block A can have one of the following relations with another previously mapped physical memory block B:
- Enclosed: block A is completely enclosed within block B, see figure below:
.. image:: /../_static/diagrams/mmu/enclosed.png
:scale: 80 %
:align: center
- Identical: block A is completely the same as block B, see figure below:
.. image:: /../_static/diagrams/mmu/identical.png
:scale: 80 %
:align: center
Note that ``esp_mmap`` driver considers the identical scenario **the same as the enclosed scenario**.
- Overlapped: block A is overlapped with block B, see figure below:
.. image:: /../_static/diagrams/mmu/overlapped.png
:scale: 80 %
:align: center
There is a special condition, when block A entirely encloses block B, see figure below:
.. image:: /../_static/diagrams/mmu/inversed_enclosed.png
:scale: 70 %
:align: center
Note that ``esp_mmap`` driver considers this scenario **the same as the overlapped scenario**.
Driver Behaviour
----------------
Memory Map
^^^^^^^^^^
You can call :cpp:func:`esp_mmu_map` to do a dynamical mapping, or :cpp:func:`esp_mmu_map_virt` if you need a specific virtual start address. These APIs allocate, or place, a virtual memory block of the required size according to the virtual memory capabilities you selected, then map it to the physical memory block you requested. The ``esp_mmap`` driver supports mapping to one or more types of physical memory, so you should specify the physical memory target when mapping.
By default, physical memory blocks and virtual memory blocks are one-to-one mapped. This means, when calling :cpp:func:`esp_mmu_map`:
* If it is the enclosed scenario, this API will return an :c:macro:`ESP_ERR_INVALID_STATE`. The ``out_ptr`` will be assigned to the start virtual memory address of the previously mapped one which encloses the to-be-mapped one.
* If it is the identical scenario, this API will behave exactly the same as the enclosed scenario.
* If it is the overlapped scenario, this API will by default return an :c:macro:`ESP_ERR_INVALID_ARG`. This means, ``esp_mmap`` driver by default does not allow mapping a physical memory address to multiple virtual memory addresses.
Specifically, you can use :c:macro:`ESP_MMU_MMAP_FLAG_PADDR_SHARED`. This flag stands for one-to-multiple mapping between a physical address and multiple virtual addresses:
* If it is the overlapped scenario, this API will allocate a new virtual memory block as requested, then map to the given physical memory block.
Mapping at a Chosen Virtual Address
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:cpp:func:`esp_mmu_map_virt` maps a physical block the same way as :cpp:func:`esp_mmu_map`, but you can pass the virtual start address as ``vaddr_start``. Passing a value of ``0`` for ``vaddr_start`` will let the driver allocate any suitable free block. With a non-zero ``vaddr_start`` value, the whole range must lie in an unmapped slot for the given capabilities and target, and the address must be valid for the MMU view implied by ``caps``.
Memory Unmap
^^^^^^^^^^^^
You can call :cpp:func:`esp_mmu_unmap` to unmap a previously mapped memory block. This API returns an :c:macro:`ESP_ERR_NOT_FOUND` if you are trying to unmap a virtual memory block that is not mapped to any physical memory block yet.
Memory Address Conversion
^^^^^^^^^^^^^^^^^^^^^^^^^
The ``esp_mmap`` driver provides two helper APIs to do the conversion between virtual memory address and physical memory address
* :cpp:func:`esp_mmu_vaddr_to_paddr` converts virtual address to physical address.
* :cpp:func:`esp_mmu_paddr_to_vaddr` converts physical address to virtual address.
Memory Synchronization
^^^^^^^^^^^^^^^^^^^^^^
MMU supported physical memories can be accessed by one or multiple methods.
SPI flash can be accessed by SPI1 (ESP-IDF ``esp_flash`` driver APIs), or by pointers. ESP-IDF ``esp_flash`` driver APIs have already considered the memory synchronization, so users do not need to worry about this.
.. only:: SOC_SPIRAM_SUPPORTED
PSRAM can be accessed by pointers, hardware guarantees the data consistency when PSRAM is only accessed via pointers.
.. only:: SOC_PSRAM_DMA_CAPABLE and not esp32s2
PSRAM can also be accessed by EDMA. Data desynchronization may happen because hardware does not guarantee the data consistency under such condition. You should call :cpp:func:`esp_cache_msync` to synchronize the Cache and the PSRAM.
See :doc:`/api-reference/system/mm_sync` for more details.
Thread Safety
=============
Following APIs in ``esp_mmu_map.h`` are not guaranteed to be thread-safe:
- :cpp:func:`esp_mmu_map_dump_mapped_blocks`
APIs in ``esp_cache.h`` are guaranteed to be thread-safe.
API Reference
=============
API Reference - ESP MMAP Driver
-------------------------------
.. include-build-file:: inc/esp_mmu_map.inc
+131
View File
@@ -0,0 +1,131 @@
Memory Synchronization
**********************
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 1
Introduction
============
.. only:: SOC_PSRAM_DMA_CAPABLE
{IDF_TARGET_NAME} can access its connected PSRAM via these ways:
- CPU
- DMA
.. only:: SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
{IDF_TARGET_NAME} can access its internal memory via these ways:
- CPU
- DMA
By default, CPU accesses the above mentioned memory via cache. Whereas DMA accesses the memory directly, without going through cache.
This leads to potential cache data coherence issue:
- When a DMA transaction changes the content of a piece of memory, and the content has been cached already. Under this condition:
- CPU may read stale data.
- The stale data in the cache may be written back to the memory. The new data updated by the previous DMA transaction will be overwritten.
- CPU changes the content of an address. The content is in the cache, but not in the memory yet (cache will write back the content to the memory according to its own strategy). Under this condition:
- The next DMA transactions to read this content from the memory will get stale data.
There are three common methods to address such cache data coherence issue:
.. list::
1. Hardware based cache Coherent Interconnect, {IDF_TARGET_NAME} does not have such ability.
2. Use the DMA buffer from non-cacheable memory. Non-cacheable memory refers to the type of memory that is accessed by CPU without going through cache.
3. Explicitly call a memory synchronization API to writeback the content in the cache back to the memory, or invalidate the content in the cache.
Memory Synchronization Driver
=============================
The suggested way to deal with such cache data coherence issue is by using the memory synchronization API :cpp:func:`esp_cache_msync` provided by ESP-IDF `esp_mm` component.
Driver Concept
--------------
Direction of the cache memory synchronization:
- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M`, for synchronization from cache to memory.
- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C`, for synchronization from memory to cache.
Type of the cache memory synchronization:
- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA`, for synchronization to a data address region.
- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_INST`, for synchronization to an instruction address region.
Driver Behaviour
----------------
Calling :cpp:func:`esp_cache_msync` will do a synchronization between cache and memory. The first parameter `addr` and the second parameter `size` together describe the memory region that is to be synchronized. About the third parameter `flags`:
.. list::
- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M`. With this flag, content in the specified address region is written back to the memory. This direction is usually used **after** the content of an address is updated by the CPU, e.g., a memset to the address. Operation in this direction should happen **before** a DMA operation to the same address.
- :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C`. With this flag, content in the specified address region is invalidated from the cache. This direction is usually used **after** the content of an address is updated by the DMA. Operation in this direction should happen **before** a CPU read operation to the same address.
The above two flags help select the synchronization direction. Specially, if neither of these two flags are used, :cpp:func:`esp_cache_msync` will by default select the :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M` direction. Users are not allowed to set both of the two flags at the same time.
.. list::
- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA`.
- :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_INST`.
The above two flags help select the type of the synchronization address. Specially, if neither of these two flags are used, :cpp:func:`esp_cache_msync` will by default select the :c:macro:`ESP_CACHE_MSYNC_FLAG_TYPE_DATA` type. Users are not allowed to set both of the two flags at the same time.
.. list::
- :c:macro:`ESP_CACHE_MSYNC_FLAG_INVALIDATE`. This flag is used to trigger a cache invalidation to the specified address region, after the region is written back to the memory. This flag is mainly used for :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_C2M` direction. For :c:macro:`ESP_CACHE_MSYNC_FLAG_DIR_M2C` direction, behaviour is the same as if the :c:macro:`ESP_CACHE_MSYNC_FLAG_INVALIDATE` flag is not set.
- :c:macro:`ESP_CACHE_MSYNC_FLAG_UNALIGNED`. This flag force the :cpp:func:`esp_cache_msync` API to do synchronization without checking the address and size alignment. For more details, see section `Address Alignment Requirement` following.
Address Alignment Requirement
=============================
There is address and size alignment requirement (in bytes) for using :cpp:func:`esp_cache_msync`. The alignment requirement comes from cache.
- An address region whose start address and size both meet the cache memory synchronization alignment requirement is defined as an **aligned address region**.
- An address region whose start address or size does not meet the cache memory synchronization alignment requirement is defined as an **unaligned address region**.
By default, if you specify an unaligned address region, :cpp:func:`esp_cache_msync` will return an :c:macro:`ESP_ERR_INVALID_ARG` error, together with the required alignment.
Warning for Address Alignment Requirement
-----------------------------------------
You can set the :c:macro:`ESP_CACHE_MSYNC_FLAG_UNALIGNED` flag to bypass such check. Note you should be very careful about using this flag. Cache memory synchronization to an unaligned address region may silently corrupt the memory.
For example, assume:
- alignment requirement is 0x40 bytes.
- a call to :cpp:func:`esp_cache_msync`, with `ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_UNALIGNED` flags, the specified address region is 0x4000_0020 ~ 0x4000_0060 (see **data C** in below graph).
Above settings will trigger a cache invalidation to the address region 0x4000_0000 ~ 0x4000_0080, see **sync item0** and **sync item1** in the below graph.
If the content in 0x4000_0000 ~ 0x4000_0020 (**data A** in the below graph) or 0x4000_0060 ~ 0x4000_0080 (**data B** in the below graph) are not written back to the memory yet, then these **data A** and **data B** will be discarded.
.. image:: /../_static/diagrams/mmu/cache_align_issue.png
:scale: 80 %
:align: center
API Reference
=============
API Reference - ESP Msync Driver
--------------------------------
.. include-build-file:: inc/esp_cache.inc
+391
View File
@@ -0,0 +1,391 @@
Over The Air Updates (OTA)
==========================
:link_to_translation:`zh_CN:[中文]`
OTA Process Overview
--------------------
The OTA update mechanism allows a device to update itself based on data received while the normal firmware is running (for example, over Wi-Fi, Bluetooth or Ethernet).
The following modes support OTA updates for certain partitions:
- **Safe update mode**. The update process for certain partitions is designed to be resilient, ensuring that even if the power is cut off during the update, the chip will remain operational and capable of booting the current application. The following partitions support this mode:
- Application. OTA requires configuring the :doc:`../../api-guides/partition-tables` of the device with at least two OTA app slot partitions (i.e., ``ota_0`` and ``ota_1``) and an OTA Data Partition. The OTA operation functions write a new app firmware image to whichever OTA app slot that is currently not selected for booting. Once the image is verified, the OTA Data partition is updated to specify that this image should be used for the next boot.
- **Unsafe update mode**. The update process is vulnerable, meaning that a power interruption during the update can cause issues that prevent the current application from loading, potentially leading to an unrecoverable state. The temporary partition receives the new image, and once it is fully downloaded, the image is copied to the final destination partition. If an interruption occurs during this final copying process, it can lead to issues. The following partitions support this mode:
- Bootloader.
- Partition table.
- Other data partitions like NVS, FAT, etc.
.. _ota_data_partition:
OTA Data Partition
------------------
An OTA data partition (type ``data``, subtype ``ota``) must be included in the :doc:`../../api-guides/partition-tables` of any project which uses the OTA functions.
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the ESP-IDF second stage bootloader boots the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted.
After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next.
The OTA data partition is two flash sectors (0x2000 bytes) in size, to prevent problems if there is a power failure while it is being written. Sectors are independently erased and written with matching data, and if they disagree a counter field is used to determine which sector was written more recently.
.. _app_rollback:
App Rollback
------------
The main purpose of the application rollback is to keep the device working after the update. This feature allows you to roll back to the previous working application in case a new application has critical errors. When the rollback process is enabled and an OTA update provides a new version of the app, one of three things can happen:
* The application works fine, :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` marks the running application with the state ``ESP_OTA_IMG_VALID``. There are no restrictions on booting this application.
* The application has critical errors and further work is not possible, a rollback to the previous application is required, :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` marks the running application with the state ``ESP_OTA_IMG_INVALID`` and reset. This application will not be selected by the bootloader for boot and will boot the previously working application.
* If the :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is set, and a reset occurs without calling either function then the application is rolled back.
The following code serves detect the initial boot for an application after the OTA update. Upon the first boot, the application checks its state and performs diagnostics. If the diagnostics are successful, the application should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` to confirm the operability of the application. If the diagnostics fail, the application should call :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` to roll back to the previous working application.
If the application is not able to boot or execute this code due to an abort/reboot/power loss error, the bootloader marks this application as ``ESP_OTA_IMG_INVALID`` in the next booting attempt and rolls back to the previous working application.
.. code:: c
const esp_partition_t *running = esp_ota_get_running_partition();
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
// run diagnostic function ...
bool diagnostic_is_ok = diagnostic();
if (diagnostic_is_ok) {
ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ...");
esp_ota_mark_app_valid_cancel_rollback();
} else {
ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ...");
esp_ota_mark_app_invalid_rollback_and_reboot();
}
}
}
For the example incorporating the above code snippet, see the :example:`system/ota/native_ota_example` example.
.. note::
The state is not written to the binary image of the application but rather to the ``otadata`` partition. The partition contains a ``ota_seq`` counter, which is a pointer to the slot (``ota_0``, ``ota_1``, ...) from which the application will be selected for boot.
App OTA State
^^^^^^^^^^^^^
States control the process of selecting a boot app:
============================= ======================================================================
States Restriction of selecting a boot app in bootloader
============================= ======================================================================
ESP_OTA_IMG_VALID None restriction. Will be selected.
ESP_OTA_IMG_UNDEFINED None restriction. Will be selected.
ESP_OTA_IMG_INVALID Will not be selected.
ESP_OTA_IMG_ABORTED Will not be selected.
ESP_OTA_IMG_NEW If :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is set it will
be selected only once. In bootloader the state immediately changes to
``ESP_OTA_IMG_PENDING_VERIFY``.
ESP_OTA_IMG_PENDING_VERIFY If :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is set it will
not be selected, and the state will change to ``ESP_OTA_IMG_ABORTED``.
============================= ======================================================================
If :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is not enabled (by default), then the use of the following functions :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` and :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` are optional, and ``ESP_OTA_IMG_NEW`` and ``ESP_OTA_IMG_PENDING_VERIFY`` states are not used.
An option in Kconfig :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` allows you to track the first boot of a new application. In this case, the application must confirm its operability by calling :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function, otherwise the application will be rolled back upon reboot. It allows you to control the operability of the application during the boot phase. Thus, a new application has only one attempt to boot successfully.
.. _ota_rollback:
Rollback Process
^^^^^^^^^^^^^^^^
The description of the rollback process when :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled:
* The new application is successfully downloaded and :cpp:func:`esp_ota_set_boot_partition` function makes this partition bootable and sets the state ``ESP_OTA_IMG_NEW``. This state means that the application is new and should be monitored for its first boot.
* Reboot :cpp:func:`esp_restart`.
* The bootloader checks for the ``ESP_OTA_IMG_PENDING_VERIFY`` state if it is set, then it will be written to ``ESP_OTA_IMG_ABORTED``.
* The bootloader selects a new application to boot so that the state is not set as ``ESP_OTA_IMG_INVALID`` or ``ESP_OTA_IMG_ABORTED``.
* The bootloader checks the selected application for ``ESP_OTA_IMG_NEW`` state if it is set, then it will be written to ``ESP_OTA_IMG_PENDING_VERIFY``. This state means that the application requires confirmation of its operability, if this does not happen and a reboot occurs, this state will be overwritten to ``ESP_OTA_IMG_ABORTED`` (see above) and this application will no longer be able to start, i.e., there will be a rollback to the previous working application.
* A new application has started and should make a self-test.
* If the self-test has completed successfully, then you must call the function :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` because the application is awaiting confirmation of operability (``ESP_OTA_IMG_PENDING_VERIFY`` state).
* If the self-test fails, then call :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function to roll back to the previous working application, while the invalid application is set ``ESP_OTA_IMG_INVALID`` state.
* If the application has not been confirmed, the state remains ``ESP_OTA_IMG_PENDING_VERIFY``, and the next boot it will be changed to ``ESP_OTA_IMG_ABORTED``, which prevents re-boot of this application. There will be a rollback to the previous working application.
Unexpected Reset
^^^^^^^^^^^^^^^^
If a power loss or an unexpected crash occurs at the time of the first boot of a new application, it will roll back the application.
Recommendation: Perform the self-test procedure as quickly as possible, to prevent rollback due to power loss.
Only ``OTA`` partitions can be rolled back. Factory partition is not rolled back.
Booting Invalid/aborted Apps
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Booting an application which was previously set to ``ESP_OTA_IMG_INVALID`` or ``ESP_OTA_IMG_ABORTED`` is possible:
* Get the last invalid application partition :cpp:func:`esp_ota_get_last_invalid_partition`.
* Pass the received partition to :cpp:func:`esp_ota_set_boot_partition`, this will update the ``otadata``.
* Restart :cpp:func:`esp_restart`. The bootloader will boot the specified application.
To determine if self-tests should be run during startup of an application, call the :cpp:func:`esp_ota_get_state_partition` function. If result is ``ESP_OTA_IMG_PENDING_VERIFY`` then self-testing and subsequent confirmation of operability is required.
Where the States Are Set
^^^^^^^^^^^^^^^^^^^^^^^^
A brief description of where the states are set:
* ``ESP_OTA_IMG_VALID`` state is set by :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function.
* ``ESP_OTA_IMG_UNDEFINED`` state is set by :cpp:func:`esp_ota_set_boot_partition` function if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is not enabled.
* ``ESP_OTA_IMG_NEW`` state is set by :cpp:func:`esp_ota_set_boot_partition` function if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled.
* ``ESP_OTA_IMG_INVALID`` state is set by function :cpp:func:`esp_ota_mark_app_invalid_rollback` or :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot`.
* ``ESP_OTA_IMG_ABORTED`` state is set if there was no confirmation of the application operability and occurs reboots (if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled).
* ``ESP_OTA_IMG_PENDING_VERIFY`` state is set in a bootloader if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled and selected app has ``ESP_OTA_IMG_NEW`` state.
.. _anti-rollback:
Anti-rollback
-------------
{IDF_TARGET_SECURE_VERSION_EFUSE_BITS:default = "16", esp32 = "32", esp32c2 = "4", esp32c5 = "9"}
Anti-rollback prevents rollback to application with security version lower than one programmed in eFuse of chip.
This function works if set :ref:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK` option. In the bootloader, when selecting a bootable application, an additional security version check is added which is on the chip and in the application image. The version in the bootable firmware must be greater than or equal to the version in the chip.
:ref:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK` and :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` options are used together. In this case, rollback is possible only on the security version which is equal or higher than the version in the chip.
A Typical Anti-rollback Scheme Is
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- New firmware released with the elimination of vulnerabilities with the previous version of security.
- After the developer makes sure that this firmware is working. He can increase the security version and release a new firmware.
- Download new application.
- To make it bootable, run the function :cpp:func:`esp_ota_set_boot_partition`. If the security version of the new application is smaller than the version in the chip, the new application will be erased. Update to new firmware is not possible.
- Reboot.
- In the bootloader, an application with a security version greater than or equal to the version in the chip will be selected. If otadata is in the initial state, and one firmware was loaded via a serial channel, whose secure version is higher than the chip, then the secure version of efuse will be immediately updated in the bootloader.
- New application booted. Then the application should perform diagnostics of the operation and if it is completed successfully, you should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function to mark the running application with the ``ESP_OTA_IMG_VALID`` state and update the secure version on chip. Note that if the :cpp:func:`esp_ota_mark_app_invalid_rollback` or :cpp:func:`esp_ota_mark_app_invalid_rollback_with_reboot` function is called a rollback may not happen as the device may not have any bootable apps. It will then return ``ESP_ERR_OTA_ROLLBACK_FAILED`` error and stay in the ``ESP_OTA_IMG_PENDING_VERIFY`` state.
- The next update of app is possible if a running app is in the ``ESP_OTA_IMG_VALID`` state.
Recommendation:
If you want to avoid the download/erase overhead in case of the app from the server has security version lower than the running app, you have to get ``new_app_info.secure_version`` from the first package of an image and compare it with the secure version of efuse. Use ``esp_efuse_check_secure_version(new_app_info.secure_version)`` function if it is true then continue downloading otherwise abort.
.. code-block:: c
....
bool image_header_was_checked = false;
while (1) {
int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE);
...
if (data_read > 0) {
if (image_header_was_checked == false) {
esp_app_desc_t new_app_info;
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
// check current version with downloading
if (esp_efuse_check_secure_version(new_app_info.secure_version) == false) {
ESP_LOGE(TAG, "This a new app can not be downloaded due to a secure version is lower than stored in efuse.");
http_cleanup(client);
task_fatal_error();
}
image_header_was_checked = true;
esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
}
}
esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
}
}
...
Restrictions:
.. list::
- The number of bits in the ``secure_version`` field is limited to {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} bits. This means that only {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} times you can do an anti-rollback. You can reduce the length of this efuse field using :ref:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD` option.
:esp32: - Anti-rollback works only if the encoding scheme for efuse is set to ``NONE``.
- Factory and Test partitions are not supported in anti rollback scheme and hence partition table should not have partition with SubType set to ``factory`` or ``test``.
``security_version``:
- In application image it is stored in ``esp_app_desc`` structure. The number is set :ref:`CONFIG_BOOTLOADER_APP_SECURE_VERSION`.
.. only:: esp32
- In ESP32, it is stored in efuse ``EFUSE_BLK3_RDATA4_REG``. (when an eFuse bit is programmed to 1, it can never be reverted to 0). The number of bits set in this register is the ``security_version`` from app.
.. _secure-ota-updates:
Secure OTA Updates Without Secure Boot
--------------------------------------
The verification of signed OTA updates can be performed even without enabling hardware secure boot. This can be achieved by setting :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT` and :ref:`CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT`.
.. only:: esp32
For more information, please refer to :ref:`signed-app-verify`.
.. _secure-signed-data-partition:
Signed Data Partition Updates
------------------------------
Data partition images can be verified using the same Secure Boot v2 signature mechanism as application images. Enable :ref:`CONFIG_SECURE_SIGNED_DATA_PARTITION` to verify data partitions with subtype ``ESP_PARTITION_SUBTYPE_DATA_UNDEFINED`` during OTA updates.
Sign data partition images using:
.. code-block:: bash
idf.py secure-sign-data --keyfile PRIVATE_SIGNING_KEY --output signed_data.bin data.bin
The signing key must match the one used for application signing, with its public key digest programmed into eFuse. The signed image format is: data content (padded to 4 KB) + 4 KB signature block (see :ref:`signature-block-format` in :doc:`/security/secure-boot-v2`).
For a complete example, see :example:`system/ota/partitions_ota`.
Tuning OTA Performance
----------------------
- Erasing the update partition at once instead of sequential erasing (default mechanism) while write operation might help in reducing the overall time taken for firmware upgrade. To enable this, set :cpp:member:`esp_https_ota_config_t::bulk_flash_erase` to true in :cpp:type:`esp_https_ota_config_t` structure. If the partition to be erased is too large, task watchdog could be triggered. It is advised to increase the watchdog timeout in such cases.
.. code-block:: c
esp_https_ota_config_t ota_config = {
.bulk_flash_erase = true,
}
- Tuning the :cpp:member:`esp_https_ota_config_t::http_config::buffer_size` can also help in improving the OTA performance.
- :cpp:type:`esp_https_ota_config_t` has a member :cpp:member:`esp_https_ota_config_t::buffer_caps` which can be used to specify the memory type to use when allocating memory to the OTA buffer. Configuring this value to MALLOC_CAP_INTERNAL might help in improving the OTA performance when SPIRAM is enabled.
- For optimizing network performance, please refer to **Improving Network Speed** section in the :doc:`/api-guides/performance/speed` for more details.
OTA Tool ``otatool.py``
-----------------------
The component ``app_update`` provides a tool :component_file:`app_update/otatool.py` for performing OTA partition-related operations on a target device. The following operations can be performed using the tool:
- read contents of otadata partition (read_otadata)
- erase otadata partition, effectively resetting device to factory app (erase_otadata)
- switch OTA partitions (switch_ota_partition)
- erasing OTA partition (erase_ota_partition)
- write to OTA partition (write_ota_partition)
- read contents of OTA partition (read_ota_partition)
The tool can either be imported and used from another Python script or invoked from shell script for users wanting to perform operation programmatically. This is facilitated by the tool's Python API and command-line interface, respectively.
Python API
^^^^^^^^^^
Before anything else, make sure that the ``otatool`` module is imported.
.. code-block:: python
import sys
import os
idf_path = os.environ["IDF_PATH"] # get value of IDF_PATH from environment
otatool_dir = os.path.join(idf_path, "components", "app_update") # otatool.py lives in $IDF_PATH/components/app_update
sys.path.append(otatool_dir) # this enables Python to find otatool module
from otatool import * # import all names inside otatool module
The starting point for using the tool's Python API to do is create an ``OtatoolTarget`` object:
.. code-block:: python
# Create a parttool.py target device connected on serial port /dev/ttyUSB1
target = OtatoolTarget("/dev/ttyUSB1")
The created object can now be used to perform operations on the target device:
.. code-block:: python
# Erase otadata, resetting the device to factory app
target.erase_otadata()
# Erase contents of OTA app slot 0
target.erase_ota_partition(0)
# Switch boot partition to that of app slot 1
target.switch_ota_partition(1)
# Read OTA partition 'ota_3' and save contents to a file named 'ota_3.bin'
target.read_ota_partition("ota_3", "ota_3.bin")
The OTA partition to operate on is specified using either the app slot number or the partition name.
More information on the Python API is available in the docstrings for the tool.
Command-line Interface
^^^^^^^^^^^^^^^^^^^^^^
The command-line interface of ``otatool.py`` has the following structure:
.. code-block:: bash
otatool.py [command-args] [subcommand] [subcommand-args]
- command-args - these are arguments that are needed for executing the main command (parttool.py), mostly pertaining to the target device
- subcommand - this is the operation to be performed
- subcommand-args - these are arguments that are specific to the chosen operation
.. code-block:: bash
# Erase otadata, resetting the device to factory app
otatool.py --port "/dev/ttyUSB1" erase_otadata
# Erase contents of OTA app slot 0
otatool.py --port "/dev/ttyUSB1" erase_ota_partition --slot 0
# Switch boot partition to that of app slot 1
otatool.py --port "/dev/ttyUSB1" switch_ota_partition --slot 1
# Read OTA partition 'ota_3' and save contents to a file named 'ota_3.bin'
otatool.py --port "/dev/ttyUSB1" read_ota_partition --name=ota_3 --output=ota_3.bin
More information can be obtained by specifying ``--help`` as argument:
.. code-block:: bash
# Display possible subcommands and show main command argument descriptions
otatool.py --help
# Show descriptions for specific subcommand arguments
otatool.py [subcommand] --help
See Also
--------
* :doc:`../../api-guides/partition-tables`
* :doc:`../storage/partition`
* :doc:`../peripherals/spi_flash/index`
* :doc:`esp_https_ota`
Application Examples
--------------------
- :example:`system/ota/native_ota_example` demonstrates how to use the `app_update` component's APIs for native over-the-air (OTA) updates on {IDF_TARGET_NAME}. For applicable SoCs, please refer to :example_file:`system/ota/native_ota_example/README.md`.
- :example:`system/ota/otatool` demonstrates how to use the OTA tool to perform operations such as reading, writing, and erasing OTA partitions, switching boot partitions, and switching to factory partition. For more information, please refer to :example_file:`system/ota/otatool/README.md`.
API Reference
-------------
.. include-build-file:: inc/esp_ota_ops.inc
Debugging OTA Failure
---------------------
.. figure:: ../../../_static/how-to-debug-when-OTA-fails-en.png
:align: center
:scale: 100%
:alt: How to Debug When OTA Fails (click to enlarge)
:figclass: align-center
How to Debug When OTA Fails (click to enlarge)
+25
View File
@@ -0,0 +1,25 @@
Performance Monitor
===================
:link_to_translation:`zh_CN:[中文]`
The Performance Monitor component provides APIs to use {IDF_TARGET_NAME} internal performance counters to profile functions and applications.
Application Examples
--------------------
- :example:`system/perfmon` demonstrates how to use the `perfmon` APIs to monitor and profile functions.
High-Level API Reference
------------------------
Header Files
^^^^^^^^^^^^
* :component_file:`perfmon/include/perfmon.h`
API Reference
-------------
.. include-build-file:: inc/xtensa_perfmon_access.inc
.. include-build-file:: inc/xtensa_perfmon_apis.inc
@@ -0,0 +1,236 @@
Power Management
================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
Power management algorithm included in ESP-IDF can adjust the advanced peripheral bus (APB) frequency, CPU frequency, and put the chip into Light-sleep mode to run an application at smallest possible power consumption, given the requirements of application components.
Application components can express their requirements by creating and acquiring power management locks.
For example:
- Driver for a peripheral clocked from APB can request the APB frequency to be set to 80 MHz while the peripheral is used.
- RTOS can request the CPU to run at the highest configured frequency while there are tasks ready to run.
- A peripheral driver may need interrupts to be enabled, which means it has to request disabling Light-sleep.
Since requesting higher APB or CPU frequencies or disabling Light-sleep causes higher current consumption, please keep the usage of power management locks by components to a minimum.
Configuration
-------------
Power management can be enabled at compile time, using the option :ref:`CONFIG_PM_ENABLE`.
Enabling power management features comes at the cost of increased interrupt latency. Extra latency depends on a number of factors, such as the CPU frequency, single/dual core mode, whether or not frequency switch needs to be done. Minimum extra latency is 0.2 us (when the CPU frequency is 240 MHz and frequency scaling is not enabled). Maximum extra latency is 40 us (when frequency scaling is enabled, and a switch from 40 MHz to 80 MHz is performed on interrupt entry).
Dynamic frequency scaling (DFS) and automatic Light-sleep can be enabled in an application by calling the function :cpp:func:`esp_pm_configure`. Its argument is a structure defining the frequency scaling settings, :cpp:class:`esp_pm_config_t`. In this structure, three fields need to be initialized:
.. list::
- ``max_freq_mhz``: Maximum CPU frequency in MHz, i.e., the frequency used when the ``ESP_PM_CPU_FREQ_MAX`` lock is acquired. This field is usually set to the default CPU frequency.
:esp32 or esp32s2: - ``min_freq_mhz``: Minimum CPU frequency in MHz, indicating the frequency used when not holding the power management lock. Note that 10 MHz is the minimum frequency required for generating a 1 MHz REF_TICK default clock.
:not esp32 and not esp32s2: - ``min_freq_mhz``: Minimum CPU frequency in MHz, indicating the frequency used when not holding the power management lock.
- ``light_sleep_enable``: Whether the system should automatically enter Light-sleep when no locks are acquired (``true``/``false``).
Alternatively, if you enable the option :ref:`CONFIG_PM_DFS_INIT_AUTO` in menuconfig, the maximum CPU frequency will be determined by the :ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ` setting, and the minimum CPU frequency will be locked to the XTAL frequency.
.. note::
Automatic Light-sleep is based on FreeRTOS Tickless Idle functionality. If automatic Light-sleep is requested while the option :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` is not enabled in menuconfig, :cpp:func:`esp_pm_configure` will return the error `ESP_ERR_NOT_SUPPORTED`.
.. note::
In Light-sleep, peripherals are clock gated, and interrupts (from GPIOs and internal peripherals) will not be generated. A wakeup source described in the :doc:`sleep_modes` documentation can be used to trigger wakeup from the Light-sleep state.
.. warning::
Automatic Light-sleep is implemented using timer wakeup. Do not manually configure the timer wakeup source.
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP and SOC_PM_SUPPORT_EXT1_WAKEUP
For example, the EXT0 and EXT1 wakeup sources can be used to wake up the chip via a GPIO.
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP and not SOC_PM_SUPPORT_EXT0_WAKEUP
For example, the EXT1 wakeup source can be used to wake up the chip via a GPIO.
Power Management Locks
----------------------
{IDF_TARGET_MAX_CPU_FREQ: default="Not updated yet", esp32="80 MHz, 160 MHz, or 240 MHz", esp32s2="80 MHz, 160 MHz, or 240 MHz", esp32s3="80 MHz, 160 MHz, or 240 MHz", esp32c2="80 MHz or 120 MHz", esp32c3="80 MHz or 160 MHz", esp32c6="80 MHz or 160 MHz", esp32p4="360 MHz", esp32c5="80 MHz, 160 MHz or 240 MHz", esp32c61="80 MHz or 160 MHz"}
Applications have the ability to acquire/release locks in order to control the power management algorithm. When an application acquires a lock, the power management algorithm operation is restricted in a way described below. When the lock is released, such restrictions are removed.
Power management locks have acquire/release counters. If the lock has been acquired a number of times, it needs to be released the same number of times to remove associated restrictions.
{IDF_TARGET_NAME} supports three types of locks described in the table below.
.. list-table::
:header-rows: 1
:widths: 25 60
* - Lock
- Description
* - ``ESP_PM_CPU_FREQ_MAX``
- Requests CPU frequency to be at the maximum value set with :cpp:func:`esp_pm_configure`. For {IDF_TARGET_NAME}, this value can be set to {IDF_TARGET_MAX_CPU_FREQ}.
* - ``ESP_PM_APB_FREQ_MAX``
- Requests the APB frequency to be at the maximum supported value. For {IDF_TARGET_NAME}, this is 80 MHz.
* - ``ESP_PM_NO_LIGHT_SLEEP``
- Disables automatic switching to Light-sleep.
{IDF_TARGET_NAME} Power Management Algorithm
---------------------------------------
The table below shows how CPU and APB frequencies will be switched if dynamic frequency scaling is enabled. You can specify the maximum CPU frequency with either :cpp:func:`esp_pm_configure` or :ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`.
.. include:: inc/power_management_{IDF_TARGET_PATH_NAME}.rst
If none of the locks are acquired, and Light-sleep is enabled in a call to :cpp:func:`esp_pm_configure`, the system will go into Light-sleep mode. The duration of Light-sleep will be determined by:
- FreeRTOS tasks blocked with finite timeouts
- Timers registered with :doc:`High resolution timer <esp_timer>` APIs
Light-sleep duration is chosen to wake up the chip before the nearest event (task being unblocked, or timer elapses).
To skip unnecessary wake-up, you can consider initializing an ``esp_timer`` with the ``skip_unhandled_events`` option as ``true``. Timers with this flag will not wake up the system and it helps to reduce consumption.
Automatic Light-sleep Time Compensation Mechanism
-------------------------------------------------
ESP-IDF uses a predictive time compensation mechanism for automatic Light-sleep. The system measures the actual wakeup overhead after each Light-sleep cycle and uses this measurement to predict the wakeup overhead for the next sleep cycle.
The system calculates sleep duration based on the next scheduled event and subtracts the predicted wakeup overhead (from the previous cycle) to set the wakeup timer. After wakeup, since FreeRTOS systick interrupts are suspended during sleep, the system needs to call :cpp:func:`vTaskStepTick()` to compensate for the ticks elapsed during sleep, maintaining the accuracy of FreeRTOS tick count. Meanwhile, it measures the actual overhead and stores it for the next prediction, creating a feedback loop that adapts to system behavior.
However, actual overhead can vary due to cache misses, CPU frequency changes, flash latency variations, or hardware state restoration time. When actual overhead exceeds prediction, the actual sleep time may exceed the expected value, causing :cpp:func:`vTaskStepTick()` to receive an excessive tick compensation value, triggering assertion failure.
The :ref:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION` option provides a safety mechanism to prevent assertion failures when wakeup overhead exceeds prediction. When enabled, the system limits the tick compensation value to prevent overflow. This option can be enabled in menuconfig via ``Component config`` > ``Power Management`` > ``Enable light sleep tick overflow protection``.
When enabled, this option handles oversleep as follows:
- If oversleep is within tolerance (configurable via :ref:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE`, default: 2 ticks), the system silently limits ``slept_ticks`` to ``xExpectedIdleTime``, preventing assertion failure
- If oversleep exceeds tolerance (may indicate a bug), the system does not limit ticks, logs an error message, and assertion failure will occur
- In rare edge cases, it may lose ticks, causing FreeRTOS tick count (``xTickCount``) to lag behind real time (``esp_timer``). Tasks using :cpp:func:`vTaskDelay()` may experience slightly longer delays than expected, and FreeRTOS software timers may have reduced accuracy.
When disabled (default), the system provides accurate tick compensation with better precision for time-critical applications. In edge cases, if wakeup overhead estimation is insufficient causing Light-sleep oversleep, assertion failure and system crash may occur.
It is recommended to keep this option disabled by default to maintain tick accuracy. Enable it only when you experience assertion failures related to :cpp:func:`vTaskStepTick()` and can accept slight inaccuracy of RTOS tick time compared to real time.
Debugging and Profiling
-----------------------
The power management subsystem provides several functions to help debug and profile power management lock usage in applications:
- :cpp:func:`esp_pm_dump_locks` - Dumps a list of all currently created locks to a specified stream, showing their types, names, and current acquisition status.
- :cpp:func:`esp_pm_get_lock_stats_all` - Retrieves statistics for all PM lock types, including the number of locks created and the number currently acquired.
- :cpp:func:`esp_pm_lock_get_stats` - Gets detailed statistics for a specific lock instance, including acquisition count and (if profiling is enabled) the number of times taken and total time held.
These functions are particularly useful for:
1. Identifying leaks where locks are acquired but never released
2. Understanding which components are preventing power savings
3. Optimizing power consumption by analyzing lock usage patterns
4. Debugging issues related to lock management in applications
To enable profiling features (timing information for individual locks), enable the :ref:`CONFIG_PM_PROFILING` option in menuconfig.
Application Example
-------------------
The :example:`lowpower/power_management` example demonstrates dynamic frequency scaling, automatic Light-sleep, and power management locks.
Dynamic Frequency Scaling and Peripheral Drivers
------------------------------------------------
When DFS is enabled, the APB frequency can be changed multiple times within a single RTOS tick. The APB frequency change does not affect the operation of some peripherals, while other peripherals may have issues. For example, Timer Group peripheral timers keeps counting, however, the speed at which they count changes proportionally to the APB frequency.
Peripheral clock sources such as ``REF_TICK``, ``XTAL``, ``RC_FAST`` (i.e., ``RTC_8M``), their frequencies will not be inflenced by APB frequency. And therefore, to ensure the peripheral behaves consistently during DFS, it is recommended to select one of these clocks as the peripheral clock source. For more specific guidelines, please refer to the "Power Management" section of each peripheral's "API Reference > Peripherals API" page.
Currently, the following peripheral drivers are aware of DFS and use the ``ESP_PM_APB_FREQ_MAX`` lock for the duration of the transaction:
.. list::
- SPI master
- I2C
:SOC_I2S_HW_VERSION_1 or not SOC_I2S_SUPPORTS_APLL: - I2S
:not SOC_I2S_HW_VERSION_1 and SOC_I2S_SUPPORTS_APLL: - I2S (if the APLL clock is used, then it will use the ``ESP_PM_NO_LIGHT_SLEEP`` lock)
- SDMMC
The following drivers hold the ``ESP_PM_APB_FREQ_MAX`` lock while the driver is enabled:
.. list::
- **SPI slave**: between calls to :cpp:func:`spi_slave_initialize` and :cpp:func:`spi_slave_free`.
- **GPTimer**: between calls to :cpp:func:`gptimer_enable` and :cpp:func:`gptimer_disable`.
- **Ethernet**: between calls to :cpp:func:`esp_eth_driver_install` and :cpp:func:`esp_eth_driver_uninstall`.
:SOC_WIFI_SUPPORTED: - **WiFi**: between calls to :cpp:func:`esp_wifi_start` and :cpp:func:`esp_wifi_stop`. If modem sleep is enabled, the lock will be released for the periods of time when radio is disabled.
:SOC_TWAI_SUPPORTED: - **TWAI**: between calls to :cpp:func:`twai_driver_install` and :cpp:func:`twai_driver_uninstall` (only when the clock source is set to :cpp:enumerator:`TWAI_CLK_SRC_APB`).
:SOC_BT_SUPPORTED and esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held, unless :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` option is set to "External 32 kHz crystal".
:SOC_BT_SUPPORTED and not esp32: - **Bluetooth**: between calls to :cpp:func:`esp_bt_controller_enable` and :cpp:func:`esp_bt_controller_disable`. If Bluetooth Modem-sleep is enabled, the ``ESP_PM_APB_FREQ_MAX`` lock will be released for the periods of time when radio is disabled. However the ``ESP_PM_NO_LIGHT_SLEEP`` lock will still be held.
:SOC_PCNT_SUPPORTED: - **PCNT**: between calls to :cpp:func:`pcnt_unit_enable` and :cpp:func:`pcnt_unit_disable`.
:SOC_SDM_SUPPORTED: - **Sigma-delta**: between calls to :cpp:func:`sdm_channel_enable` and :cpp:func:`sdm_channel_disable`.
:SOC_MCPWM_SUPPORTED: - **MCPWM**: between calls to :cpp:func:`mcpwm_timer_enable` and :cpp:func:`mcpwm_timer_disable`, as well as :cpp:func:`mcpwm_capture_timer_enable` and :cpp:func:`mcpwm_capture_timer_disable`.
.. only:: SOC_PM_SUPPORT_TOP_PD
Light-sleep Peripheral Power Down
---------------------------------
{IDF_TARGET_NAME} supports power-down peripherals during Light-sleep.
If :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` is enabled, when the driver initializes the peripheral, the driver will register the working register context of the peripheral to the sleep retention link. Before entering sleep, the ``REG_DMA`` peripheral reads the configuration in the sleep retention link, and back up the register context to memory according to the configuration. ``REG_DMA`` also restores context from memory to peripheral registers on wakeup.
Currently ESP-IDF supports Light-sleep context retention for the following peripherals. Their context is automatically restored, or they provide some option for the user to enable this feature and goes into peripheral power down mode.
.. list::
- INT_MTX
- TEE/APM
- IO_MUX / GPIO
- MSPI (SPI0/1)
- SYSTIMER
:SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
:SOC_LEDC_SUPPORT_SLEEP_RETENTION: - LEDC
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
:SOC_MCPWM_SUPPORT_SLEEP_RETENTION: - MCPWM
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
:SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor
:SOC_TWAI_SUPPORT_SLEEP_RETENTION: - All TWAIs
:SOC_PARLIO_SUPPORT_SLEEP_RETENTION: - PARL_IO
:SOC_SPI_SUPPORT_SLEEP_RETENTION: - All GPSPIs
:SOC_EMAC_SUPPORT_SLEEP_RETENTION: - EMAC
:SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION: - I80 LCD
Some peripherals haven't support Light-sleep context retention, or it cannot survive from the register lose. They will prevent the power-down of peripherals even when the feature is enabled.
.. list::
:SOC_SDIO_SLAVE_SUPPORTED: - SDIO Slave
:SOC_PCNT_SUPPORTED: - PCNT
The following peripherals (and those not listed in any group of this section) are not yet supported. If your application uses these peripherals, they may not work well after waking up from sleep.
.. list::
- ASSIST_DEBUG
- Trace
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
- USB-Serial-JTAG
- SARADC
.. note::
When the peripheral power domain is powered down during sleep, both the IO_MUX and GPIO modules are inactive, meaning the chip pins' state is not maintained by these modules. To preserve the state of an IO during sleep, it's essential to call :cpp:func:`gpio_hold_dis` and :cpp:func:`gpio_hold_en` before and after configuring the GPIO state. This action ensures that the IO configuration is latched and prevents the IO from becoming floating while in sleep mode.
API Reference
-------------
.. include-build-file:: inc/esp_pm.inc
+268
View File
@@ -0,0 +1,268 @@
POSIX Support (Including POSIX Threads Support)
===============================================
:link_to_translation:`zh_CN:[中文]`
Overview
--------
ESP-IDF is based on FreeRTOS but offers a range of POSIX-compatible APIs that allow easy porting of third-party code. This includes support for common parts of the POSIX Threads ``pthread`` API.
POSIX Threads are implemented in ESP-IDF as wrappers around equivalent FreeRTOS features. The runtime memory or performance overhead of using the pthreads API is quite low, but not every feature available in either pthreads or FreeRTOS is available via the ESP-IDF pthreads support.
Pthreads can be used in ESP-IDF by including standard ``pthread.h`` header, which is included in the toolchain libc. An additional ESP-IDF specific header, ``esp_pthread.h``, provides additional non-POSIX APIs for using some ESP-IDF features with pthreads.
Besides POSIX Threads, ESP-IDF also supports :ref:`POSIX message queues <posix_message_queues>`.
C++ Standard Library implementations for ``std::thread``, ``std::mutex``, ``std::condition_variable``, etc., are realized using pthreads and other POSIX APIs (via GCC libstdc++). Therefore, restrictions mentioned here also apply to the equivalent C++ standard library functionality.
If you identify a useful API that you would like to see implemented in ESP-IDF, please open a `feature request on GitHub <https://github.com/espressif/esp-idf/issues>`_ with the details.
RTOS Integration
----------------
Unlike many operating systems using POSIX Threads, ESP-IDF is a real-time operating system with a real-time scheduler. This means that a thread will only stop running if a higher priority task is ready to run, the thread blocks on an OS synchronization structure like a mutex, or the thread calls any of the functions ``sleep``, :cpp:func:`vTaskDelay`, or ``usleep``.
.. note::
When calling a standard libc or C++ sleep function, such as ``usleep`` defined in ``unistd.h``, the task will only block and yield the core if the sleep time is longer than :ref:`one FreeRTOS tick period <CONFIG_FREERTOS_HZ>`. If the time is shorter, the thread will busy-wait instead of yielding to another RTOS task.
.. note::
The POSIX ``errno`` is provided by esp_libc in ESP-IDF. Thus the configuration ``configUSE_POSIX_ERRNO`` is not used and should stay disabled.
By default, all POSIX Threads have the same RTOS priority, but it is possible to change this by calling a :ref:`custom API <esp-pthread>`.
Standard Features
-----------------
The following standard APIs are implemented in ESP-IDF.
Refer to `standard POSIX Threads documentation <https://man7.org/linux/man-pages/man7/pthreads.7.html>`__, or ``pthread.h``, for details about the standard arguments and behaviour of each function. Differences or limitations compared to the standard APIs are noted below.
.. _posix_thread_api:
Thread APIs
^^^^^^^^^^^
* ``pthread_create()``
- The ``attr`` argument is supported for setting stack size and detach state only. Other attribute fields are ignored.
- Unlike FreeRTOS task functions, the ``start_routine`` function is allowed to return. A detached type thread is automatically deleted if the function returns. The default joinable type thread will be suspended until ``pthread_join()`` is called on it.
* ``pthread_join()``
* ``pthread_detach()``
* ``pthread_exit()``
* ``sched_yield()``
* ``pthread_self()``
- An assert will fail if this function is called from a FreeRTOS task which is not a pthread.
* ``pthread_equal()``
Thread Attributes
^^^^^^^^^^^^^^^^^
* ``pthread_attr_init()``
* ``pthread_attr_destroy()``
- This function does not need to free any resources and instead resets the ``attr`` structure to defaults. The implementation is the same as ``pthread_attr_init()``.
* ``pthread_attr_getstacksize()`` / ``pthread_attr_setstacksize()``
* ``pthread_attr_getdetachstate()`` / ``pthread_attr_setdetachstate()``
Once
^^^^
* ``pthread_once()``
Static initializer constant ``PTHREAD_ONCE_INIT`` is supported.
.. note::
This function can be called from tasks created using either pthread or FreeRTOS APIs.
Mutexes
^^^^^^^
POSIX Mutexes are implemented as FreeRTOS Mutex Semaphores (normal type for "fast" or "error check" mutexes, and Recursive type for "recursive" mutexes). This means that they have the same priority inheritance behavior as mutexes created with :cpp:func:`xSemaphoreCreateMutex`.
* ``pthread_mutex_init()``
* ``pthread_mutex_destroy()``
* ``pthread_mutex_lock()``
* ``pthread_mutex_timedlock()``
* ``pthread_mutex_trylock()``
* ``pthread_mutex_unlock()``
* ``pthread_mutexattr_init()``
* ``pthread_mutexattr_destroy()``
* ``pthread_mutexattr_gettype()`` / ``pthread_mutexattr_settype()``
Static initializer constant ``PTHREAD_MUTEX_INITIALIZER`` is supported, but the non-standard static initializer constants for other mutex types are not supported.
.. note::
These functions can be called from tasks created using either pthread or FreeRTOS APIs.
Condition Variables
^^^^^^^^^^^^^^^^^^^
* ``pthread_cond_init()``
- The ``attr`` argument is not implemented and is ignored.
* ``pthread_cond_destroy()``
* ``pthread_cond_signal()``
* ``pthread_cond_broadcast()``
* ``pthread_cond_wait()``
* ``pthread_cond_timedwait()``
Static initializer constant ``PTHREAD_COND_INITIALIZER`` is supported.
* The resolution of ``pthread_cond_timedwait()`` timeouts is the RTOS tick period (see :ref:`CONFIG_FREERTOS_HZ`). Timeouts may be delayed up to one tick period after the requested timeout.
.. note::
These functions can be called from tasks created using either pthread or FreeRTOS APIs.
Semaphores
^^^^^^^^^^
In ESP-IDF, POSIX **unnamed** semaphores are implemented. The accessible API is described below. It implements `semaphores as specified in the POSIX standard <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html>`_, unless specified otherwise.
* `sem_init() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html>`_
* `sem_destroy() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html>`_
- ``pshared`` is ignored. Semaphores can always be shared between FreeRTOS tasks.
* `sem_post() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html>`_
- If the semaphore has a value of ``SEM_VALUE_MAX`` already, ``-1`` is returned and ``errno`` is set to ``EAGAIN``.
* `sem_wait() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html>`_
* `sem_trywait() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html>`_
* `sem_timedwait() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html>`_
- The time value passed by abstime will be rounded up to the next FreeRTOS tick.
- The actual timeout happens after the tick that the time was rounded to and before the following tick.
- It is possible, though unlikely, that the task is preempted directly after the timeout calculation, delaying the timeout of the following blocking operating system call by the duration of the preemption.
* `sem_getvalue() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html>`_
Read/Write Locks
^^^^^^^^^^^^^^^^
The following API functions of the POSIX reader-writer locks specification are implemented:
* `pthread_rwlock_init() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_init.html>`_
- The ``attr`` argument is not implemented and is ignored.
* `pthread_rwlock_destroy() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_destroy.html>`_
* `pthread_rwlock_rdlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_rdlock.html>`_
* `pthread_rwlock_tryrdlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_tryrdlock.html>`_
* `pthread_rwlock_wrlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_wrlock.html>`_
* `pthread_rwlock_trywrlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_trywrlock.html>`_
* `pthread_rwlock_unlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_unlock.html>`_
* `pthread_rwlock_timedwrlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_timedwrlock.html>`_
* `pthread_rwlock_timedrdlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_timedrdlock.html>`_
The static initializer constant ``PTHREAD_RWLOCK_INITIALIZER`` is supported.
.. note::
These functions can be called from tasks created using either pthread or FreeRTOS APIs.
Thread-Specific Data
^^^^^^^^^^^^^^^^^^^^
* ``pthread_key_create()``
- The ``destr_function`` argument is supported and will be called if a thread function exits normally, calls ``pthread_exit()``, or if the underlying task is deleted directly using the FreeRTOS function :cpp:func:`vTaskDelete`.
* ``pthread_key_delete()``
* ``pthread_setspecific()`` / ``pthread_getspecific()``
.. note::
These functions can be called from tasks created using either pthread or FreeRTOS APIs. When calling these functions from tasks created using FreeRTOS APIs, :ref:`CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS` config option must be enabled to ensure the thread-specific data is cleaned up before the task is deleted.
.. note::
There are other options for thread local storage in ESP-IDF, including options with higher performance. See :doc:`/api-guides/thread-local-storage`.
.. _posix_message_queues:
Message Queues
^^^^^^^^^^^^^^
The message queue implementation is based on the `FreeRTOS-Plus-POSIX <https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/index.html>`_ project. Message queues are not made available in any filesystem on ESP-IDF. Message priorities are not supported.
The following API functions of the POSIX message queue specification are implemented:
* `mq_open() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html>`_
- The ``name`` argument has, besides the POSIX specification, the following additional restrictions:
- It has to begin with a leading slash.
- It has to be no more than 255 + 2 characters long (including the leading slash, excluding the terminating null byte). However, memory for ``name`` is dynamically allocated internally, so the shorter it is, the fewer memory it will consume.
- The ``mode`` argument is not implemented and is ignored.
- Supported ``oflags``: ``O_RDWR``, ``O_CREAT``, ``O_EXCL``, and ``O_NONBLOCK``.
* `mq_close() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html>`_
* `mq_unlink() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html>`_
* `mq_receive() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html>`_
- Since message priorities are not supported, ``msg_prio`` is unused.
* `mq_timedreceive() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html>`_
- Since message priorities are not supported, ``msg_prio`` is unused.
* `mq_send() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html>`_
- Since message priorities are not supported, ``msg_prio`` has no effect.
* `mq_timedsend() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html>`_
- Since message priorities are not supported, ``msg_prio`` has no effect.
* `mq_getattr() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html>`_
`mq_notify() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_notify.html>`_ and `mq_setattr() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html>`_ are not implemented.
Building
........
To use the POSIX message queue API, please add ``rt`` as a requirement in your component's ``CMakeLists.txt``.
.. note::
If you have used `FreeRTOS-Plus-POSIX <https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/index.html>`_ in another FreeRTOS project before, please note that the include paths in IDF are POSIX-like. Hence, applications include ``mqueue.h`` directly instead of using the subdirectory include ``FreeRTOS_POSIX/mqueue.h``.
Not Implemented
---------------
The ``pthread.h`` header is a standard header and includes additional APIs and features which are not implemented in ESP-IDF. These include:
* ``pthread_cancel()`` returns ``ENOSYS`` if called.
* ``pthread_condattr_init()`` returns ``ENOSYS`` if called.
* `mq_notify() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_notify.html>`_ returns ``ENOSYS`` if called.
* `mq_setattr() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html>`_ returns ``ENOSYS`` if called.
Other POSIX Threads functions (not listed here) are not implemented and will produce either a compiler or a linker error if referenced from an ESP-IDF application.
.. _esp-pthread:
ESP-IDF Extensions
------------------
The API :cpp:func:`esp_pthread_set_cfg` defined in the ``esp_pthreads.h`` header offers custom extensions to control how subsequent calls to ``pthread_create()`` behaves. Currently, the following configuration can be set:
.. list::
- Default stack size of new threads, if not specified when calling ``pthread_create()`` (overrides :ref:`CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT`).
- Stack memory capabilities determine which kind of memory is used for allocating pthread stacks. The field takes ESP-IDF heap capability flags, as defined in :component_file:`heap/include/esp_heap_caps.h`. The memory must be 8-bit accessible (MALLOC_CAP_8BIT), besides other custom flags the user can choose from. The user is responsible for ensuring the correctness of the stack memory capabilities. For more information about memory locations, refer to the documentation of :ref:`memory_capabilities`.
- RTOS priority of new threads (overrides :ref:`CONFIG_PTHREAD_TASK_PRIO_DEFAULT`).
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - Core affinity / core pinning of new threads (overrides :ref:`CONFIG_PTHREAD_TASK_CORE_DEFAULT`).
- FreeRTOS task name for new threads (overrides :ref:`CONFIG_PTHREAD_TASK_NAME_DEFAULT`)
This configuration is scoped to the calling thread (or FreeRTOS task), meaning that :cpp:func:`esp_pthread_set_cfg` can be called independently in different threads or tasks. If the ``inherit_cfg`` flag is set in the current configuration then any new thread created will inherit the creator's configuration (if that thread calls ``pthread_create()`` recursively), otherwise the new thread will have the default configuration.
Application Examples
--------------------
- :example:`system/pthread` demonstrates using the pthreads API to create threads.
- :example:`cxx/pthread` demonstrates using C++ Standard Library functions with threads.
API Reference
-------------
.. include-build-file:: inc/esp_pthread.inc
+150
View File
@@ -0,0 +1,150 @@
Random Number Generation
========================
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_RF_NAME: default="Wi-Fi or Bluetooth", esp32s2="Wi-Fi", esp32h2="Bluetooth or 802.15.4 Thread/Zigbee", esp32h4="Bluetooth or 802.15.4 Thread/Zigbee", esp32c6="Wi-Fi or Bluetooth or 802.15.4 Thread/Zigbee", esp32c5="Wi-Fi or Bluetooth or 802.15.4 Thread/Zigbee"}
{IDF_TARGET_RF_IS: default="are", esp32s2="is"}
{IDF_TARGET_NAME} contains a hardware random number generator (RNG). You can use the APIs :cpp:func:`esp_random` and :cpp:func:`esp_fill_random` to obtained random values from it.
Every 32-bit value that the system reads from the RNG_DATA_REG register of the random number generator is a true random number. These true random numbers are generated based on the thermal noise in the system and the asynchronous clock mismatch.
.. only:: SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED
- Noise comes from the high-speed ADC, the SAR ADC, or both. When the high-speed ADC or SAR ADC is enabled, the generated bit streams are fed into the random number generator through an XOR logic gate as random seeds.
.. only:: esp32p4
- Thermal noise comes from count values generated by the ring oscillator (BUF_CHAIN) implemented with BUF_CELL, together with the SAR ADC entropy source. Both act as entropy sources to generate random numbers.
.. only:: esp32s31
- Thermal noise comes from multiple entropy sources, including the ring oscillator (BUF_CHAIN) implemented with BUF_CELL, the RFADC, the SAR ADC, and the 40 MHz clock. Their outputs are continuously processed through CRC32 calculations and fed into the random number generator.
.. only:: not esp32
- RC_FAST_CLK is an asynchronous clock source, and it increases the RNG entropy by introducing circuit metastability. See the :ref:`secondary entropy` section for more details.
The following diagram shows the noise sources for the RNG on the {IDF_TARGET_NAME}:
.. only:: SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED
.. image:: /../_static/esp_rng_noise_source_rf_available.svg
:align: center
.. only:: not SOC_WIFI_SUPPORTED and not SOC_IEEE802154_SUPPORTED and not SOC_BT_SUPPORTED
.. image:: /../_static/esp_rng_noise_source_rf_unavailable.svg
:align: center
The hardware RNG produces true random numbers so long as one or more of the following conditions are met:
.. list::
:SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED: - RF subsystem is enabled, i.e., {IDF_TARGET_RF_NAME} {IDF_TARGET_RF_IS} enabled. When enabled, the RF subsystem internally enables the High Speed ADC that can be used as the entropy source. The High Speed ADC may only be available when the respective RF subsystem is active (e.g., not in sleep mode). See the :ref:`enabling RF subsystem` section for more details.
- The internal entropy source SAR ADC has been enabled by calling :cpp:func:`bootloader_random_enable` and not yet disabled by calling :cpp:func:`bootloader_random_disable`.
- While the ESP-IDF :ref:`second-stage-bootloader` is running. This is because the default ESP-IDF bootloader implementation calls :cpp:func:`bootloader_random_enable` when the bootloader starts, and :cpp:func:`bootloader_random_disable` before executing the application.
When any of these conditions are true, samples of physical noise are continuously mixed into the internal hardware RNG state to provide entropy. Consult the **{IDF_TARGET_NAME} Technical Reference Manual** > **Random Number Generator (RNG)** [`PDF <{IDF_TARGET_TRM_EN_URL}#rng>`__] chapter for more details.
If none of the above conditions are true, the output of the RNG should be considered as pseudo-random only.
.. only:: SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED
.. _enabling RF subsystem:
Enabling RF subsystem
---------------------
The RF subsystem can be enabled with help of one of the following APIs:
.. list::
:SOC_WIFI_SUPPORTED: - Wi-Fi: :cpp:func:`esp_wifi_start`
:SOC_BT_SUPPORTED: - Bluetooth (NimBLE): :cpp:func:`nimble_port_init()` which internally calls :cpp:func:`esp_bt_controller_enable()`
:SOC_BT_SUPPORTED: - Bluetooth (Bluedroid): :cpp:func:`esp_bt_controller_enable()`
:SOC_IEEE802154_SUPPORTED: - Thread/Zigbee: :cpp:func:`esp_openthread_init`
Startup
-------
During startup, the ESP-IDF bootloader temporarily enables the non-RF internal entropy source (SAR ADC using internal reference voltage noise) that provides entropy for any first boot key generation.
.. only:: not SOC_WIFI_SUPPORTED and not SOC_IEEE802154_SUPPORTED and not SOC_BT_SUPPORTED
For {IDF_TARGET_NAME}, the High Speed ADC is not available. Hence, the non-RF internal entropy source (SAR ADC) is kept enabled by default at the time of application startup.
.. only:: SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED
However, after the application starts executing, then normally only pseudo-random numbers are available until {IDF_TARGET_RF_NAME} {IDF_TARGET_RF_IS} initialized or until the internal entropy source has been enabled again.
To re-enable the entropy source temporarily during application startup, or for an application that does not use {IDF_TARGET_RF_NAME}, call the function :cpp:func:`bootloader_random_enable` to re-enable the internal entropy source. The function :cpp:func:`bootloader_random_disable` must be called to disable the entropy source again before using any of the following features:
.. list::
- ADC
:esp32: - I2S
:SOC_WIFI_SUPPORTED or SOC_IEEE802154_SUPPORTED or SOC_BT_SUPPORTED: - {IDF_TARGET_RF_NAME}
.. note::
The entropy source enabled during the boot process by the ESP-IDF Second Stage Bootloader seeds the internal RNG state with some entropy. However, the internal hardware RNG state is not large enough to provide a continuous stream of true random numbers. This is why a continuous entropy source must be enabled whenever true random numbers are required.
.. note::
If an application requires a source of true random numbers but cannot permanently enable a hardware entropy source, consider using a strong software DRBG implementation such as the mbedTLS CTR-DRBG or HMAC-DRBG, with an initial seed of entropy from hardware RNG true random numbers.
.. only:: not esp32
.. _secondary entropy:
Secondary Entropy
-----------------
{IDF_TARGET_NAME} RNG contains a secondary entropy source, based on sampling an asynchronous 8 MHz internal oscillator (see the Technical Reference Manual for details). This entropy source is always enabled in ESP-IDF and is continuously mixed into the RNG state by hardware. In testing, this secondary entropy source was sufficient to pass the `Dieharder`_ random number test suite without the main entropy source enabled (test input was created by concatenating short samples from continuously resetting {IDF_TARGET_NAME}). However, it is currently only guaranteed that true random numbers are produced when the main entropy source is also enabled as described above.
API Reference
-------------
.. include-build-file:: inc/esp_random.inc
.. include-build-file:: inc/bootloader_random.inc
``getrandom()``
---------------
A compatible version of the Linux ``getrandom()`` function is also provided for ease of porting:
.. code-block:: c
#include <sys/random.h>
ssize_t getrandom(void *buf, size_t buflen, unsigned int flags);
This function is implemented by calling :cpp:func:`esp_fill_random` internally.
The ``flags`` argument is ignored. This function is always non-blocking but the strength of any random numbers is dependent on the same conditions described above.
Return value is -1 (with ``errno`` set to ``EFAULT``) if the ``buf`` argument is NULL, and equal to ``buflen`` otherwise.
``getentropy()``
----------------
A compatible version of the Linux ``getentropy()`` function is also provided for easy porting:
.. code-block:: c
#include <unistd.h>
int getentropy(void *buffer, size_t length);
This function is implemented by calling :cpp:func:`getrandom` internally.
The strength of any random numbers is dependent on the same conditions described above.
Return value is 0 on success and -1 otherwise with ``errno`` set to:
- ``EFAULT`` if the ``buffer`` argument is NULL.
- ``EIO`` if the ``length`` is more then 256.
.. _Dieharder: https://webhome.phy.duke.edu/~rgb/General/dieharder.php
@@ -0,0 +1,728 @@
Sleep Modes
===========
:link_to_translation:`zh_CN:[中文]`
{IDF_TARGET_SPI_POWER_DOMAIN:default="VDD_SPI", esp32="VDD_SDIO"}
{IDF_TARGET_RTC_POWER_DOMAIN:default="VDD3P3_RTC", esp32c5="VDDPST1", esp32c6="VDDPST1", esp32c61="VDDPST1", esp32p4="VDD_LP"}
Overview
--------
{IDF_TARGET_NAME} supports two major power saving modes: Light-sleep and Deep-sleep. According to the features used by an application, there are some sub sleep modes. See :ref:`sleep_modes` for these sleep modes and sub sleep modes. Additionally, there are some power-down options that can be configured to further reduce the power consumption. See :ref:`power_down_options` for more details.
There are several wakeup sources in the sleep modes. These sources can also be combined so that the chip will wake up when any of the sources are triggered. :ref:`api-reference-wakeup-source` describes these wakeup sources and configuration APIs in detail.
The configuration of power-down options and wakeup sources are optional. They can be configured at any moment before entering the sleep modes.
Then the application can call sleep start APIs to enter one of the sleep modes. See :ref:`enter_sleep` for more details. When the wakeup condition is met, the application is awoken from sleep. See :ref:`wakeup_cause` on how to get the wakeup cause, and :ref:`disable_sleep_wakeup_source` on how to handle the wakeup sources after wakeup.
.. _sleep_modes:
Sleep Modes
-----------
In Light-sleep mode, the digital peripherals, most of the RAM, and CPUs are clock-gated and their supply voltage is reduced. Upon exit from Light-sleep, the digital peripherals, RAM, and CPUs resume operation and their internal states are preserved.
In Deep-sleep mode, the CPUs, most of the RAM, and all digital peripherals that are clocked from APB_CLK are powered off. The only parts of the chip that remain powered on are:
.. list::
- RTC controller
:SOC_ULP_SUPPORTED: - ULP coprocessor
:SOC_RTC_FAST_MEM_SUPPORTED: - RTC FAST memory
:SOC_RTC_SLOW_MEM_SUPPORTED: - RTC SLOW memory
.. only:: SOC_WIFI_SUPPORTED and SOC_BT_SUPPORTED
Wi-Fi/Bluetooth and Sleep Modes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In Deep-sleep and Light-sleep modes, the wireless peripherals are powered down. Before entering Deep-sleep or Light-sleep modes, the application must disable Wi-Fi and Bluetooth using the appropriate calls (i.e., :cpp:func:`nimble_port_stop`, :cpp:func:`nimble_port_deinit`, :cpp:func:`esp_bluedroid_disable`, :cpp:func:`esp_bluedroid_deinit`, :cpp:func:`esp_bt_controller_disable`, :cpp:func:`esp_bt_controller_deinit`, :cpp:func:`esp_wifi_stop`). Wi-Fi and Bluetooth connections are not maintained in Deep-sleep or Light-sleep mode, even if these functions are not called.
If Wi-Fi/Bluetooth connections need to be maintained, enable Wi-Fi/Bluetooth Modem-sleep mode and automatic Light-sleep feature (see :doc:`Power Management APIs <power_management>`). This allows the system to wake up from sleep automatically when required by the Wi-Fi/Bluetooth driver, thereby maintaining the connection.
.. only:: SOC_WIFI_SUPPORTED and not SOC_BT_SUPPORTED
Wi-Fi and Sleep Modes
^^^^^^^^^^^^^^^^^^^^^^^
In Deep-sleep and Light-sleep modes, the wireless peripherals are powered down. Before entering Deep-sleep or Light-sleep modes, applications must disable Wi-Fi using the appropriate calls (:cpp:func:`esp_wifi_stop`). Wi-Fi connections are not maintained in Deep-sleep or Light-sleep mode, even if these functions are not called.
If Wi-Fi connections need to be maintained, enable Wi-Fi Modem-sleep mode and automatic Light-sleep feature (see :doc:`Power Management APIs <power_management>`). This will allow the system to wake up from sleep automatically when required by the Wi-Fi driver, thereby maintaining a connection to the AP.
.. only:: esp32s2 or esp32s3 or esp32c2 or esp32c3
Sub Sleep Modes
^^^^^^^^^^^^^^^
Tables below list the sub sleep modes in the first row and the features they support in the first column. Modes that support more features may consume more power during sleep mode. The sleep system automatically selects the mode that satisfies all the features required by the user while consuming least power.
Deep-sleep:
.. list-table::
:widths: auto
:header-rows: 2
* -
- DSLP_ULTRA_LOW
- DSLP_DEFAULT
- DSLP_8MD256/
* -
-
-
- DSLP_ADC_TSENS
* - ULP/Touch sensor (ESP32-S2 and ESP32-S3 only)
- Y
- Y
- Y
* - RTC IO input/RTC memory at high temperature
-
- Y
- Y
* - ADC_TSEN_MONITOR
-
-
- Y
* - 8MD256 as the clock source for RTC_SLOW_CLK
-
-
- Y
Features:
1. RTC IO input/RTC memory at high temperature (experimental): Use RTC IO as input pins, or use RTC memory at high temperature. The chip can go into ultra low power mode when these features are disabled. Controlled by API :cpp:func:`esp_sleep_sub_mode_config` with `ESP_SLEEP_ULTRA_LOW_MODE` argument.
2. ADC_TSEN_MONITOR: Use ADC/Temperature Sensor in monitor mode (controlled by ULP). Enabled by API :cpp:func:`ulp_adc_init` or its higher level APIs. Only available for ESP32-S2 and ESP32-S3 chips with monitor mode.
3. 8MD256 as the clock source for RTC_SLOW_CLK: When 8MD256 is selected as the clock source for RTC_SLOW_CLK using the Kconfig option ``CONFIG_RTC_CLK_SRC_INT_8MD256``, the chip will automatically enter this sub sleep mode during Deep-sleep mode.
Light-sleep:
.. list-table::
:widths: auto
:header-rows: 2
* -
- LSLP_DEFAULT
- LSLP_ADC_TSENS
- LSLP_8MD256
- LSLP_LEDC8M/
* -
-
-
-
- LSLP_XTAL_FPU
* - ULP/Touch sensor (ESP32-S2 and ESP32-S3 only)
- Y
- Y
- Y
- Y
* - RTC IO input/RTC memory at high temperature
- Y
- Y
- Y
- Y
* - ADC_TSEN_MONITOR
-
- Y
- Y
- Y
* - 8MD256 as the clock source for RTC_SLOW_CLK
-
-
- Y
- Y
* - 8 MHz RC clock source used by digital peripherals
-
-
-
- Y
* - Keep the XTAL clock on
-
-
-
- Y
Features: (Also see 8MD256 and ADC_TSEN_MONITOR features for Deep-sleep mode above)
1. 8 MHz RC clock source used by digital peripherals: Currently, only LEDC uses this clock source during Light-sleep mode. When LEDC selects this clock source, this feature is automatically enabled.
2. Keep the XTAL clock on: Keep the XTAL clock on during Light-sleep mode. Controlled by ``ESP_PD_DOMAIN_XTAL`` power domain.
.. only:: esp32s2
{IDF_TARGET_NAME} uses the same power mode for LSLP_8MD256, LSLP_LEDC8M, and LSLP_XTAL_FPU features.
.. only:: esp32s3
Default mode of {IDF_TARGET_NAME} already supports ADC_TSEN_MONITOR feature.
.. only:: esp32c2 or esp32c3
{IDF_TARGET_NAME} does not have ADC_TSEN_MONITOR or LSLP_ADC_TSENS feature.
.. _api-reference-wakeup-source:
Wakeup Sources
--------------
Wakeup sources can be enabled using ``esp_sleep_enable_X_wakeup`` APIs. Wakeup sources are not disabled after wakeup, you can disable them using :cpp:func:`esp_sleep_disable_wakeup_source` API if you do not need them any more. See :ref:`disable_sleep_wakeup_source`.
Following are the wakeup sources supported on {IDF_TARGET_NAME}.
Timer
^^^^^
The RTC controller has a built-in timer which can be used to wake up the chip after a predefined amount of time. Time is specified at microsecond precision, but the actual resolution depends on the clock source selected for RTC_SLOW_CLK.
.. only:: SOC_ULP_SUPPORTED
For details on RTC clock options, see **{IDF_TARGET_NAME} Technical Reference Manual** > **ULP Coprocessor** [`PDF <{IDF_TARGET_TRM_EN_URL}#ulp>`__].
RTC peripherals or RTC memories do not need to be powered on during sleep in this wakeup mode.
:cpp:func:`esp_sleep_enable_timer_wakeup` function can be used to enable sleep wakeup using a timer.
.. only:: SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
Touchpad
^^^^^^^^^
The RTC IO module contains the logic to trigger wakeup when a touch sensor interrupt occurs. To wakeup from a touch sensor interrupt, users need to configure the touch pad interrupt before the chip enters Deep-sleep or Light-sleep modes.
.. only:: esp32
Revisions 0 and 1 of ESP32 only support this wakeup mode when RTC peripherals are not forced to be powered on (i.e., ESP_PD_DOMAIN_RTC_PERIPH should be set to ESP_PD_OPTION_AUTO).
:cpp:func:`esp_sleep_enable_touchpad_wakeup` function can be used to enable this wakeup source.
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP
External Wakeup (``ext0``)
^^^^^^^^^^^^^^^^^^^^^^^^^^
The RTC IO module contains the logic to trigger wakeup when one of RTC GPIOs is set to a predefined logic level. RTC IO is part of the RTC peripherals power domain, so RTC peripherals will be kept powered on during Deep-sleep if this wakeup source is requested.
The RTC IO module is enabled in this mode, so internal pullup or pulldown resistors can also be used. They need to be configured by the application using :cpp:func:`rtc_gpio_pullup_en` and :cpp:func:`rtc_gpio_pulldown_en` functions before calling :cpp:func:`esp_deep_sleep_start`.
.. only:: esp32
In revisions 0 and 1 of ESP32, this wakeup source is incompatible with ULP and touch wakeup sources.
:cpp:func:`esp_sleep_enable_ext0_wakeup` function can be used to enable this wakeup source.
.. warning::
After waking up from sleep, the IO pad used for wakeup will be configured as RTC IO. Therefore, before using this pad as digital GPIO, users need to reconfigure it using :cpp:func:`rtc_gpio_deinit` function.
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP
.. _sleep-ext1-wakeup:
External Wakeup (``ext1``)
^^^^^^^^^^^^^^^^^^^^^^^^^^
The RTC controller contains the logic to trigger wakeup using multiple RTC GPIOs. One of the following two logic functions can be used to trigger ext1 wakeup:
.. only:: esp32
- wake up if any of the selected pins is high (``ESP_EXT1_WAKEUP_ANY_HIGH``)
- wake up if all the selected pins are low (``ESP_EXT1_WAKEUP_ALL_LOW``)
.. only:: not esp32
- wake up if any of the selected pins is high (``ESP_EXT1_WAKEUP_ANY_HIGH``)
- wake up if any of the selected pins is low (``ESP_EXT1_WAKEUP_ANY_LOW``)
This wakeup source is controlled by the RTC controller. It supports wakeup even when the RTC peripheral is powered down. Although the power domain of the RTC peripheral, where RTC IOs are located, is powered down during sleep modes, ESP-IDF will automatically lock the state of the wakeup pin before the system enters sleep modes and unlock upon exiting sleep modes. Therefore, the internal pull-up or pull-down resistors can still be configured for the wakeup pin::
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_en(gpio_num);
If we turn off the ``RTC_PERIPH`` domain, we will use the HOLD feature to maintain the pull-up and pull-down on the pins during sleep. HOLD feature will be acted on the pin internally before the system enters sleep modes, and this can further reduce power consumption::
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_en(gpio_num);
If certain chips lack the ``RTC_PERIPH`` domain, we can only use the HOLD feature to maintain the pull-up and pull-down on the pins during sleep modes::
gpio_pullup_dis(gpio_num);
gpio_pulldown_en(gpio_num);
:cpp:func:`esp_sleep_enable_ext1_wakeup_io` function can be used to append ext1 wakeup IO and set corresponding wakeup level.
:cpp:func:`esp_sleep_disable_ext1_wakeup_io` function can be used to remove ext1 wakeup IO.
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
The RTC controller also supports triggering wakeup, allowing configurable IO to use different wakeup levels simultaneously. This can be configured with :cpp:func:`esp_sleep_enable_ext1_wakeup_io`.
.. only:: not SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
.. note::
Due to hardware limitation, when we use more than one IO for EXT1 wakeup, it is not allowed to configure different wakeup levels for the IOs, and there is corresponding inspection mechanism in :cpp:func:`esp_sleep_enable_ext1_wakeup_io`.
.. warning::
- To use the EXT1 wakeup, the IO pad(s) are configured as RTC IO. Therefore, before using these pads as digital GPIOs, users need to reconfigure them by calling the :cpp:func:`rtc_gpio_deinit` function.
- If the RTC peripherals are configured to be powered down (which is by default), the wakeup IOs will be set to the holding state before entering sleep. Therefore, after the chip wakes up from Light-sleep, please call ``rtc_gpio_hold_dis`` to disable the hold function to perform any pin re-configuration. For Deep-sleep wakeup, this is already being handled at the application startup stage.
.. only:: SOC_ULP_SUPPORTED
ULP Coprocessor Wakeup
^^^^^^^^^^^^^^^^^^^^^^
ULP coprocessor can run while the chip is in sleep mode, and may be used to poll sensors, monitor ADC or GPIO states, and wake up the chip when a specific event is detected. ULP coprocessor is part of the RTC peripherals power domain, and it runs the program stored in RTC SLOW memory. RTC SLOW memory will be powered on during sleep if this wakeup mode is requested. RTC peripherals will be automatically powered on before ULP coprocessor starts running the program; once the program stops running, RTC peripherals are automatically powered down again.
.. only:: esp32
Revisions 0 and 1 of ESP32 only support this wakeup mode when RTC peripherals are not forced to be powered on (i.e., ESP_PD_DOMAIN_RTC_PERIPH should be set to ESP_PD_OPTION_AUTO).
:cpp:func:`esp_sleep_enable_ulp_wakeup` function can be used to enable this wakeup source.
.. only:: SOC_PM_SUPPORT_USB_WAKEUP
USB Wakeup (Light-sleep Only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{IDF_TARGET_NAME} can wake up from Light-sleep when activity is detected on the USB 2.0 High-Speed OTG bus. This wakeup source is intended for USB device applications that enter Light-sleep while the USB host has suspended the bus, and wake up when the host resumes the bus.
This wakeup source is available only on USB-OTG capable targets with High-Speed USB support. It is not supported by USB Serial/JTAG peripherals.
The power domain for the high-speed connectivity peripherals (``ESP_PD_DOMAIN_CNNT``) must remain powered on during sleep. Use :cpp:func:`esp_sleep_pd_config` to configure this::
esp_sleep_pd_config(ESP_PD_DOMAIN_CNNT, ESP_PD_OPTION_ON);
:cpp:func:`esp_sleep_enable_usb_wakeup` function can be used to enable this wakeup source.
.. only:: SOC_RTCIO_WAKE_SUPPORTED
GPIO Wakeup from Light-sleep
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. only:: SOC_PM_SUPPORT_EXT0_WAKEUP and SOC_PM_SUPPORT_EXT1_WAKEUP
In addition to EXT0 and EXT1 wakeup sources described above, one more method of wakeup from external inputs is available in Light-sleep mode. With this wakeup source, each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. Unlike EXT0 and EXT1 wakeup sources, which can only be used with RTC IOs, this wakeup source can be used with any IO (RTC or digital).
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP and not SOC_PM_SUPPORT_EXT0_WAKEUP
In addition to the EXT1 wakeup source described above, one more method of wakeup from external inputs is available in Light-sleep mode. With this wakeup source, each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. Unlike the EXT1 wakeup source, which can only be used with RTC IOs, this wakeup source can be used with any IO (RTC or digital).
.. only:: not (SOC_PM_SUPPORT_EXT0_WAKEUP or SOC_PM_SUPPORT_EXT1_WAKEUP)
One more method of wakeup from external inputs is available in Light-sleep mode. With this wakeup source, each pin can be individually configured to trigger wakeup on high or low level using :cpp:func:`gpio_wakeup_enable` function. This wakeup source can be used with any IO (RTC or digital).
:cpp:func:`esp_sleep_enable_gpio_wakeup` function can be used to enable this wakeup source.
.. warning::
Before entering Light-sleep mode, check if any GPIO pin to be driven is part of the {IDF_TARGET_SPI_POWER_DOMAIN} power domain. If so, this power domain must be configured to remain ON during sleep.
For example, on ESP32-WROOM-32 board, GPIO16 and GPIO17 are linked to {IDF_TARGET_SPI_POWER_DOMAIN} power domain. If they are configured to remain high during Light-sleep, the power domain should be configured to remain powered ON. This can be done with :cpp:func:`esp_sleep_pd_config()`::
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);
.. only:: SOC_PM_SUPPORT_TOP_PD
.. note::
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
In Light-sleep mode, if you set Kconfig option :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` to continue using :cpp:func:`gpio_wakeup_enable` for GPIO wakeup, you need to first call :cpp:func:`rtc_gpio_init` and :cpp:func:`rtc_gpio_set_direction`, setting the RTCIO to input mode.
Alternativelyyou can use :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` directly in that condition for GPIO wakeup, because the digital IO power domain is being powered off.
.. only:: not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
In Light-sleep mode, if you set Kconfig option :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` to continue using :cpp:func:`gpio_wakeup_enable` for GPIO wakeup, you need to first call :cpp:func:`rtc_gpio_init` and :cpp:func:`rtc_gpio_set_direction`, setting the RTCIO to input mode.
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
.. _deep_sleep_gpio_wakeup:
GPIO Wakeup from Deep-sleep
^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to the GPIO wakeup mechanism available in Light-sleep mode, {IDF_TARGET_NAME} also supports waking up from Deep-sleep using GPIOs.
This wakeup source is implemented by :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown`, which allows selecting one or more GPIOs and the wakeup level (high or low). Only GPIOs powered by the {IDF_TARGET_RTC_POWER_DOMAIN} power domain can be used as Deep-sleep GPIO wakeup sources. The exact set of supported pins can be checked in the `datasheet <{IDF_TARGET_DATASHEET_EN_URL}>`__ > Section IO Pins.
.. note::
This API also works for Light-sleep mode when the peripheral power domain is powered down (see :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`). In this case, it should be used instead of :cpp:func:`esp_sleep_enable_gpio_wakeup` because the GPIO module is powered down during sleep.
For a complete example of using GPIO to wake up from Deep-sleep, see :example:`system/deep_sleep`.
.. only:: not SOC_RTCIO_WAKE_SUPPORTED and not esp32h2
GPIO Wakeup
^^^^^^^^^^^
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
There are two GPIO wakeup APIs available, each designed for different sleep scenarios:
.. only:: not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
On {IDF_TARGET_NAME}, :cpp:func:`esp_sleep_enable_gpio_wakeup` together with :cpp:func:`gpio_wakeup_enable` can wake the chip from Light-sleep.
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP
To wake from Deep-sleep using RTC GPIOs, use EXT1 wakeup (:cpp:func:`esp_sleep_enable_ext1_wakeup_io`); see :ref:`sleep-ext1-wakeup`.
**1. :cpp:func:`esp_sleep_enable_gpio_wakeup` - For Light-sleep (GPIO module powered on)**
Any IO can be used as the external input to wake up the chip from Light-sleep when the GPIO module remains powered on. Each pin can be individually configured to trigger wakeup on high or low level using the :cpp:func:`gpio_wakeup_enable` function. Then the :cpp:func:`esp_sleep_enable_gpio_wakeup` function should be called to enable this wakeup source.
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
.. note::
This API is **not available** when :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` is enabled, because the GPIO module is powered down during sleep in this case. Use :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` instead.
.. only:: not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
.. note::
When :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` is enabled, to keep using :cpp:func:`gpio_wakeup_enable`, call :cpp:func:`rtc_gpio_init` and :cpp:func:`rtc_gpio_set_direction` so the pin is used as an RTC GPIO input.
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
**2. :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` - For Deep-sleep and Light-sleep (peripheral powerdown)**
IOs that are powered by the VDD3P3_RTC power domain can be used to wake up the chip from Deep-sleep or Light-sleep when the peripheral power domain is powered down. The wakeup pin and wakeup trigger level can be configured by calling :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown`. This function works for:
- Deep-sleep mode (always)
- Light-sleep mode when :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` is enabled
.. only:: SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED
On {IDF_TARGET_NAME} the API also accepts edge-triggered wakeup modes: ``ESP_GPIO_WAKEUP_GPIO_POSEDGE`` (rising edge), ``ESP_GPIO_WAKEUP_GPIO_NEGEDGE`` (falling edge), and ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE`` (both edges). For ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE``, the internal pull-up/pull-down is disabled (when :ref:`CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS` is enabled) because the idle level is ambiguous; an external pull or an already-stable line is recommended.
.. note::
Only GPIOs powered by the VDD3P3_RTC power domain (RTC IOs) can be used with this API. The exact set of supported pins can be checked in the `datasheet <{IDF_TARGET_DATASHEET_EN_URL}>`__ > Section IO Pins.
.. note::
Any GPIO/IO wakeup signal -- whether level or edge -- must be held (or have a pulse width) of at least 3 RTC slow-clock cycles to be reliably sampled by the wakeup logic. The duration of one slow-clock cycle depends on :ref:`CONFIG_RTC_CLK_SRC` (e.g. RC_SLOW @ ~136 kHz ~= 7.4 us/cycle, XTAL32K @ 32.768 kHz ~= 30.5 us/cycle). This applies to both :cpp:func:`esp_sleep_enable_gpio_wakeup` and :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown`.
.. only:: esp32h2
GPIO Wakeup
^^^^^^^^^^^
Any IO can be used as the external input to wake up the chip from Light-sleep. Each pin can be individually configured using :cpp:func:`gpio_wakeup_enable` (low/high level only). Then the :cpp:func:`esp_sleep_enable_gpio_wakeup` function should be called to enable this wakeup source.
.. _uart_wakeup_light_sleep:
UART Wakeup (Light-sleep Only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When {IDF_TARGET_NAME} receives UART input from external devices, it is often necessary to wake up the chip when input data is available. The UART peripheral supports multiple wakeup modes that can wake up the chip from Light-sleep. The wakeup mode and its parameters can be configured using :cpp:func:`uart_wakeup_setup` function.
The UART wakeup supports the following modes:
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
**Mode 0 (UART_WK_MODE_ACTIVE_THRESH) - Active Edge Threshold Wakeup**
When all clocks are powered down, the chip can be woken up by toggling the RXD pin for a certain number of cycles. The chip wakes up when the number of rising edges is greater than or equal to threshold value. The threshold value can be configured using the ``rx_edge_threshold`` field in :cpp:type:`uart_wakeup_cfg_t` structure.
.. only:: SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
**Mode 1 (UART_WK_MODE_FIFO_THRESH) - RX FIFO Threshold Wakeup**
Since the UART Core clock remains active, the UART RX can still receive data and store it in the RX FIFO. The chip can be woken up from Light-sleep when the number of bytes in the RX FIFO exceeds the configured threshold. The threshold value can be configured using the ``rx_fifo_threshold`` field in :cpp:type:`uart_wakeup_cfg_t` structure.
.. only:: SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
**Mode 2 (UART_WK_MODE_START_BIT) - Start Bit Detection Wakeup**
The chip wakes up when the UART RX detects a start bit.
.. only:: SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
**Mode 3 (UART_WK_MODE_CHAR_SEQ) - Character Sequence Detection Wakeup**
The chip wakes up when the UART RX receives a specific character sequence. The character sequence can be configured using the ``wake_chars_seq`` field in :cpp:type:`uart_wakeup_cfg_t` structure. The character sequence supports wildcard matching using '*' to represent any symbol.
:cpp:func:`esp_sleep_enable_uart_wakeup` function can be used to enable this wakeup source.
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
After waking-up from UART wakeup mode 0, you should send some extra data through the UART port or reset the UART module in Active mode, otherwise, the next UART wake-up would trigger with two less rising edges than the configured threshold value.
.. only:: SOC_PM_SUPPORT_TOP_PD
.. note::
In Light-sleep mode, setting Kconfig option :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` will invalidate UART wakeup.
.. only:: SOC_ULP_LP_UART_SUPPORTED
LP_UART can wake up the ULP LP core coprocessor. LP_UART supports the same wakeup modes as the HP UART described above, including active edge threshold wakeup, RX FIFO threshold wakeup, start bit detection wakeup, and character sequence detection wakeup.
To use LP_UART to wake up the ULP LP core, follow these steps:
#. Set the :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` flag in the ``wakeup_source`` field of the :cpp:type:`ulp_lp_core_cfg_t` structure.
#. Initialize the LP UART (call :cpp:func:`lp_core_uart_init`).
#. Configure the LP_UART wakeup mode using the :cpp:func:`lp_core_uart_wakeup_setup` function with a :cpp:type:`uart_wakeup_cfg_t` structure, using the same configuration method as HP UART.
.. only:: SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
.. note::
On chips with ``SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED``, the LP UART wakeup signal remains triggered after a wakeup event. The LP core startup flow (:cpp:func:`ulp_lp_core_update_wakeup_cause`) automatically calls :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` and :cpp:func:`lp_core_uart_clear_buf` to clear this state. If the standard startup flow is not used, you must handle this manually; otherwise, repeated wakeups will occur.
For example code on LP_UART wakeup, refer to :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup`.
.. _disable_sleep_wakeup_source:
Disable Sleep Wakeup Source
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Previously configured wakeup sources can be disabled later using :cpp:func:`esp_sleep_disable_wakeup_source` API. This function deactivates trigger for the given wakeup source. Additionally, it can disable all triggers if the argument is ``ESP_SLEEP_WAKEUP_ALL``.
.. _power_down_options:
Power-down Options
------------------
The application can force specific powerdown modes for RTC peripherals and RTC memories. In Deep-sleep mode, we can also isolate some IOs to further reduce current consumption.
Power-down of RTC Peripherals and Memories
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, :cpp:func:`esp_deep_sleep_start` and :cpp:func:`esp_light_sleep_start` functions power down all RTC power domains which are not needed by the enabled wakeup sources. To override this behaviour, :cpp:func:`esp_sleep_pd_config` function is provided.
.. only:: esp32
Note: in revision 0 of ESP32, RTC FAST memory is always kept enabled in Deep-sleep, so that the Deep-sleep stub can run after reset. This can be overridden, if the application does not need clean reset behaviour after Deep-sleep.
.. only:: SOC_RTC_SLOW_MEM_SUPPORTED
If some variables in the program are placed into RTC SLOW memory (for example, using ``RTC_DATA_ATTR`` attribute), RTC SLOW memory will be kept powered on by default. This can be overridden using :cpp:func:`esp_sleep_pd_config` function, if desired.
.. only:: not SOC_RTC_SLOW_MEM_SUPPORTED and SOC_RTC_FAST_MEM_SUPPORTED
In {IDF_TARGET_NAME}, there is only RTC FAST memory, so if some variables in the program are marked by ``RTC_DATA_ATTR``, ``RTC_SLOW_ATTR`` or ``RTC_FAST_ATTR`` attributes, all of them go to RTC FAST memory. It will be kept powered on by default. This can be overridden using :cpp:func:`esp_sleep_pd_config` function, if desired.
.. _spi_flash_power_down_dpd:
Flash Entering Deep Power-Down Mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For Light-sleep, ESP-IDF recommends lowering SPI Flash sleep current using **Deep Power-Down (DPD)** first: enable :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD` so the SPI Flash enters its deep power-down command mode while the supply rail remains on. Current draw is typically very low (often below 1 µA for many SPI Flash devices), without the wake-up delay of fully cycling the SPI Flash supply.
In almost all use cases, DPD offers better overall trade-offs than cutting SPI Flash supply power—both safer for execution and still very low power.
.. note::
**Mutually exclusive strategies:** Power-down SPI Flash during Light-sleep (:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` or ``esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF)``) **cannot be combined** with DPD. Kconfig exposes :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD` only when :ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` is disabled.
.. warning::
Before using this feature, check the datasheet of the SPI Flash device used on your chip to ensure it supports the Deep Power-Down mode.
.. _spi_flash_power_down:
Power-down of Flash
^^^^^^^^^^^^^^^^^^^^^^^^
By default, to avoid potential issues, :cpp:func:`esp_light_sleep_start` function does **not** power down SPI Flash. To be more specific, it takes time to power down the SPI Flash and during this period the system may be woken up, which then actually powers up the SPI Flash before this SPI Flash could be powered down completely. As a result, there is a chance that the SPI Flash may not work properly.
So, in theory, it is ok if you only wake up the system after the SPI Flash is completely powered down. However, in reality, the SPI Flash power-down period can be hard to predict (for example, this period can be much longer when you add filter capacitors to the SPI Flash's power supply circuit) and uncontrollable (for example, the asynchronous wake-up signals make the actual sleep time uncontrollable).
.. warning::
If a filter capacitor is added to your SPI Flash power supply circuit, please do everything possible to avoid powering down SPI Flash.
Therefore, it is recommended not to power down SPI Flash when using ESP-IDF. For power-sensitive applications, it is recommended to use Kconfig option :ref:`CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND` to reduce the power consumption of the SPI Flash during Light-sleep, instead of powering down the SPI Flash.
.. only:: SOC_SPIRAM_SUPPORTED
It is worth mentioning that PSRAM has a similar Kconfig option :ref:`CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND`.
However, for those who have fully understood the risk and are still willing to power down the SPI Flash to further reduce the power consumption, please check the following mechanisms:
.. list::
- Setting Kconfig option :ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` only powers down the SPI Flash when the RTC timer is the only wake-up source **and** the sleep time is longer than the SPI Flash power-down period.
- Calling ``esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF)`` powers down SPI Flash when the RTC timer is not enabled as a wakeup source **or** the sleep time is longer than the SPI Flash power-down period.
.. note::
.. list::
- ESP-IDF does not provide any mechanism that can power down the SPI Flash in all conditions when Light-sleep.
- :cpp:func:`esp_deep_sleep_start` function forces power down SPI Flash regardless of user configuration.
.. _spi_flash_sleep_strategy_recommendations:
Flash Sleep Strategy Recommendations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In sleep scenarios, the SPI Flash handling method directly affects system safety, and power consumption. Different application scenarios prioritize these factors differently, so it is important to choose an appropriate SPI Flash sleep strategy.
Keep Flash Powered On
"""""""""""""""""""""""""""""
The standby power consumption of different SPI Flash varies. In ESP series chips, the standby power consumption of SPI Flash is typically below 30 µA. In the following scenarios, it is recommended to keep the SPI Flash powered on:
1. The system has extremely high stability requirements and cannot accept any potential risks from SPI Flash power-off.
2. Sleep duration is short or unpredictable, for example, when asynchronous wake-up sources exist (GPIO, UART, etc.).
3. Large filter capacitors exist in the SPI Flash power supply circuit, making it difficult to estimate the actual SPI Flash power-down time.
In the above cases, keeping the SPI Flash powered on is the most conservative and safest choice, but note that its standby power consumption is relatively high (about 10-30 µA).
Flash Entering Deep Power-Down (DPD) Mode
"""""""""""""""""""""""""""""""""""""""""
When standby power is still too high, prefer **Deep Power-Down** via :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`; see :ref:`spi_flash_power_down_dpd` for figures, timings, and how to enable it.
DPD mode is suitable for the following scenarios:
1. Significant reduction in SPI Flash power consumption during sleep is needed, but the risk of SPI Flash re-powering should be avoided.
2. Sleep duration is short or unpredictable, for example, when asynchronous wake-up sources exist (GPIO, UART, etc.).
3. SPI Flash chip used explicitly supports Deep Power-Down mode.
.. only:: not SOC_PM_FLASH_KEEP_POWER_IN_LSLP
Power Down Flash
""""""""""""""""""""
You can refer to :ref:`spi_flash_power_down` to power down the SPI Flash during sleep. After the following conditions are met or after thorough evaluation, you may consider this strategy:
1. The application has strict requirements for extremely low power consumption.
2. Wake-up sources are controllable, typically only RTC timer wake-up sources are enabled.
3. It can be ensured that the actual sleep time is greater than the time required for the SPI Flash to completely power down. For ESP series chips, the time required for the SPI Flash to completely power down may be greater than 300ms. If parallel capacitors exist in the SPI Flash power supply circuit, longer sleep time may be required.
4. If the sleep time is too short, the power consumption during the SPI Flash power-on and power-down processes may exceed the power consumption when keeping it powered on.
5. There is sufficient control over SPI Flash power supply and IO states to avoid SPI Flash leakage due to pin pull-up during sleep.
Since the SPI Flash power-down process is greatly affected by hardware design, IO impedance characteristics, power supply, and environmental factors, ESP-IDF cannot guarantee that the SPI Flash will be safely powered down in Light-sleep mode. Therefore, this method is only suitable for scenarios with controllable risks and thorough verification.
Configuring IOs (Deep-sleep Only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some {IDF_TARGET_NAME} IOs have internal pullups or pulldowns, which are enabled by default. If an external circuit drives this pin in Deep-sleep mode, current consumption may increase due to current flowing through these pullups and pulldowns.
.. only:: SOC_RTCIO_HOLD_SUPPORTED and SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
To isolate a pin to prevent extra current draw, call :cpp:func:`rtc_gpio_isolate` function.
For example, on ESP32-WROVER module, GPIO12 is pulled up externally, and it also has an internal pulldown in the ESP32 chip. This means that in Deep-sleep, some current flows through these external and internal resistors, increasing Deep-sleep current above the minimal possible value.
Add the following code before :cpp:func:`esp_deep_sleep_start` to remove such extra current::
rtc_gpio_isolate(GPIO_NUM_12);
.. only:: esp32c2 or esp32c3
In Deep-sleep mode:
- digital GPIOs (GPIO6 ~ 21) are in a high impedance state.
- RTC GPIOs (GPIO0 ~ 5) can be in the following states, depending on their hold function enabled or not:
- if the hold function is not enabled, RTC GPIOs will be in a high impedance state.
- if the hold function is enabled, RTC GPIOs will retain the pin state latched at that hold moment.
.. _enter_sleep:
Entering Sleep
--------------
:cpp:func:`esp_light_sleep_start` or :cpp:func:`esp_deep_sleep_start` functions can be used to enter Light-sleep or Deep-sleep modes correspondingly. After that, the system configures the parameters of RTC controller according to the requested wakeup sources and power-down options.
It is also possible to enter sleep modes with no wakeup sources configured. In this case, the chip will be in sleep modes indefinitely until external reset is applied.
.. note::
The sleep process will disable the cache, so the task stack of the task requesting sleep must be located in internal memory (DRAM or RTC fast memory). If a task with its stack in PSRAM requests Light-sleep or Deep-sleep, it will be rejected and an error will be returned.
UART Output Handling
^^^^^^^^^^^^^^^^^^^^
Before entering sleep, the sleep flow prepares the **console UART** (the UART used for debug output, selected by :ref:`CONFIG_ESP_CONSOLE_UART_NUM`) so that APB clock changes or power-down do not cause garbled output or undefined behavior. The strategy applied is configurable and affects data integrity, sleep entry time, and power consumption.
**Default behavior (auto mode)**
If you do not call :cpp:func:`esp_sleep_set_console_uart_handling_mode`, the following default strategy is used:
- **Deep-sleep**: Always wait until all data in the console UART FIFO has been transmitted before entering sleep, so that all debug output is sent and no data is lost.
- **Light-sleep**: Behavior depends on whether the UART power domain is powered down:
- If the UART remains powered (e.g. HP peripheral domain not powered down): UART output is **suspended** after the current frame completes; after wakeup it is resumed and any remaining data in the UART TX FIFO before sleep continues to be sent.
- If the UART power domain is powered down: The sleep flow waits until all data in the console UART TX FIFO has been transmitted before entering sleep; data in other UARTs is discarded to enter sleep faster.
**Configuring console UART handling**
You can override the default by calling :cpp:func:`esp_sleep_set_console_uart_handling_mode` and choosing one of the following modes (see :cpp:enum:`esp_sleep_uart_handling_mode_t`):
- :cpp:enumerator:`ESP_SLEEP_AUTO_FLUSH_SUSPEND_UART` (default): Automatically choose flush or suspend based on sleep type and power domain, as described above.
- :cpp:enumerator:`ESP_SLEEP_ALWAYS_FLUSH_UART` : Always wait until all data in the console UART TX FIFO has been transmitted before entering sleep. Use when you must guarantee that all debug output is visible; sleep entry will take longer and the chip will stay in Active state longer, increasing power consumption.
- :cpp:enumerator:`ESP_SLEEP_ALWAYS_SUSPEND_UART` : Wait for the current UART frame to complete, then suspend the UART. If the UART stays powered during Light-sleep, transmission continues after wake. If the UART power domain is powered down, unsent data will be lost.
- :cpp:enumerator:`ESP_SLEEP_ALWAYS_DISCARD_UART` : Discard all unsent data in the console UART FIFO and enter sleep immediately. Use for the fastest sleep entry and lowest power when debug output can be discarded.
- :cpp:enumerator:`ESP_SLEEP_NO_HANDLING` : Do not perform any handling on the console UART before sleep. Use only when the UART state is known to be safe (e.g. no pending output or the console UART is disabled).
.. note::
The sleep flow runs in a critical section. When using a mode that flushes the console UART (e.g. :cpp:enumerator:`ESP_SLEEP_ALWAYS_FLUSH_UART` , or the default behavior for Light-sleep/Deep-sleep when the HP peripheral domain is powered down), set :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` to be **greater than** ``SOC_UART_FIFO_LEN`` × (time to send one character at the current baud rate). Otherwise, if too much data is queued in the TX FIFO, the flush may take longer than the interrupt watchdog timeout and trigger a watchdog reset during sleep entry.
Example: ensure all debug output is sent before every sleep::
.. code-block:: C
fflush(stdout);
esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_FLUSH_UART);
esp_light_sleep_start();
Example: minimize sleep entry time and allow discarding console output::
.. code-block:: C
esp_sleep_set_console_uart_handling_mode(ESP_SLEEP_ALWAYS_DISCARD_UART);
esp_deep_sleep_start();
.. _wakeup_cause:
Checking Sleep Wakeup Cause
---------------------------
:cpp:func:`esp_sleep_get_wakeup_cause` function can be used to check which wakeup source has triggered wakeup from sleep mode.
.. only:: SOC_TOUCH_SENSOR_SUPPORTED
For touchpad, it is possible to identify which touch pin has caused wakeup using :cpp:func:`esp_sleep_get_touchpad_wakeup_status` functions.
.. only:: SOC_PM_SUPPORT_EXT1_WAKEUP
For ext1 wakeup sources, it is possible to identify which GPIO has caused wakeup using :cpp:func:`esp_sleep_get_ext1_wakeup_status` functions.
Application Examples
--------------------
.. list::
- :example:`protocols/sntp` demonstrates the implementation of basic functionality of Deep-sleep, where ESP module is periodically waken up to retrieve time from NTP server.
:SOC_WIFI_SUPPORTED: - :example:`wifi/power_save` demonstrates the usage of Wi-Fi Modem-sleep mode and automatic Light-sleep feature to maintain Wi-Fi connections.
:SOC_BT_SUPPORTED: - :example:`bluetooth/nimble/power_save` demonstrates the usage of Bluetooth Modem-sleep mode and automatic Light-sleep feature to maintain Bluetooth connections.
:SOC_ULP_SUPPORTED: - :example:`system/deep_sleep` demonstrates the usage of various Deep-sleep wakeup triggers and ULP coprocessor programming.
:not SOC_ULP_SUPPORTED and not esp32c3 and not esp32h2 and SOC_PM_SUPPORT_EXT1_WAKEUP and SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP: - :example:`system/deep_sleep` demonstrates the usage of Deep-sleep wakeup triggered by various sources, such as the RTC timer, GPIOs, EXT1, supported by {IDF_TARGET_NAME}.
:not SOC_ULP_SUPPORTED and not esp32c3 and not esp32h2 and SOC_PM_SUPPORT_EXT1_WAKEUP and not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP: - :example:`system/deep_sleep` demonstrates the usage of Deep-sleep wakeup triggered by various sources, such as the RTC timer and EXT1, supported by {IDF_TARGET_NAME}.
:not SOC_ULP_SUPPORTED and not esp32c3 and not esp32h2 and not SOC_PM_SUPPORT_EXT1_WAKEUP: - :example:`system/deep_sleep` demonstrates the usage of Deep-sleep wakeup triggered by various sources, such as the RTC timer, GPIOs, supported by {IDF_TARGET_NAME}.
:esp32c3: - :example:`system/deep_sleep` demonstrates the usage of Deep-sleep wakeup triggered by various sources, such as the RTC timer, GPIOs, supported by ESP32-C3.
:esp32h2: - :example:`system/deep_sleep` demonstrates the usage of Deep-sleep wakeup triggered by various sources, such as the RTC timer and EXT1, supported by ESP32-H2.
- :example:`system/light_sleep` demonstrates the usage of Light-sleep wakeup triggered by various sources, such as the timer, GPIOs, supported by {IDF_TARGET_NAME}.
:SOC_PM_SUPPORT_USB_WAKEUP: - :example:`peripherals/usb/device/tusb_cdc_acm_wakeup` demonstrates the usage of USB 2.0 wakeup from Light-sleep.
:SOC_TOUCH_SENSOR_SUPPORTED and SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP: - :example:`peripherals/touch_sensor/touch_sens_sleep` demonstrates the usage of Light-sleep and Deep-sleep wakeup triggered by the touch sensor.
:SOC_VBAT_SUPPORTED: - :example:`lowpower/vbat` demonstrates the use of backup battery power (VBAT) during Deep-sleep, allowing the RTC timer to keep running after the main power is removed.
API Reference
-------------
.. include-build-file:: inc/esp_sleep.inc
+36
View File
@@ -0,0 +1,36 @@
SoC Capability Macros
=====================
:link_to_translation:`zh_CN:[中文]`
Different models of ESP chips integrate various hardware modules. Even the same type of module may have subtle differences across different chips. ESP-IDF provides a small "database" to describe the differences between chips (please note, only differences are described, not commonalities). The contents of this "database" are defined as macros in the **soc/soc_caps.h** file, referred to as **SoC capability macros**. Users can utilize these macros in their code with conditional compilation directives (such as ``#if``) to control which code is actually compiled.
.. note::
Please note that the contents of **soc/soc_caps.h** are currently unstable and may undergo significant changes in the future.
Using SoC Capability Macros
---------------------------
We recommend accessing SoC capability macros indirectly through the following macro functions:
.. list-table::
:widths: 30 60 80
:header-rows: 1
* - Macro Function
- Description
- Example
* - :c:macro:`SOC_IS`
- Determines the chip model
- ``#if SOC_IS(ESP32)`` checks if the chip is ESP32
* - :c:macro:`SOC_HAS`
- Checks if the chip has a specific hardware module or feature
- ``#if SOC_HAS(DAC)`` checks if the chip has a DAC module
API Reference
-------------
.. include-build-file:: inc/soc_caps.inc
.. include-build-file:: inc/soc_caps_eval.inc
@@ -0,0 +1,201 @@
System Time
===========
:link_to_translation:`zh_CN:[中文]`
Overview
--------
{IDF_TARGET_NAME} uses two hardware timers for the purpose of keeping system time. System time can be kept by using either one or both of the hardware timers depending on the application's purpose and accuracy requirements for system time. The two hardware timers are:
- **RTC timer**: This timer allows time keeping in various sleep modes, and can also persist time keeping across any resets (with the exception of power-on resets which reset the RTC timer). The frequency deviation depends on the `RTC Timer Clock Sources`_ and affects the accuracy only in sleep modes, in which case the time will be measured at 6.6667 μs resolution.
- **High-resolution timer**: This timer is not available in sleep modes and will not persist over a reset, but has greater accuracy. The timer uses the APB_CLK clock source (typically 80 MHz), which has a frequency deviation of less than ±10 ppm. Time will be measured at 1 μs resolution.
The possible combinations of hardware timers used to keep system time are listed below:
- RTC and high-resolution timer (default)
- RTC
- High-resolution timer
- None
It is recommended that users stick to the default option as it provides the highest accuracy. However, users can also select a different setting via the :ref:`CONFIG_LIBC_TIME_SYSCALL` configuration option.
.. _rtc-clock-source-choice:
RTC Timer Clock Sources
------------------------
The RTC timer has the following clock sources:
.. list::
- ``Internal 90150 kHz (depending on chip) RC oscillator`` (default): Features the lowest Deep-sleep current consumption and no dependence on any external components. However, the frequency stability of this clock source is affected by temperature fluctuations, so time may drift in both Deep-sleep and Light-sleep modes.
:not esp32c2: - ``External 32 kHz crystal``: Requires a 32 kHz crystal to be connected to the external crystal pins. This source provides a better frequency stability at the expense of a slightly higher (by 1 μA) Deep-sleep current consumption. Refer to the `datasheet <{IDF_TARGET_DATASHEET_EN_URL}>`__ for information on which pins to connect to.
- ``External 32 kHz oscillator``: Allows using a 32 kHz clock generated by an external circuit. The external clock signal must be connected to the external oscillator pin. The input amplitude must ensure that the digital circuit can correctly distinguish between logic high and low levels. Test results show that 1.7 V is the threshold between high and low levels. Therefore, make sure the input waveform has a peak value greater than 1.7 V and a minimum value lower than 1.7 V. For details on pin connections, please refer to the `datasheet <{IDF_TARGET_DATASHEET_EN_URL}>`__.
:esp32 or esp32s2 or esp32s3 or esp32c2 or esp32c3: - ``Internal 8.517.5 MHz oscillator (depending on chip), divided by 256``: Provides better frequency stability than the ``Internal 90150 kHz RC oscillator`` at the expense of a higher (by 5 μA) Deep-sleep current consumption. It also does not require external components.
The choice depends on your requirements for system time accuracy and power consumption in sleep modes. To modify the RTC clock source, set :ref:`CONFIG_RTC_CLK_SRC` in project configuration.
More details about the wiring requirements for the external crystal or external oscillator, please refer to the `Hardware Design Guidelines <https://docs.espressif.com/projects/esp-hardware-design-guidelines/en/latest/{IDF_TARGET_PATH_NAME}>`_.
Selecting RTC Timer Clock Source
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the default **internal RC oscillator** when:
- Minimizing sleep current consumption is critical for battery-powered or energy-constrained devices.
- High time accuracy during sleep modes is not required. Time drifting in the range of several seconds per day is acceptable.
- Minimizing external components and hardware complexity is a priority.
- The operating temperature is relatively stable (reducing frequency variation).
- Bluetooth LE with power saving is not used, or only used for legacy advertising/scanning without connections.
Use an **external 32 kHz crystal** or **external 32 kHz oscillator** when:
- Accurate time-keeping during Deep-sleep and Light-sleep modes is required.
- A small increase in sleep current (typically a few μA) fits within the power budget.
- Adding external components is acceptable for the design.
- Operating temperature may vary significantly.
- Bluetooth LE with power saving is enabled and connections are required.
Some chips may provide the **internal oscillator** option, which is a trade-off between the internal RC oscillator and external 32 kHz crystal/oscillator options. It does not require external components while providing better frequency stability than the internal RC oscillator but at the cost of higher sleep current consumption. If Bluetooth LE is used please verify the internal oscillator meets Bluetooth LE sleep clock accuracy requirements (see below).
In most designs, the additional sleep current is a reasonable trade-off for significantly improved RTC Timer frequency stability and reduced time drift during sleep.
**Bluetooth LE** requires sleep clock accuracy within 500 PPM. The RTC clock source may not meet this requirement, leading to connection establishment failures, unexpected timeouts, or incompatibility with non-Espressif peer devices.
.. only:: SOC_BLE_SUPPORTED
For a detailed comparison of Bluetooth LE clock configurations and power consumption, refer to :doc:`Low Power Mode in Bluetooth LE </api-guides/low-power-mode/low-power-mode-ble>`.
Get Current Time
----------------
To get the current time, use the POSIX function ``gettimeofday()``. Additionally, you can use the following standard C library functions to obtain time and manipulate it:
.. code-block:: bash
gettimeofday
time
asctime
clock
ctime
difftime
gmtime
localtime
mktime
strftime
adjtime*
To stop smooth time adjustment and update the current time immediately, use the POSIX function ``settimeofday()``.
If you need to obtain time with one second resolution, use the following code snippet:
.. code-block:: c
time_t now;
char strftime_buf[64];
struct tm timeinfo;
time(&now);
// Set timezone to China Standard Time
setenv("TZ", "CST-8", 1);
tzset();
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
ESP_LOGI(TAG, "The current date/time in Shanghai is: %s", strftime_buf);
If you need to obtain time with one microsecond resolution, use the code snippet below:
.. code-block:: c
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
int64_t time_us = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
.. _system-time-sntp-sync:
SNTP Time Synchronization
-------------------------
To set the current time, you can use the POSIX functions ``settimeofday()`` and ``adjtime()``. They are used internally in the lwIP SNTP library to set current time when a response from the NTP server is received. These functions can also be used separately from the lwIP SNTP library.
Some lwIP APIs, including SNTP functions, are not thread safe, so it is recommended to use :doc:`esp_netif component <../network/esp_netif>` when interacting with SNTP module.
To initialize a particular SNTP server and also start the SNTP service, simply create a default SNTP server configuration with a particular server name, then call :cpp:func:`esp_netif_sntp_init()` to register that server and start the SNTP service.
.. code-block:: c
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
This code automatically performs time synchronization once a reply from the SNTP server is received. Sometimes it is useful to wait until the time gets synchronized, :cpp:func:`esp_netif_sntp_sync_wait()` can be used for this purpose. Applications can also subscribe to an event posted when time is synchronized (``NETIF_SNTP_EVENT``, ID ``NETIF_SNTP_TIME_SYNC``). The event data is a pointer to :cpp:type:`esp_netif_sntp_time_sync_t` containing the synchronized ``timeval``:
.. code-block:: c
if (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(10000)) != ESP_OK) {
printf("Failed to update system time within 10s timeout");
}
To configure multiple NTP servers (or use more advanced settings, such as DHCP provided NTP servers), please refer to the detailed description of :ref:`esp_netif-sntp-api` in :doc:`esp_netif <../network/esp_netif>` documentation.
The lwIP SNTP library could work in one of the following sync modes:
- :cpp:enumerator:`SNTP_SYNC_MODE_IMMED` (default): Updates system time immediately upon receiving a response from the SNTP server after using ``settimeofday()``.
- :cpp:enumerator:`SNTP_SYNC_MODE_SMOOTH`: Updates time smoothly by gradually reducing time error using the function ``adjtime()``. If the difference between the SNTP response time and system time is more than 35 minutes, update system time immediately by using ``settimeofday()``.
If you want to choose the :cpp:enumerator:`SNTP_SYNC_MODE_SMOOTH` mode, please set the :cpp:member:`esp_sntp_config::smooth` to ``true`` in the SNTP configuration struct. Otherwise (and by default) the :cpp:enumerator:`SNTP_SYNC_MODE_IMMED` mode will be used.
For setting a callback function that is called when time gets synchronized, use the :cpp:member:`esp_sntp_config::sync_cb` field in the configuration struct.
An application with this initialization code periodically synchronizes the time. The time synchronization period is determined by :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` (the default value is one hour). To modify the variable, set :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` in project configuration.
A code example that demonstrates the implementation of time synchronization based on the lwIP SNTP library is provided in the :example:`protocols/sntp` directory.
Note that it is also possible to use lwIP API directly, but care must be taken to thread safety. Here we list the thread-safe APIs:
- :cpp:func:`sntp_set_time_sync_notification_cb` can be used to set a callback function that notifies of the time synchronization process.
- :cpp:func:`sntp_get_sync_status` and :cpp:func:`sntp_set_sync_status` can be used to get/set time synchronization status.
- :cpp:func:`sntp_set_sync_mode` can be used to set the synchronization mode.
- :cpp:func:`esp_sntp_setoperatingmode` sets the preferred operating mode.:cpp:enumerator:`ESP_SNTP_OPMODE_POLL` and :cpp:func:`esp_sntp_init` initializes SNTP module.
- :cpp:func:`esp_sntp_setservername` configures one SNTP server.
Timezones
---------
To set the local timezone, use the following POSIX functions:
1. Call ``setenv()`` to set the ``TZ`` environment variable to the correct value based on the device location. The format of the time string is the same as described in the `GNU libc documentation <https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html>`_ (although the implementation is different).
2. Call ``tzset()`` to update C library runtime data for the new timezone.
Once these steps are completed, call the standard C library function ``localtime()``, and it returns the correct local time taking into account the timezone offset and daylight saving time.
Year 2036 and 2038 Overflow Issues
----------------------------------
SNTP/NTP 2036 Overflow
^^^^^^^^^^^^^^^^^^^^^^
SNTP/NTP timestamps are represented as 64-bit unsigned fixed point numbers, where the first 32 bits represent the integer part, and the last 32 bits represent the fractional part. The 64-bit unsigned fixed point number represents the number of seconds since 00:00 on 1st of January 1900, thus SNTP/NTP times will overflow in the year 2036.
To address this issue, lifetime of the SNTP/NTP timestamps has been extended by convention by using the MSB (bit 0 by convention) of the integer part to indicate time ranges between years 1968 to 2104 (see `RFC2030 <https://www.rfc-editor.org/rfc/rfc2030>`_ for more details). This convention is implemented in lwIP library SNTP module. Therefore SNTP-related functions in ESP-IDF are future-proof until year 2104.
Unix Time 2038 Overflow
^^^^^^^^^^^^^^^^^^^^^^^
Unix time (type ``time_t``) was previously represented as a 32-bit signed integer, leading to an overflow in year 2038 (i.e., `Y2K38 issue <https://en.wikipedia.org/wiki/Year_2038_problem>`_). To address the Y2K38 issue, ESP-IDF uses a 64-bit signed integer to represent ``time_t`` starting from release v5.0, thus deferring ``time_t`` overflow for another 292 billion years.
API Reference
-------------
.. include-build-file:: inc/esp_sntp.inc
+213
View File
@@ -0,0 +1,213 @@
ULP FSM Coprocessor Programming
===============================
:link_to_translation:`zh_CN:[中文]`
The Ultra Low Power (ULP) coprocessor is a simple finite state machine (FSM) which is designed to perform measurements using the ADC, temperature sensor, and external I2C sensors, while the main processors are in Deep-sleep mode. The ULP coprocessor can access the ``RTC_SLOW_MEM`` memory region, and registers in the ``RTC_CNTL``, ``RTC_IO``, and ``SARADC`` peripherals. The ULP coprocessor uses fixed-width 32-bit instructions, 32-bit memory addressing, and has 4 general-purpose 16-bit registers. This coprocessor is referred to as ``ULP FSM`` in ESP-IDF.
.. only:: esp32s2 or esp32s3
{IDF_TARGET_NAME} provides a second type of ULP coprocessor which is based on a RISC-V instruction set architecture. For details regarding ``ULP RISC-V``, please refer to :doc:`ULP-RISC-V Coprocessor <../../../api-reference/system/ulp-risc-v>`.
Installing the Toolchain
------------------------
The ULP FSM coprocessor code is written in assembly and compiled using the `binutils-esp32ulp toolchain`_.
If you have already set up ESP-IDF with CMake build system according to the :doc:`Getting Started Guide <../../../get-started/index>`, then the ULP FSM toolchain will already be installed.
Programming ULP FSM
-------------------
The ULP FSM can be programmed using the supported instruction set. Alternatively, the ULP FSM coprocessor can also be programmed using C Macros on the main CPU. These two methods are described in the following section:
.. toctree::
:maxdepth: 1
Instruction set reference for {IDF_TARGET_NAME} ULP <ulp_instruction_set>
Programming using macros (legacy) <ulp_macros>
Compiling the ULP Code
-----------------------
To compile the ULP FSM code as part of the component, the following steps must be taken:
1. The ULP FSM code, written in assembly, must be added to one or more files with ``.S`` extension. These files must be placed into a separate directory inside the component directory, for instance, ``ulp/``.
.. note::
When registering the component (via ``idf_component_register``), this directory should not be added to the ``SRC_DIRS`` argument. The logic behind this is that the ESP-IDF build system will compile files found in ``SRC_DIRS`` based on their extensions. For ``.S`` files, ``{IDF_TARGET_TOOLCHAIN_PREFIX}-as`` assembler is used. This is not desirable for ULP FSM assembly files, so the easiest way to achieve the distinction is by placing ULP FSM assembly files into a separate directory. The ULP FSM assembly source files should also **not** be added to ``SRCS`` for the same reason. See the steps below for how to properly add ULP FSM assembly source files.
2. Call ``ulp_embed_binary`` from the component CMakeLists.txt after registration. For example::
...
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_s_sources ulp/ulp_assembly_source_file.S)
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}" TYPE fsm)
The first argument to ``ulp_embed_binary`` specifies the ULP FSM binary name. The name specified here will also be used by other generated artifacts such as the ELF file, map file, header file and linker export file. The second argument specifies the ULP FSM assembly source files. The third argument specifies the list of component source files which include the header file to be generated. This list is needed to build the dependencies correctly and ensure that the generated header file will be created before any of these files are compiled. Finally, the fourth argument ``TYPE`` is optional, but it must be provided as ``TYPE fsm`` to compile using FSM toolchain, if both ``CONFIG_ULP_COPROC_TYPE_FSM`` and ``CONFIG_ULP_COPROC_TYPE_RISCV`` are selected in menu option ``ULP Coprocessor types``. See the section below for the concept of generated header files for ULP applications.
Variables in the ULP code will be prefixed with ``ulp_`` (default value) in this generated header file.
If you need to embed multiple ULP programs, you may add a custom prefix in order to avoid conflicting variable names like this:
.. code-block:: cmake
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_sources "ulp/ulp_c_source_file.c" "ulp/ulp_assembly_source_file.S")
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}" PREFIX "ULP::")
The additional PREFIX argument can be a C style prefix (like ``ulp2_``) or a C++ style prefix (like ``ULP::``).
3. Build the application as usual (e.g., ``idf.py app``).
Inside, the build system takes the following steps to build an ULP FSM program:
1. **Run each assembly file (foo.S) through the C preprocessor.** This step generates the preprocessed assembly files (foo.ulp.S) in the component build directory. This step also generates dependency files (foo.ulp.d).
2. **Run preprocessed assembly sources through the assembler.** This produces object (foo.ulp.o) and listing (foo.ulp.lst) files. Listing files are generated for debugging purposes and are not used at later stages of the build process.
3. **Run the linker script template through the C preprocessor.** The template is located in ``components/ulp/ld`` directory.
4. **Link the object files into an output ELF file** (``ulp_app_name.elf``). The Map file (``ulp_app_name.map``) generated at this stage may be useful for debugging purposes.
5. **Dump the contents of the ELF file into a binary** (``ulp_app_name.bin``) which can then be embedded into the application.
6. **Generate a list of global symbols** (``ulp_app_name.sym``) in the ELF file using ``esp32ulp-elf-nm``.
7. **Create an LD export script and a header file** (``ulp_app_name.ld`` and ``ulp_app_name.h``) containing the symbols from ``ulp_app_name.sym``. This is done using the ``esp32ulp_mapgen.py`` utility.
8. **Add the generated binary to the list of binary files** to be embedded into the application.
Accessing the ULP FSM Program Variables
---------------------------------------
Global symbols defined in the ULP FSM program may be used inside the main program.
For example, the ULP FSM program may define a variable ``measurement_count`` which will define the number of ADC measurements the program needs to make before waking up the chip from Deep-sleep::
.global measurement_count
measurement_count: .long 0
// later, use measurement_count
move r3, measurement_count
ld r3, r3, 0
The main program needs to initialize this variable before the ULP program is started. The build system makes this possible by generating the ``${ULP_APP_NAME}.h`` and ``${ULP_APP_NAME}.ld`` files which define the global symbols present in the ULP program. Each global symbol defined in the ULP program is included in these files and are prefixed with ``ulp_``.
The header file contains the declaration of the symbol::
extern uint32_t ulp_measurement_count;
Note that all symbols (variables, arrays, functions) are declared as ``uint32_t``. For functions and arrays, take the address of the symbol and cast it to the appropriate type.
The generated linker script file defines the locations of symbols in RTC_SLOW_MEM::
PROVIDE ( ulp_measurement_count = 0x50000060 );
To access the ULP program variables from the main program, the generated header file should be included using an ``include`` statement. This will allow the ULP program variables to be accessed as regular variables::
#include "ulp_app_name.h"
// later
void init_ulp_vars() {
ulp_measurement_count = 64;
}
.. only:: esp32
Note that the ULP FSM program can only use the lower 16 bits of each 32-bit word in RTC memory, because the registers are 16-bit, and there is no instruction to load from the high part of the word. Likewise, the ULP store instruction writes register values into the lower 16 bits of the 32-bit word in RTC memory. The upper 16 bits are written with a value which depends on the address of the store instruction, thus when reading variables written by the ULP coprocessor, the main application needs to mask the upper 16 bits, for example:
::
printf("Last measurement value: %d\n", ulp_last_measurement & UINT16_MAX);
Starting the ULP FSM Program
----------------------------
To run a ULP FSM program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_load_binary` function, and then start it using the :cpp:func:`ulp_run` function.
Note that the ``Enable Ultra Low Power (ULP) Coprocessor`` option must be enabled in menuconfig to work with ULP. To select the FSM type for ULP, please go to menu option ``ULP Coprocessor types`` and select ``CONFIG_ULP_COPROC_TYPE_FSM``. To reserve memory for the ULP, the ``RTC slow memory reserved for coprocessor`` option must be set to a value big enough to store ULP code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
Each ULP program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (suppose ULP_APP_NAME was defined to ``ulp_app_name``)::
extern const uint8_t bin_start[] asm("_binary_ulp_app_name_bin_start");
extern const uint8_t bin_end[] asm("_binary_ulp_app_name_bin_end");
void start_ulp_program() {
ESP_ERROR_CHECK( ulp_load_binary(
0 // load address, set to 0 when using default linker scripts
bin_start,
(bin_end - bin_start) / sizeof(uint32_t)) );
}
Once the program is loaded into RTC memory, the application can start it by passing the address of the entry point to the ``ulp_run`` function::
ESP_ERROR_CHECK( ulp_run(&ulp_entry - RTC_SLOW_MEM) );
Declaration of the entry point symbol comes from the generated header file mentioned above, ``${ULP_APP_NAME}.h``. In the assembly source of the ULP FSM application, this symbol must be marked as ``.global``::
.global entry
entry:
// code starts here
.. only:: esp32
ESP32 ULP Program Flow
-----------------------
ESP32 ULP coprocessor is started by a timer. The timer is started once :cpp:func:`ulp_run` is called. The timer counts the number of RTC_SLOW_CLK ticks (by default, produced by an internal 150 kHz RC oscillator). The number of ticks is set using ``SENS_ULP_CP_SLEEP_CYCx_REG`` registers (x = 0..4). When starting the ULP for the first time, ``SENS_ULP_CP_SLEEP_CYC0_REG`` will be used to set the number of timer ticks. Later the ULP program can select another ``SENS_ULP_CP_SLEEP_CYCx_REG`` register using ``sleep`` instruction.
The application can set ULP timer period values (SENS_ULP_CP_SLEEP_CYCx_REG, x = 0..4) using ``ulp_set_wakeup_period`` function.
Once the timer counts the number of ticks set in the selected ``SENS_ULP_CP_SLEEP_CYCx_REG`` register, ULP coprocessor powers up and starts running the program from the entry point set in the call to :cpp:func:`ulp_run`.
The program runs until it encounters a ``halt`` instruction or an illegal instruction. Once the program halts the ULP coprocessor powers down and the timer is started again.
To disable the timer (effectively preventing the ULP program from running again), clear the ``RTC_CNTL_ULP_CP_SLP_TIMER_EN`` bit in the ``RTC_CNTL_STATE0_REG`` register. This can be done both from ULP code and from the main program.
.. only:: esp32s2 or esp32s3
{IDF_TARGET_NAME} ULP Program Flow
----------------------------------
{IDF_TARGET_NAME} ULP coprocessor is started by a timer. The timer is started once :cpp:func:`ulp_run` is called. The timer counts a number of RTC_SLOW_CLK ticks (by default, produced by an internal 90 kHz RC oscillator). The number of ticks is set using ``RTC_CNTL_ULP_CP_TIMER_1_REG`` register.
The application can set ULP timer period values by :cpp:func:`ulp_set_wakeup_period` function.
Once the timer counts the number of ticks set in the selected ``RTC_CNTL_ULP_CP_TIMER_1_REG`` register, ULP coprocessor powers up and starts running the program from the entry point set in the call to :cpp:func:`ulp_run`.
The program runs until it encounters a ``halt`` instruction or an illegal instruction. Once the program halts, ULP coprocessor powers down, and the timer is started again.
To disable the timer (effectively preventing the ULP program from running again), clear the ``RTC_CNTL_ULP_CP_SLP_TIMER_EN`` bit in the ``RTC_CNTL_ULP_CP_TIMER_REG`` register. This can be done both from ULP code and from the main program.
Application Examples
--------------------
* :example:`system/ulp/ulp_fsm/ulp` demonstrates how to program the ULP FSM coprocessor to count pulses on an IO while the main CPUs are running other code or are in deep sleep, with the pulse count saved into NVS upon wakeup.
.. only:: esp32 or esp32s3
* :example:`system/ulp/ulp_fsm/ulp_adc` demonstrates how to use the ULP FSM coprocessor to periodically measure input voltage on a specific ADC channel during deep sleep, compare it to the set threshold, and wake up the system if the voltage is outside the threshold.
.. only:: esp32s2 or esp32s3
* :example:`system/ulp/ulp_fsm_riscv_combined/counter` demonstrates how to use both the ULP FSM and ULP RISC-V coprocessors sequentially within the same application, counting from 0 to 100 with the FSM and from 100 to 500 with the RISC-V coprocessor while the HP core remains in sleep mode until the counting completes.
API Reference
-------------
.. include-build-file:: inc/ulp_fsm_common.inc
.. include-build-file:: inc/ulp_common.inc
.. _binutils-esp32ulp toolchain: https://github.com/espressif/binutils-gdb
@@ -0,0 +1,475 @@
ULP LP Core Coprocessor Programming
===================================
:link_to_translation:`zh_CN:[中文]`
The ULP LP core (Low-power core) coprocessor is a variant of the ULP present in {IDF_TARGET_NAME}. It features ultra-low power consumption while also being able to stay powered on while the main CPU stays in low-power modes. This enables the LP core coprocessor to handle tasks like GPIO or sensor readings while the main CPU is in sleep mode, resulting in significant overall power savings for the entire system.
The ULP LP core coprocessor has the following features:
* An RV32I (32-bit RISC-V ISA) processor, with the multiplication/division (M), atomic (A), and compressed (C) extensions.
* Interrupt controller.
* Includes a debug module that supports external debugging via JTAG.
* Can access all of the High-power (HP) SRAM and peripherals when the entire system is active.
* Can access the Low-power (LP) SRAM and peripherals when the HP system is in sleep mode.
.. only:: SOC_LP_CORE_HAS_PMP
On supported targets, the LP core includes RISC-V Physical Memory Protection (PMP). Enable :ref:`CONFIG_ULP_LP_CORE_MEMPROT` to apply a deny-by-default layout at LP-core startup: LP RAM is split into an executable region (code and read-only data) and a read-write region (writable data, stack, and shared memory), LP peripheral address space is read-write, and an optional region covers HP UART MMIO when using :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. It cannot be used together with :ref:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM`. Addresses that do not fall into an allowed region cause a load, store, or instruction access fault.
Compiling Code for the ULP LP Core
----------------------------------
The ULP LP core code is compiled together with your ESP-IDF project as a separate binary and automatically embedded into the main project binary. There are two ways to achieve this:
Using ``ulp_embed_binary``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Place the ULP LP core code, written in C or assembly (with the ``.S`` extension), in a dedicated directory within the component directory, such as ``ulp/``.
2. After registering the component in the ``CMakeLists.txt`` file, call the ``ulp_embed_binary`` function. Here is an example:
.. code-block:: cmake
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_sources "ulp/ulp_c_source_file.c" "ulp/ulp_assembly_source_file.S")
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}")
The first argument to ``ulp_embed_binary`` specifies the ULP binary name. The name specified here is also used by other generated artifacts such as the ELF file, map file, header file, and linker export file. The second argument specifies the ULP source files. Finally, the third argument specifies the list of component source files which include the header file to be generated. This list is needed to build the dependencies correctly and ensure that the generated header file is created before any of these files are compiled. See the section below for the concept of generated header files for ULP applications.
Variables in the ULP code will be prefixed with ``ulp_`` (default value) in this generated header file.
If you need to embed multiple ULP programs, you may add a custom prefix in order to avoid conflicting variable names like this:
.. code-block:: cmake
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_sources "ulp/ulp_c_source_file.c" "ulp/ulp_assembly_source_file.S")
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}" PREFIX "ULP::")
The additional PREFIX argument can be a C style prefix (like ``ulp2_``) or a C++ style prefix (like ``ULP::``).
Using a Custom CMake Project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is also possible to create a custom CMake project for the LP core. This gives more control over the build process and allows you to set compile options, link external libraries and all other things that are possible with a regular CMake project.
To do this, add the ULP project as an external project in your component ``CMakeLists.txt`` file:
.. code-block:: cmake
ulp_add_project("ULP_APP_NAME" "${CMAKE_SOURCE_DIR}/PATH_TO_DIR_WITH_ULP_PROJECT_FILE/")
Create a folder which contains your ULP project files and a ``CMakeLists.txt`` file, located at the path given to ``ulp_add_project``. The ``CMakeLists.txt`` file should look like this:
.. code-block:: cmake
cmake_minimum_required(VERSION 3.22)
# Project/target name is passed from the main project to allow IDF to have a dependency on this target
# as well as embed the binary into the main app
project(${ULP_APP_NAME})
add_executable(${ULP_APP_NAME} main.c)
# Import the ULP project helper functions
include(IDFULPProject)
# Apply default compile options
ulp_apply_default_options(${ULP_APP_NAME})
# Apply default sources provided by the IDF ULP component
ulp_apply_default_sources(${ULP_APP_NAME})
# Add targets for building the binary, as well as the linkerscript which exports ULP shared variables to the main app
ulp_add_build_binary_targets(${ULP_APP_NAME})
# Everything below this line is optional and can be used to customize the build process
# Create a custom library
set(lib_path "${CMAKE_CURRENT_LIST_DIR}/lib")
add_library(custom_lib STATIC "${lib_path}/lib_src.c")
target_include_directories(custom_lib PUBLIC "${lib_path}/")
# Link the library
target_link_libraries(${ULP_APP_NAME} PRIVATE custom_lib)
# Set custom compile flags
target_compile_options(${ULP_APP_NAME} PRIVATE -msave-restore)
Building Your Project
~~~~~~~~~~~~~~~~~~~~~~
To compile and build your project:
1. Enable :ref:`CONFIG_ULP_COPROC_ENABLED` in menuconfig, and inside ``ULP Coprocessor types`` menu, select :ref:`CONFIG_ULP_COPROC_TYPE_LP_CORE`. The :ref:`CONFIG_ULP_COPROC_RESERVE_MEM` option reserves RTC memory for the ULP, and must be set to a value big enough to store both the ULP LP core code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
2. Build the application as usual (e.g., ``idf.py app``).
During the build process, the following steps are taken to build ULP program:
1. **Run each source file through the C compiler and assembler.** This step generates the object files ``.obj.c`` or ``.obj.S`` in the component build directory depending on the source file processed.
2. **Run the linker script template through the C preprocessor.** The template is located in ``components/ulp/ld`` directory.
3. **Link the object files into an output ELF file** (``ulp_app_name.elf``). The Map file ``ulp_app_name.map`` generated at this stage may be useful for debugging purposes.
4. **Dump the contents of the ELF file into a binary** (``ulp_app_name.bin``) which can then be embedded into the application.
5. **Generate a list of global symbols** (``ulp_app_name.sym``) in the ELF file using ``riscv32-esp-elf-nm``.
6. **Create an LD export script and a header file** ``ulp_app_name.ld`` and ``ulp_app_name.h`` containing the symbols from ``ulp_app_name.sym``. This is done using the ``esp32ulp_mapgen.py`` utility.
7. **Add the generated binary to the list of binary files** to be embedded into the application.
.. _ulp-lp-core-access-variables:
Accessing the ULP LP Core Program Variables
-------------------------------------------
Global symbols defined in the ULP LP core program may be used inside the main program.
For example, the ULP LP core program may define a variable ``measurement_count`` which defines the number of GPIO measurements the program needs to make before waking up the chip from Deep-sleep.
.. code-block:: c
volatile int measurement_count;
int some_function()
{
//read the measurement count for later use.
int temp = measurement_count;
...do something.
}
The main program can access the global ULP LP core program variables as the build system makes this possible by generating the ``${ULP_APP_NAME}.h`` and ``${ULP_APP_NAME}.ld`` files which define the global symbols present in the ULP LP core program. Each global symbol defined in the ULP LP core program is included in these files and are prefixed with ``ulp_``.
The header file contains the declaration of the symbol:
.. code-block:: c
extern uint32_t ulp_measurement_count;
Note that all symbols (variables, functions) are declared as ``uint32_t``. Arrays are declared as ``uint32_t [SIZE]``. For functions, take the address of the symbol and cast it to the appropriate type.
To access the ULP LP core program variables from the main program, the generated header file should be included using an ``include`` statement. This allows the ULP LP core program variables to be accessed as regular variables.
.. code-block:: c
#include "ulp_app_name.h"
void init_ulp_vars() {
ulp_measurement_count = 64;
}
.. note::
- Variables declared in the global scope of the LP core program reside in either the ``.bss`` or ``.data`` section of the binary. These sections are initialized when the LP core binary is loaded and executed. Accessing these variables from the main program on the HP-Core before the first LP core run may result in undefined behavior.
- The ``ulp_`` prefix is the default value. You can specify the prefix to use with ``ulp_embed_binary`` to avoid name collisions for multiple ULP programs.
Starting the ULP LP Core Program
--------------------------------
To run a ULP LP core program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_lp_core_load_binary` function, and then start it using the :cpp:func:`ulp_lp_core_run` function.
Each ULP LP core program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (supposed ULP_APP_NAME was defined to ``ulp_app_name``):
.. code-block:: c
extern const uint8_t bin_start[] asm("_binary_ulp_app_name_bin_start");
extern const uint8_t bin_end[] asm("_binary_ulp_app_name_bin_end");
void start_ulp_program() {
ESP_ERROR_CHECK( ulp_lp_core_load_binary( bin_start,
(bin_end - bin_start)) );
}
Once the program is loaded into LP memory, the application can be configured and started by calling :cpp:func:`ulp_lp_core_run`:
.. code-block:: c
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER, // LP core will be woken up periodically by LP timer
.lp_timer_sleep_duration_us = 10000,
};
ESP_ERROR_CHECK( ulp_lp_core_run(&cfg) );
Running the LP Core from HP Memory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:ref:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM` allows placing most of the LP core application in reserved HP SRAM instead of LP RAM. This can be useful when the application is too large to fit in LP RAM, while still keeping the LP reset and handler code in LP memory.
When this option is enabled, :ref:`CONFIG_ULP_COPROC_RESERVE_HP_MEM_BYTES` reserves a window at the top of HP SRAM for the LP core binary. During :cpp:func:`ulp_lp_core_load_binary`, LP-memory segments are still loaded into the reserved LP region, while data and code segments mapped to the HP-memory window are copied into the reserved HP SRAM region.
This mode has an important limitation: the LP core cannot keep running while the chip is in Deep-sleep, because HP SRAM is powered down in that sleep mode. Use this mode for cases where the LP core only needs to run while the HP system remains powered, and keep the default LP-memory-only mode for Deep-sleep use cases.
:ref:`CONFIG_ULP_LP_CORE_MEMPROT` cannot be enabled together with this HP-memory mode.
ULP LP Core Program Flow
------------------------
How the ULP LP core coprocessor is started depends on the wake-up source selected in :cpp:type:`ulp_lp_core_cfg_t`. The most common use-case is for the ULP to periodically wake up, do some measurements before either waking up the main CPU or going back to sleep again.
The ULP has the following wake-up sources:
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU` - LP core can be woken up by the HP CPU.
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER` - LP core can be woken up by the LP timer.
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_ETM` - LP core can be woken up by an ETM event.
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_IO` - LP core can be woken up when LP IO level changes.
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` - LP core can be woken up when LP UART receives wakeup data based on different modes.
When the ULP is woken up, it will go through the following steps:
.. list::
:CONFIG_ESP_ROM_HAS_LP_ROM: #. Unless :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` is specified, run ROM start-up code and jump to the entry point in LP RAM. ROM start-up code will initialize LP UART as well as print boot messages.
#. Initialize system feature, e.g., interrupts
#. Call user code ``main()``
#. Return from ``main()``
#. If ``lp_timer_sleep_duration_us`` is specified, then configure the next wake-up alarm
#. Call :cpp:func:`ulp_lp_core_halt`
ULP LP Core Peripheral Support
------------------------------
To enhance the capabilities of the ULP LP core coprocessor, it has access to peripherals that operate in the low-power domain. The ULP LP core coprocessor can interact with these peripherals when the main CPU is in sleep mode, and can wake up the main CPU once a wake-up condition is reached. The following peripherals are supported:
.. list::
* LP IO
:SOC_LP_CORE_SUPPORT_I2C: * LP I2C
:SOC_ULP_LP_UART_SUPPORTED: * LP UART
:SOC_LP_SPI_SUPPORTED: * LP SPI
:SOC_LP_MAILBOX_SUPPORTED: * LP Mailbox
.. only:: CONFIG_ESP_ROM_HAS_LP_ROM
ULP LP Core ROM
---------------
The ULP LP core ROM is a small pre-built piece of code located in LP-ROM, which can't be modified. Similar to the bootloader ROM code ran by the main CPU, this code is executed when the ULP LP core coprocessor is started. The ROM code initializes the ULP LP core coprocessor and then jumps to the user program. The ROM code also prints boot messages if the LP UART has been initialized.
The ROM code is not executed if :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` is set to true. This is useful when you need the ULP to wake-up as quickly as possible and the extra overhead of initializing and printing is unwanted.
In addition to the boot-up code mentioned above, the ROM code also provides the following functions and interfaces:
* :component_file:`ROM.ld Interface <esp_rom/{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}lp.rom.ld>`
* :component_file:`newlib.ld Interface <esp_rom/{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}lp.rom.newlib.ld>`
Since these functions are already present in LP-ROM no matter what, using these in your program allows you to reduce the RAM footprint of your ULP application.
ULP LP Core Interrupts
----------------------
The LP core coprocessor can be configured to handle interrupts from various sources. Examples of such interrupts could be LP IO low/high or LP timer interrupts. To register a handler for an interrupt, simply override any of the weak handlers provided by IDF. A complete list of handlers can be found in :component_file:`ulp_lp_core_interrupts.h <ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h>`. For details on which interrupts are available on a specific target, please consult **{IDF_TARGET_NAME} Technical Reference Manual** [`PDF <{IDF_TARGET_TRM_EN_URL}#ulp>`__].
For example, to override the handler for the LP IO interrupt, you can define the following function in your ULP LP core code:
.. code-block:: c
void LP_CORE_ISR_ATTR ulp_lp_core_lp_io_intr_handler(void)
{
// Handle the interrupt and clear the interrupt source
}
:c:macro:`LP_CORE_ISR_ATTR` is a macro that is used to define the interrupt handler function. This macro ensures that registers are saved and restored correctly when the interrupt handler is called.
In addition to configuring the interrupt related registers for the interrupt source you want to handle, you also need to enable the interrupts globally in the LP core interrupt controller. This can be done using the :cpp:func:`ulp_lp_core_intr_enable` function.
ULP LP Core Clock Configuration
-------------------------------
{IDF_TARGET_XTAL_FREQ:default="Not updated", esp32c5="48 MHz", esp32p4="40 MHz", esp32s31="40 MHz"}
The ULP LP Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details.
.. only:: SOC_CLK_LP_FAST_SUPPORT_XTAL
On {IDF_TARGET_NAME}, ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as its clock source. This allows the ULP LP Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK``, which runs at around 20 MHz. However, there is a trade-off: this clock is normally powered down during sleep to reduce power consumption, but if XTAL is selected as the source, it will remain powered up during sleep, which increases power consumption. If you only plan to use the LP Core as a coprocessor while the HP Core is active, then selecting XTAL can enhance both the performance and frequency stability of the LP Core.
To enable this feature, set ``CONFIG_RTC_FAST_CLK_SRC`` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``.
Debugging ULP LP-Core Applications
----------------------------------
When programming the LP core, it can sometimes be challenging to figure out why the program is not behaving as expected. Here are some strategies to help you debug your LP core program:
.. only:: SOC_ULP_LP_UART_SUPPORTED
* Use the LP UART to print: the LP core has access to the LP UART peripheral, which can be used for printing information independently of the main CPU sleep state. See :example:`system/ulp/lp_core/lp_uart/lp_uart_print` for an example of how to use this driver.
* Routing :cpp:func:`lp_core_printf` to the HP-Core console UART with :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. This allows you to easily print LP core information to the already connected HP-Core console UART. The drawback of this approach is that it requires the main CPU to be awake and since there is no synchronization between the LP and HP cores, the output may be interleaved.
* Share program state through shared variables: as described in :ref:`ulp-lp-core-access-variables`, both the main CPU and the ULP core can easily access global variables in RTC memory. Writing state information to such a variable from the ULP and reading it from the main CPU can help you discern what is happening on the ULP core. The downside of this approach is that it requires the main CPU to be awake, which will not always be the case. Keeping the main CPU awake might even, in some cases, mask problems, as some issues may only occur when certain power domains are powered down.
.. only:: SOC_ULP_LP_UART_SUPPORTED
* Panic handler: the LP core has a panic handler that can dump the state of the LP core registers by the LP UART when an exception is detected. To enable the panic handler, set the :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` option to ``y``. This option can be kept disabled to reduce LP-RAM usage by the LP core application. To recover a backtrace from the panic dump, it is possible to use ``idf.py monitor``.
.. warning::
If multiple ULP applications are used in a single project, backtrace decoding might not work correctly. In such cases, it is recommended to use the esp-idf-monitor_ tool directly with the correct ULP ELF file:
.. code-block:: bash
python -m esp_idf_monitor --toolchain-prefix riscv32-esp-elf- --target {IDF_TARGET_PATH_NAME} --decode-panic backtrace PATH_TO_ULP_ELF_FILE
Debugging ULP LP Core Applications with GDB and OpenOCD
-------------------------------------------------------
It is also possible to debug code running on LP core using GDB and OpenOCD as you usually do for HP cores, but it has some specifics and limitations.
Debugging Session
~~~~~~~~~~~~~~~~~
Run OpenOCD with special config file for LP core debugging support. And then run GDB with special ``gdbinit`` file.
.. code-block:: bash
openocd -f board/{IDF_TARGET_PATH_NAME}-lpcore-builtin.cfg
riscv32-esp-elf-gdb -x gdbinit <path to main program ELF>
Below is the ``gdbinit`` file content with inline comments. For more details, see the next section.
.. code-block:: bash
# connect to target
target extended-remote :3333
# reset chip
mon reset halt
maintenance flush register-cache
# add symbols and debugging info for ULP program
add-symbol <path to ULP program ELF>
# temporary HW breakpoint to setup breakpoints
# if you need more than HW supports
thb main
commands
# set breakpoints here
# At this moment ULP program is loaded into RAM and when there are
# no free HW breakpoints slots available GDB will set SW ones
b func1
b func2
b func3
# resume execution
c
end
# start main program after reset
c
LP Core Debugging Specifics
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. list::
#. For convenient debugging, you may need to add ``-O0`` compile option for ULP app in its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
:not esp32p4 and not esp32s31: #. LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app, add ``-fsanitize=undefined -fno-sanitize=shift-base`` compile option to its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
#. To be able to debug program running on LP core, debugging information and symbols need to be loaded to GDB. It can be done via GDB command line or in ``gdbinit`` file. See section above.
#. Upon startup, LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function.
#. When using IDEs, it may lack support for configuring breakpoint actions or commands shown in ``gdbinit`` above. Consequently, you have to preset all breakpoints before debug session start and disable all of them except for ``main``. When program stops at ``main``, enable the remaining breakpoints and resume execution manually.
Limitations
~~~~~~~~~~~
#. Currently, debugging is not supported when either HP or LP core enters any sleep mode. So it limits available debugging scenarios.
#. FreeRTOS support in OpenOCD is disabled when debugging LP core, so you won't be able to see tasks running in the system. Instead, there will be several threads representing HP and LP cores:
.. code-block:: bash
(gdb) info thread
Id Target Id Frame
1 Thread 1 "{IDF_TARGET_PATH_NAME}.cpu0" (Name: {IDF_TARGET_PATH_NAME}.cpu0, state: debug-request) 0x40803772 in esp_cpu_wait_for_intr ()
at /home/user/projects/esp/esp-idf/components/esp_hw_support/cpu.c:64
* 2 Thread 2 "{IDF_TARGET_PATH_NAME}.cpu1" (Name: {IDF_TARGET_PATH_NAME}.cpu1, state: breakpoint) do_things (max=1000000000)
at /home/user/projects/esp/esp-idf/examples/system/ulp/lp_core/debugging/main/lp_core/main.c:21
#. When setting HW breakpoint in GDB, it is set on both cores, so the number of available HW breakpoints is limited to the number of them supported by LP core ({IDF_TARGET_SOC_CPU_BREAKPOINTS_NUM} for {IDF_TARGET_NAME}).
#. OpenOCD flash support is disabled. It does not matter for LP core application because it is run completely from RAM and GDB can use SW breakpoints for it. But if you want to set a breakpoint on function from flash used by the code running on HP core (e.g., `app_main`), you should request to set HW breakpoint explicitly via ``hb`` and ``thb`` GDB commands.
#. Since the main and ULP programs are linked as separate binaries, it is possible for them to have global symbols (such as functions or variables) with the same name. If you set a breakpoint using the function name, GDB will apply it to all instances of that function. This can cause issues if one of the functions is located in the flash, as OpenOCD currently doesn't support flash when debugging the LP core. In such cases, you can set breakpoints using the source line or the function's memory address instead.
Application Examples
--------------------
.. list::
- :example:`system/ulp/lp_core/gpio` polls GPIO while main CPU is in Deep-sleep.
:SOC_LP_CORE_SUPPORT_I2C: - :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met.
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core.
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core.
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` shows how to trigger a wakeup using the LP UART specific character sequence wakeup mode.
:SOC_LP_MAILBOX_SUPPORTED: - :example:`system/ulp/lp_core/lp_mailbox` shows how to use the mailbox for both synchronous and asynchronous communication between the HP and LP cores. Depending on the target, the implementation may use the hardware mailbox controller (if available) or a software-only implementation using interrupts.
- :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU.
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode.
- :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app.
- :example:`system/ulp/lp_core/debugging` shows how to debug code running on LP core using GDB and OpenOCD.
API Reference
-------------
Main CPU API Reference
~~~~~~~~~~~~~~~~~~~~~~
.. include-build-file:: inc/ulp_lp_core.inc
.. only:: SOC_LP_CORE_SUPPORT_I2C
.. include-build-file:: inc/lp_core_i2c.inc
.. only:: SOC_ULP_LP_UART_SUPPORTED
.. include-build-file:: inc/lp_core_uart.inc
.. only:: SOC_LP_SPI_SUPPORTED
.. include-build-file:: inc/lp_core_spi.inc
.. only:: SOC_LP_CORE_SUPPORT_ETM
.. include-build-file:: inc/lp_core_etm.inc
.. include-build-file:: inc/lp_core_types.inc
LP Core API Reference
~~~~~~~~~~~~~~~~~~~~~~
.. include-build-file:: inc/ulp_lp_core_utils.inc
.. include-build-file:: inc/ulp_lp_core_gpio.inc
.. only:: SOC_LP_CORE_SUPPORT_I2C
.. include-build-file:: inc/ulp_lp_core_i2c.inc
.. only:: SOC_ULP_LP_UART_SUPPORTED
.. include-build-file:: inc/ulp_lp_core_uart.inc
.. only:: SOC_LP_MAILBOX_SUPPORTED
.. include-build-file:: inc/ulp_lp_core_mailbox.inc
.. include-build-file:: inc/ulp_lp_core_print.inc
.. include-build-file:: inc/ulp_lp_core_interrupts.inc
.. only:: SOC_LP_SPI_SUPPORTED
.. include-build-file:: inc/ulp_lp_core_spi.inc
.. _esp-idf-monitor: https://github.com/espressif/esp-idf-monitor
.. only:: SOC_UART_HAS_LP_UART
.. include-build-file:: inc/ulp_lp_core_lp_uart_shared.inc
+352
View File
@@ -0,0 +1,352 @@
ULP RISC-V Coprocessor Programming
==================================
:link_to_translation:`zh_CN:[中文]`
The ULP RISC-V coprocessor is a variant of the ULP present in {IDF_TARGET_NAME}. Similar to ULP FSM, the ULP RISC-V coprocessor can perform tasks such as sensor readings while the main CPU stays in low power modes. The main difference between ULP FSM and ULP RISC-V is that the latter can be programmed in C using standard GNU tools. The ULP RISC-V coprocessor can access the RTC_SLOW_MEM memory region, and registers in ``RTC_CNTL``, ``RTC_IO``, and ``SARADC`` peripherals. The RISC-V processor is a 32-bit fixed point machine. Its instruction set is based on RV32IMC which includes hardware multiplication and division, and compressed code.
Installing the ULP RISC-V Toolchain
-----------------------------------
The ULP RISC-V coprocessor code is written in C (assembly is also possible) and compiled using the RISC-V toolchain based on GCC.
If you have already set up ESP-IDF with CMake build system according to the :doc:`Getting Started Guide <../../../get-started/index>`, then the toolchain should already be installed.
.. note::
In earlier versions of ESP-IDF, RISC-V toolchain had a different prefix: ``riscv-none-embed-gcc``.
Compiling Code for the ULP RISC-V
----------------------------------
The ULP RISC-V code is compiled together with your ESP-IDF project as a separate binary and automatically embedded into the main project binary. There are two ways to achieve this:
Using ``ulp_embed_binary``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. Place the ULP RISC-V code, written in C or assembly (with the ``.S`` extension), in a dedicated directory within the component directory, such as ``ulp/``.
2. After registering the component in the ``CMakeLists.txt`` file, call the ``ulp_embed_binary`` function. Here is an example:
.. code-block:: cmake
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_sources "ulp/ulp_c_source_file.c" "ulp/ulp_assembly_source_file.S")
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}" TYPE riscv)
The first argument to ``ulp_embed_binary`` specifies the ULP binary name. The name specified here is also used by other generated artifacts such as the ELF file, map file, header file, and linker export file. The second argument specifies the ULP source files. The third argument specifies the list of component source files which include the header file to be generated. This list is needed to build the dependencies correctly and ensure that the generated header file is created before any of these files are compiled. Finally, The fourth argument ``TYPE`` is optional, but it must be provided as ``TYPE riscv`` to compile using risc-v toolchain, if both :ref:`CONFIG_ULP_COPROC_TYPE_FSM` and :ref:`CONFIG_ULP_COPROC_TYPE_RISCV` are selected in menu option ``ULP Coprocessor types``. See the section below for the concept of generated header files for ULP applications.
Variables in the ULP code will be prefixed with ``ulp_`` (default value) in this generated header file.
If you need to embed multiple ULP programs, you may add a custom prefix in order to avoid conflicting variable names like this:
.. code-block:: cmake
idf_component_register()
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_sources "ulp/ulp_c_source_file.c" "ulp/ulp_assembly_source_file.S")
set(ulp_exp_dep_srcs "ulp_c_source_file.c")
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}" PREFIX "ULP::")
The additional PREFIX argument can be a C style prefix (like ``ulp2_``) or a C++ style prefix (like ``ULP::``).
Using a Custom CMake Project
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is also possible to create a custom CMake project for the ULP RISC-V. This gives more control over the build process and allows you to set compile options, link external libraries and all other things that are possible with a regular CMake project.
To do this, add the ULP project as an external project in your component ``CMakeLists.txt`` file:
.. code-block:: cmake
ulp_add_project("ULP_APP_NAME" "${CMAKE_SOURCE_DIR}/PATH_TO_DIR_WITH_ULP_PROJECT_FILE/")
Create a folder which contains your ULP project files and a ``CMakeLists.txt`` file, located at the path given to ``ulp_add_project``. The ``CMakeLists.txt`` file should look like this:
.. code-block:: cmake
cmake_minimum_required(VERSION 3.22)
# Project/target name is passed from the main project to allow IDF to have a dependency on this target
# as well as embed the binary into the main app
project(${ULP_APP_NAME})
add_executable(${ULP_APP_NAME} main.c)
# Import the ULP project helper functions
include(IDFULPProject)
# Apply default compile options
ulp_apply_default_options(${ULP_APP_NAME})
# Apply default sources provided by the IDF ULP component
ulp_apply_default_sources(${ULP_APP_NAME})
# Add targets for building the binary, as well as the linkerscript which exports ULP shared variables to the main app
ulp_add_build_binary_targets(${ULP_APP_NAME})
# Everything below this line is optional and can be used to customize the build process
# Create a custom library
set(lib_path "${CMAKE_CURRENT_LIST_DIR}/lib")
add_library(custom_lib STATIC "${lib_path}/lib_src.c")
target_include_directories(custom_lib PUBLIC "${lib_path}/")
# Link the library
target_link_libraries(${ULP_APP_NAME} PRIVATE custom_lib)
# Set custom compile flags
target_compile_options(${ULP_APP_NAME} PRIVATE -msave-restore)
Building Your Project
^^^^^^^^^^^^^^^^^^^^^
To compile and build your project:
1. Enable :ref:`CONFIG_ULP_COPROC_ENABLED` in menuconfig, and inside ``ULP Coprocessor types`` menu, select :ref:`CONFIG_ULP_COPROC_TYPE_RISCV`. The :ref:`CONFIG_ULP_COPROC_RESERVE_MEM` option reserves RTC memory for the ULP, and must be set to a value big enough to store both the ULP RISC-V code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
2. Build the application as usual (e.g., ``idf.py app``).
During the build process, the following steps are taken to build ULP program:
1. **Run each source file through the C compiler and assembler.** This step generates the object files ``.obj.c`` or ``.obj.S`` in the component build directory depending on the source file processed.
2. **Run the linker script template through the C preprocessor.** The template is located in ``components/ulp/ld`` directory.
3. **Link the object files into an output ELF file** (``ulp_app_name.elf``). The Map file ``ulp_app_name.map`` generated at this stage may be useful for debugging purposes.
4. **Dump the contents of the ELF file into a binary** (``ulp_app_name.bin``) which can then be embedded into the application.
5. **Generate a list of global symbols** (``ulp_app_name.sym``) in the ELF file using ``riscv32-esp-elf-nm``.
6. **Create an LD export script and a header file** ``ulp_app_name.ld`` and ``ulp_app_name.h`` containing the symbols from ``ulp_app_name.sym``. This is done using the ``esp32ulp_mapgen.py`` utility.
7. **Add the generated binary to the list of binary files** to be embedded into the application.
.. _ulp-riscv-access-variables:
Accessing the ULP RISC-V Program Variables
------------------------------------------
Global symbols defined in the ULP RISC-V program may be used inside the main program.
For example, the ULP RISC-V program may define a variable ``measurement_count`` which will define the number of ADC measurements the program needs to make before waking up the chip from deep sleep.
.. code-block:: c
volatile int measurement_count;
int some_function()
{
//read the measurement count for later use.
int temp = measurement_count;
...do something.
}
The main program can access the global ULP RISC-V program variables as the build system makes this possible by generating the ``${ULP_APP_NAME}.h`` and ``${ULP_APP_NAME}.ld`` files which define the global symbols present in the ULP RISC-V program. Each global symbol defined in the ULP RISC-V program is included in these files and are prefixed with ``ulp_``.
The header file contains the declaration of the symbol:
.. code-block:: c
extern uint32_t ulp_measurement_count;
Note that all symbols (variables, functions) are declared as ``uint32_t``. Arrays are declared as ``uint32_t [SIZE]``. For functions, take the address of the symbol and cast it to the appropriate type.
To access the ULP RISC-V program variables from the main program, the generated header file should be included using an ``include`` statement. This will allow the ULP RISC-V program variables to be accessed as regular variables.
.. code-block:: c
#include "ulp_app_name.h"
void init_ulp_vars() {
ulp_measurement_count = 64;
}
.. note::
- Variables declared in the global scope of the ULP RISC-V program reside in either the ``.bss`` or ``.data`` section of the binary. These sections are initialized when the ULP RISC-V binary is loaded and executed. Accessing these variables from the main program on the main CPU before the first ULP RISC-V run may result in undefined behavior.
- The ``ulp_`` prefix is the default value. You can specify the prefix to use with ``ulp_embed_binary`` to avoid name collisions for multiple ULP programs.
Mutual Exclusion
^^^^^^^^^^^^^^^^
If mutual exclusion is needed when accessing a variable shared between the main program and ULP, then this can be achieved by using the ULP RISC-V lock API:
* :cpp:func:`ulp_riscv_lock_acquire`
* :cpp:func:`ulp_riscv_lock_release`
The ULP does not have any hardware instructions to facilitate mutual exclusion, so the lock API achieves this through a software algorithm (`Peterson's algorithm <https://en.wikipedia.org/wiki/Peterson%27s_algorithm>`_).
The locks are intended to only be called from a single thread in the main program, and will not provide mutual exclusion if used simultaneously from multiple threads.
Starting the ULP RISC-V Program
-------------------------------
To run a ULP RISC-V program, the main application needs to load the ULP program into RTC memory using the :cpp:func:`ulp_riscv_load_binary` function, and then start it using the :cpp:func:`ulp_riscv_run` function.
Note that the :ref:`CONFIG_ULP_COPROC_ENABLED` and :ref:`CONFIG_ULP_COPROC_TYPE_RISCV` options must be enabled in menuconfig to work with ULP RISC-V. To reserve memory for the ULP, the ``RTC slow memory reserved for coprocessor`` option must be set to a value big enough to store ULP RISC-V code and data. If the application components contain multiple ULP programs, then the size of the RTC memory must be sufficient to hold the largest one.
Each ULP RISC-V program is embedded into the ESP-IDF application as a binary blob. The application can reference this blob and load it in the following way (suppose ULP_APP_NAME was defined to ``ulp_app_name``):
.. code-block:: c
extern const uint8_t bin_start[] asm("_binary_ulp_app_name_bin_start");
extern const uint8_t bin_end[] asm("_binary_ulp_app_name_bin_end");
void start_ulp_program() {
ESP_ERROR_CHECK( ulp_riscv_load_binary( bin_start,
(bin_end - bin_start)) );
}
Once the program is loaded into RTC memory, the application can start it by calling the :cpp:func:`ulp_riscv_run` function:
.. code-block:: c
ESP_ERROR_CHECK( ulp_riscv_run() );
ULP RISC-V Program Flow
-----------------------
{IDF_TARGET_RTC_CLK_FRE:default="150 kHz", esp32s2="90 kHz", esp32s3="136 kHz"}
The ULP RISC-V coprocessor is started by a timer. The timer is started once :cpp:func:`ulp_riscv_run` is called. The timer counts the number of RTC_SLOW_CLK ticks (by default, produced by an internal {IDF_TARGET_RTC_CLK_FRE} RC oscillator). The number of ticks is set using ``RTC_CNTL_ULP_CP_TIMER_1_REG`` register. When starting the ULP, ``RTC_CNTL_ULP_CP_TIMER_1_REG`` will be used to set the number of timer ticks.
The application can set ULP timer period values (RTC_CNTL_ULP_CP_TIMER_1_REG) using the :cpp:func:`ulp_set_wakeup_period` function.
Once the timer counts the number of ticks set in the ``RTC_CNTL_ULP_CP_TIMER_1_REG`` register, the ULP RISC-V coprocessor will power up and start running the program from the entry point set in the call to :cpp:func:`ulp_riscv_run`.
The program runs until the field ``RTC_CNTL_COCPU_DONE`` in register ``RTC_CNTL_COCPU_CTRL_REG`` gets written or when a trap occurs due to illegal processor state. Once the program halts, the ULP RISC-V coprocessor will power down, and the timer will be started again.
To disable the timer (effectively preventing the ULP program from running again), please clear the ``RTC_CNTL_ULP_CP_SLP_TIMER_EN`` bit in the ``RTC_CNTL_ULP_CP_TIMER_REG`` register. This can be done both from the ULP code and from the main program.
ULP RISC-V Peripheral Support
------------------------------
To enhance the capabilities of the ULP RISC-V coprocessor, it has access to peripherals which operate in the low-power (RTC) domain. The ULP RISC-V coprocessor can interact with these peripherals when the main CPU is in sleep mode, and can wake up the main CPU once a wakeup condition is reached. The following peripherals are supported.
RTC I2C
^^^^^^^^
The RTC I2C controller provides I2C master functionality in the RTC domain. The ULP RISC-V coprocessor can read from or write to I2C slave devices using this controller. To use the RTC I2C peripheral, call the :cpp:func:`ulp_riscv_i2c_master_init` from your application running on the main core before initializing the ULP RISC-V core and going to sleep.
Once the RTC I2C controller is initialized, the I2C slave device address must be programmed via the :cpp:func:`ulp_riscv_i2c_master_set_slave_addr` API before any read or write operation is performed.
.. note::
The RTC I2C peripheral issues two kinds of I2C transactions:
- **READ**: [start] → write device address → write device sub-register address → [repeated start] → write device address → read N bytes → [stop]
- **WRITE**: [start] → write device address → write device sub-register address → [repeated start] → write device address → write N bytes → [stop]
In both cases, sending the sub-register address is required and cannot be disabled. Therefore, the peripheral always expects a slave sub-register address to be set using the :cpp:func:`ulp_riscv_i2c_master_set_slave_reg_addr` API. If it is not set explicitly, the peripheral uses the value in ``SENS_SAR_I2C_CTRL_REG[18:11]`` as the sub-register address for subsequent transactions.
This behavior makes the RTC I2C peripheral incompatible with:
- Devices that do not expect a sub-register address write before initiating a read or write transaction.
- Devices requiring 16-bit or wider register addresses, since only 8-bit addressing is supported.
.. note::
There is no hardware atomicity protection in accessing the RTC I2C peripheral between the main CPU and the ULP RISC-V core. Therefore, care must be taken that both cores are not accessing the peripheral simultaneously.
In case your RTC I2C based ULP RISC-V program is not working as expected, the following sanity checks can help in debugging the issue:
* Incorrect SDA/SCL pin selection: The SDA pin can only be set up as GPIO1 or GPIO3 and SCL pin can only be set up as GPIO0 or GPIO2. Make sure that the pin configuration is correct.
* Incorrect I2C timing parameters: The RTC I2C bus timing configuration is limited by the I2C standard bus specification. Any timing parameters which violate the standard I2C bus specifications would result in an error. For details on the timing parameters, please read the `standard I2C bus specifications <https://en.wikipedia.org/wiki/I%C2%B2C>`_.
* If the I2C slave device or sensor does not require a sub-register address to be programmed, it may not be compatible with the RTC I2C peripheral. Please refer the notes above.
* If the RTC driver reports a ``Write Failed!`` or ``Read Failed!`` error log when running on the main CPU, then make sure:
* The I2C slave device or sensor works correctly with the standard I2C master on Espressif SoCs. This would rule out any problems with the I2C slave device itself.
* If the RTC I2C interrupt status log reports a ``TIMEOUT`` error or ``ACK`` error, it could typically mean that the I2C device did not respond to a ``START`` condition sent out by the RTC I2C controller. This could happen if the I2C slave device is not connected properly to the controller pins or if the I2C slave device is in a bad state. Make sure that the I2C slave device is in a good state and connected properly before continuing.
* If the RTC I2C interrupt log does not report any error status, it could mean that the driver is not fast enough in receiving data from the I2C slave device. This could happen as the RTC I2C controller does not have a TX/RX FIFO to store multiple bytes of data but rather, it depends on single byte transmissions using an interrupt status polling mechanism. This could be mitigated to some extent by making sure that the SCL clock of the peripheral is running as fast as possible. This can be tweaked by configuring the SCL low period and SCL high period values in the initialization config parameters for the peripheral.
* Other methods of debugging problems would be to ensure that the RTC I2C controller is operational **only** on the main CPU **without** any ULP RISC-V code interfering and **without** any sleep mode being activated. This is the basic configuration under which the RTC I2C peripheral must work. This way you can rule out any potential issues due to the ULP or sleep modes.
ULP RISC-V Interrupt Handling
------------------------------
The ULP RISC-V core supports interrupt handling from certain internal and external events. By design, the ULP RISC-V core can handle interrupts from the following sources:
.. list-table:: ULP RISC-V interrupt sources
:widths: 10 5 5
:header-rows: 1
* - Interrupt Source
- Type
- IRQ
* - Internal Timer Interrupt
- Internal
- 0
* - EBREAK or ECALL or Illegal Instruction
- Internal
- 1
* - Unaligned Memory Access
- Internal
- 2
* - RTC Peripheral Sources
- External
- 31
Interrupt handling is enabled via special 32-bit registers Q0-Q3 and custom R-type instructions. For more information, see *{IDF_TARGET_NAME} Technical Reference Manual* > *ULP Coprocessor* > *ULP-RISC-V* > *ULP-RISC-V Interrupts* [`PDF <{IDF_TARGET_TRM_EN_URL}>`__].
All interrupts are enabled globally during start-up. When an interrupt occurs, the processor jumps to the IRQ vector. The IRQ vector performs the task of saving the register context and then calling the global interrupt dispatcher. The ULP RISC-V driver implements a *weak* interrupt dispatcher :cpp:func:`_ulp_riscv_interrupt_handler` which serves as the central point for handling all interrupts. This global dispatcher calls respective interrupt handlers which have been allocated via the :cpp:func:`ulp_riscv_intr_alloc`.
Interrupt handling on the ULP RISC-V is not fully featured yet. At present, interrupt handling for internal interrupt sources is not supported. Support is provided for two RTC peripheral sources, viz., software-triggered interrupts and RTC IO-triggered interrupts. ULP RISC-V does not support nested interrupts. If users need custom interrupt handling then they may override the default global interrupt dispatcher by defining their own :cpp:func:`_ulp_riscv_interrupt_handler`.
Debugging Your ULP RISC-V Program
----------------------------------
When programming the ULP RISC-V, it can sometimes be challenging to figure out why the program is not behaving as expected. Due to the simplicity of the core, many of the standard methods of debugging, e.g., JTAG or ``printf``, are simply not available.
Keeping this in mind, here are some ways that may help you debug your ULP RISC-V program:
* Share program state through shared variables: as described in :ref:`ulp-riscv-access-variables`, both the main CPU and the ULP core can easily access global variables in RTC memory. Writing state information to such a variable from the ULP and reading it from the main CPU can help you discern what is happening on the ULP core. The downside of this approach is that it requires the main CPU to be awake, which will not always be the case. Keeping the main CPU awake might even, in some cases, mask problems, as some issues may only occur when certain power domains are powered down.
* Use the bit-banged UART driver to print: the ULP RISC-V component comes with a low-speed bit-banged UART TX driver that can be used for printing information independently of the main CPU state. See :example:`system/ulp/ulp_riscv/uart_print` for an example of how to use this driver.
* Trap signal: the ULP RISC-V has a hardware trap that will trigger under certain conditions, e.g., illegal instruction. This will cause the main CPU to be woken up with the wake-up cause :cpp:enumerator:`ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG`.
Application Examples
--------------------
* :example:`system/ulp/ulp_riscv/gpio` demonstrates how to program the ULP-RISC-V coprocessor to monitor a GPIO pin and wake up the main CPU when its state changes.
* :example:`system/ulp/ulp_riscv/uart_print` demonstrates how to program the ULP-RISC-V coprocessor on the development board to bitbang a UART TX line, allowing for output logging directly from the ULP-RISC-V coprocessor even when the main CPU is in deep sleep.
.. only:: esp32s2
* :example:`system/ulp/ulp_riscv/ds18b20_onewire` demonstrates how to use the ULP-RISC-V co-processor to read temperature from a DS18B20 sensor over 1-Wire, and wake up the main CPU from deep-sleep when the temperature exceeds a set limit.
* :example:`system/ulp/ulp_riscv/i2c` demonstrates how to use the RTC I2C peripheral from the ULP RISC-V coprocessor in deep sleep mode to periodically measure temperature and pressure values from the BMP180 sensor and wake up the main CPU when these values exceed a certain threshold.
* :example:`system/ulp/ulp_riscv/interrupts` demonstrates how the ULP-RISC-V coprocessor can register and handle software and RTC IO triggered interrupts, keeping a count of the software interrupts and waking up the main processor from deep sleep after a certain threshold or when a button is pressed.
* :example:`system/ulp/ulp_riscv/adc` demonstrates how to use the ULP-RISC-V coprocessor to periodically measure input voltage and wake up the system from deep sleep if the voltage exceeds a set threshold.
* :example:`system/ulp/ulp_riscv/gpio_interrupt` demonstrates how to program the ULP-RISC-V coprocessor to wake up from a RTC IO interrupt using GPIO0 as the input signal, and how to configure and run the coprocessor, putting the chip into deep sleep mode until the wakeup source pin is pulled low.
* :example:`system/ulp/ulp_riscv/touch` demonstrates how to program the ULP RISC-V coprocessor to periodically scan and read touch pad sensors, and wake up the main CPU when a touch pad is active.
.. only:: esp32s2 or esp32s3
* :example:`system/ulp/ulp_fsm_riscv_combined/counter` demonstrates how to use both the ULP FSM and ULP RISC-V coprocessors sequentially within the same application, counting from 0 to 100 with the FSM and from 100 to 500 with the RISC-V coprocessor while the HP core remains in sleep mode until the counting completes.
API Reference
-------------
.. include-build-file:: inc/ulp_riscv.inc
.. include-build-file:: inc/ulp_riscv_lock_shared.inc
.. include-build-file:: inc/ulp_riscv_lock.inc
.. include-build-file:: inc/ulp_riscv_i2c.inc
+29
View File
@@ -0,0 +1,29 @@
Ultra Low Power (ULP) coprocessor
===================================
:link_to_translation:`zh_CN:[中文]`
The Ultra Low Power (ULP) coprocessor is designed to perform tasks while the main CPU is in deep sleep mode, allowing for power savings and extended battery life in applications. The ULP coprocessor can monitor sensors, control peripherals, and handle other tasks that do not require the main CPU's computing power. It can also wake up the main CPU when specific conditions are met, such as when a sensor reading exceeds a predefined threshold.
.. only:: not SOC_ULP_SUPPORTED
.. note:: The ULP coprocessor is not supported on {IDF_TARGET_NAME}.
.. only:: SOC_ULP_SUPPORTED
The ULP coprocessor on a chip may include one or more of the following types, but only one can operate at a time:
- **ULP FSM**: A finite state machine (FSM) based ULP coprocessor. It is suitable for simple tasks, as applications for this type must be written using assembly language or C macros. This type is supported by ESP32, ESP32-S2, and ESP32-S3.
- **ULP RISC-V**: A RISC-V based ULP coprocessor. It offers enhanced computational capabilities and flexibility, making it suitable for more complex applications written in C. This type is supported by ESP32-S2 and ESP32-S3.
- **ULP LP Core**: A RISC-V based ULP coprocessor that combines the advantages of the **ULP RISC-V** type with additional features, such as extended memory access, broader peripheral access, a debug module, and an interrupt controller. This coprocessor is capable of operating even when the entire system is active. This type is supported by ESP32-C5, ESP32-C6, ESP32-P4, and upcoming chips.
NOTE: Chips like ESP32-S2 and ESP32-S3 support both **ULP FSM** and **ULP RISC-V**. User can enable both of them in menuconfig at compile time, and choose which one to use at run time.
.. toctree::
:maxdepth: 1
:SOC_ULP_FSM_SUPPORTED: ulp-fsm
:SOC_RISCV_COPROC_SUPPORTED: ulp-risc-v
:SOC_LP_CORE_SUPPORTED: ulp-lp-core
Code examples for this API section are provided in the :example:`system/ulp` directory of ESP-IDF examples.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,61 @@
Programming ULP FSM Coprocessor Using C Macros (Legacy)
=======================================================
:link_to_translation:`zh_CN:[中文]`
In addition to the existing binutils port for the {IDF_TARGET_NAME} ULP coprocessor, it is possible to generate programs for the ULP FSM coprocessor by embedding assembly-like macros into an {IDF_TARGET_NAME} application. Here is an example how this can be done::
const ulp_insn_t program[] = {
I_MOVI(R3, 16), // R3 <- 16
I_LD(R0, R3, 0), // R0 <- RTC_SLOW_MEM[R3 + 0]
I_LD(R1, R3, 1), // R1 <- RTC_SLOW_MEM[R3 + 1]
I_ADDR(R2, R0, R1), // R2 <- R0 + R1
I_ST(R2, R3, 2), // R2 -> RTC_SLOW_MEM[R2 + 2]
I_HALT()
};
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);
The ``program`` array is an array of ``ulp_insn_t``, i.e., ULP coprocessor instructions. Each ``I_XXX`` preprocessor define translates into a single 32-bit instruction. Arguments of these preprocessor defines can be register numbers (``R0 — R3``) and literal constants. See the API reference section at the end of this guide for descriptions of instructions and arguments they take.
.. note::
Because some of the instruction macros expand to inline function calls, defining such array in global scope will cause the compiler to produce an "initializer element is not constant" error. To fix this error, move the definition of instructions array into local scope.
.. note::
Load, store and move instructions use **addresses expressed in 32-bit words**. Address 0 corresponds to the first word of ``RTC_SLOW_MEM``.
This is different from how address arguments are handled in assembly code of the same instructions. See the section :ref:`ulp-fsm-addressing` for more details for reference.
To generate branch instructions, special ``M_`` preprocessor defines are used. ``M_LABEL`` define can be used to define a branch target. Label identifier is a 16-bit integer. ``M_Bxxx`` defines can be used to generate branch instructions with target set to a particular label.
Implementation note: these ``M_`` preprocessor defines will be translated into two ulp_insn_t values: one is a token value which contains label number, and the other is the actual instruction. ``ulp_process_macros_and_load`` function resolves the label number to the address, modifies the branch instruction to use the correct address, and removes the extra ``ulp_insn_t`` token which contains the label number.
Here is an example of using labels and branches::
const ulp_insn_t program[] = {
I_MOVI(R0, 34), // R0 <- 34
M_LABEL(1), // label_1
I_MOVI(R1, 32), // R1 <- 32
I_LD(R1, R1, 0), // R1 <- RTC_SLOW_MEM[R1]
I_MOVI(R2, 33), // R2 <- 33
I_LD(R2, R2, 0), // R2 <- RTC_SLOW_MEM[R2]
I_SUBR(R3, R1, R2), // R3 <- R1 - R2
I_ST(R3, R0, 0), // R3 -> RTC_SLOW_MEM[R0 + 0]
I_ADDI(R0, R0, 1), // R0++
M_BL(1, 64), // if (R0 < 64) goto label_1
I_HALT(),
};
RTC_SLOW_MEM[32] = 42;
RTC_SLOW_MEM[33] = 18;
size_t load_addr = 0;
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(load_addr, program, &size);
ulp_run(load_addr);
API Reference
-------------
.. include-build-file:: inc/ulp.inc
+216
View File
@@ -0,0 +1,216 @@
Watchdogs
=========
:link_to_translation:`zh_CN:[中文]`
The purpose of a watchdog timer is to monitor the system's operation and automatically recover from software or hardware faults by restarting the system if it becomes unresponsive.
Overview
--------
ESP-IDF supports multiple types of watchdog timers:
.. list::
- Interrupt Watchdog Timer (IWDT)
- Task Watchdog Timer (TWDT)
- RTC/LP Watchdog Timer (RTC_WDT/LP_WDT)
:SOC_XT_WDT_SUPPORTED: - XTAL32K Watchdog Timer (Crystal 32K Watchdog Timer, i.e., XTWDT)
The Interrupt Watchdog Timer (IWDT) is responsible for ensuring that ISRs (Interrupt Service Routines) are not blocked from running for a prolonged period of time, and prevents an ISR from getting stuck during execution.
The Task Watchdog Timer (TWDT) is responsible for detecting instances of tasks running without yielding for too long.
The RTC/LP Watchdog Timer (RTC_WDT) can be used to track the boot time from power-up until the user's main function. It can also be used during panic handling and in the low-power domain.
The various watchdog timers can be enabled by :ref:`project-configuration-menu`. However, the TWDT can also be enabled during runtime.
.. _app-hardware-watchdog-timers:
Hardware Watchdog Timers
------------------------
The chips have two groups of watchdog timers:
.. list::
:not esp32c2: - Main System Watchdog Timer (MWDT_WDT) - used by Interrupt Watchdog Timer (IWDT) and Task Watchdog Timer (TWDT).
:esp32c2: - Main System Watchdog Timer (MWDT_WDT) - used by Interrupt Watchdog Timer (IWDT).
- RTC Watchdog Timer (RTC_WDT) - used to track the boot time from power-up until the user's main function (by default RTC Watchdog is disabled immediately before the user's main function).
Refer to the :ref:`bootloader-watchdog` section to understand how watchdogs are utilized in the bootloader.
The app's behaviour can be adjusted so the RTC Watchdog remains enabled after app startup. The Watchdog would need to be explicitly reset (i.e., fed) or disabled by the app to avoid the chip reset. To do this, set the :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` option, modify the app as needed, and then recompile the app. In this case, the following APIs should be used:
.. list::
- :cpp:func:`wdt_hal_disable`: see :ref:`hw-abstraction-hal-layer-disable-rtc-wdt`
- :cpp:func:`wdt_hal_feed`: see :ref:`hw-abstraction-hal-layer-feed-rtc-wdt`
:esp32 or esp32s2: - :cpp:func:`rtc_wdt_feed`
:esp32 or esp32s2: - :cpp:func:`rtc_wdt_disable`
If RTC_WDT is not reset/disabled in time, the chip will be automatically reset. See :ref:`RTC-Watchdog-Timeout` for more information.
Interrupt Watchdog Timer (IWDT)
-------------------------------
{IDF_TARGET_IWDT_TIMER_GROUP:default="Timer Group 1", esp32c2="Timer Group 0"}
The purpose of the IWDT is to ensure that interrupt service routines (ISRs) are not blocked from running for a prolonged period of time (i.e., the IWDT timeout period). Preventing ISRs from running in a timely manner is undesirable as it can increase ISR latency, and also prevent task switching (as task switching is executed from an ISR). The things that can block ISRs from running include:
- Disabling interrupts
- Critical Sections (also disables interrupts)
- Other same/higher priority ISRs which block same/lower priority ISRs from running
The IWDT utilizes the MWDT_WDT watchdog timer in {IDF_TARGET_IWDT_TIMER_GROUP} as its underlying hardware timer and leverages the FreeRTOS tick interrupt on each CPU to feed the watchdog timer. If the tick interrupt on a particular CPU is not executed within the IWDT timeout period, it indicates that something is blocking ISRs from being run on that CPU (see the list of reasons above).
When the IWDT times out, the default action is to invoke the panic handler and display the panic reason as ``Interrupt wdt timeout on CPU0`` or ``Interrupt wdt timeout on CPU1`` (as applicable). Depending on the panic handler's configured behavior (see :ref:`CONFIG_ESP_SYSTEM_PANIC`), users can then debug the source of the IWDT timeout (via the backtrace, OpenOCD, gdbstub etc) or simply reset the chip (which may be preferred in a production environment).
If for whatever reason the panic handler is unable to run after an IWDT timeout, the IWDT has a second stage timeout that will hard-reset the chip (i.e., a system reset).
Configuration
^^^^^^^^^^^^^
- The IWDT is enabled by default via the :ref:`CONFIG_ESP_INT_WDT` option.
- The IWDT's timeout is configured by setting the :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` option.
.. list::
:SOC_SPIRAM_SUPPORTED: - Note that the default timeout is higher if PSRAM support is enabled, as a critical section or interrupt routine that accesses a large amount of PSRAM takes longer to complete in some circumstances.
- The configured timeout duration for IWDT should always be at least twice longer than the period between two FreeRTOS ticks, e.g., if two FreeRTOS ticks occur 10 ms apart, then IWDT timeout duration should at least be more than 20 ms (see :ref:`CONFIG_FREERTOS_HZ`).
Tuning
^^^^^^
If you find the IWDT timeout is triggered because an interrupt or critical section is running longer than the timeout period, consider rewriting the code:
- Critical sections should be made as short as possible. Any non-critical code/computation should be placed outside the critical section.
- Interrupt handlers should also perform the minimum possible amount of computation. Users can consider deferring any computation to a task by having the ISR push data to a task using queues.
Neither critical sections or interrupt handlers should ever block waiting for another event to occur. If changing the code to reduce the processing time is not possible or desirable, it is possible to increase the :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` setting instead.
.. _task-watchdog-timer:
Task Watchdog Timer (TWDT)
--------------------------
The Task Watchdog Timer (TWDT) is used to monitor particular tasks, ensuring that they are able to execute within a given timeout period. By default the TWDT watches the Idle Tasks of each CPU, however any task can subscribe to be watched by the TWDT. By watching the Idle Tasks of each CPU, the TWDT can detect instances of tasks running for a prolonged period of time without yielding. This can be an indicator of poorly written code that spinloops on a peripheral, or a task that is stuck in an infinite loop.
.. only:: not esp32c2
The TWDT is built around the MWDT_WDT watchdog timer in Timer Group 0. When a timeout occurs, an interrupt is triggered.
.. only:: esp32c2
The {IDF_TARGET_NAME} has only a single Timer Group, used by Interrupt Watchdog (IWDT). Thus, the Task Watchdog is built around the ``esp_timer`` component in order to implement a software timer. When a timeout occurs, an interrupt is triggered, notifying the ``esp_timer``'s main task. The latter then executes the TWDT callback previously registered.
Users can define the function ``esp_task_wdt_isr_user_handler`` in the user code, in order to receive the timeout event and extend the default behavior.
Usage
^^^^^
The following functions can be used to watch tasks using the TWDT:
- :cpp:func:`esp_task_wdt_init` to initialize the TWDT and subscribe the idle tasks.
- :cpp:func:`esp_task_wdt_add` subscribes other tasks to the TWDT.
- Once subscribed, :cpp:func:`esp_task_wdt_reset` should be called from the task to feed the TWDT.
- :cpp:func:`esp_task_wdt_delete()` unsubscribes a previously subscribed task.
- :cpp:func:`esp_task_wdt_deinit()` unsubscribes the idle tasks and deinitializes the TWDT.
In the case where applications need to watch at a more granular level (i.e., ensure that a particular functions/stub/code-path is called), the TWDT allows subscription of ``users``.
- :cpp:func:`esp_task_wdt_add_user` to subscribe an arbitrary user of the TWDT. This function returns a user handle to the added user.
- :cpp:func:`esp_task_wdt_reset_user` must be called using the user handle in order to prevent a TWDT timeout.
- :cpp:func:`esp_task_wdt_delete_user` unsubscribes an arbitrary user of the TWDT.
Configuration
^^^^^^^^^^^^^
The default timeout period for the TWDT is set using config item :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S`. This should be set to at least as long as you expect any single task needs to monopolize the CPU (for example, if you expect the app will do a long intensive calculation and should not yield to other tasks). It is also possible to change this timeout at runtime by calling :cpp:func:`esp_task_wdt_init`.
.. note::
Erasing large flash areas can be time consuming and can cause a task to run continuously, thus triggering a TWDT timeout. The following two methods can be used to avoid this:
- Increase :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` in menuconfig for a larger watchdog timeout period.
- You can also call :cpp:func:`esp_task_wdt_init` again to increase the watchdog timeout period before erasing a large flash area.
For more information, you can refer to :doc:`../peripherals/spi_flash/index`.
The following config options control TWDT configuration. They are all enabled by default:
{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task", esp32s3="CPU0 Idle task", esp32p4="CPU0 Idle task"}
.. list::
- :ref:`CONFIG_ESP_TASK_WDT_EN` - enables TWDT feature. If this option is disabled, TWDT cannot be used, even if initialized at runtime.
- :ref:`CONFIG_ESP_TASK_WDT_INIT` - initializes the TWDT automatically during startup. If this option is disabled, it is still possible to initialize the Task WDT at runtime by calling :cpp:func:`esp_task_wdt_init`.
- :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - subscribes {IDF_TARGET_IDLE_TASK} to the TWDT during startup. If this option is disabled, it is still possible to subscribe the idle task by calling :cpp:func:`esp_task_wdt_init` again, or by using :cpp:func:`esp_task_wdt_add` and passing the idle task handle obtained via :cpp:func:`xTaskGetIdleTaskHandleForCore`.
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - Subscribes CPU1 Idle task to the TWDT during startup.
.. note::
On a TWDT timeout the default behaviour is to simply print a warning and a backtrace before continuing running the app. If you want a timeout to cause a panic and a system reset then this can be configured through :ref:`CONFIG_ESP_TASK_WDT_PANIC`.
.. only:: SOC_XT_WDT_SUPPORTED
XTAL32K Watchdog Timer (XTWDT)
------------------------------
One of the optional clock inputs to the {IDF_TARGET_NAME} is an external 32 kHz crystal oscillator (XTAL32K) that is used as a clock source (``XTAL32K_CLK``) to various subsystems (such as the RTC).
The XTWDT is a dedicated watchdog timer used to ensure that the XTAL32K is functioning correctly. When ``XTAL32K_CLK`` works as the clock source of ``RTC_SLOW_CLK`` and stops oscillating, the XTWDT will detect this and generate an interrupt. It also provides functionality for automatically switching over to the internal, but less accurate oscillator as the ``RTC_SLOW_CLK`` source.
Since the switch to the backup clock is done in hardware it can also happen during Deep Sleep. This means that even if ``XTAL32K_CLK`` stops functioning while the chip is in Deep Sleep, waiting for a timer to expire, it is still able to wake-up as planned.
If the ``XTAL32K_CLK`` starts functioning normally again, you can call ``esp_xt_wdt_restore_clk`` to switch back to this clock source and re-enable the watchdog timer.
Configuration
"""""""""""""
- When the external 32 KHz crystal or oscillator is selected (:ref:`CONFIG_RTC_CLK_SRC`) the XTWDT can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration option.
- The timeout is configured by setting the :ref:`CONFIG_ESP_XT_WDT_TIMEOUT` option.
- The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration option.
Timeout Stages
--------------
Hardware watchdog timers in ESP-IDF have four timeout stages. If the WDT is not fed in the previous stage within the configured timeout duration of that stage, it will trigger the next stage. Each stage can be configured to take one of the actions listed below after the timeout duration:
- Trigger an interrupt. When the stage expires, an interrupt is triggered.
- Reset a CPU core. When the stage expires the designated CPU core will be reset.
- Reset the main system. When the stage expires, the main system, including the MWDTs, will be reset. The main system includes the CPU and all peripherals. The RTC is an exception to this, and it will not be reset.
- Reset the main system and RTC. When the stage expires the main system and the RTC will both be reset. This action is only available in the RTC_WDT.
- Disabled. This stage will have no effects on the system.
The typical configuration of the stages can be done by having interrupt actions in the earlier stages and allowing stepwise handling up to a final system reset action in the later stages.
Stages can be configured via :cpp:func:`wdt_hal_config_stage` (or equivalent APIs), selecting actions per stage to match application behavior.
JTAG & Watchdogs
----------------
While debugging using OpenOCD, the CPUs are halted every time a breakpoint is reached. However if the watchdog timers continue to run when a breakpoint is encountered, they will eventually trigger a reset making it very difficult to debug code. Therefore OpenOCD will disable the hardware timers of both the interrupt and task watchdogs at every breakpoint. Moreover, OpenOCD will not re-enable them upon leaving the breakpoint. This means that interrupt watchdog and task watchdog functionality will essentially be disabled. No warnings or panics from either watchdogs will be generated when the {IDF_TARGET_NAME} is connected to OpenOCD via JTAG.
Common Error Logs When WDT Triggers and Possible Resolutions
------------------------------------------------------------
- ``Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0).`` followed by a backtrace: Indicates that the Interrupt Watchdog Timer (IWDT) has detected that interrupts have been blocked on CPU 0 for longer than the configured timeout period. This can be fixed by reducing the duration of long-running ISRs or critical sections, or by increasing the IWDT timeout period.
- ``Task watchdog got triggered. The following tasks/users did not reset the watchdog in time: - IDLE0 (CPU 0), Tasks currently running: CPU 0: main, CPU 1: IDLE1``: Indicates that the Task Watchdog Timer (TWDT) has detected that one or more tasks have not yielded within the configured timeout period, and hence the IDLE task couldn't feed the TWDT in time. This can be fixed by ensuring that tasks yield appropriately, reducing the duration of long-running tasks, or by increasing the TWDT timeout period. The user can also use :cpp:func:`esp_task_wdt_add`, :cpp:func:`esp_task_wdt_add_user` and :cpp:func:`esp_task_wdt_reset_user` APIs to find out which task and which code path inside that task is taking the longest time and causing the TWDT timeout.
- :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` is enabled and causes WDT timeout: Make sure RTC WDT is fed frequently enough from user code.
- WDT Reset happens during boot-up: Ensure that a valid second stage bootloader is flashed correctly and investigate possible communication issues with external flash.
- WDT Reset happens during operation: Try to identify when it happens, is it during a panic, a restart or enter/exit Light-sleep? If it happens during any of these system operations, it could point towards an issue inside ESP-IDF.
Application Examples
--------------------
- :example:`system/task_watchdog` demonstrates how to initialize, subscribe and unsubscribe tasks and users to the task watchdog, and how tasks and users can reset (feed) the task watchdog.
API Reference
-------------
.. include-build-file:: inc/esp_task_wdt.inc