docs(kconfig): update kconfig ref links to use menuitem

This commit is contained in:
Marius Vikhammer
2026-08-06 13:06:20 +02:00
parent c6e80a336a
commit 4d332f710e
304 changed files with 2362 additions and 2372 deletions

View File

@@ -104,12 +104,12 @@
3. 镜像有一个校验和字节,位于最后一个段之后。此字节写在一个十六字节填充边界上,因此应用程序镜像可能需要填充。
4. 如果在 :cpp:type:`esp_image_header_t` 中设置了 ``hash_appended`` 字段,则会附加 SHA256 校验和字段。SHA256 哈希值的计算范围是从第一个字节开始,到这个字段为止。该字段长度为 32 字节。
5. 如果选项 :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 ECDSA那么应用程序镜像将有额外的 68 字节用于 ECDSA 签名,其中包括:
5. 如果选项 :menuitem:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 ECDSA那么应用程序镜像将有额外的 68 字节用于 ECDSA 签名,其中包括:
* 版本号4 字节)
* 签名数据64 字节)
6. 如果选项 :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 RSA 或 ECDSA (V2),则应用程序镜像将有一个额外的签名扇区,大小为 4K 字节。关于此签名扇区格式的更多内容,请参考 :ref:`signature-block-format`
6. 如果选项 :menuitem:`CONFIG_SECURE_SIGNED_APPS_SCHEME` 设置为 RSA 或 ECDSA (V2),则应用程序镜像将有一个额外的签名扇区,大小为 4K 字节。关于此签名扇区格式的更多内容,请参考 :ref:`signature-block-format`
.. _app-image-format-application-description:

View File

@@ -64,8 +64,8 @@
* ``magic_byte``esp_bootloader_desc 结构体的魔术字节
* ``reserved``:保留供 IDF 未来使用
* ``secure_version``:引导加载程序防回滚功能使用的安全版本,请参阅:ref:`CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE`
* ``version``:引导加载程序版本,参见 :ref:`CONFIG_BOOTLOADER_PROJECT_VER`
* ``secure_version``:引导加载程序防回滚功能使用的安全版本,请参阅:menuitem:`CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE`
* ``version``:引导加载程序版本,参见 :menuitem:`CONFIG_BOOTLOADER_PROJECT_VER`
* ``idf_ver``IDF 版本。[#f1]_
* ``date````time``:编译日期和时间
* ``reserved2``:保留供 IDF 未来使用

View File

@@ -99,7 +99,7 @@ ESP-IDF 兼容性检查
如果构建的应用程序需要支持特定芯片的多个版本,可通过 Kconfig 指定支持的最小和最大芯片版本号。
最小芯片版本号可以通过 Kconfig 选项 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 来选择。设置最小芯片版本后,软件只能在较新的芯片版本上运行,以便支持某些功能或修复某些错误。
最小芯片版本号可以通过 Kconfig 选项 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 来选择。设置最小芯片版本后,软件只能在较新的芯片版本上运行,以便支持某些功能或修复某些错误。
最大芯片版本号无法指定,只能由当前使用的 ESP-IDF 版本自动决定。ESP-IDF 会拒绝启动任何超过最大芯片版本号的芯片版本。由于特定版本的 ESP-IDF 无法预知未来的芯片版本更新,因此最大芯片版本号通常设置为 ``maximum supported MAJOR version + 99``。可以设置 “忽略最大版本” eFuse 来绕过最大版本限制,但这不能确保软件正常工作。
@@ -119,7 +119,7 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中
要解决此问题,
- 确保使用的芯片达到了要求的最低版本及以上。
- 减小 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 的值并重建镜像,使镜像的版本与当前芯片版本兼容。
- 减小 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 的值并重建镜像,使镜像的版本与当前芯片版本兼容。
1. 如果应用程序所需的芯片版本不处于最小和最大芯片版本的区间范围内,会发生重启并显示以下消息:
@@ -134,8 +134,8 @@ EFuse 块版本号与芯片版本号类似,但是它主要影响在 eFuse 中
芯片版本号检查主要根据二级引导加载程序和应用程序二进制镜像中包含的 :cpp:type:`esp_image_header_t` 标头,其中记录了可以运行该软件的芯片版本号。这一标头有 3 个与版本相关的字段:
- ``min_chip_rev`` - 镜像所需芯片的最小主版本号(但对于 ESP32-C3该字段指次版本号。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
- ``min_chip_rev_full`` - 镜像所需芯片的最小版本号,格式为 ``major * 100 + minor``。其值由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
- ``min_chip_rev`` - 镜像所需芯片的最小主版本号(但对于 ESP32-C3该字段指次版本号。其值由 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
- ``min_chip_rev_full`` - 镜像所需芯片的最小版本号,格式为 ``major * 100 + minor``。其值由 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MIN` 确定。
- ``max_chip_rev_full`` - 镜像所需芯片的最大版本号,格式为 ``major * 100 + minor``。其值由 ``CONFIG_{IDF_TARGET_CFG_PREFIX}_REV_MAX_FULL`` 确定。用户无法对其进行修改,仅当 ESP-IDF 支持新版本时由乐鑫官方进行更改。
而 eFuse 块版本的要求则存储在 :cpp:type:`esp_app_desc_t` 结构体中。该结构体对象位于应用程序的二进制进项文件中。由于 eFuse 块版本信息主要影响 ADC 校准,而二级引导加载程序的镜像不涉及 ADC因此我们只需要检查应用程序镜像的 eFuse 块版本信息。有 2 个与 eFuse 块版本相关的字段:

View File

@@ -111,7 +111,7 @@ eFuse 字段通过 CSV 文件中特定格式的表格进行定义。通过这种
.. only:: esp32
- ``MAX_BLK_LEN`` 考虑了 eFuse 的编码方案。
- 根据 :ref:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR` 选择的编码方案,``MAX_BLK_LEN`` 可能是 256("None")、192 ("3/4") 或 128 ("REPEAT") 位。
- 根据 :menuitem:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR` 选择的编码方案,``MAX_BLK_LEN`` 可能是 256("None")、192 ("3/4") 或 128 ("REPEAT") 位。
- ``comment``
@@ -256,7 +256,7 @@ eFuse 支持各种编码方式,能够检测或纠正错误,保护 eFuse 数
* 在烧录期间从 ``esptool`` 应用程序日志中查看。
* 在应用程序中调用 :cpp:func:`esp_efuse_get_coding_scheme` 函数查看 EFUSE_BLK3 块的编码方式。
CSV 文件中指定的 eFuse 字段必须始终符合芯片使用的 eFuse 编码方案。可以通过 :ref:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR` 选择 CSV 文件使用的编码方案。生成源文件时,如果 CSV 文件中的内容不符合编码方案,则会显示错误信息。在这种情况下,必须调整错误行的 ``bit_start````bit_count``,以满足所选编码方案的限制。
CSV 文件中指定的 eFuse 字段必须始终符合芯片使用的 eFuse 编码方案。可以通过 :menuitem:`CONFIG_EFUSE_CODE_SCHEME_SELECTOR` 选择 CSV 文件使用的编码方案。生成源文件时,如果 CSV 文件中的内容不符合编码方案,则会显示错误信息。在这种情况下,必须调整错误行的 ``bit_start````bit_count``,以满足所选编码方案的限制。
.. note::
@@ -540,11 +540,11 @@ eFuse 位序采取小字节序(参见下方示例),这说明 eFuse 位按
虚拟 eFuse
^^^^^^^^^^^^^^
Kconfig 选项 :ref:`CONFIG_EFUSE_VIRTUAL` 在 eFuse 管理器中虚拟了 eFuse 值,因此写入操作是仿真操作,不会永久更改 eFuse 值。这对于应用程序调试和单元测试很有用处。
Kconfig 选项 :menuitem:`CONFIG_EFUSE_VIRTUAL` 在 eFuse 管理器中虚拟了 eFuse 值,因此写入操作是仿真操作,不会永久更改 eFuse 值。这对于应用程序调试和单元测试很有用处。
在启动时eFuses 被复制到 RAM 中。此时,所有的 eFuse 操作(读和写)都是通过 RAM 执行,而不是通过实际的 eFuse 寄存器执行的。
除了 :ref:`CONFIG_EFUSE_VIRTUAL` 选项外,还有 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项,该选项可将 eFuse 保留在 flash 内存中。要使用此模式partition_table 在 ``partition.csv`` 中包含名为 ``efuse`` 的分区:
除了 :menuitem:`CONFIG_EFUSE_VIRTUAL` 选项外,还有 :menuitem:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项,该选项可将 eFuse 保留在 flash 内存中。要使用此模式partition_table 在 ``partition.csv`` 中包含名为 ``efuse`` 的分区:
.. code-block:: none
@@ -555,9 +555,9 @@ Kconfig 选项 :ref:`CONFIG_EFUSE_VIRTUAL` 在 eFuse 管理器中虚拟了 eFuse
flash 加密测试
""""""""""""""
flash 加密是一项硬件功能,需要物理烧录 eFuse ``key````FLASH_CRYPT_CNT``。如果 flash 加密实际未启用,那么启用 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项只是提供了测试的可能性,而不会加密 flash 中的任何内容,即使日志中显示了加密操作。
flash 加密是一项硬件功能,需要物理烧录 eFuse ``key````FLASH_CRYPT_CNT``。如果 flash 加密实际未启用,那么启用 :menuitem:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项只是提供了测试的可能性,而不会加密 flash 中的任何内容,即使日志中显示了加密操作。
为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :ref:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了引导加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。
为此,可使用 :cpp:func:`bootloader_flash_write` 函数。但是,如果运行应用程序时芯片已启用 flash 加密,或者以 :menuitem:`CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH` 选项创建了引导加载程序,则 flash 加密/解密操作会正常进行。这意味着数据写入加密 flash 分区时被加密,从加密分区读取时被解密。
``espefuse``
^^^^^^^^^^^^
@@ -610,7 +610,7 @@ Token 包括一个 CRC32 校验和,用于检测截断和意外修改。
* 在设备上:
* :cpp:func:`esp_efuse_token_dump()` — 始终支持生成 ``EFSR`` token``EFSW````EFSRW`` 需要启用 :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`,因为它们会暴露尚未烧写、也尚未受读保护的暂存值。
* :cpp:func:`esp_efuse_token_dump()` — 始终支持生成 ``EFSR`` token``EFSW````EFSRW`` 需要启用 :menuitem:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`,因为它们会暴露尚未烧写、也尚未受读保护的暂存值。
* :cpp:func:`esp_efuse_token_burn()` — 接受 ``EFSW`` token 并在设备上应用暂存写入。
* 在主机上:
@@ -676,8 +676,8 @@ Base64URL 使用与 Base64 相同的字母表,但将 ``+`` 替换为 ``-``
Token 类型值:
* ``ESP_EFUSE_TOKEN_FROM_READ`` — 已烧写的 eFuse 的 token``EFSR`` 开头)。
* ``ESP_EFUSE_TOKEN_FROM_STAGED`` — 暂存写入的 token``EFSW`` 开头)。它会显示尚未烧写、也尚未受读保护的值,因此可能以明文暴露密钥。需要启用 :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`。仅此类型可被烧写回。
* ``ESP_EFUSE_TOKEN_FROM_READ_STAGED`` — 组合 token``EFSRW`` 开头)。它包含同样的暂存部分,因此也具有相同的明文密钥暴露风险。需要启用 :ref:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`
* ``ESP_EFUSE_TOKEN_FROM_STAGED`` — 暂存写入的 token``EFSW`` 开头)。它会显示尚未烧写、也尚未受读保护的值,因此可能以明文暴露密钥。需要启用 :menuitem:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`。仅此类型可被烧写回。
* ``ESP_EFUSE_TOKEN_FROM_READ_STAGED`` — 组合 token``EFSRW`` 开头)。它包含同样的暂存部分,因此也具有相同的明文密钥暴露风险。需要启用 :menuitem:`CONFIG_EFUSE_ENABLE_STAGED_TOKEN_API`
如果 ``buf == NULL``token 将打印到控制台INFO 级别),不包含颜色、标签或时间戳。

View File

@@ -210,7 +210,7 @@
事件循环性能分析
--------------------
要启动数据收集,统计所有已创建事件循环的数据,请激活配置选项 :ref:`CONFIG_ESP_EVENT_LOOP_PROFILING`,函数 :cpp:func:`esp_event_dump` 可将收集的统计数据输出到文件流中。有关转储信息的更多详情,请参阅 :cpp:func:`esp_event_dump` API 参考。
要启动数据收集,统计所有已创建事件循环的数据,请激活配置选项 :menuitem:`CONFIG_ESP_EVENT_LOOP_PROFILING`,函数 :cpp:func:`esp_event_dump` 可将收集的统计数据输出到文件流中。有关转储信息的更多详情,请参阅 :cpp:func:`esp_event_dump` API 参考。
应用示例
-------------------

View File

@@ -43,13 +43,13 @@ ESP HTTPS OTA 升级
要使用分段镜像下载功能,需要:
* **启用组件级配置**:在 menuconfig 中启用 :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config````ESP HTTPS OTA````Enable partial HTTP download for OTA``)
* **启用组件级配置**:在 menuconfig 中启用 :menuitem:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config````ESP HTTPS OTA````Enable partial HTTP download for OTA``)
* **在应用程序中启用该功能**:在 :cpp:struct:`esp_https_ota_config_t` 配置结构中设置 ``partial_http_download`` 字段
启用该配置后,固件镜像将通过多个指定大小的 HTTP 请求进行下载。通过将 ``max_http_request_size`` 设置为所需值,即可指定每个请求的最大内容长度。
在从 AWS S3 等服务获取镜像时,这一选项非常有用。在启用该选项时,可以将 mbedTLS Rx 的 buffer 大小(即 :ref:`CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN`)设置为较小的值。不启用此配置时,无法将其设置为较小值。
在从 AWS S3 等服务获取镜像时,这一选项非常有用。在启用该选项时,可以将 mbedTLS Rx 的 buffer 大小(即 :menuitem:`CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN`)设置为较小的值。不启用此配置时,无法将其设置为较小值。
mbedTLS Rx buffer 的默认大小为 16 KB但如果将 ``partial_http_download````max_http_request_size`` 设置为 4 KB便能将 mbedTLS Rx 的 buffer 减小到 4 KB。使用这一配置方式预计可以节省约 12 KB 内存。

View File

@@ -232,7 +232,7 @@ FreeRTOS 定时器
1. 设置 Kconfig 选项
- 启用 :ref:`CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD`
- 启用 :menuitem:`CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD`
2. 创建定时器
@@ -273,7 +273,7 @@ FreeRTOS 定时器
1. 设置 Kconfig 选项以获取更详细的输出:
- 启用 :ref:`CONFIG_ESP_TIMER_PROFILING`
- 启用 :menuitem:`CONFIG_ESP_TIMER_PROFILING`
.. note::
@@ -281,7 +281,7 @@ FreeRTOS 定时器
2. 调用函数 :cpp:func:`esp_timer_dump`,在代码中必要的位置打印信息并用于调试定时器。
3. 结束调试后,考虑禁用 :ref:`CONFIG_ESP_TIMER_PROFILING`
3. 结束调试后,考虑禁用 :menuitem:`CONFIG_ESP_TIMER_PROFILING`
故障排除
@@ -295,7 +295,7 @@ FreeRTOS 定时器
.. list::
- :ref:`使用中断分发法 <Using ESP_TIMER_ISR Callback Method>`
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - 使用 Kconfig 选项 :ref:`CONFIG_ESP_TIMER_TASK_AFFINITY`,将 esp_timer 安装到负载较轻的 CPU 核上运行。
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - 使用 Kconfig 选项 :menuitem:`CONFIG_ESP_TIMER_TASK_AFFINITY`,将 esp_timer 安装到负载较轻的 CPU 核上运行。
分发回调函数时延迟显著
@@ -315,7 +315,7 @@ FreeRTOS 定时器
在分发回调函数时栈溢出
^^^^^^^^^^^^^^^^^^^^^^
如果在执行回调函数时遇到栈溢出的错误,请考虑减少回调函数内的栈使用量;或者,尝试通过调整 :ref:`CONFIG_ESP_TIMER_TASK_STACK_SIZE` 来增加 ESP 定时器任务栈的大小。
如果在执行回调函数时遇到栈溢出的错误,请考虑减少回调函数内的栈使用量;或者,尝试通过调整 :menuitem:`CONFIG_ESP_TIMER_TASK_STACK_SIZE` 来增加 ESP 定时器任务栈的大小。
应用示例

View File

@@ -49,14 +49,14 @@ ESP-IDF FreeRTOS
关于用户可配置内核选项的完整列表,请参见 :ref:`Kconfig 选项参考 <configuration-options-reference>`。下列为常用的内核配置选项:
- :ref:`CONFIG_FREERTOS_UNICORE`:仅在核 0 上运行 FreeRTOS。注意**不等同于运行原生 FreeRTOS。** 另外,此选项还可能影响除 :component:`freertos` 外其他组件的行为。关于在单核上运行 FreeRTOS 的更多内容,请参考 :ref:`freertos-idf-single-core` (使用 ESP-IDF FreeRTOS 时)或参考 Amazon SMP FreeRTOS 的官方文档,还可以在 ESP-IDF 组件中搜索 ``CONFIG_FREERTOS_UNICORE``
- :menuitem:`CONFIG_FREERTOS_UNICORE`:仅在核 0 上运行 FreeRTOS。注意**不等同于运行原生 FreeRTOS。** 另外,此选项还可能影响除 :component:`freertos` 外其他组件的行为。关于在单核上运行 FreeRTOS 的更多内容,请参考 :ref:`freertos-idf-single-core` (使用 ESP-IDF FreeRTOS 时)或参考 Amazon SMP FreeRTOS 的官方文档,还可以在 ESP-IDF 组件中搜索 ``CONFIG_FREERTOS_UNICORE``
.. only:: not SOC_HP_CPU_HAS_MULTIPLE_CORES
.. note::
由于 {IDF_TARGET_NAME} 是一个单核 SoC所以总是会启用 :ref:`CONFIG_FREERTOS_UNICORE` 配置。
由于 {IDF_TARGET_NAME} 是一个单核 SoC所以总是会启用 :menuitem:`CONFIG_FREERTOS_UNICORE` 配置。
- :ref:`CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY` 可以向后兼容某些 FreeRTOS 宏、类型或函数,这些宏、类型或函数已在 v8.0 及以上版本中弃用。
- :menuitem:`CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY` 可以向后兼容某些 FreeRTOS 宏、类型或函数,这些宏、类型或函数已在 v8.0 及以上版本中弃用。
端口配置
^^^^^^^^^^^^^^^^^^
@@ -96,27 +96,27 @@ ESP-IDF FreeRTOS
- 优先级
* - 空闲任务 (``IDLEx``)
- 为每个 CPU 核创建并分配一个空闲任务 (``IDLEx``),其中 ``x`` 是 CPU 核的编号。 当启用单核配置时,``x`` 将被删除。
- :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE`
- :menuitem:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE`
- 核 x
- ``0``
* - FreeRTOS 定时器任务 (``Tmr Svc``)
- 如果应用程序调用了任何 FreeRTOS 定时器 APIFreeRTOS 会创建定时器服务或守护任务
- :ref:`CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH`
- :menuitem:`CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH`
- 核 0
- :ref:`CONFIG_FREERTOS_TIMER_TASK_PRIORITY`
- :menuitem:`CONFIG_FREERTOS_TIMER_TASK_PRIORITY`
* - 主任务 (``main``)
- 简单调用 ``app_main`` 的任务在 ``app_main`` 返回时会自我删除
- :ref:`CONFIG_ESP_MAIN_TASK_STACK_SIZE`
- :ref:`CONFIG_ESP_MAIN_TASK_AFFINITY`
- :menuitem:`CONFIG_ESP_MAIN_TASK_STACK_SIZE`
- :menuitem:`CONFIG_ESP_MAIN_TASK_AFFINITY`
- ``1``
* - IPC 任务 (``ipcx``)
- 当 :ref:`CONFIG_FREERTOS_UNICORE` 为假时,为每个 CPU 核创建并分配一个 IPC 任务 (``ipcx``)。IPC 任务用于实现处理器间调用 (IPC) 功能
- :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE`
- 当 :menuitem:`CONFIG_FREERTOS_UNICORE` 为假时,为每个 CPU 核创建并分配一个 IPC 任务 (``ipcx``)。IPC 任务用于实现处理器间调用 (IPC) 功能
- :menuitem:`CONFIG_ESP_IPC_TASK_STACK_SIZE`
- 核 x
- ``24``
* - ESP 定时器任务 (``esp_timer``)
- ESP-IDF 创建 ESP 定时器任务用于处理 ESP 定时器回调
- :ref:`CONFIG_ESP_TIMER_TASK_STACK_SIZE`
- :menuitem:`CONFIG_ESP_TIMER_TASK_STACK_SIZE`
- 核 0
- ``22``

View File

@@ -391,8 +391,8 @@ ESP-IDF tick 钩子 和 idle 钩子
FreeRTOS 允许应用程序在编译时提供一个 tick 钩子和一个 idle 钩子:
- FreeRTOS tick 钩子可以通过 :ref:`CONFIG_FREERTOS_USE_TICK_HOOK` 选项启用。应用程序必须提供 ``void vApplicationTickHook( void )`` 回调。
- FreeRTOS idle 钩子可以通过 :ref:`CONFIG_FREERTOS_USE_IDLE_HOOK` 选项启用。应用程序必须提供 ``void vApplicationIdleHook( void )`` 回调。
- FreeRTOS tick 钩子可以通过 :menuitem:`CONFIG_FREERTOS_USE_TICK_HOOK` 选项启用。应用程序必须提供 ``void vApplicationTickHook( void )`` 回调。
- FreeRTOS idle 钩子可以通过 :menuitem:`CONFIG_FREERTOS_USE_IDLE_HOOK` 选项启用。应用程序必须提供 ``void vApplicationIdleHook( void )`` 回调。
然而FreeRTOS tick 钩子和 idle 钩子有以下不足:

View File

@@ -15,7 +15,7 @@ FreeRTOS (IDF)
原始 FreeRTOS下文称 Vanilla FreeRTOS是一款小巧高效的实时操作系统适用于许多单核 MCU 和 SoC。但为了支持双核 ESP 芯片,如 ESP32、ESP32-S3、ESP32-P4ESP-IDF 特别提供了支持双核对称多处理 (SMP) 的 FreeRTOS 实现(下文称 IDF FreeRTOS
IDF FreeRTOS 源代码基于 Vanilla FreeRTOS v10.5.1,但内核行为和 API 都有重大修改,以支持双核 SMP。不过用户也可以启用 :ref:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核,详情请参阅 :ref:`freertos-idf-single-core`
IDF FreeRTOS 源代码基于 Vanilla FreeRTOS v10.5.1,但内核行为和 API 都有重大修改,以支持双核 SMP。不过用户也可以启用 :menuitem:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核,详情请参阅 :ref:`freertos-idf-single-core`
.. note::
@@ -438,7 +438,7 @@ IDF FreeRTOS 中,特定核进入和退出临界区的过程如下:
.. note::
如需在 ISR 例程中使用 ``float`` 类型,请参考配置选项:ref:`CONFIG_FREERTOS_FPU_IN_ISR`
如需在 ISR 例程中使用 ``float`` 类型,请参考配置选项:menuitem:`CONFIG_FREERTOS_FPU_IN_ISR`
.. note::
@@ -487,9 +487,9 @@ IDF FreeRTOS 中,特定核进入和退出临界区的过程如下:
单核模式
^^^^^^^^
尽管 IDF FreeRTOS 是为双核 SMP 专门设计的,但也可通过启用 :ref:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核。
尽管 IDF FreeRTOS 是为双核 SMP 专门设计的,但也可通过启用 :menuitem:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核。
对于 ESP32-S2 和 ESP32-C3 等单核芯片,:ref:`CONFIG_FREERTOS_UNICORE` 选项始终启用。对于 ESP32 和 ESP32-S3 等多核芯片也可以设置 :ref:`CONFIG_FREERTOS_UNICORE`,对于多核目标(如 ESP32 和 ESP32-S3也可以设置 :ref:`CONFIG_FREERTOS_UNICORE`,但启用该选项后应用仅在核 0 上运行。
对于 ESP32-S2 和 ESP32-C3 等单核芯片,:menuitem:`CONFIG_FREERTOS_UNICORE` 选项始终启用。对于 ESP32 和 ESP32-S3 等多核芯片也可以设置 :menuitem:`CONFIG_FREERTOS_UNICORE`,对于多核目标(如 ESP32 和 ESP32-S3也可以设置 :menuitem:`CONFIG_FREERTOS_UNICORE`,但启用该选项后应用仅在核 0 上运行。
在单核模式下IDF FreeRTOS 与 Vanilla FreeRTOS 完全相同,因此无需考虑前文提到的对内核行为的 SMP 更改。因此,在单核模式下构建 IDF FreeRTOS 具有以下特点:

View File

@@ -35,7 +35,7 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 <heap-information>`、:ref:`
- 定义 :cpp:func:`esp_heap_trace_alloc_hook` 获取堆内存分配操作成功的提示。
- 定义 :cpp:func:`esp_heap_trace_free_hook` 获取堆内存释放操作成功的提示。
要启用此功能,请设置 :ref:`CONFIG_HEAP_USE_HOOKS` 选项。:cpp:func:`esp_heap_trace_alloc_hook`:cpp:func:`esp_heap_trace_free_hook` 具有弱声明(即 ``__attribute__((weak))``),因此无需为这两个钩子提供声明。鉴于从 ISR 中分配和释放堆内存在技术上是可行的(**但强烈不建议**:cpp:func:`esp_heap_trace_alloc_hook` 和 :cpp:func:`esp_heap_trace_free_hook` 可能会从 ISR 中调用。
要启用此功能,请设置 :menuitem:`CONFIG_HEAP_USE_HOOKS` 选项。:cpp:func:`esp_heap_trace_alloc_hook`:cpp:func:`esp_heap_trace_free_hook` 具有弱声明(即 ``__attribute__((weak))``),因此无需为这两个钩子提供声明。鉴于从 ISR 中分配和释放堆内存在技术上是可行的(**但强烈不建议**:cpp:func:`esp_heap_trace_alloc_hook` 和 :cpp:func:`esp_heap_trace_free_hook` 可能会从 ISR 中调用。
不建议在钩子函数中执行(或调用 API 函数执行)阻塞操作或堆内存分配与释放。一般而言,最好保持代码简洁,避免在钩子函数中进行复杂计算。
@@ -67,7 +67,7 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 <heap-information>`、:ref:`
用户可以使用 :cpp:func:`heap_caps_register_failed_alloc_callback` 注册回调函数,每次内存分配操作失败时都会调用该函数。
此外,若启用 :ref:`CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS` 选项,可以在任何分配操作失败时,自动中止系统。
此外,若启用 :menuitem:`CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS` 选项,可以在任何分配操作失败时,自动中止系统。
要注册内存分配失败的回调函数,请参阅如下示例:
@@ -111,7 +111,7 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 <heap-information>`、:ref:`
断言
^^^^^^^^^^
如 :component_file:`heap/multi_heap.c` 等堆的实现方式包含许多断言,堆内存损坏则断言失败。为高效检测堆内存损坏,请确保在项目配置中通过 :ref:`CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL` 选项启用断言。
如 :component_file:`heap/multi_heap.c` 等堆的实现方式包含许多断言,堆内存损坏则断言失败。为高效检测堆内存损坏,请确保在项目配置中通过 :menuitem:`CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL` 选项启用断言。
如果堆完整性断言失败,将打印一行类似 ``CORRUPT HEAP: multi_heap.c:225 detected at 0x3ffbb71c`` 的内容,打印的内存地址即内容损坏的堆结构地址。
@@ -135,7 +135,7 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 <heap-information>`、:ref:`
暂时提高堆内存损坏检测级别,可以进一步获取有关堆内存损坏错误的详细信息。
在项目配置菜单中,可以在 ``Component config`` 下找到 ``Heap memory debugging`` 菜单,其中的 :ref:`CONFIG_HEAP_CORRUPTION_DETECTION` 选项可以设置为以下三种级别:
在项目配置菜单中,可以在 ``Component config`` 下找到 ``Heap memory debugging`` 菜单,其中的 :menuitem:`CONFIG_HEAP_CORRUPTION_DETECTION` 选项可以设置为以下三种级别:
基本模式(无 canary 标记)
@@ -202,12 +202,12 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 <heap-information>`、:ref:`
KASAN 是一种由编译器辅助的堆内存和 DRAM 内存安全检查工具。启用后GCC 会为内存加载和存储操作插入运行时检查,对照影子内存区域进行校验。一旦发生违规访问(缓冲区溢出、下溢、释放后使用等),会在访问发生处立即报告。
可在 ``Component config`` > ``Compiler options`` > ``Enable Kernel Address Sanitizer (KASAN)`` 中启用该功能(参见 :ref:`CONFIG_COMPILER_KASAN`。该选项目前标记为实验性功能,需先开启 ``Make experimental features visible``\ (参见 :ref:`CONFIG_IDF_EXPERIMENTAL_FEATURES`)。
启用 :menuitem:`CONFIG_COMPILER_KASAN` 即可使用该功能。该选项目前标记为实验性功能,需先启用 :menuitem:`CONFIG_IDF_EXPERIMENTAL_FEATURES`
KASAN 在开发和调试阶段最为有用:
- 通过可配置的分配红区检测堆内存越界访问(参见 :ref:`CONFIG_KASAN_HEAP_REDZONE_SIZE`
- 启用已释放内存块隔离队列后,可捕获释放后使用问题(参见 :ref:`CONFIG_KASAN_QUARANTINE_SIZE`
- 通过可配置的分配红区检测堆内存越界访问(参见 :menuitem:`CONFIG_KASAN_HEAP_REDZONE_SIZE`
- 启用已释放内存块隔离队列后,可捕获释放后使用问题(参见 :menuitem:`CONFIG_KASAN_QUARANTINE_SIZE`
- 会为大多数应用程序和组件代码插桩;底层 HAL/ROM/bootloader 代码会被自动排除
需要权衡的方面:
@@ -216,7 +216,7 @@ KASAN 在开发和调试阶段最为有用:
- 影子内存会占用约 4264 KiB 的内部 DRAM取决于目标芯片
- 运行时开销较大,请勿在量产固件中启用
KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内存毒化功能,应将 :ref:`CONFIG_HEAP_CORRUPTION_DETECTION` 保持为 ``Basic (no poisoning)``\ (默认值)。
KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内存毒化功能,应将 :menuitem:`CONFIG_HEAP_CORRUPTION_DETECTION` 保持为 ``Basic (no poisoning)``\ (默认值)。
如需进行人为故障注入和回归测试,请参阅 ``tools/test_apps/system/kasan_test`` 下的 ``kasan_test`` 应用程序。
@@ -226,11 +226,11 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
堆任务跟踪
----------
可以通过 menuconfig 启用堆任务跟踪功能:``Component config`` > ``Heap memory debugging`` > ``Enable heap task tracking`` (参见 :ref:`CONFIG_HEAP_TASK_TRACKING`
可以通过 :menuitem:`CONFIG_HEAP_TASK_TRACKING` 启用堆任务跟踪功能
该功能允许用户跟踪自启动以来每个任务的堆内存使用情况,并提供一系列统计信息,这些信息可以通过 getter 函数获取,或直接输出到用户指定的流中。此功能有助于识别内存使用模式和潜在的内存泄漏。
用户还可以通过 menuconfig 启用额外配置:``Component config`` > ``Heap memory debugging`` > ``Keep information about the memory usage of deleted tasks`` (参见 :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS`,以便在任务被删除后仍然保留其统计信息。
用户还可以启用 :menuitem:`CONFIG_HEAP_TRACK_DELETED_TASKS`,以便在任务被删除后仍然保留其统计信息。
.. note::
@@ -300,7 +300,7 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
│ task_name │ ALIVE │ 0 │ 7152 │ 1 │
└────────────────────┴─────────┴──────────────────────┴───────────────────┴─────────────────┘
:cpp:func:`heap_caps_print_all_task_stat_overview` 可输出所有任务(若启用 :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS`,则包括已删除任务)的堆使用概览。
:cpp:func:`heap_caps_print_all_task_stat_overview` 可输出所有任务(若启用 :menuitem:`CONFIG_HEAP_TRACK_DELETED_TASKS`,则包括已删除任务)的堆使用概览。
.. code-block:: text
@@ -362,7 +362,7 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
用户可使用 :cpp:func:`heap_caps_get_single_task_stat` 获取指定任务的信息。通过该 API 获取的信息与 :cpp:func:`heap_caps_print_single_task_stat` 的输出内容一致。
用户可使用 :cpp:func:`heap_caps_get_all_task_stat` 获取所有任务(若启用 :ref:`CONFIG_HEAP_TRACK_DELETED_TASKS`,则包括已删除任务)的统计信息概览。通过该 API 获取的信息与 :cpp:func:`heap_caps_print_all_task_stat` 的输出内容一致。
用户可使用 :cpp:func:`heap_caps_get_all_task_stat` 获取所有任务(若启用 :menuitem:`CONFIG_HEAP_TRACK_DELETED_TASKS`,则包括已删除任务)的统计信息概览。通过该 API 获取的信息与 :cpp:func:`heap_caps_print_all_task_stat` 的输出内容一致。
每个 getter 函数都需要一个指向数据结构的指针,该结构用于堆任务跟踪收集指定任务(或所有任务)的统计信息。该数据结构包含指向数组的指针,用户可以选择静态或动态分配这些数组。
@@ -401,7 +401,7 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
确定存在泄漏的代码后,请执行以下步骤:
- 启用 :ref:`CONFIG_HEAP_TRACING_DEST` 选项。
- 启用 :menuitem:`CONFIG_HEAP_TRACING_DEST` 选项。
- 在程序早期调用函数 :cpp:func:`heap_trace_init_standalone` 注册一个可用于记录内存跟踪的缓冲区。
- 在有内存泄漏之嫌的代码块前,调用函数 :cpp:func:`heap_trace_start` 记录系统中的所有内存分配和释放操作。
- 在可疑代码执行完毕后调用 :cpp:func:`heap_trace_stop` 函数可停止跟踪内存的分配和释放。
@@ -564,11 +564,11 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
每个跟踪条目记录的调用栈深度可以在项目配置菜单下进行配置,选择 ``Heap Memory Debugging`` > ``Enable heap tracing`` > :ref:`CONFIG_HEAP_TRACING_STACK_DEPTH`。每个内存分配最多可以记录 32 个栈帧(默认为 2每增加一个栈帧每个 ``heap_trace_record_t`` 记录的内存使用量将增加 8 个字节。
每个跟踪条目记录的调用栈深度可以通过 :menuitem:`CONFIG_HEAP_TRACING_STACK_DEPTH` 进行配置。每个内存分配最多可以记录 32 个栈帧(默认为 2每增加一个栈帧每个 ``heap_trace_record_t`` 记录的内存使用量将增加 8 个字节。
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
默认情况下,每个跟踪条目的调用栈深度为 0不记录调用者 PC仍会跟踪分配地址、大小等相关字段。启用 ``CONFIG_ESP_SYSTEM_USE_FRAME_POINTER`` 后才能遍历调用栈,然后可在项目配置菜单下配置深度,选择 ``Heap Memory Debugging`` > ``Enable heap tracing`` > :ref:`CONFIG_HEAP_TRACING_STACK_DEPTH`。每个内存分配最多可以记录 32 个栈帧(默认为 2每增加一个栈帧每个 ``heap_trace_record_t`` 记录的内存使用量将增加 8 个字节。
默认情况下,每个跟踪条目的调用栈深度为 0不记录调用者 PC仍会跟踪分配地址、大小等相关字段。启用 :menuitem:`CONFIG_ESP_SYSTEM_USE_FRAME_POINTER` 后才能遍历调用栈,然后可通过 :menuitem:`CONFIG_HEAP_TRACING_STACK_DEPTH` 配置深度。每个内存分配最多可以记录 32 个栈帧(默认为 2每增加一个栈帧每个 ``heap_trace_record_t`` 记录的内存使用量将增加 8 个字节。
最后,将打印“泄漏”的总字节数(即在跟踪期间分配但未释放的总字节数),以及它所代表的总分配次数。
@@ -577,28 +577,29 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
默认情况下,堆追踪使用一个静态分配的双向链表来存储追踪记录。这种方式的缺点是,当链表中的记录条目数量增加时,查找特定记录的耗时也会随之增加,从而导致运行性能下降。因此,在需要存储大量记录时,双向链表的使用效率很低(甚至可能导致功能无法使用,因为从列表中检索条目所需的时间会阻碍应用程序的正常运行)。
为了解决这个问题,可以前往 ``Component config`` > ``Heap Memory Debugging`` 配置菜单 > 启用 :ref:`CONFIG_HEAP_TRACE_HASH_MAP` 选项,使用哈希表机制来存储记录。这样就可以在不严重影响性能的情况下追踪大量记录。
为了解决这个问题,可以启用 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP` 选项,使用哈希表机制来存储记录。这样就可以在不严重影响性能的情况下追踪大量记录。
每个哈希表条目是一个单向链表,用于存储具有相同哈希 ID 的记录。
每条记录的哈希 ID 是基于它们追踪的内存指针计算的。使用的哈希函数基于修改后的 Fowler-Noll-Vo 哈希函数,确保了所有记录在范围 [0, 哈希表大小) 内均匀分布。其中哈希表大小可以前往项目配置菜单 ``Component config`` > ``Heap Memory Debugging`` > 设置 :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 来定义。
每条记录的哈希 ID 是基于它们追踪的内存指针计算的。使用的哈希函数基于修改后的 Fowler-Noll-Vo 哈希函数,确保了所有记录在范围 [0, 哈希表大小) 内均匀分布。其中哈希表大小可以通过 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 来定义。
.. note::
.. list::
- 选项 :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 定义了哈希表中的条目数量。记录的总数量仍由用户在调用 :cpp:func:`heap_trace_init_standalone` 时定义。如果最大记录数为 ``N``,而哈希表的条目数为 ``H``,那么每个条目最多可包含 ``N / H`` 条记录。
- 选项 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 定义了哈希表中的条目数量。记录的总数量仍由用户在调用 :cpp:func:`heap_trace_init_standalone` 时定义。如果最大记录数为 ``N``,而哈希表的条目数为 ``H``,那么每个条目最多可包含 ``N / H`` 条记录。
- 哈希表是对双向链表的补充,而无法替代双向链表。因为使用哈希表可能会导致显著的内存开销。
:SOC_SPIRAM_SUPPORTED: - 存储哈希表所用的内存是动态分配的(默认分配在内部内存中),但用户可以通过前往 ``Component config`` > ``Heap Memory Debugging`` > 设置:ref:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM` 选项,将哈希表强制存储在外部内存中(此选项仅在启用了 :ref:`CONFIG_SPIRAM` 的条件下可用)。
:SOC_SPIRAM_SUPPORTED: - 存储哈希表所用的内存是动态分配的(默认分配在内部内存中),但用户可以通过 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM` 选项,将哈希表强制存储在外部内存中(此选项仅在启用了 :menuitem:`CONFIG_SPIRAM` 的条件下可用)。
主机模式
^^^^^^^^^^^^^^^
确定存在泄漏的代码后,请执行以下步骤:
- 在项目配置菜单中,前往 ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` 并选择 ``Host-Based``
- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` 并选择 ``JTAG``
- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` 并选择 ``SEGGER SystemView``
- :menuitem:`CONFIG_HEAP_TRACING_DEST` 设置为 ``Host-Based``
- :menuitem:`CONFIG_APPTRACE_DESTINATION` 设置为 ``JTAG``
- ``espressif/esp_sysview`` 托管组件依赖添加到 ``idf_component.yml``
- 启用 :menuitem:`CONFIG_ESP_TRACE_LIB_EXTERNAL`
- 在程序早期,调用函数 :cpp:func:`heap_trace_init_tohost`,初始化 JTAG 堆内存跟踪模块。
- 在有内存泄漏之嫌的代码块前,调用函数 :cpp:func:`heap_trace_start` 开始记录系统中的内存分配和释放操作。
@@ -776,11 +777,11 @@ KASAN 使用自己的堆内存钩子和红区方案。请勿同时启用堆内
运行堆内存跟踪时,堆内存分配或释放操作的速度明显变慢。增加为各内存分配的栈帧深度(见上文)也会造成这种性能影响。
为减轻堆内存跟踪运行时的性能损失,请启用 :ref:`CONFIG_HEAP_TRACE_HASH_MAP`。此时,将使用哈希映射机制处理堆内存跟踪记录,减少堆内存分配或释放操作的执行时长。设置 :ref:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 的值可以调整哈希映射的大小。
为减轻堆内存跟踪运行时的性能损失,请启用 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP`。此时,将使用哈希映射机制处理堆内存跟踪记录,减少堆内存分配或释放操作的执行时长。设置 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP_SIZE` 的值可以调整哈希映射的大小。
.. only:: SOC_SPIRAM_SUPPORTED
默认情况下,哈希映射会放置在内部 RAM 中,启用 :ref:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM` 时也可将其放置在外部 RAM 中。要启用此配置,请确保已启用 :ref:`CONFIG_SPIRAM`:ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`
默认情况下,哈希映射会放置在内部 RAM 中,启用 :menuitem:`CONFIG_HEAP_TRACE_HASH_MAP_IN_EXT_RAM` 时也可将其放置在外部 RAM 中。要启用此配置,请确保已启用 :menuitem:`CONFIG_SPIRAM`:menuitem:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`
内存泄漏误报
^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -13,7 +13,7 @@ ESP32 仍可使用大于等于 4 MiB 大小的 SPI RAM 芯片。不过,这些
使用注意事项
--------------
使用 Himem API 前,必须在 menuconfig 中启用 :ref:`CONFIG_SPIRAM_BANKSWITCH_ENABLE`,并在 :ref:`CONFIG_SPIRAM_BANKSWITCH_RESERVE` 中设置为此预留的储存体数量。这会减少由 ``malloc()`` 等函数分配的外部内存量,但允许使用 Himem API 将任何剩余内存映射到预留的存储体中。
使用 Himem API 前,必须在 menuconfig 中启用 :menuitem:`CONFIG_SPIRAM_BANKSWITCH_ENABLE`,并在 :menuitem:`CONFIG_SPIRAM_BANKSWITCH_RESERVE` 中设置为此预留的储存体数量。这会减少由 ``malloc()`` 等函数分配的外部内存量,但允许使用 Himem API 将任何剩余内存映射到预留的存储体中。
Himem API 可以看作是存储体切换方案的一个抽象。具体而言,该 API 允许声明一个或多个地址空间存储体(在 API 中称为“regions”以及一个或多个需映射到此范围的内存存储体。

View File

@@ -28,10 +28,10 @@ IPC 功能允许一个特定的内核(下文称“调用内核”)触发另
- IPC 回调应该尽可能简短。 **IPC 回调决不能阻塞或让出**
- IPC 任务是以尽可能高的优先级创建的(即 ``configMAX_PRIORITIES - 1``)。
- 如果启用了 :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,执行回调前会降低目标内核的 IPC 任务优先级,使其等于调用内核的优先级。
- 如果禁用了 :ref:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,目标内核将始终以尽可能高的优先级执行回调。
- 如果启用了 :menuitem:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,执行回调前会降低目标内核的 IPC 任务优先级,使其等于调用内核的优先级。
- 如果禁用了 :menuitem:`CONFIG_ESP_IPC_USES_CALLERS_PRIORITY`,目标内核将始终以尽可能高的优先级执行回调。
- 如果回调较为复杂,用户可能需要通过 :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE` 来配置 IPC 任务的堆栈大小。
- 如果回调较为复杂,用户可能需要通过 :menuitem:`CONFIG_ESP_IPC_TASK_STACK_SIZE` 来配置 IPC 任务的堆栈大小。
- IPC 功能受内部互斥锁保护。因此,如果同时收到来自两个或多个调用内核的 IPC 请求,将按照“先到先得”的原则按顺序处理。
API 用法
@@ -62,15 +62,15 @@ IPC 功能提供了以下 API用于在目标内核的任务上下文中执行
.. list::
:CONFIG_IDF_TARGET_ARCH_XTENSA: - 由于回调是在高优先级中断上下文中执行的,因此,回调必须完全用汇编语言编写。如需了解更多关于用汇编语言编写回调的内容,请参阅下文的 API 使用介绍。
- 保留的高优先级中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 选项。
- 保留的高优先级中断的优先级取决于 :menuitem:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 选项。
当回调执行时,需考虑以下几点:
.. list::
- 调用内核会禁用 3 级及以下优先级的中断。
:CONFIG_IDF_TARGET_ARCH_XTENSA: - 虽然保留中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,无论 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 如何设置,目标内核都会禁用 5 级及以下优先级的中断。
:CONFIG_IDF_TARGET_ARCH_RISCV: - 虽然保留中断的优先级取决于 :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,目标内核会禁用所有的中断。
:CONFIG_IDF_TARGET_ARCH_XTENSA: - 虽然保留中断的优先级取决于 :menuitem:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,无论 :menuitem:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL` 如何设置,目标内核都会禁用 5 级及以下优先级的中断。
:CONFIG_IDF_TARGET_ARCH_RISCV: - 虽然保留中断的优先级取决于 :menuitem:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`,但是在执行 IPC ISR 回调期间,目标内核会禁用所有的中断。
API 用法
^^^^^^^^^

View File

@@ -6,7 +6,7 @@
概述
--------
ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log V1****Log V2**,可通过 :ref:`CONFIG_LOG_VERSION` 参数进行选择。本文档概述了这两个日志系统版本的特性、配置及使用方法,并比较了二者的性能表现。
ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log V1****Log V2**,可通过 :menuitem:`CONFIG_LOG_VERSION` 参数进行选择。本文档概述了这两个日志系统版本的特性、配置及使用方法,并比较了二者的性能表现。
- **Log V1**:默认的原始实现方式,具备简洁性,针对早期日志和 DRAM 日志进行了优化,但 flash 占用较高,缺乏灵活性。
- **Log V2**:增强的实现方式,更加灵活,降低了 flash 占用,并集中处理日志格式,但需要更多的堆栈。
@@ -62,9 +62,9 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
通过日志级别设置,可以选择将哪些日志包含在二进制文件中,并决定这些日志在运行时的可见性。日志级别设置包括以下两种:
- **日志级别**:指定在运行时显示哪些级别的日志。引导加载程序的 **日志级别** 通过 :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` 配置,而应用程序的 **日志级别** 通过 :ref:`CONFIG_LOG_DEFAULT_LEVEL` 设置。通过函数 ``esp_log_get_default_level`` 能够获取当前日志级别。
- **日志级别**:指定在运行时显示哪些级别的日志。引导加载程序的 **日志级别** 通过 :menuitem:`CONFIG_BOOTLOADER_LOG_LEVEL` 配置,而应用程序的 **日志级别** 通过 :menuitem:`CONFIG_LOG_DEFAULT_LEVEL` 设置。通过函数 ``esp_log_get_default_level`` 能够获取当前日志级别。
- **最高日志级别**:指定将哪些日志级别包含在二进制文件中。高于此级别的日志会在编译时丢弃,不包含在最终镜像中。对于应用程序,**最高日志级别** 可以设置得高于 **日志级别**,从而在二进制文件中包含额外的日志,必要时,便可通过 :cpp:func:`esp_log_level_set` 启用这些日志以帮助调试。使用 :ref:`CONFIG_LOG_MAXIMUM_LEVEL` 选项可以为应用程序启用此功能。引导加载程序不支持此功能,其 **最高日志级别** 始终与 **日志级别** 相同。
- **最高日志级别**:指定将哪些日志级别包含在二进制文件中。高于此级别的日志会在编译时丢弃,不包含在最终镜像中。对于应用程序,**最高日志级别** 可以设置得高于 **日志级别**,从而在二进制文件中包含额外的日志,必要时,便可通过 :cpp:func:`esp_log_level_set` 启用这些日志以帮助调试。使用 :menuitem:`CONFIG_LOG_MAXIMUM_LEVEL` 选项可以为应用程序启用此功能。引导加载程序不支持此功能,其 **最高日志级别** 始终与 **日志级别** 相同。
例如,如果将 **日志级别** 设置为 **Warning****最高日志级别** 设置为 **Debug**,则二进制文件会包含 **Error****Warning****Info****Debug** 级别的日志。然而,在运行时仅输出 **Error****Warning** 级别的日志,除非通过 :cpp:func:`esp_log_level_set` 显式更改日志级别。根据具体需求,日志级别可以提高或降低。
@@ -95,7 +95,7 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
仅应用程序支持在运行时更改日志级别,启动引导加载程序不支持此功能。
默认情况下,系统启动时会启用 **日志级别** 以下的所有日志级别。可以使用函数 :cpp:func:`esp_log_level_set` 全局或按模块设置 **日志级别**。模块可通过标签识别,这些标签是人类可读以零结尾的 ASCII 字符串。此功能依赖于 :ref:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`,此选项默认启用。如无需此功能,可以将其禁用,以减少代码量并提升性能。
默认情况下,系统启动时会启用 **日志级别** 以下的所有日志级别。可以使用函数 :cpp:func:`esp_log_level_set` 全局或按模块设置 **日志级别**。模块可通过标签识别,这些标签是人类可读以零结尾的 ASCII 字符串。此功能依赖于 :menuitem:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`,此选项默认启用。如无需此功能,可以将其禁用,以减少代码量并提升性能。
例如,将所有组件的日志级别设置为 ``ERROR`` (全局设置):
@@ -103,7 +103,7 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
esp_log_level_set("*", ESP_LOG_ERROR);
根据模块(标签)调整日志输出的功能依赖于 :ref:`CONFIG_LOG_TAG_LEVEL_IMPL`,该选项默认启用。如不需要此功能,可以将其禁用,以减少代码量并提升性能。
根据模块(标签)调整日志输出的功能依赖于 :menuitem:`CONFIG_LOG_TAG_LEVEL_IMPL`,该选项默认启用。如不需要此功能,可以将其禁用,以减少代码量并提升性能。
例如,仅将 Wi-Fi 组件的日志级别设置为 ``WARNING`` (特定模块设置):
@@ -190,24 +190,24 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
日志系统支持以下格式选项,并且同时适用于应用程序和引导加载程序:
- **Color**:增加颜色代码,全局增强日志的可见性。由 :ref:`CONFIG_LOG_COLORS` 控制,默认情况下禁用,因为 ESP-IDF 监视工具 `idf.py monitor` 可以通过 **级别名称** 检测日志级别并应用标准的 IDF 颜色方案。
- **Color**:增加颜色代码,全局增强日志的可见性。由 :menuitem:`CONFIG_LOG_COLORS` 控制,默认情况下禁用,因为 ESP-IDF 监视工具 `idf.py monitor` 可以通过 **级别名称** 检测日志级别并应用标准的 IDF 颜色方案。
- 对于 **Log V2**,选项 :ref:`CONFIG_LOG_COLORS_SUPPORT` 支持在运行时为特定日志、文件或组件添加颜色输出,即使全局颜色已禁用。此时要为特定上下文启用颜色,请使用 ``ESP_LOG_COLOR_DISABLED``
- 对于 **Log V2**,选项 :menuitem:`CONFIG_LOG_COLORS_SUPPORT` 支持在运行时为特定日志、文件或组件添加颜色输出,即使全局颜色已禁用。此时要为特定上下文启用颜色,请使用 ``ESP_LOG_COLOR_DISABLED``
.. note::
IDF Monitor 需要依据上述日志消息格式,才能自动为日志添加颜色高亮效果。对格式的最低要求是:日志级别名称后接时间戳,且每条日志消息必须以换行符结尾。例如,``I (56): Log message\n``。如果未遵循此格式(例如禁用了时间戳),自动日志着色将失效。在这种情况下,建议在 menuconfig 中启用 :ref:`CONFIG_LOG_COLORS` 配置项。此外还有一个限制,即对于多行日志消息,只有第一行会被正确着色。
IDF Monitor 需要依据上述日志消息格式,才能自动为日志添加颜色高亮效果。对格式的最低要求是:日志级别名称后接时间戳,且每条日志消息必须以换行符结尾。例如,``I (56): Log message\n``。如果未遵循此格式(例如禁用了时间戳),自动日志着色将失效。在这种情况下,建议在 menuconfig 中启用 :menuitem:`CONFIG_LOG_COLORS` 配置项。此外还有一个限制,即对于多行日志消息,只有第一行会被正确着色。
- **Level Name**表示日志详细级别的单个字母I, W, E, D, V显示在每条日志消息的开头用于识别日志级别。这在禁用颜色时非常有用例如在禁用颜色时 ESP-IDF 监视工具就会使用该信息。
- **Timestamp**:为日志消息全局添加时间戳。由 :ref:`CONFIG_LOG_TIMESTAMP_SOURCE` 控制。
- **Timestamp**:为日志消息全局添加时间戳。由 :menuitem:`CONFIG_LOG_TIMESTAMP_SOURCE` 控制。
- **None**:不显示时间戳。在日志分析或调试中,当时间不关键时非常有用,还能够节省处理性能和内存。仅适用于 **Log V2**
- **Milliseconds since boot** `(18532)` (默认):通过 RTOS 时钟 tick 计数乘以 tick 周期得出。
- **System time (HH:MM:SS.sss)** `14:31:18.532`:以小时、分钟、秒和毫秒显示时间。
- **System time (YY-MM-DD HH:MM:SS.sss)** `(2023-08-15 14:31:18.532)`:同上,还包括日期。
- **Unix time in milliseconds** `(1692099078532)`:以毫秒显示 Unix 时间。
- 对于 **Log V2**,选项 :ref:`CONFIG_LOG_TIMESTAMP_SUPPORT` 支持在运行时为特定日志、文件或组件添加时间戳输出,即使全局时间戳已禁用。要为特定上下文启用 **Milliseconds since boot** 时间戳,请使用 ``ESP_LOG_TIMESTAMP_DISABLED``
- 对于 **Log V2**,选项 :menuitem:`CONFIG_LOG_TIMESTAMP_SUPPORT` 支持在运行时为特定日志、文件或组件添加时间戳输出,即使全局时间戳已禁用。要为特定上下文启用 **Milliseconds since boot** 时间戳,请使用 ``ESP_LOG_TIMESTAMP_DISABLED``
- **Tag**:显示用户定义的源模块标识符。
@@ -226,15 +226,15 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
- 默认为 ``0``,即启用所有格式化项,如颜色、时间戳、标记和末尾换行。
- 定义为 ``1`` 时,为指定范围禁用所有的格式化项。
- **ESP_LOG_COLOR_DISABLED**:要求启用 :ref:`CONFIG_LOG_COLORS_SUPPORT`
- **ESP_LOG_COLOR_DISABLED**:要求启用 :menuitem:`CONFIG_LOG_COLORS_SUPPORT`
- 如果全局颜色 (:ref:`CONFIG_LOG_COLORS`) 已禁用,则定义为 ``0``,以启用指定范围的颜色输出。
- 如果启用了全局颜色 (:ref:`CONFIG_LOG_COLORS`),则定义为 ``1``,表示禁用指定范围的颜色输出。
- 如果全局颜色 (:menuitem:`CONFIG_LOG_COLORS`) 已禁用,则定义为 ``0``,以启用指定范围的颜色输出。
- 如果启用了全局颜色 (:menuitem:`CONFIG_LOG_COLORS`),则定义为 ``1``,表示禁用指定范围的颜色输出。
- **ESP_LOG_TIMESTAMP_DISABLED**:要求启用 :ref:`CONFIG_LOG_TIMESTAMP_SUPPORT`
- **ESP_LOG_TIMESTAMP_DISABLED**:要求启用 :menuitem:`CONFIG_LOG_TIMESTAMP_SUPPORT`
- 如果已禁用全局时间戳(:ref:`CONFIG_LOG_TIMESTAMP_SOURCE`),则定义为 ``0``,以启用指定范围的时间戳输出。
- 如果全局时间戳(:ref:`CONFIG_LOG_TIMESTAMP_SOURCE`)已启用,则定义为 ``1``,表示禁用指定范围的时间戳输出。
- 如果已禁用全局时间戳(:menuitem:`CONFIG_LOG_TIMESTAMP_SOURCE`),则定义为 ``0``,以启用指定范围的时间戳输出。
- 如果全局时间戳(:menuitem:`CONFIG_LOG_TIMESTAMP_SOURCE`)已启用,则定义为 ``1``,表示禁用指定范围的时间戳输出。
- **ESP_LOG_MODE_BINARY_EN**:要求启用 ``CONFIG_LOG_MODE_BINARY````CONFIG_BOOTLOADER_LOG_MODE_BINARY`` 配置项。
@@ -295,7 +295,7 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
下列三种设置可在运行时全局更改日志级别,或为单个模块(标签)更改日志级别:
- **Dynamic Log Level Control** :ref:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`,默认已启用):动态日志级别控制。启用后,可以通过 :cpp:func:`esp_log_level_set` 函数在运行时更改日志级别。该功能提高了灵活性,但也增加了内存和性能开销。如需考虑二进制文件的大小,并且无需在运行时动态更改日志级别,建议禁用此选项,特别是在 :ref:`CONFIG_LOG_TAG_LEVEL_IMPL` 设置为 **None** 时,以尽量减小程序大小。
- **Dynamic Log Level Control** :menuitem:`CONFIG_LOG_DYNAMIC_LEVEL_CONTROL`,默认已启用):动态日志级别控制。启用后,可以通过 :cpp:func:`esp_log_level_set` 函数在运行时更改日志级别。该功能提高了灵活性,但也增加了内存和性能开销。如需考虑二进制文件的大小,并且无需在运行时动态更改日志级别,建议禁用此选项,特别是在 :menuitem:`CONFIG_LOG_TAG_LEVEL_IMPL` 设置为 **None** 时,以尽量减小程序大小。
如果你的应用程序不需要动态调整日志级别,禁用此选项可以提高效率:
@@ -307,7 +307,7 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
- 提高日志操作性能,最多提高 10 倍。
- **Tag-Level Checks** :ref:`CONFIG_LOG_TAG_LEVEL_IMPL`,默认值为 **Cache + Linked List**):标签级别检查,决定了如何检查每个标签的日志级别,影响内存使用和查找速度:
- **Tag-Level Checks** :menuitem:`CONFIG_LOG_TAG_LEVEL_IMPL`,默认值为 **Cache + Linked List**):标签级别检查,决定了如何检查每个标签的日志级别,影响内存使用和查找速度:
- **None**:完全禁用按标签进行日志级别检查,能够减少开销,但失去了运行时的灵活性。
@@ -315,21 +315,21 @@ ESP-IDF 提供了一套灵活的日志系统,包括两个可配置版本 **Log
- **Cache + Linked List** (默认):缓存 + 链表,通过缓存与链表结合的方式进行日志标签级别检查,实现了内存占用和运行速度之间的平衡。缓存用于存储最近访问的日志标签及其对应的日志级别,加速了常用标签的查找。这是因为缓存方式会比较标签指针,与执行完整字符串相比速度更快。对不常用标签,通过链表进行日志级别查找。注意,使用动态标签定义时,此选项可能无法正常工作,因为它依赖缓存中的标签指针比较,不适用于动态定义的标签。此混合方法利用了常用标签的缓存速度优势和不常用标签的链表存储效率,提升了日志级别查找的总体效率。选择此选项会自动启用 **Dynamic Log Level Control**
有一些缓存配置可以平衡内存使用和查找性能。这些配置决定了日志标签级别的存储和访问方式,详见 :ref:`CONFIG_LOG_TAG_LEVEL_CACHE_IMPL`
有一些缓存配置可以平衡内存使用和查找性能。这些配置决定了日志标签级别的存储和访问方式,详见 :menuitem:`CONFIG_LOG_TAG_LEVEL_CACHE_IMPL`
- **Array**:数组方式,实现简单,不进行重新排序,适合注重简洁性的低内存应用。
- **Binary Min-Heap** (默认配置)最小二叉堆,优化的实现方式,支持快速查找并自动重新排序,适用于具有充足内存的高性能应用。其容量由 **缓存大小** (:ref:`CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE`) 定义,默认包含 31 个条目。
- **Binary Min-Heap** (默认配置)最小二叉堆,优化的实现方式,支持快速查找并自动重新排序,适用于具有充足内存的高性能应用。其容量由 **缓存大小** (:menuitem:`CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE`) 定义,默认包含 31 个条目。
缓存容量越大,查找常用日志标签的性能越高,但内存消耗也会增加。相反,缓存容量越小越节省内存,但可能导致不常用的日志标签被更频繁地移除。
- **Master Log Level** :ref:`CONFIG_LOG_MASTER_LEVEL`,默认禁用):这是一个可选设置,专为特定调试场景设计。此设置启用后,会在生成时间戳和标签缓存查找之前,启用全局 master 日志级别检查。这一选项适用于编译大量日志的情况,可以在运行时有选择地启用或禁用日志,同时在不需要日志输出时尽量减少对性能的影响。
- **Master Log Level** :menuitem:`CONFIG_LOG_MASTER_LEVEL`,默认禁用):这是一个可选设置,专为特定调试场景设计。此设置启用后,会在生成时间戳和标签缓存查找之前,启用全局 master 日志级别检查。这一选项适用于编译大量日志的情况,可以在运行时有选择地启用或禁用日志,同时在不需要日志输出时尽量减少对性能的影响。
例如,通常可以在在时间紧迫或 CPU 密集型操作期间临时禁用日志,并在之后重新启用日志。
.. note:: 对于 **Log V1**,此功能可能会基于已编译日志的数量而显著增加程序大小。对于 **Log V2** 影响很小,因为检查已集成到了日志处理程序中。
如果启用此功能master 日志级别默认为 :ref:`CONFIG_LOG_DEFAULT_LEVEL`,并可在运行时通过 :cpp:func:`esp_log_set_level_master` 进行调整。此全局检查优先于 ``esp_log_get_default_level``
如果启用此功能master 日志级别默认为 :menuitem:`CONFIG_LOG_DEFAULT_LEVEL`,并可在运行时通过 :cpp:func:`esp_log_set_level_master` 进行调整。此全局检查优先于 ``esp_log_get_default_level``
以下代码片段演示了此功能的原理。将 **Master Log Level** 设置为 ``ESP_LOG_NONE``,会在全局范围内禁用所有日志。此时,:cpp:func:`esp_log_level_set` 不会影响日志输出。但是,当 **Master Log Level** 调整为更高级别后,日志会按照 :cpp:func:`esp_log_level_set` 的配置打印出来:
@@ -665,13 +665,13 @@ buffer 日志需特殊处理
在 IRAM 与 DRAM 共用同一内存池的芯片上,这也会减少相应的可用堆空间(约 1.2 KB
为消除该开销,请禁用 :ref:`CONFIG_LOG_API_CONSTRAINED_ENV_SAFE` (默认启用)。禁用后:
为消除该开销,请禁用 :menuitem:`CONFIG_LOG_API_CONSTRAINED_ENV_SAFE` (默认启用)。禁用后:
- ``ESP_DRAM_LOGx````ESP_EARLY_LOGx`` 直接展开为 ``esp_rom_printf()`` (真正的 ROM 函数,无需 IRAM 开销),完全绕过 ``esp_log()`` 处理流程。
- 在受限环境中,普通的 ``ESP_LOGx`` 调用将使用标准 ``vprintf`` 函数。如果 ``vprintf`` 位于 flash 中,此类调用可能导致崩溃。对于必须在缓存被禁用时或在 ISR 中使用的日志,请使用 ``ESP_DRAM_LOGx``
- ``esp_rom_vprintf`` 不会被引用,因此链接器会将其从二进制文件中排除。
若启用 :ref:`CONFIG_LOG_API_CONSTRAINED_ENV_SAFE`,则保留原始 **Log V2** 行为:所有受限环境的日志都通过 ``esp_log()`` 路由,并使用 ``esp_rom_vprintf`` 作为早期/DRAM 日志的格式化函数。
若启用 :menuitem:`CONFIG_LOG_API_CONSTRAINED_ENV_SAFE`,则保留原始 **Log V2** 行为:所有受限环境的日志都通过 ``esp_log()`` 路由,并使用 ``esp_rom_vprintf`` 作为早期/DRAM 日志的格式化函数。
通过 JTAG 将日志记录到主机
------------------------------

View File

@@ -52,7 +52,7 @@ MAC 地址
.. note::
在 ESP32-P4 上,:ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 固定为单个通用管理型 MAC 地址。
在 ESP32-P4 上,:menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 固定为单个通用管理型 MAC 地址。
.. only:: (not esp32s2) and (not esp32p4) and (not esp32h2) and (not esp32h21) and (not esp32h4) and (not esp32s31)
@@ -78,7 +78,7 @@ MAC 地址
.. note::
:ref:`配置选项 <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` 配置了乐鑫提供的全局 MAC 地址的数量。
:menuitem:`配置选项 <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` 配置了乐鑫提供的全局 MAC 地址的数量。
.. only:: esp32s31
@@ -104,7 +104,7 @@ MAC 地址
.. note::
{IDF_TARGET_NAME} 在 eFuse 中仅提供两个全局管理型 MAC 地址,因此 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 默认为两个。其中的“四个”选项仅在使用客户自定义基准 MAC 范围时可用(参见 :ref:`自定义基准 MAC <MAC-Address-Allocation>`),且该范围内每个设备需分配 4 个全局管理型 MAC 地址。若在使用乐鑫 eFuse 默认基准 MAC 时选择“四个”SoftAP 和以太网会占用 base+1/+3 的全局 MAC 槽位,而这些槽位在本芯片上并未分配,可能与蓝牙 MAC 发生冲突。
{IDF_TARGET_NAME} 在 eFuse 中仅提供两个全局管理型 MAC 地址,因此 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 默认为两个。其中的“四个”选项仅在使用客户自定义基准 MAC 范围时可用(参见 :ref:`自定义基准 MAC <MAC-Address-Allocation>`),且该范围内每个设备需分配 4 个全局管理型 MAC 地址。若在使用乐鑫 eFuse 默认基准 MAC 时选择“四个”SoftAP 和以太网会占用 base+1/+3 的全局 MAC 槽位,而这些槽位在本芯片上并未分配,可能与蓝牙 MAC 发生冲突。
.. only:: esp32h2 or esp32h21 or esp32h4
@@ -121,7 +121,7 @@ MAC 地址
.. note::
{IDF_TARGET_NAME} 在 eFuse 中仅提供一个全局管理型 MAC 地址MAC_FACTORY以及用于构造 IEEE 802.15.4 EUI-64 的 MAC_EXT 字段。:ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 固定为 1。蓝牙直接复用基准 MAC —— 由于 {IDF_TARGET_NAME} 没有 Wi-FiBT 偏移不会生效,因此不需要第二个全局 MAC 槽位。
{IDF_TARGET_NAME} 在 eFuse 中仅提供一个全局管理型 MAC 地址MAC_FACTORY以及用于构造 IEEE 802.15.4 EUI-64 的 MAC_EXT 字段。:menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES` 固定为 1。蓝牙直接复用基准 MAC —— 由于 {IDF_TARGET_NAME} 没有 Wi-FiBT 偏移不会生效,因此不需要第二个全局 MAC 槽位。
.. only:: esp32s2
@@ -144,7 +144,7 @@ MAC 地址
.. note::
:ref:`配置选项 <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` 配置了乐鑫提供的全局 MAC 地址的数量。
:menuitem:`配置选项 <CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES>` 配置了乐鑫提供的全局 MAC 地址的数量。
.. only:: not SOC_EMAC_SUPPORTED
@@ -162,7 +162,7 @@ MAC 地址
乐鑫已将默认的基准 MAC 地址预烧录至 eFuse {IDF_TARGET_BASE_MAC_BLOCK} 中。如需设置自定义基准 MAC 地址,请在初始化任一网络接口或调用 :cpp:func:`esp_read_mac` 函数前调用 :cpp:func:`esp_base_mac_addr_set` 函数。自定义基准 MAC 地址可以存储在任何支持的存储设备中(例如 flash、NVS
分配自定义基准 MAC 地址时,应避免 MAC 地址重叠。请根据上面的表格配置选项 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES`,设置可从自定义基准 MAC 地址生成的有效全局 MAC 地址。
分配自定义基准 MAC 地址时,应避免 MAC 地址重叠。请根据上面的表格配置选项 :menuitem:`CONFIG_{IDF_TARGET_CFG_PREFIX}_UNIVERSAL_MAC_ADDRESSES`,设置可从自定义基准 MAC 地址生成的有效全局 MAC 地址。
.. note::
@@ -292,7 +292,7 @@ SDK 版本
若需手动设置版本,需要在项目的 ``CMakeLists.txt`` 文件中设置 ``PROJECT_VER`` 变量,即在 ``CMakeLists.txt`` 文件中,在包含 ``project.cmake`` 之前添加 ``set(PROJECT_VER "0.1.0.1")``
如果设置了 :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` 选项,则将使用 :ref:`CONFIG_APP_PROJECT_VER` 的值。否则,如果在项目中未设置 ``PROJECT_VER`` 变量,则该变量将从 ``$(PROJECT_PATH)/version.txt`` 文件(若有)中检索,或使用 git 命令 ``git describe`` 检索。如果两者都不可用,则 ``PROJECT_VER`` 将被设置为 “1”。应用程序可通过调用 :cpp:func:`esp_app_get_description`:cpp:func:`esp_ota_get_partition_description` 函数来获取应用程序的版本信息。
如果设置了 :menuitem:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` 选项,则将使用 :menuitem:`CONFIG_APP_PROJECT_VER` 的值。否则,如果在项目中未设置 ``PROJECT_VER`` 变量,则该变量将从 ``$(PROJECT_PATH)/version.txt`` 文件(若有)中检索,或使用 git 命令 ``git describe`` 检索。如果两者都不可用,则 ``PROJECT_VER`` 将被设置为 “1”。应用程序可通过调用 :cpp:func:`esp_app_get_description`:cpp:func:`esp_ota_get_partition_description` 函数来获取应用程序的版本信息。
应用示例
--------------

View File

@@ -42,7 +42,7 @@ OTA 数据分区的容量是 2 个 flash 扇区的大小0x2000 字节),
* 应用程序运行正常,:cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 将正在运行的应用程序状态标记为 ``ESP_OTA_IMG_VALID``,启动此应用程序无限制。
* 应用程序出现严重错误,无法继续工作,必须回滚到此前的版本,:cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 将正在运行的版本标记为 ``ESP_OTA_IMG_INVALID`` 然后复位。引导加载程序不会选取此版本,而是启动此前正常运行的版本。
* 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,则无需调用函数便可复位,回滚至之前的应用版本。
* 如果 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,则无需调用函数便可复位,回滚至之前的应用版本。
可使用以下代码检测 OTA 更新后应用程序的首次启动。首次启动时,应用程序会检查其状态并执行检测。如果检测成功,应用程序调用 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 函数,确认应用运行成功。如果检测失败,应用程序调用 :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 函数,回滚至之前的应用版本。
@@ -84,23 +84,23 @@ OTA 数据分区的容量是 2 个 flash 扇区的大小0x2000 字节),
ESP_OTA_IMG_UNDEFINED 没有限制,可以选取。
ESP_OTA_IMG_INVALID 不会选取。
ESP_OTA_IMG_ABORTED 不会选取。
ESP_OTA_IMG_NEW 如使能 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`
ESP_OTA_IMG_NEW 如使能 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`
则仅会选取一次。在引导加载程序中,状态立即变为
``ESP_OTA_IMG_PENDING_VERIFY``
ESP_OTA_IMG_PENDING_VERIFY 如使能 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`
ESP_OTA_IMG_PENDING_VERIFY 如使能 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE`
则不会选取,状态变为 ``ESP_OTA_IMG_ABORTED``
============================= ========================================================
如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 没有使能(默认情况),则 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback`:cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 为可选功能,``ESP_OTA_IMG_NEW````ESP_OTA_IMG_PENDING_VERIFY`` 不会使用。
如果 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 没有使能(默认情况),则 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback`:cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 为可选功能,``ESP_OTA_IMG_NEW````ESP_OTA_IMG_PENDING_VERIFY`` 不会使用。
Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户追踪新版应用程序的第一次启动。应用程序需调用 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 函数确认可以运行,否则将会在重启时回滚至旧版本。该功能可让用户在启动阶段控制应用程序的可操作性。新版应用程序仅有一次机会尝试是否能成功启动。
Kconfig 中的 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户追踪新版应用程序的第一次启动。应用程序需调用 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 函数确认可以运行,否则将会在重启时回滚至旧版本。该功能可让用户在启动阶段控制应用程序的可操作性。新版应用程序仅有一次机会尝试是否能成功启动。
.. _ota_rollback:
回滚过程
^^^^^^^^
:ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能时,回滚过程如下:
:menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能时,回滚过程如下:
* 新版应用程序下载成功,:cpp:func:`esp_ota_set_boot_partition` 函数将分区设为可启动,状态设为 ``ESP_OTA_IMG_NEW``。该状态表示应用程序为新版本,第一次启动需要监测。
* 重新启动 :cpp:func:`esp_restart`
@@ -138,11 +138,11 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户
下文简单描述了如何设置应用程序状态:
* ``ESP_OTA_IMG_VALID`` 由函数 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 设置。
* 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 没有使能,``ESP_OTA_IMG_UNDEFINED`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。
* 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,``ESP_OTA_IMG_NEW`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。
* 如果 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 没有使能,``ESP_OTA_IMG_UNDEFINED`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。
* 如果 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,``ESP_OTA_IMG_NEW`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。
* ``ESP_OTA_IMG_INVALID`` 由函数 :cpp:func:`esp_ota_mark_app_invalid_rollback`:cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 设置。
* 如果应用程序的可操作性无法确认,发生重启(:ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能),则设置 ``ESP_OTA_IMG_ABORTED``
* 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,选取的应用程序状态为 ``ESP_OTA_IMG_NEW``,则在引导加载程序中设置 ``ESP_OTA_IMG_PENDING_VERIFY``
* 如果应用程序的可操作性无法确认,发生重启(:menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能),则设置 ``ESP_OTA_IMG_ABORTED``
* 如果 :menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,选取的应用程序状态为 ``ESP_OTA_IMG_NEW``,则在引导加载程序中设置 ``ESP_OTA_IMG_PENDING_VERIFY``
.. _anti-rollback:
@@ -153,9 +153,9 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户
防回滚机制可以防止回滚到安全版本号低于芯片 eFuse 中烧录程序的应用程序版本。
设置 :ref:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK`,启动防回滚机制。在引导加载程序中选取可启动的应用程序,会额外检查芯片和应用程序镜像的安全版本号。可启动固件中的应用安全版本号必须等于或高于芯片中的应用安全版本号。
设置 :menuitem:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK`,启动防回滚机制。在引导加载程序中选取可启动的应用程序,会额外检查芯片和应用程序镜像的安全版本号。可启动固件中的应用安全版本号必须等于或高于芯片中的应用安全版本号。
:ref:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK`:ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 一起使用。此时,只有安全版本号等于或高于芯片中的应用安全版本号时才会回滚。
:menuitem:`CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK`:menuitem:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 一起使用。此时,只有安全版本号等于或高于芯片中的应用安全版本号时才会回滚。
典型的防回滚机制
@@ -206,13 +206,13 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户
.. list::
- ``secure_version`` 字段最多有 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 位。也就是说,防回滚最多可以做 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 次。用户可以使用 :ref:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD` 减少该 eFuse 字段的长度。
- ``secure_version`` 字段最多有 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 位。也就是说,防回滚最多可以做 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 次。用户可以使用 :menuitem:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD` 减少该 eFuse 字段的长度。
:esp32: - 防回滚仅在 eFuse 编码机制设置为 ``NONE`` 时生效。
- 防回滚不支持工厂和测试分区,因此分区表中不应有设置为 ``工厂````测试`` 的分区。
``security_version``:
- 存储在应用程序镜像中的 ``esp_app_desc`` 里。版本号用 :ref:`CONFIG_BOOTLOADER_APP_SECURE_VERSION` 设置。
- 存储在应用程序镜像中的 ``esp_app_desc`` 里。版本号用 :menuitem:`CONFIG_BOOTLOADER_APP_SECURE_VERSION` 设置。
.. only:: esp32
@@ -224,7 +224,7 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户
没有安全启动的安全 OTA 升级
---------------------------
即便硬件安全启动没有使能,也可验证已签名的 OTA 升级。可通过设置 :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT`:ref:`CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT` 实现。
即便硬件安全启动没有使能,也可验证已签名的 OTA 升级。可通过设置 :menuitem:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT`:menuitem:`CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT` 实现。
.. only:: esp32
@@ -235,7 +235,7 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户
签名数据分区的更新
------------------
数据分区镜像可以使用与应用镜像相同的 Secure Boot v2 签名机制进行验证。启用 :ref:`CONFIG_SECURE_SIGNED_DATA_PARTITION`,以便在 OTA 更新期间验证子类型为 ``ESP_PARTITION_SUBTYPE_DATA_UNDEFINED`` 的数据分区。
数据分区镜像可以使用与应用镜像相同的 Secure Boot v2 签名机制进行验证。启用 :menuitem:`CONFIG_SECURE_SIGNED_DATA_PARTITION`,以便在 OTA 更新期间验证子类型为 ``ESP_PARTITION_SUBTYPE_DATA_UNDEFINED`` 的数据分区。
使用以下命令对数据分区镜像进行签名:

View File

@@ -21,7 +21,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
电源管理配置
-------------
编译时可使用 :ref:`CONFIG_PM_ENABLE` 选项启用电源管理功能。
编译时可使用 :menuitem:`CONFIG_PM_ENABLE` 选项启用电源管理功能。
启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关例如CPU 频率、单/双核模式、是否需要进行频率切换等。CPU 频率为 240 MHz 且未启用频率调节时,最小额外延迟为 0.2 us如果启用频率调节且在中断入口将频率由 40 MHz 调节至 80 MHz则最大额外延迟为 40 us。
@@ -29,7 +29,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
.. list::
- ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`
- ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :menuitem:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`
:esp32 or esp32s2: - ``min_freq_mhz``:最小 CPU 频率 (MHz)即未持有电源管理锁时所使用的频率。注意10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。
@@ -38,11 +38,11 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
- ``light_sleep_enable``:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (``true``/``false``)。
如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
如果在 menuconfig 中启用了 :menuitem:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :menuitem:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。
.. note::
自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。
自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :menuitem:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。
.. note::
@@ -88,7 +88,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
{IDF_TARGET_NAME} 电源管理算法
--------------------------------
下表列出了启用动态调频时如何切换 CPU 频率和 APB 频率。可以使用 :cpp:func:`esp_pm_configure`:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ` 指定 CPU 最大频率。
下表列出了启用动态调频时如何切换 CPU 频率和 APB 频率。可以使用 :cpp:func:`esp_pm_configure`:menuitem:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ` 指定 CPU 最大频率。
.. include:: inc/power_management_{IDF_TARGET_PATH_NAME}.rst
@@ -110,10 +110,10 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会
但实际开销可能因缓存未命中、CPU 频率变化、Flash 延迟变化或硬件状态恢复时间而有所不同。当实际开销超过预测值时,实际睡眠时间可能超过预期,导致 :cpp:func:`vTaskStepTick()` 接收到的 tick 补偿值过大,触发断言失败。
:ref:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION` 选项提供了一个安全机制,用于在唤醒开销超过预测时防止断言失败。启用后,系统会限制 tick 补偿值以防止溢出。在 menuconfig 中可通过 ``Component config`` > ``Power Management`` > ``Enable light sleep tick overflow protection`` 启用此选项。
:menuitem:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION` 选项提供了一个安全机制,用于在唤醒开销超过预测时防止断言失败。启用后,系统会限制 tick 补偿值以防止溢出。
启用该选项时,系统对睡过超时情况的处理如下:
- 如果睡过超时在容忍范围内(可通过 :ref:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE` 配置默认2 个 tick系统会静默地将 ``slept_ticks`` 限制为 ``xExpectedIdleTime``,防止断言失败
- 如果睡过超时在容忍范围内(可通过 :menuitem:`CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE` 配置默认2 个 tick系统会静默地将 ``slept_ticks`` 限制为 ``xExpectedIdleTime``,防止断言失败
- 如果睡过超时超过容忍范围(可能存在 bug系统不会限制 tick会抛出错误日志并触发断言失败
- 在极少数边缘场景下可能会丢失 tick导致 FreeRTOS tick 计数(``xTickCount``)落后于真实时间(``esp_timer``),使用 :cpp:func:`vTaskDelay()` 的任务可能比预期延迟稍长FreeRTOS 软件定时器精度可能降低。
@@ -137,7 +137,7 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会
3. 通过分析锁使用模式来优化功耗
4. 调试与应用程序中锁管理相关的问题
要启用性能分析功能(单个锁的计时信息),请在 menuconfig 中启用 :ref:`CONFIG_PM_PROFILING` 选项。
要启用性能分析功能(单个锁的计时信息),请在 menuconfig 中启用 :menuitem:`CONFIG_PM_PROFILING` 选项。
应用示例
-------------------
@@ -170,7 +170,7 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会
- **Ethernet**:从调用 :cpp:func:`esp_eth_driver_install`:cpp:func:`esp_eth_driver_uninstall` 期间。
:SOC_WIFI_SUPPORTED: - **WiFi**:从调用 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间。如果启用了调制解调器睡眠模式,广播关闭时将释放此管理锁。
:SOC_TWAI_SUPPORTED: - **TWAI**:从调用 :cpp:func:`twai_driver_install` 至 :cpp:func:`twai_driver_uninstall` 期间 (只有在 TWAI 时钟源选择为 :cpp:enumerator:`TWAI_CLK_SRC_APB` 的时候生效)。
:SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。
:SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :menuitem:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。
:SOC_BT_SUPPORTED and not esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。
:SOC_PCNT_SUPPORTED: - **PCNT**:从调用 :cpp:func:`pcnt_unit_enable` 至 :cpp:func:`pcnt_unit_disable` 期间。
:SOC_SDM_SUPPORTED: - **Sigma-delta**:从调用 :cpp:func:`sdm_channel_enable` 至 :cpp:func:`sdm_channel_disable` 期间。
@@ -183,7 +183,7 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会
{IDF_TARGET_NAME} 支持在 Light-sleep 时掉电外设的电源域.
如果在 menuconfig 中启用了 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,在初始化外设时,驱动会将外设工作的寄存器上下文注册到休眠备份链表中,在进入休眠前,``REG_DMA`` 外设会读取休眠备份链表中的配置,根据链表中的配置将外设的寄存器上下文备份至内存,``REG_DMA`` 也会在唤醒时将上下文从内存恢复到外设寄存中。
如果在 menuconfig 中启用了 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,在初始化外设时,驱动会将外设工作的寄存器上下文注册到休眠备份链表中,在进入休眠前,``REG_DMA`` 外设会读取休眠备份链表中的配置,根据链表中的配置将外设的寄存器上下文备份至内存,``REG_DMA`` 也会在唤醒时将上下文从内存恢复到外设寄存中。
目前 IDF 支持以下外设的 Light-sleep 上下文备份,它们的上下文会自动恢复,或者提供了相关的选项允许用户进入外设下电模式:

View File

@@ -25,7 +25,7 @@ RTOS 集成
.. note::
如果调用 C 标准库或 C++ sleep 函数,例如在 ``unistd.h`` 中定义的 ``usleep``,那么只有当睡眠时间超过 :ref:`一个 FreeRTOS 滴答周期 <CONFIG_FREERTOS_HZ>` 时,任务才会阻塞并让出内核。如果时间较短,线程将处于忙等待状态,不会让步给另一个 RTOS 任务。
如果调用 C 标准库或 C++ sleep 函数,例如在 ``unistd.h`` 中定义的 ``usleep``,那么只有当睡眠时间超过 :menuitem:`一个 FreeRTOS 滴答周期 <CONFIG_FREERTOS_HZ>` 时,任务才会阻塞并让出内核。如果时间较短,线程将处于忙等待状态,不会让步给另一个 RTOS 任务。
.. note::
@@ -110,7 +110,7 @@ POSIX 互斥锁被实现为 FreeRTOS 互斥信号量(普通类型用于“快
支持静态初始化常量 ``PTHREAD_COND_INITIALIZER``
* ``pthread_cond_timedwait()`` 超时的分辨率为 RTOS 滴答周期(参见 :ref:`CONFIG_FREERTOS_HZ`)。在请求超时后,超时最多会延迟一个滴答周期。
* ``pthread_cond_timedwait()`` 超时的分辨率为 RTOS 滴答周期(参见 :menuitem:`CONFIG_FREERTOS_HZ`)。在请求超时后,超时最多会延迟一个滴答周期。
.. note::
@@ -173,7 +173,7 @@ ESP-IDF 中实现了 POSIX 读写锁规范的以下 API 函数:
.. note::
在 pthread 或 FreeRTOS API 创建的任务中都可以调用此函数。当从 FreeRTOS API 创建的任务中调用这些函数时,必须先启用 :ref:`CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS` 配置选项,以确保在删除任务之前清理线程数据。
在 pthread 或 FreeRTOS API 创建的任务中都可以调用此函数。当从 FreeRTOS API 创建的任务中调用这些函数时,必须先启用 :menuitem:`CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS` 配置选项,以确保在删除任务之前清理线程数据。
.. note::
@@ -248,11 +248,11 @@ ESP-IDF 扩展
.. list::
- 如果调用 ``pthread_create()`` 时未指定默认堆栈大小,可设置新线程的默认堆栈大小(覆盖 :ref:`CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT`)。
- 如果调用 ``pthread_create()`` 时未指定默认堆栈大小,可设置新线程的默认堆栈大小(覆盖 :menuitem:`CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT`)。
- 堆栈内存属性决定用于分配 pthread 堆栈的内存类型。该字段使用 ESP-IDF 堆属性标志,这一标志在 :component_file:`heap/include/esp_heap_caps.h` 文件中定义。为了确保分配的内存能够通过 8 位地址访问 (MALLOC_CAP_8BIT),用户必须设置相应的标志,此外也可添加其他自定义标志。用户应当确保选择了正确的堆栈内存属性。了解内存位置的更多信息,请参考 :ref:`memory_capabilities` 文档。
- 新线程的 RTOS 优先级(覆盖 :ref:`CONFIG_PTHREAD_TASK_PRIO_DEFAULT`)。
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - 新线程的内核亲和性/内核固定(覆盖 :ref:`CONFIG_PTHREAD_TASK_CORE_DEFAULT`)。
- 新线程的 FreeRTOS 任务名称(覆盖 :ref:`CONFIG_PTHREAD_TASK_NAME_DEFAULT`
- 新线程的 RTOS 优先级(覆盖 :menuitem:`CONFIG_PTHREAD_TASK_PRIO_DEFAULT`)。
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - 新线程的内核亲和性/内核固定(覆盖 :menuitem:`CONFIG_PTHREAD_TASK_CORE_DEFAULT`)。
- 新线程的 FreeRTOS 任务名称(覆盖 :menuitem:`CONFIG_PTHREAD_TASK_NAME_DEFAULT`
此配置的作用范围是调用线程或 FreeRTOS 任务,这意味着 :cpp:func:`esp_pthread_set_cfg` 可以在不同的线程或任务中独立调用。如果在当前配置中设置了 ``inherit_cfg`` 标志,那么当一个线程递归调用 ``pthread_create()`` 时,任何新创建的线程都会继承该线程的配置,否则新线程将采用默认配置。

View File

@@ -332,13 +332,13 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
在 Light-sleep 模式下,如果设置 Kconfig 选项 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,为了继续使用 :cpp:func:`gpio_wakeup_enable` 用于 GPIO 唤醒, 需要先调用 :cpp:func:`rtc_gpio_init` 和 :cpp:func:`rtc_gpio_set_direction`,用于设置 RTC IO 为输入模式。
在 Light-sleep 模式下,如果设置 Kconfig 选项 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,为了继续使用 :cpp:func:`gpio_wakeup_enable` 用于 GPIO 唤醒, 需要先调用 :cpp:func:`rtc_gpio_init` 和 :cpp:func:`rtc_gpio_set_direction`,用于设置 RTC IO 为输入模式。
或者, 可以使用直接调用 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` 用于 GPIO 唤醒,因为此时 digital IO 的电源域已经被关闭。
.. only:: not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
在 Light-sleep 模式下,如果设置 Kconfig 选项 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,为了继续使用 :cpp:func:`gpio_wakeup_enable` 用于 GPIO 唤醒, 需要先调用 :cpp:func:`rtc_gpio_init` 和 :cpp:func:`rtc_gpio_set_direction`,用于设置 RTC IO 为输入模式。
在 Light-sleep 模式下,如果设置 Kconfig 选项 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,为了继续使用 :cpp:func:`gpio_wakeup_enable` 用于 GPIO 唤醒, 需要先调用 :cpp:func:`rtc_gpio_init` 和 :cpp:func:`rtc_gpio_set_direction`,用于设置 RTC IO 为输入模式。
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
@@ -352,7 +352,7 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
该唤醒源由 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` 函数实现,用户可以配置一个或多个 GPIO 管脚以及唤醒电平(高电平或低电平)。只有由 {IDF_TARGET_RTC_POWER_DOMAIN} 电源域供电的 GPIO 管脚才能用作 Deep-sleep GPIO 唤醒源。具体支持的管脚请参考 `datasheet <{IDF_TARGET_DATASHEET_CN_URL}>`__ > IO 管脚。
.. note::
该 API 同样适用于外设电源域掉电时的 Light-sleep 模式(参见 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`)。在这种情况下,应使用此 API 而不是 :cpp:func:`esp_sleep_enable_gpio_wakeup`,因为 GPIO 模块在睡眠期间会被断电。
该 API 同样适用于外设电源域掉电时的 Light-sleep 模式(参见 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`)。在这种情况下,应使用此 API 而不是 :cpp:func:`esp_sleep_enable_gpio_wakeup`,因为 GPIO 模块在睡眠期间会被断电。
完整示例请参考 :example:`system/deep_sleep`
@@ -380,12 +380,12 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
.. note::
当启用 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时,此 API **不可用**,因为 GPIO 模块在睡眠期间会被断电。请使用 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` 替代。
当启用 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时,此 API **不可用**,因为 GPIO 模块在睡眠期间会被断电。请使用 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` 替代。
.. only:: not SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
.. note::
当启用 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时,若仍要使用 :cpp:func:`gpio_wakeup_enable`,请先调用 :cpp:func:`rtc_gpio_init` 与 :cpp:func:`rtc_gpio_set_direction`,将管脚配置为 RTC GPIO 输入。
当启用 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时,若仍要使用 :cpp:func:`gpio_wakeup_enable`,请先调用 :cpp:func:`rtc_gpio_init` 与 :cpp:func:`rtc_gpio_set_direction`,将管脚配置为 RTC GPIO 输入。
.. only:: SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
@@ -394,17 +394,17 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
可将由 VDD3P3_RTC 电源域供电的 IO 用于芯片的 Deep-sleep 唤醒,或在外设电源域掉电时的 Light-sleep 唤醒。调用 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown` 函数可以配置相应的唤醒管脚和唤醒触发电平。此函数适用于:
- Deep-sleep 模式(始终可用)
- 启用 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时的 Light-sleep 模式
- 启用 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 时的 Light-sleep 模式
.. only:: SOC_RTC_GPIO_EDGE_WAKEUP_SUPPORTED
在 {IDF_TARGET_NAME} 上,该 API 还支持边沿触发的唤醒模式:``ESP_GPIO_WAKEUP_GPIO_POSEDGE``(上升沿)、``ESP_GPIO_WAKEUP_GPIO_NEGEDGE``(下降沿)和 ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE``(任意沿)。对于 ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE``,当启用 :ref:`CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS` 时,由于空闲电平不确定,驱动会关闭内部上拉/下拉,建议使用外部上/下拉电阻或保证进入睡眠前线路电平稳定。
在 {IDF_TARGET_NAME} 上,该 API 还支持边沿触发的唤醒模式:``ESP_GPIO_WAKEUP_GPIO_POSEDGE``(上升沿)、``ESP_GPIO_WAKEUP_GPIO_NEGEDGE``(下降沿)和 ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE``(任意沿)。对于 ``ESP_GPIO_WAKEUP_GPIO_ANYEDGE``,当启用 :menuitem:`CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS` 时,由于空闲电平不确定,驱动会关闭内部上拉/下拉,建议使用外部上/下拉电阻或保证进入睡眠前线路电平稳定。
.. note::
只有由 VDD3P3_RTC 电源域供电的 GPIORTC IO可以与此 API 一起使用。具体支持的管脚请参考 `datasheet <{IDF_TARGET_DATASHEET_CN_URL}>`__ > IO 管脚。
.. note::
使用 IO 唤醒源(无论是电平模式还是边沿模式)将芯片从睡眠中唤醒时,唤醒信号必须保持(电平模式)或脉冲宽度(边沿模式)至少 3 个 RTC 慢时钟周期,唤醒逻辑才能可靠采样。一个慢时钟周期的时长取决于 :ref:`CONFIG_RTC_CLK_SRC` 的配置(例如 RC_SLOW @ ~136 kHz ≈ 7.4 µs/周期XTAL32K @ 32.768 kHz ≈ 30.5 µs/周期)。该约束同样适用于 :cpp:func:`esp_sleep_enable_gpio_wakeup` 和 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown`
使用 IO 唤醒源(无论是电平模式还是边沿模式)将芯片从睡眠中唤醒时,唤醒信号必须保持(电平模式)或脉冲宽度(边沿模式)至少 3 个 RTC 慢时钟周期,唤醒逻辑才能可靠采样。一个慢时钟周期的时长取决于 :menuitem:`CONFIG_RTC_CLK_SRC` 的配置(例如 RC_SLOW @ ~136 kHz ≈ 7.4 µs/周期XTAL32K @ 32.768 kHz ≈ 30.5 µs/周期)。该约束同样适用于 :cpp:func:`esp_sleep_enable_gpio_wakeup` 和 :cpp:func:`esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown`
.. only:: esp32h2
@@ -457,7 +457,7 @@ UART 唤醒支持以下模式:
.. note::
在 Light-sleep 模式下,设置 Kconfig 选项 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 将使 UART 唤醒失效。
在 Light-sleep 模式下,设置 Kconfig 选项 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 将使 UART 唤醒失效。
.. only:: SOC_ULP_LP_UART_SUPPORTED
@@ -513,12 +513,12 @@ RTC 外设和内存断电
SPI Flash 进入 deep power-down 模式
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
为降低 Light-sleep 期间 SPI Flash 的功耗ESP-IDF **优先推荐**采用 **Deep Power-DownDPD**:通过启用配置项 :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`,令 SPI Flash 在供电保持开启的前提下进入器件内部的深度休眠指令状态。多数 SPI Flash 在 DPD 下电流可降至极低水平(常低于 1 µA同时可避免反复上下电带来的唤醒延迟。
为降低 Light-sleep 期间 SPI Flash 的功耗ESP-IDF **优先推荐**采用 **Deep Power-DownDPD**:通过启用配置项 :menuitem:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`,令 SPI Flash 在供电保持开启的前提下进入器件内部的深度休眠指令状态。多数 SPI Flash 在 DPD 下电流可降至极低水平(常低于 1 µA同时可避免反复上下电带来的唤醒延迟。
在几乎所有应用场景中,相较彻底切断 SPI Flash 供电DPD 在安全性与功耗之间通常是更好的折中。
.. note::
**两种方式互斥:** Light-sleep 下的 SPI Flash **断电**:ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 或通过 ``esp_sleep_pd_config````ESP_PD_DOMAIN_VDDSDIO`` 置为关闭)与 **DPD** **不可同时使用** 在 menuconfig 中仅能在禁用 :ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 后再启用 :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`
**两种方式互斥:** Light-sleep 下的 SPI Flash **断电**:menuitem:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 或通过 ``esp_sleep_pd_config````ESP_PD_DOMAIN_VDDSDIO`` 置为关闭)与 **DPD** **不可同时使用** 在 menuconfig 中仅能在禁用 :menuitem:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 后再启用 :menuitem:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`
.. warning::
@@ -537,17 +537,17 @@ SPI Flash 断电
如果在 SPI Flash 的供电电路上添加了滤波电容,那么应当尽一切可能避免 SPI Flash 断电。
因为这些不可控的因素ESP-IDF 很难保证 SPI Flash 断电的绝对安全。因此 ESP-IDF 不推荐用户断电 SPI Flash。对于一些功耗敏感型应用可以通过设置 Kconfig 配置项 :ref:`CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND` 来减少 Light-sleep 期间 SPI Flash 的功耗。这种方式在几乎所有场景下都要比断电 SPI Flash 更好,兼顾了安全性和功耗。
因为这些不可控的因素ESP-IDF 很难保证 SPI Flash 断电的绝对安全。因此 ESP-IDF 不推荐用户断电 SPI Flash。对于一些功耗敏感型应用可以通过设置 Kconfig 配置项 :menuitem:`CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND` 来减少 Light-sleep 期间 SPI Flash 的功耗。这种方式在几乎所有场景下都要比断电 SPI Flash 更好,兼顾了安全性和功耗。
.. only:: SOC_SPIRAM_SUPPORTED
值得一提的是PSRAM 也有一个类似的 Kconfig 配置项 :ref:`CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND`
值得一提的是PSRAM 也有一个类似的 Kconfig 配置项 :menuitem:`CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND`
考虑到有些用户能够充分评估断电 SPI Flash 的风险,并希望通过断电 SPI Flash 来获得更低的功耗,因此 ESP-IDF 提供了两种断电 SPI Flash 的机制:
.. list::
- 设置 Kconfig 配置项 :ref:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 将使 ESP-IDF 以一个严格的条件来断电 SPI Flash。严格的条件具体指的是RTC timer 是唯一的唤醒源 **且** 睡眠时间比 SPI Flash 彻底断电所需时间更长。
- 设置 Kconfig 配置项 :menuitem:`CONFIG_ESP_SLEEP_POWER_DOWN_FLASH` 将使 ESP-IDF 以一个严格的条件来断电 SPI Flash。严格的条件具体指的是RTC timer 是唯一的唤醒源 **且** 睡眠时间比 SPI Flash 彻底断电所需时间更长。
- 调用函数 ``esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF)`` 将使 ESP-IDF 以一个宽松的条件来断电 SPI Flash。宽松的条件具体指的是 RTC timer 唤醒源未被使能 **或** 睡眠时间比 SPI Flash 彻底断电所需时间更长。
.. note::
@@ -580,7 +580,7 @@ SPI Flash 不掉电
SPI Flash 进入 deep power-downDPD模式
""""""""""""""""""""""""""""""""""""""""""
若待机功耗仍偏高,应优先采用 **Deep Power-DownDPD**,通过 :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD` 降低休眠电流;功耗数据、时序及启用方式参见前文 :ref:`spi_flash_power_down_dpd`
若待机功耗仍偏高,应优先采用 **Deep Power-DownDPD**,通过 :menuitem:`CONFIG_ESP_SLEEP_SET_FLASH_DPD` 降低休眠电流;功耗数据、时序及启用方式参见前文 :ref:`spi_flash_power_down_dpd`
DPD 模式适用于以下场景:
@@ -648,7 +648,7 @@ DPD 模式适用于以下场景:
UART 输出处理
^^^^^^^^^^^^^^^^^^^^
进入睡眠前,睡眠流程会对**控制台 UART**(用于调试输出的 UART:ref:`CONFIG_ESP_CONSOLE_UART_NUM` 选定)进行准备,以避免 APB 时钟变化或掉电导致输出乱码或未定义行为。所采用的策略可配置,会影响数据完整性、进入睡眠的时间以及功耗。
进入睡眠前,睡眠流程会对**控制台 UART**(用于调试输出的 UART:menuitem:`CONFIG_ESP_CONSOLE_UART_NUM` 选定)进行准备,以避免 APB 时钟变化或掉电导致输出乱码或未定义行为。所采用的策略可配置,会影响数据完整性、进入睡眠的时间以及功耗。
**默认行为(自动模式)**
@@ -671,7 +671,7 @@ UART 输出处理
.. note::
睡眠流程在临界区中执行,当使用会冲刷控制台 UART 的模式(如 :cpp:enumerator:`ESP_SLEEP_ALWAYS_FLUSH_UART` ,或 HP 外设域掉电时的 Light-sleep/Deep-sleep 默认行为)时,请将 :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 配置为**大于** ``SOC_UART_FIFO_LEN`` ×(当前波特率下发送一个字符所需时间)。否则若 TX FIFO 中积压数据过多,冲刷时间可能超过中断看门狗超时,会在进入睡眠过程中触发看门狗复位。
睡眠流程在临界区中执行,当使用会冲刷控制台 UART 的模式(如 :cpp:enumerator:`ESP_SLEEP_ALWAYS_FLUSH_UART` ,或 HP 外设域掉电时的 Light-sleep/Deep-sleep 默认行为)时,请将 :menuitem:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 配置为**大于** ``SOC_UART_FIFO_LEN`` ×(当前波特率下发送一个字符所需时间)。否则若 TX FIFO 中积压数据过多,冲刷时间可能超过中断看门狗超时,会在进入睡眠过程中触发看门狗复位。
示例:在每次睡眠前确保所有调试输出已发出::

View File

@@ -19,7 +19,7 @@
- 高分辨率定时器
-
默认时钟源的时间精度最高,建议使用该配置。此外,你可以通过配置选项 :ref:`CONFIG_LIBC_TIME_SYSCALL` 来选择其他时钟源。
默认时钟源的时间精度最高,建议使用该配置。此外,你可以通过配置选项 :menuitem:`CONFIG_LIBC_TIME_SYSCALL` 来选择其他时钟源。
.. _rtc-clock-source-choice:
@@ -39,7 +39,7 @@ RTC 定时器有以下时钟源:
:esp32 or esp32s2 or esp32s3 or esp32c2 or esp32c3: - ``内置 8.517.5 MHz 振荡器(频率取决于芯片型号)的 256 分频时钟``:频率稳定性优于 ``内置 90150 kHz RC 振荡器``,同样无需外部元件,但 Deep-sleep 模式下电流消耗更高(比默认模式高 5 μA
时钟源的选择取决于系统时间精度要求和睡眠模式下的功耗要求。要修改 RTC 时钟源,请在项目配置中设置 :ref:`CONFIG_RTC_CLK_SRC`
时钟源的选择取决于系统时间精度要求和睡眠模式下的功耗要求。要修改 RTC 时钟源,请在项目配置中设置 :menuitem:`CONFIG_RTC_CLK_SRC`
想要了解外部无源晶振和有源晶振的更多布线要求,请参考 `硬件设计指南 <https://docs.espressif.com/projects/esp-hardware-design-guidelines/zh_CN/latest/{IDF_TARGET_PATH_NAME}>`_
@@ -154,7 +154,7 @@ lwIP SNTP 库可在下列任一同步模式下工作:
设置时间同步时的回调函数,请使用配置结构体中的 :cpp:member:`esp_sntp_config::sync_cb` 字段。
添加此初始化代码后,应用程序将定期同步时间。时间同步周期由 :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` 设置(默认为一小时)。如需修改,请在项目配置中设置 :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY`
添加此初始化代码后,应用程序将定期同步时间。时间同步周期由 :menuitem:`CONFIG_LWIP_SNTP_UPDATE_DELAY` 设置(默认为一小时)。如需修改,请在项目配置中设置 :menuitem:`CONFIG_LWIP_SNTP_UPDATE_DELAY`
如需查看示例代码,请前往 :example:`protocols/sntp` 目录。该目录下的示例展示了如何基于 lwIP SNTP 库实现时间同步。

View File

@@ -15,7 +15,7 @@ ULP LP 内核协处理器具有以下功能:
.. only:: SOC_LP_CORE_HAS_PMP
在支持的芯片上LP 内核提供 RISC-V 物理内存保护PMP。启用 :ref:`CONFIG_ULP_LP_CORE_MEMPROT`LP 内核启动时会配置默认拒绝访问的 PMP 布局LP RAM 分为可执行区代码与只读数据与可读写区可写数据、栈与共享内存LP 外设地址空间为可读写;启用 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT` 时还会为 HP UART MMIO 增加相应条目。PMP 不能与 :ref:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM` 同时启用。未落入允许区域的访问将触发加载、存储或取指访问异常。
在支持的芯片上LP 内核提供 RISC-V 物理内存保护PMP。启用 :menuitem:`CONFIG_ULP_LP_CORE_MEMPROT`LP 内核启动时会配置默认拒绝访问的 PMP 布局LP RAM 分为可执行区代码与只读数据与可读写区可写数据、栈与共享内存LP 外设地址空间为可读写;启用 :menuitem:`CONFIG_ULP_HP_UART_CONSOLE_PRINT` 时还会为 HP UART MMIO 增加相应条目。PMP 不能与 :menuitem:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM` 同时启用。未落入允许区域的访问将触发加载、存储或取指访问异常。
编译 ULP LP 内核代码
--------------------
@@ -109,7 +109,7 @@ ULP LP 内核代码会与 ESP-IDF 项目共同编译,生成一个单独的二
若想编译和构建项目,请执行以下操作:
1. 在 menuconfig 中启用 :ref:`CONFIG_ULP_COPROC_ENABLED`,并``ULP Coprocessor types`` 菜单中勾选 :ref:`CONFIG_ULP_COPROC_TYPE_LP_CORE`:ref:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP LP 内核代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。
1. 启用 :menuitem:`CONFIG_ULP_COPROC_ENABLED`,并勾选 :menuitem:`CONFIG_ULP_COPROC_TYPE_LP_CORE`:menuitem:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP LP 内核代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。
2. 按照常规步骤构建应用程序(例如 ``idf.py app``)。
@@ -209,13 +209,13 @@ ULP LP 内核代码会与 ESP-IDF 项目共同编译,生成一个单独的二
从 HP 内存运行 LP 内核
~~~~~~~~~~~~~~~~~~~~~~
:ref:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM` 允许将 LP 内核应用的大部分代码和数据放到预留的 HP SRAM 中,而不是仅放在 LP RAM 中。当应用程序过大、无法完全放入 LP RAM 时,这种方式会很有用,同时仍然会将 LP 复位和处理程序代码保留在 LP 内存中。
:menuitem:`CONFIG_ULP_COPROC_RUN_FROM_HP_MEM` 允许将 LP 内核应用的大部分代码和数据放到预留的 HP SRAM 中,而不是仅放在 LP RAM 中。当应用程序过大、无法完全放入 LP RAM 时,这种方式会很有用,同时仍然会将 LP 复位和处理程序代码保留在 LP 内存中。
启用该选项后,:ref:`CONFIG_ULP_COPROC_RESERVE_HP_MEM_BYTES` 会在 HP SRAM 顶部预留一段专供 LP 内核使用的内存窗口。在调用 :cpp:func:`ulp_lp_core_load_binary` 时,位于 LP 内存的段仍会加载到预留的 LP 区域,而映射到 HP 内存窗口的代码段和数据段则会复制到预留的 HP SRAM 区域。
启用该选项后,:menuitem:`CONFIG_ULP_COPROC_RESERVE_HP_MEM_BYTES` 会在 HP SRAM 顶部预留一段专供 LP 内核使用的内存窗口。在调用 :cpp:func:`ulp_lp_core_load_binary` 时,位于 LP 内存的段仍会加载到预留的 LP 区域,而映射到 HP 内存窗口的代码段和数据段则会复制到预留的 HP SRAM 区域。
该模式有一个重要限制:芯片进入 Deep-sleep 后LP 内核无法继续运行,因为该睡眠模式下 HP SRAM 会被断电。因此,这种模式适用于 LP 内核只需要在 HP 系统保持上电时运行的场景;如果应用需要在 Deep-sleep 期间继续运行,则应继续使用默认的纯 LP 内存模式。
:ref:`CONFIG_ULP_LP_CORE_MEMPROT` 不能与 HP 内存模式同时启用。
:menuitem:`CONFIG_ULP_LP_CORE_MEMPROT` 不能与 HP 内存模式同时启用。
ULP LP 内核程序流程
-------------------
@@ -312,7 +312,7 @@ ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `
* 使用 LP UART 打印LP 内核可以访问 LP UART 外设,在主 CPU 处于睡眠状态时独立打印信息。有关使用此驱动程序的示例,请参阅 :example:`system/ulp/lp_core/lp_uart/lp_uart_print`
* 通过 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART可以轻松地将 LP 内核信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 内核与 HP 内未同步,输出可能会交错。
* 通过 :menuitem:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART可以轻松地将 LP 内核信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 内核与 HP 内未同步,输出可能会交错。
* 通过共享变量共享程序状态:如 :ref:`ulp-lp-core-access-variables` 所述,主 CPU 和 ULP 内核都可以轻松访问 RTC 内存中的全局变量。若想了解 ULP 内核的运行状态,可以将状态信息从 ULP 写入变量中,并通过主 CPU 读取信息。这种方法的缺点在于它需要主 CPU 一直处于唤醒状态,而这通常很难实现。另外,若主 CPU 一直处于唤醒状态,可能会掩盖某些问题,因为部分问题只会在特定电源域断电时发生。

View File

@@ -38,7 +38,7 @@ ULP RISC-V 协处理器代码以 C 语言(或汇编语言)编写,使用基
ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}" TYPE riscv)
``ulp_embed_binary`` 的第一个参数指定生成的 ULP 二进制文件名。该文件名也用于其他生成的文件,如 ELF 文件、映射文件、头文件和链接器导出文件。第二个参数指定 ULP 源文件。第三个参数指定组件源文件列表,其中包括生成的头文件。此列表用以正确构建依赖,并确保在编译这些文件前创建要生成的头文件。第四个参数 ``TYPE`` 为可选项,但在 menu 选项 ``ULP Coprocessor types`` 中同时勾选 :ref:`CONFIG_ULP_COPROC_TYPE_FSM`:ref:`CONFIG_ULP_COPROC_TYPE_RISCV` 时,必须填写为 ``TYPE riscv`` 才能使用 RISC-V 工具链编译。有关 ULP 应用程序生成头文件的概念,请参阅本文档后续章节。
``ulp_embed_binary`` 的第一个参数指定生成的 ULP 二进制文件名。该文件名也用于其他生成的文件,如 ELF 文件、映射文件、头文件和链接器导出文件。第二个参数指定 ULP 源文件。第三个参数指定组件源文件列表,其中包括生成的头文件。此列表用以正确构建依赖,并确保在编译这些文件前创建要生成的头文件。第四个参数 ``TYPE`` 为可选项,但在 menu 选项 ``ULP Coprocessor types`` 中同时勾选 :menuitem:`CONFIG_ULP_COPROC_TYPE_FSM`:menuitem:`CONFIG_ULP_COPROC_TYPE_RISCV` 时,必须填写为 ``TYPE riscv`` 才能使用 RISC-V 工具链编译。有关 ULP 应用程序生成头文件的概念,请参阅本文档后续章节。
在这个生成的头文件中ULP 代码中的变量默认以 ``ulp_`` 作为前缀。
@@ -108,7 +108,7 @@ ULP RISC-V 协处理器代码以 C 语言(或汇编语言)编写,使用基
若想编译和构建项目,请执行以下操作:
1. 在 menuconfig 中启用 :ref:`CONFIG_ULP_COPROC_ENABLED`,并``ULP Coprocessor types`` 菜单中勾选 `CONFIG_ULP_COPROC_TYPE_RISCV`:ref:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP RISC-V 代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。
1. 启用 :menuitem:`CONFIG_ULP_COPROC_ENABLED`,并勾选 :menuitem:`CONFIG_ULP_COPROC_TYPE_RISCV`:menuitem:`CONFIG_ULP_COPROC_RESERVE_MEM` 选项为 ULP 保留 RTC 内存,因此必须设置为一个足够大的值,以存储 ULP RISC-V 代码和数据。如果应用程序组件包含多个 ULP 程序,那么 RTC 内存的大小必须足够容纳其中最大的程序。
2. 按照常规步骤构建应用程序(例如 ``idf.py app``)。
@@ -193,7 +193,7 @@ ULP 中的所有硬件指令都不支持互斥,所以 Lock API 需通过一种
要运行 ULP RISC-V 程序,主程序需要调用 :cpp:func:`ulp_riscv_load_binary` 函数,将 ULP 程序加载到 RTC 内存中,然后调用 :cpp:func:`ulp_riscv_run` 函数,启动 ULP RISC-V 程序。
注意,必须在 menuconfig 中启用 :ref:`CONFIG_ULP_COPROC_ENABLED`:ref:`CONFIG_ULP_COPROC_TYPE_RISCV` 选项才能使用 ULP RISC-V。 ``RTC slow memory reserved for coprocessor`` 选项设置的值必须足够存储 ULP RISC-V 代码和数据。如果应用程序组件包含多个 ULP 程序RTC 内存必须足以容纳最大的程序。
注意,必须在 menuconfig 中启用 :menuitem:`CONFIG_ULP_COPROC_ENABLED`:menuitem:`CONFIG_ULP_COPROC_TYPE_RISCV` 选项才能使用 ULP RISC-V。 ``RTC slow memory reserved for coprocessor`` 选项设置的值必须足够存储 ULP RISC-V 代码和数据。如果应用程序组件包含多个 ULP 程序RTC 内存必须足以容纳最大的程序。
每个 ULP RISC-V 程序均以二进制 BLOB 的形式嵌入到 ESP-IDF 应用程序中。应用程序可以引用此 BLOB并以下面的方式加载此 BLOB假设 ULP_APP_NAME 已被定义为 ``ulp_app_name``

View File

@@ -40,7 +40,7 @@ RTC/LP 看门狗定时器用于追踪从上电到用户主函数执行的启动
请参阅 :ref:`bootloader-watchdog` 小节,了解如何在引导加载程序中使用看门狗。
用户可以调整应用程序行为,使 RTC 看门狗在应用程序启动后保持启用状态。应用程序需要显式重置(即喂狗)或禁用看门狗,以避免芯片重置。具体而言,用户可设置 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 选项,根据需要修改应用程序并重新编译。此过程中应使用以下 API
用户可以调整应用程序行为,使 RTC 看门狗在应用程序启动后保持启用状态。应用程序需要显式重置(即喂狗)或禁用看门狗,以避免芯片重置。具体而言,用户可设置 :menuitem:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 选项,根据需要修改应用程序并重新编译。此过程中应使用以下 API
.. list::
@@ -64,20 +64,20 @@ IWDT 的目的是,确保中断服务例程 (ISR) 运行不会受到长时间
IWDT 利用 {IDF_TARGET_IWDT_TIMER_GROUP} 中的 MWDT_WDT 看门狗定时器作为其底层硬件定时器,并在每个 CPU 上使用 FreeRTOS 时钟滴答中断,即 tick 中断。如果某个 CPU 上的 tick 中断没有在 IWDT 超时前运行,就表明该 CPU 上的 ISR 运行受阻(参见上文原因列表)。
当 IWDT 超时后,默认操作是调用紧急处理程序 (Panic Handler),并显示 出错原因( ``Interrupt wdt timeout on CPU0````Interrupt wdt timeout on CPU1``,视情况而定)。根据紧急处理程序的配置行为(参见 :ref:`CONFIG_ESP_SYSTEM_PANIC`用户可通过回溯、OpenOCD、gdbstub 等来调试 IWDT 超时问题,也可以重置芯片(这在生产环境中可能是首选)。
当 IWDT 超时后,默认操作是调用紧急处理程序 (Panic Handler),并显示 出错原因( ``Interrupt wdt timeout on CPU0````Interrupt wdt timeout on CPU1``,视情况而定)。根据紧急处理程序的配置行为(参见 :menuitem:`CONFIG_ESP_SYSTEM_PANIC`用户可通过回溯、OpenOCD、gdbstub 等来调试 IWDT 超时问题,也可以重置芯片(这在生产环境中可能是首选)。
如果出于某种原因IWDT 超时后紧急处理程序无法运行IWDT 还可以通过其二阶段超时来硬重置芯片(即系统重置)。
配置
^^^^^^^^^^^^^
- IWDT 默认通过 :ref:`CONFIG_ESP_INT_WDT` 选项启用。
- 通过 :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 选项设置 IWDT 超时。
- IWDT 默认通过 :menuitem:`CONFIG_ESP_INT_WDT` 选项启用。
- 通过 :menuitem:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 选项设置 IWDT 超时。
.. list::
:SOC_SPIRAM_SUPPORTED: - 注意,如果启用了 PSRAM 支持,那么默认的超时时间会更长,因为在某些情况下,临界区或中断例程访问大量 PSRAM 需要更长时间。
- IWDT 的配置超时时间应至少为 FreeRTOS tick 周期的两倍时长。例如,如果 FreeRTOS tick 周期间隔为 10 毫秒,则 IWDT 的超时时间应至少为 20 毫秒(参见 :ref:`CONFIG_FREERTOS_HZ`)。
- IWDT 的配置超时时间应至少为 FreeRTOS tick 周期的两倍时长。例如,如果 FreeRTOS tick 周期间隔为 10 毫秒,则 IWDT 的超时时间应至少为 20 毫秒(参见 :menuitem:`CONFIG_FREERTOS_HZ`)。
调优
^^^^^^
@@ -87,7 +87,7 @@ IWDT 利用 {IDF_TARGET_IWDT_TIMER_GROUP} 中的 MWDT_WDT 看门狗定时器作
- 临界区应尽可能短。任何非关键的代码或计算都应放在临界区外。
- 中断处理程序也应尽可能减少计算量。考虑让 ISR 使用队列向任务推送数据,从而将计算推迟到任务中进行。
临界区或中断处理程序都不应阻塞其他事件。如果不能或不希望通过更改代码减少处理时间,可以通过设置 :ref:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 延长超时时间。
临界区或中断处理程序都不应阻塞其他事件。如果不能或不希望通过更改代码减少处理时间,可以通过设置 :menuitem:`CONFIG_ESP_INT_WDT_TIMEOUT_MS` 延长超时时间。
.. _task-watchdog-timer:
@@ -128,13 +128,13 @@ IWDT 利用 {IDF_TARGET_IWDT_TIMER_GROUP} 中的 MWDT_WDT 看门狗定时器作
配置
^^^^^^^^^^^^^
TWDT 的默认超时时间可以通过 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 配置项进行设置,并应至少设置为任何单个任务预计需要独占 CPU 的时长,例如某应用程序将进行长时间的密集计算且不让位给其他任务时的预计时长。也可以调用 :cpp:func:`esp_task_wdt_init`,在运行时更改此时间。
TWDT 的默认超时时间可以通过 :menuitem:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 配置项进行设置,并应至少设置为任何单个任务预计需要独占 CPU 的时长,例如某应用程序将进行长时间的密集计算且不让位给其他任务时的预计时长。也可以调用 :cpp:func:`esp_task_wdt_init`,在运行时更改此时间。
.. note::
擦除较大的 flash 区域可能会非常耗时,并可能导致任务连续运行,触发 TWDT 超时。以下两种方法可以避免这种情况:
- 在 menuconfig 中增加 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S`,延长看门狗超时时间。
- 在 menuconfig 中增加 :menuitem:`CONFIG_ESP_TASK_WDT_TIMEOUT_S`,延长看门狗超时时间。
- 在擦除 flash 区域前,再次调用 :cpp:func:`esp_task_wdt_init` 增加看门狗超时时间。
如需了解更多信息,请参考 :doc:`../peripherals/spi_flash/index`
@@ -145,15 +145,15 @@ TWDT 的默认超时时间可以通过 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 配
.. list::
- :ref:`CONFIG_ESP_TASK_WDT_EN` - 启用 TWDT 功能。如果禁用此选项, TWDT 即使运行时已初始化也无法使用。
- :ref:`CONFIG_ESP_TASK_WDT_INIT` - TWDT 在启动期间自动初始化。禁用此选项时,仍可以调用 :cpp:func:`esp_task_wdt_init` 在运行时初始化 TWDT。
- :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - 在启动期间将 {IDF_TARGET_IDLE_TASK}注册到 TWDT。如果禁用此选项。如果禁用此选项仍然可以通过再次调用 :cpp:func:`esp_task_wdt_init`,或者使用 :cpp:func:`esp_task_wdt_add` 并传入通过 :cpp:func:`xTaskGetIdleTaskHandleForCore` 获取的空闲任务句柄来订阅空闲任务。
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 空闲任务在启动时订阅了 TWDT。
- :menuitem:`CONFIG_ESP_TASK_WDT_EN` - 启用 TWDT 功能。如果禁用此选项, TWDT 即使运行时已初始化也无法使用。
- :menuitem:`CONFIG_ESP_TASK_WDT_INIT` - TWDT 在启动期间自动初始化。禁用此选项时,仍可以调用 :cpp:func:`esp_task_wdt_init` 在运行时初始化 TWDT。
- :menuitem:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - 在启动期间将 {IDF_TARGET_IDLE_TASK}注册到 TWDT。如果禁用此选项。如果禁用此选项仍然可以通过再次调用 :cpp:func:`esp_task_wdt_init`,或者使用 :cpp:func:`esp_task_wdt_add` 并传入通过 :cpp:func:`xTaskGetIdleTaskHandleForCore` 获取的空闲任务句柄来订阅空闲任务。
:SOC_HP_CPU_HAS_MULTIPLE_CORES: - :menuitem:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 空闲任务在启动时订阅了 TWDT。
.. note::
如果 TWDT 超时,会默认在继续运行应用程序前打印警告和回溯。如希望超时触发系统严重错误和系统重置,可以通过 :ref:`CONFIG_ESP_TASK_WDT_PANIC` 进行配置。
如果 TWDT 超时,会默认在继续运行应用程序前打印警告和回溯。如希望超时触发系统严重错误和系统重置,可以通过 :menuitem:`CONFIG_ESP_TASK_WDT_PANIC` 进行配置。
.. only:: SOC_XT_WDT_SUPPORTED
@@ -172,9 +172,9 @@ TWDT 的默认超时时间可以通过 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 配
配置
"""""""""""""
- 选择外部 32 KHz 晶体或振荡器时 (:ref:`CONFIG_RTC_CLK_SRC`),通过 :ref:`CONFIG_ESP_XT_WDT` 配置选项启用 XTWDT。
- 设置 :ref:`CONFIG_ESP_XT_WDT_TIMEOUT` 选项来配置超时时间。
- 通过 :ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` 配置选项启用自动切换备用时钟功能。
- 选择外部 32 KHz 晶体或振荡器时 (:menuitem:`CONFIG_RTC_CLK_SRC`),通过 :menuitem:`CONFIG_ESP_XT_WDT` 配置选项启用 XTWDT。
- 设置 :menuitem:`CONFIG_ESP_XT_WDT_TIMEOUT` 选项来配置超时时间。
- 通过 :menuitem:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` 配置选项启用自动切换备用时钟功能。
超时阶段
--------
@@ -201,7 +201,7 @@ WDT 触发时的常见错误日志及可能的解决方法
- ``Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0).``,并伴随回溯信息:表示 IWDT 检测到 CPU 0 上的中断被阻塞,且阻塞时间超过了所配置的超时时间。可以通过缩短 ISR 或临界区的持续时间、或者增加 IWDT 的超时时间来解决该问题。
- ``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``:表示 TWDT 检测到一个或多个任务在所配置的超时时间内没有让出 CPU导致空闲任务无法及时对 TWDT 进行喂狗。可以通过确保任务能够适当让出 CPU、缩短长时间运行任务的执行时间或者增加 TWDT 的超时时间来解决该问题。用户还可以使用 :cpp:func:`esp_task_wdt_add`、:cpp:func:`esp_task_wdt_add_user` 以及 :cpp:func:`esp_task_wdt_reset_user` 等 API 来定位哪个任务以及该任务中的哪段代码执行时间最长,从而导致 TWDT 超时。
- 启用了 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 并导致 WDT 超时:请确保在用户代码中及时对 RTC WDT 进行喂狗。
- 启用了 :menuitem:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 并导致 WDT 超时:请确保在用户代码中及时对 RTC WDT 进行喂狗。
- 在启动过程中发生 WDT 复位:请确保已正确烧录有效的二级引导加载程序,并检查是否存在与外部 flash 通信相关的问题。
- 在系统运行过程中发生 WDT 复位:请尝试确定复位发生的具体时机,例如是否发生在系统严重错误 (panic)、重启,或进入/退出 Light-sleep 的过程中。如果是在这些系统操作期间发生,则可能由 ESP-IDF 内部的问题引起。