mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
docs(kconfig): update kconfig ref links to use menuitem
This commit is contained in:
@@ -170,7 +170,7 @@
|
||||
.. only:: esp32p4
|
||||
|
||||
.. warning::
|
||||
如果 RMII 时钟模式配置为 :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_OUT`,EMAC 将通过整数分频器从 MPLL 获取 50 MHz RMII 参考时钟。当同时启用 PSRAM 时,两个外设共享 MPLL,PSRAM 会将 MPLL 锁定在由其速度配置决定的频率上。如果 PSRAM 速度配置为 80 MHz (:ref:`CONFIG_SPIRAM_SPEED`),MPLL 将运行在 320 MHz,而 320 MHz 无法通过任何整数分频得到满足 ±50 ppm 容差要求的 50 MHz(最接近的候选值为 320 / 6 ≈ 53.33 MHz)。在此配置下,EMAC 初始化将失败。
|
||||
如果 RMII 时钟模式配置为 :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_OUT`,EMAC 将通过整数分频器从 MPLL 获取 50 MHz RMII 参考时钟。当同时启用 PSRAM 时,两个外设共享 MPLL,PSRAM 会将 MPLL 锁定在由其速度配置决定的频率上。如果 PSRAM 速度配置为 80 MHz (:menuitem:`CONFIG_SPIRAM_SPEED`),MPLL 将运行在 320 MHz,而 320 MHz 无法通过任何整数分频得到满足 ±50 ppm 容差要求的 50 MHz(最接近的候选值为 320 / 6 ≈ 53.33 MHz)。在此配置下,EMAC 初始化将失败。
|
||||
|
||||
如果必须使用 80 MHz 的 PSRAM 速度,请通过外部时钟源(PHY 或振荡器)提供 ``REF_CLK``,并配置为 :cpp:enumerator:`emac_rmii_clock_mode_t::EMAC_CLK_EXT_IN`。
|
||||
|
||||
@@ -265,9 +265,9 @@ MAC 的相关配置可以在 :cpp:class:`eth_mac_config_t` 中找到,具体包
|
||||
|
||||
.. list::
|
||||
|
||||
* **网络流量由短且频繁的帧主导时**:如果你的网络流量主要由短且频繁发送(或接收)的帧组成,可能会遇到吞吐量低于预期(尽管额定为 100 Mbps),以及接收过程中丢帧等问题。在发送时,套接字发送 API 可能会返回 ``errno`` 为 ``ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别)。这些问题的主要原因是,默认的内存配置针对较大帧进行了优化。默认情况下 :ref:`CONFIG_ETH_DMA_BUFFER_SIZE` 设置为 512 字节,以确保 *数据缓冲区* 与 *描述符* 大小的开销比。要解决此问题,可以增加缓冲区数量, :ref:`CONFIG_ETH_DMA_RX_BUFFER_NUM` 或 :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM`。此外,还可以减小 :ref:`CONFIG_ETH_DMA_BUFFER_SIZE`,使其与网络中典型帧的大小相匹配,从而合理控制以太网驱动的内存占用。
|
||||
* **网络流量由短且频繁的帧主导时**:如果你的网络流量主要由短且频繁发送(或接收)的帧组成,可能会遇到吞吐量低于预期(尽管额定为 100 Mbps),以及接收过程中丢帧等问题。在发送时,套接字发送 API 可能会返回 ``errno`` 为 ``ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别)。这些问题的主要原因是,默认的内存配置针对较大帧进行了优化。默认情况下 :menuitem:`CONFIG_ETH_DMA_BUFFER_SIZE` 设置为 512 字节,以确保 *数据缓冲区* 与 *描述符* 大小的开销比。要解决此问题,可以增加缓冲区数量, :menuitem:`CONFIG_ETH_DMA_RX_BUFFER_NUM` 或 :menuitem:`CONFIG_ETH_DMA_TX_BUFFER_NUM`。此外,还可以减小 :menuitem:`CONFIG_ETH_DMA_BUFFER_SIZE`,使其与网络中典型帧的大小相匹配,从而合理控制以太网驱动的内存占用。
|
||||
|
||||
* **高吞吐量导致缓冲区耗尽时**:如果套接字发送 API 间歇性返回 ``errno`` 为 ``ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别),且吞吐量接近额定的 100 Mbps,这通常表明接近硬件限制。在这种情况下,硬件无法跟上传输请求。解决方案是,增加 :ref:`CONFIG_ETH_DMA_TX_BUFFER_NUM`,以缓存更多的帧,并缓解传输请求的短时峰值。然而,如果请求的流量持续超过额定吞吐量,此方法将失效,需通过应用层通过软件限制带宽。
|
||||
* **高吞吐量导致缓冲区耗尽时**:如果套接字发送 API 间歇性返回 ``errno`` 为 ``ENOMEM``,并显示 `TX 缓冲区大小不足`(如果启用了调试日志级别),且吞吐量接近额定的 100 Mbps,这通常表明接近硬件限制。在这种情况下,硬件无法跟上传输请求。解决方案是,增加 :menuitem:`CONFIG_ETH_DMA_TX_BUFFER_NUM`,以缓存更多的帧,并缓解传输请求的短时峰值。然而,如果请求的流量持续超过额定吞吐量,此方法将失效,需通过应用层通过软件限制带宽。
|
||||
|
||||
PHY 的相关配置可以在 :cpp:class:`eth_phy_config_t` 中找到,具体包括:
|
||||
|
||||
|
||||
@@ -137,8 +137,8 @@ IP 事件
|
||||
|
||||
.. note::
|
||||
|
||||
丢失 IP 事件由一个可配置的定时器触发,可通过 :ref:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` 启用或禁用,
|
||||
延迟由 :ref:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL` 配置。当 IP 地址丢失时定时器启动,事件将在配置的
|
||||
丢失 IP 事件由一个可配置的定时器触发,可通过 :menuitem:`CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE` 启用或禁用,
|
||||
延迟由 :menuitem:`CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL` 配置。当 IP 地址丢失时定时器启动,事件将在配置的
|
||||
时间间隔后触发(默认 120 秒)。为保持向后兼容,将时间间隔设置为 0 也会禁用该定时器。
|
||||
|
||||
.. _esp-netif structure:
|
||||
|
||||
@@ -106,11 +106,11 @@ ESP-NOW 数据可以从 Station 或 SoftAP 接口发送。确保在发送 ESP-NO
|
||||
|
||||
.. only:: esp32c2
|
||||
|
||||
配对设备的最大数量是 20,其中加密设备的数量不超过 4,默认值是 2。如果想要修改加密设备的数量,在 Wi-Fi menuconfig 设置 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`。
|
||||
配对设备的最大数量是 20,其中加密设备的数量不超过 4,默认值是 2。如果想要修改加密设备的数量,在 Wi-Fi menuconfig 设置 :menuitem:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`。
|
||||
|
||||
.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c6 or esp32c5
|
||||
|
||||
配对设备的最大数量是 20,其中加密设备的数量不超过 17,默认值是 7。如果想要修改加密设备的数量,在 Wi-Fi menuconfig 设置 :ref:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`。
|
||||
配对设备的最大数量是 20,其中加密设备的数量不超过 17,默认值是 7。如果想要修改加密设备的数量,在 Wi-Fi menuconfig 设置 :menuitem:`CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM`。
|
||||
|
||||
发送 ESP-NOW 数据
|
||||
-----------------
|
||||
|
||||
@@ -185,9 +185,9 @@ ADC 校准驱动程序会提供 ADC 校准方案。对于驱动程序来说,
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_ADC_CALI_EFUSE_TP_ENABLE` - 如果校准相关的 eFuse 值没有配置为 :cpp:type:`ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP`,则可以禁用该选项,减小代码大小。
|
||||
- :ref:`CONFIG_ADC_CALI_EFUSE_VREF_ENABLE` - 如果校准相关的 eFuse 值没有配置为 :cpp:type:`ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF`,则可以禁用该选项,减小代码大小。
|
||||
- :ref:`CONFIG_ADC_CALI_LUT_ENABLE` - 如果校准 ADC 原始结果时,衰减没有设置成 :c:macro:`ADC_ATTEN_DB_12`,则可以禁用该选项,减小代码大小。
|
||||
- :menuitem:`CONFIG_ADC_CALI_EFUSE_TP_ENABLE` - 如果校准相关的 eFuse 值没有配置为 :cpp:type:`ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP`,则可以禁用该选项,减小代码大小。
|
||||
- :menuitem:`CONFIG_ADC_CALI_EFUSE_VREF_ENABLE` - 如果校准相关的 eFuse 值没有配置为 :cpp:type:`ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF`,则可以禁用该选项,减小代码大小。
|
||||
- :menuitem:`CONFIG_ADC_CALI_LUT_ENABLE` - 如果校准 ADC 原始结果时,衰减没有设置成 :c:macro:`ADC_ATTEN_DB_12`,则可以禁用该选项,减小代码大小。
|
||||
|
||||
|
||||
.. _adc-minimize-noise:
|
||||
|
||||
@@ -252,7 +252,7 @@ ADC 控制
|
||||
|
||||
在调用 :cpp:func:`adc_continuous_register_event_callbacks` 时,还可以通过参数 ``user_data`` 注册自己的上下文,该用户数据将直接传递给回调函数。
|
||||
|
||||
此回调函数可能由于 :c:macro:`ESP_ERR_INVALID_ARG` 等原因返回错误。启用 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,如果回调函数失败并报错,可能是因为回调函数不在内部 RAM 中,请查看错误日志了解详情。此外,如果回调函数出现 :c:macro:`ESP_ERR_INVALID_STATE` 错误,表明 ADC 连续转换模式驱动已经启动,此时不应添加回调。
|
||||
此回调函数可能由于 :c:macro:`ESP_ERR_INVALID_ARG` 等原因返回错误。启用 :menuitem:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,如果回调函数失败并报错,可能是因为回调函数不在内部 RAM 中,请查看错误日志了解详情。此外,如果回调函数出现 :c:macro:`ESP_ERR_INVALID_STATE` 错误,表明 ADC 连续转换模式驱动已经启动,此时不应添加回调。
|
||||
|
||||
|
||||
转换完成事件
|
||||
@@ -266,7 +266,7 @@ ADC 控制
|
||||
|
||||
.. note::
|
||||
|
||||
启用 Kconfig 选项 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,注册的回调函数以及回调函数中调用的函数应放置在 IRAM 中,涉及的变量也应放置在内部 RAM 中。
|
||||
启用 Kconfig 选项 :menuitem:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,注册的回调函数以及回调函数中调用的函数应放置在 IRAM 中,涉及的变量也应放置在内部 RAM 中。
|
||||
|
||||
缓冲池溢出事件
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
@@ -395,15 +395,15 @@ ADC 连续转换模式读取的原始数据需要进一步解析才能获得可
|
||||
:esp32: - ESP32 DevKitC:由于存在外部自动烧录电路,GPIO 0 不能用于 ADC 连续转换模式。
|
||||
:esp32: - ESP-WROVER-KIT:由于部分 GPIO 管脚可能已经用于其他目的,GPIO 0、2、4 和 15 不能用于 ADC 连续转换模式。
|
||||
:esp32s2: - ADC 连续转换模式驱动使用 SPI3 外设作为硬件 DMA FIFO。因此,如果 SPI3 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。
|
||||
:esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。
|
||||
:esp32s3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-S3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。
|
||||
:esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :menuitem:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。
|
||||
:esp32s3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-S3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :menuitem:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。
|
||||
|
||||
.. _adc-continuous-power-management:
|
||||
|
||||
电源管理
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
启用电源管理,即启用 :ref:`CONFIG_PM_ENABLE` 时,系统在空闲状态下,可能会调整 APB 时钟频率,这可能会改变 ADC 连续转换的行为。
|
||||
启用电源管理,即启用 :menuitem:`CONFIG_PM_ENABLE` 时,系统在空闲状态下,可能会调整 APB 时钟频率,这可能会改变 ADC 连续转换的行为。
|
||||
|
||||
然而,通过获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁,ADC 连续转换模式驱动可以阻止这种改变。调用 :cpp:func:`adc_continuous_start` 启动连续转换后即可获取该锁。同样,调用 :cpp:func:`adc_continuous_stop` 停止转换后将释放该锁。因此,必须确保 :cpp:func:`adc_continuous_start` 和 :cpp:func:`adc_continuous_stop` 成对出现,否则电源管理将失效。
|
||||
|
||||
@@ -413,7 +413,7 @@ ADC 连续转换模式读取的原始数据需要进一步解析才能获得可
|
||||
IRAM 安全
|
||||
^^^^^^^^^
|
||||
|
||||
ADC 连续转换模式驱动的所有 API 均非 IRAM 安全。禁用 cache 时,不应运行这类 API。启用 Kconfig 选项 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 可确保驱动的内部 ISR 处理程序为 IRAM 安全,此时即使禁用 cache,驱动仍然会将转换结果保存到其内部缓冲池中。
|
||||
ADC 连续转换模式驱动的所有 API 均非 IRAM 安全。禁用 cache 时,不应运行这类 API。启用 Kconfig 选项 :menuitem:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 可确保驱动的内部 ISR 处理程序为 IRAM 安全,此时即使禁用 cache,驱动仍然会将转换结果保存到其内部缓冲池中。
|
||||
|
||||
|
||||
.. _adc-continuous-thread-safety:
|
||||
|
||||
@@ -163,7 +163,7 @@ ADC 单次转换模式驱动基于 {IDF_TARGET_NAME} SAR ADC 模块实现,不
|
||||
:SOC_ADC_DMA_SUPPORTED: - 一个 ADC 单元每次只能在一种操作模式下运行,可以是连续模式或单次模式。:cpp:func:`adc_oneshot_start` 提供了保护措施。
|
||||
:SOC_ADC_DIFF_SUPPORTED: - 在单端模式下,如果使用 N 端通道作为输入接口,其原始数据极性是反向的。输入电压范围为 -2 V ~ 2 V 时,N 端 raw 值为 4393~0。请使用 ADC 校准 API。
|
||||
:esp32 or esp32s2 or esp32s3: - Wi-Fi 也使用 ADC2,:cpp:func:`adc_oneshot_read` 提供了 Wi-Fi 驱动与 ADC 单次转换模式驱动间的保护。
|
||||
:esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 单次转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3`,强制使用 ADC2。
|
||||
:esp32c3: - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 单次转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_cn.pdf>`__。出于兼容性考虑,可以启用 :menuitem:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3`,强制使用 ADC2。
|
||||
:esp32: - ESP32-DevKitC:GPIO0 已用于自动烧录功能,不能用于 ADC 单次转换模式。
|
||||
:esp32: - ESP-WROVER-KIT:GPIO0、GPIO2、GPIO4 和 GPIO15 已有其他用途,不能用于 ADC 单次转换模式。
|
||||
|
||||
@@ -172,7 +172,7 @@ ADC 单次转换模式驱动基于 {IDF_TARGET_NAME} SAR ADC 模块实现,不
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
启用电源管理,即启用 :ref:`CONFIG_PM_ENABLE` 时,系统在空闲状态下可能会调整系统时钟频率。然而,ADC 单次转换模式驱动以轮询例程运行,:cpp:func:`adc_oneshot_read` 会不断检查 CPU 是否完成读取,直到函数返回。在此期间,ADC 单次转换模式驱动程序所在的任务不会受阻塞。因此,在读取时时钟频率保持稳定。
|
||||
启用电源管理,即启用 :menuitem:`CONFIG_PM_ENABLE` 时,系统在空闲状态下可能会调整系统时钟频率。然而,ADC 单次转换模式驱动以轮询例程运行,:cpp:func:`adc_oneshot_read` 会不断检查 CPU 是否完成读取,直到函数返回。在此期间,ADC 单次转换模式驱动程序所在的任务不会受阻塞。因此,在读取时时钟频率保持稳定。
|
||||
|
||||
|
||||
.. _adc-oneshot-iram-safe:
|
||||
@@ -201,7 +201,7 @@ flash 写入/擦除、OTA 等原因都可能导致 cache 禁用,此时,默
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM` 决定了放置 ADC 快速读取函数的位置,即 IRAM 或 flash 中,详情请参阅 :ref:`adc-oneshot-iram-safe`。
|
||||
- :menuitem:`CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM` 决定了放置 ADC 快速读取函数的位置,即 IRAM 或 flash 中,详情请参阅 :ref:`adc-oneshot-iram-safe`。
|
||||
|
||||
|
||||
应用示例
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
|
||||
.. note::
|
||||
|
||||
如果启用了 :ref:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`,请确保回调函数和所访问的数据都位于内部 RAM。
|
||||
如果启用了 :menuitem:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`,请确保回调函数和所访问的数据都位于内部 RAM。
|
||||
|
||||
场景二:使用外部参考信号比较两个模拟量
|
||||
========================================
|
||||
@@ -535,16 +535,16 @@
|
||||
电源管理
|
||||
--------
|
||||
|
||||
当启用 :ref:`CONFIG_PM_ENABLE` 后,睡眠和时钟切换可能会影响比较器行为。驱动会在需要时自动持有电源管理锁,因此使能比较器后,系统可能会被阻止进入 light sleep。
|
||||
当启用 :menuitem:`CONFIG_PM_ENABLE` 后,睡眠和时钟切换可能会影响比较器行为。驱动会在需要时自动持有电源管理锁,因此使能比较器后,系统可能会被阻止进入 light sleep。
|
||||
|
||||
如果你的应用比较关注功耗,建议只在确实需要时才使能比较器。
|
||||
|
||||
IRAM 安全
|
||||
---------
|
||||
|
||||
如果你希望在 cache 被禁用时,比较器中断仍能正常工作,请启用 :ref:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`。
|
||||
如果你希望在 cache 被禁用时,比较器中断仍能正常工作,请启用 :menuitem:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`。
|
||||
|
||||
如果还希望相关控制函数在这种情况下也可调用,请启用 :ref:`CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM`。
|
||||
如果还希望相关控制函数在这种情况下也可调用,请启用 :menuitem:`CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM`。
|
||||
|
||||
以下控制 API 可以放入 IRAM:
|
||||
|
||||
@@ -569,11 +569,11 @@ Kconfig 选项
|
||||
|
||||
最常用的 Kconfig 选项有:
|
||||
|
||||
- :ref:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`
|
||||
- :menuitem:`CONFIG_ANA_CMPR_ISR_CACHE_SAFE`
|
||||
让默认 ISR 路径在 cache 关闭时仍可工作。如果你的比较器中断需要覆盖 cache-off 场景,应启用此项。
|
||||
- :ref:`CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM`
|
||||
- :menuitem:`CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM`
|
||||
将可在 ISR 中调用的运行期控制 API 放入 IRAM,保证这些 API 在 cache 关闭时仍可调用。
|
||||
- :ref:`CONFIG_ANA_CMPR_ENABLE_DEBUG_LOG`
|
||||
- :menuitem:`CONFIG_ANA_CMPR_ENABLE_DEBUG_LOG`
|
||||
打开驱动调试日志,便于联调与问题定位。启用后会增加固件体积和日志输出量。
|
||||
|
||||
示例
|
||||
|
||||
@@ -327,8 +327,8 @@ Kconfig 选项
|
||||
|
||||
.. list::
|
||||
|
||||
:SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`,详情请参阅 :ref:`cam-thread-safety`。
|
||||
:SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`,详情请参阅 :ref:`cam-thread-safety`。
|
||||
:SOC_MIPI_CSI_SUPPORTED: - :menuitem:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`,详情请参阅 :ref:`cam-thread-safety`。
|
||||
:SOC_ISP_DVP_SUPPORTED: - :menuitem:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`,详情请参阅 :ref:`cam-thread-safety`。
|
||||
|
||||
.. _cam-iram-safe:
|
||||
|
||||
@@ -341,8 +341,8 @@ IRAM 安全
|
||||
|
||||
.. list::
|
||||
|
||||
:SOC_MIPI_CSI_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`
|
||||
:SOC_ISP_DVP_SUPPORTED: - :ref:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`
|
||||
:SOC_MIPI_CSI_SUPPORTED: - :menuitem:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE`
|
||||
:SOC_ISP_DVP_SUPPORTED: - :menuitem:`CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE`
|
||||
|
||||
- 即使 cache 被禁用也能启用中断服务
|
||||
- 将 ISR 使用的所有函数放入 IRAM
|
||||
|
||||
@@ -299,7 +299,7 @@ Kconfig 选项
|
||||
|
||||
以下 Kconfig 选项可用于配置 CORDIC 驱动:
|
||||
|
||||
- :ref:`CONFIG_CORDIC_ONESHOT_CTRL_FUNC_IN_IRAM` - 计算函数放入 IRAM。
|
||||
- :menuitem:`CONFIG_CORDIC_ONESHOT_CTRL_FUNC_IN_IRAM` - 计算函数放入 IRAM。
|
||||
|
||||
API 参考
|
||||
============
|
||||
|
||||
@@ -83,7 +83,7 @@ DAC 通道可以通过 DMA 连续转换数字信号,这种模式下有三种
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
在 ESP32 上,DAC 的数字控制器可以在内部连接到 I2S0,并借用其 DMA 进行连续转换。虽然 DAC 转换仅需 8 位数据,但它必须是左移的 8 位(即 16 位中的高 8 位),以满足 I2S 通信格式。默认状态下驱动程序将自动扩充数据至 16 位,如需手动扩充,请在 menuconfig 中禁用 :ref:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN`。
|
||||
在 ESP32 上,DAC 的数字控制器可以在内部连接到 I2S0,并借用其 DMA 进行连续转换。虽然 DAC 转换仅需 8 位数据,但它必须是左移的 8 位(即 16 位中的高 8 位),以满足 I2S 通信格式。默认状态下驱动程序将自动扩充数据至 16 位,如需手动扩充,请在 menuconfig 中禁用 :menuitem:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN`。
|
||||
|
||||
DAC 的数字控制器的时钟也来自 I2S0,有以下两种时钟源可选:
|
||||
|
||||
@@ -110,7 +110,7 @@ DAC 外设中包含一个余弦波发生器,可以在通道上产生余弦波
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
启用电源管理时(即开启 :ref:`CONFIG_PM_ENABLE`),系统会在进入 Light-sleep 模式前调整或停止 DAC 时钟源,这可能会影响 DAC 信号,从而导致数据无法正确转换。
|
||||
启用电源管理时(即开启 :menuitem:`CONFIG_PM_ENABLE`),系统会在进入 Light-sleep 模式前调整或停止 DAC 时钟源,这可能会影响 DAC 信号,从而导致数据无法正确转换。
|
||||
|
||||
在连续模式下使用 DAC 驱动时,可以通过获取电源管理锁来防止系统在 DMA 或余弦波模式下改变或停止时钟源。时钟源为 APB 时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。时钟源为 APLL 时(仅在 DMA 模式下),锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`。在进行 DAC 转换时(即 DMA 或余弦波发生器运行时),驱动程序会保证在调用 :cpp:func:`dac_continuous_enable` 后获取电源管理锁。同样地,在调用 :cpp:func:`dac_continuous_disable` 时,驱动程序会释放锁。
|
||||
|
||||
@@ -119,7 +119,7 @@ IRAM 安全
|
||||
|
||||
默认情况下,由于写入或擦除 flash 等原因导致 cache 被禁用时,DAC 的 DMA 中断将产生延迟,无法及时执行 DMA EOF 中断。
|
||||
|
||||
在实时应用中,可通过启用 Kconfig 选项 :ref:`CONFIG_DAC_ISR_IRAM_SAFE` 来避免此种情况发生,启用后:
|
||||
在实时应用中,可通过启用 Kconfig 选项 :menuitem:`CONFIG_DAC_ISR_IRAM_SAFE` 来避免此种情况发生,启用后:
|
||||
|
||||
1. 即使在 cache 被禁用的情况下,也可以启用中断服务。
|
||||
|
||||
@@ -137,12 +137,12 @@ IRAM 安全
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_DAC_ISR_IRAM_SAFE` 控制默认 ISR 处理程序在 cache 被禁用时能否继续运行。更多信息可参考 :ref:`dac-iram-safe`。
|
||||
- :ref:`CONFIG_DAC_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用该选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_DAC_ISR_IRAM_SAFE` 控制默认 ISR 处理程序在 cache 被禁用时能否继续运行。更多信息可参考 :ref:`dac-iram-safe`。
|
||||
- :menuitem:`CONFIG_DAC_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用该选项将增加固件的二进制文件大小。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
- :ref:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` 会在驱动中自动将 8 位数据扩展为 16 位数据,以满足 I2S DMA 格式。
|
||||
- :menuitem:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` 会在驱动中自动将 8 位数据扩展为 16 位数据,以满足 I2S DMA 格式。
|
||||
|
||||
应用示例
|
||||
--------
|
||||
|
||||
@@ -51,7 +51,7 @@ API 函数 :cpp:func:`esp_ds_sign` 和 :cpp:func:`esp_ds_start_sign` 在 RSA_DS
|
||||
|
||||
**PSA 密码学驱动程序**
|
||||
|
||||
RSA_DS 外设也通过 **PSA Crypto RSA_DS 驱动程序** 对外提供访问接口,因此可以使用标准 PSA API 执行签名(PKCS#1 v1.5 或 PSS)和 RSA 解密(PKCS#1 v1.5 或 OAEP)。在 ``Component config`` > ``mbedTLS`` 中启用 ``CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL``。要在 ESP-TLS 中配合使用 RSA_DS 外设(例如 TLS 客户端认证),请参阅 ESP-TLS 文档中的 :ref:`digital-signature-with-esp-tls`。
|
||||
RSA_DS 外设也通过 **PSA Crypto RSA_DS 驱动程序** 对外提供访问接口,因此可以使用标准 PSA API 执行签名(PKCS#1 v1.5 或 PSS)和 RSA 解密(PKCS#1 v1.5 或 OAEP)。启用 :menuitem:`CONFIG_MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL`。要在 ESP-TLS 中配合使用 RSA_DS 外设(例如 TLS 客户端认证),请参阅 ESP-TLS 文档中的 :ref:`digital-signature-with-esp-tls`。
|
||||
|
||||
.. _configure-the-ds-peripheral:
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ ECDSA 密钥可以通过 ``idf.py`` 脚本在外部编程。以下是关于编
|
||||
|
||||
{IDF_TARGET_NAME} 的 ECDSA_DS 外设支持 ECDSA-P192 和 ECDSA-P256 两种曲线操作,但默认仅启用 ECDSA-P256 操作。可以通过以下配置项启用 ECDSA-P192 操作:
|
||||
|
||||
- :ref:`CONFIG_ESP_ECDSA_ENABLE_P192_CURVE` 启用对 ECDSA-P192 曲线操作的支持,使设备可以同时执行 192 位和 256 位的 ECDSA 曲线操作。但请注意,如果 eFuse 写保护期间已永久禁用 ECDSA-P192 操作,则启用该配置项也无法重新启用该功能。
|
||||
- :menuitem:`CONFIG_ESP_ECDSA_ENABLE_P192_CURVE` 启用对 ECDSA-P192 曲线操作的支持,使设备可以同时执行 192 位和 256 位的 ECDSA 曲线操作。但请注意,如果 eFuse 写保护期间已永久禁用 ECDSA-P192 操作,则启用该配置项也无法重新启用该功能。
|
||||
|
||||
- :cpp:func:`esp_efuse_enable_ecdsa_p192_curve_mode()` 可用于以编程方式启用 ECDSA-P192 曲线操作。它会向 eFuse 写入相应值,从而使设备支持 P-192 和 P-256 曲线操作。但请注意,若对应的 eFuse 区域已被写保护,则此 API 将调用失败。
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ ETM 通道分析
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
当启用电源管理时,即 :ref:`CONFIG_PM_ENABLE` 打开的时候,系统可能会调整或禁用时钟源,并在进入睡眠前关闭 ETM 外设依赖的电源。这会导致事件和任务之间的连接信息被丢失,ETM 通道在唤醒后无法正常工作。因此,默认情况下,驱动程序会获取电源管理锁,以禁止系统关闭 ETM 外设。
|
||||
当启用电源管理时,即 :menuitem:`CONFIG_PM_ENABLE` 打开的时候,系统可能会调整或禁用时钟源,并在进入睡眠前关闭 ETM 外设依赖的电源。这会导致事件和任务之间的连接信息被丢失,ETM 通道在唤醒后无法正常工作。因此,默认情况下,驱动程序会获取电源管理锁,以禁止系统关闭 ETM 外设。
|
||||
|
||||
.. only:: SOC_ETM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
@@ -161,7 +161,7 @@ ETM 核心驱动程序具备线程安全性。
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_ETM_ENABLE_DEBUG_LOG` 用于启用调试日志输出,启用此选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_ETM_ENABLE_DEBUG_LOG` 用于启用调试日志输出,启用此选项将增加固件的二进制文件大小。
|
||||
|
||||
API 参考
|
||||
-------------
|
||||
|
||||
@@ -311,7 +311,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
|
||||
关于低功耗
|
||||
----------
|
||||
|
||||
当启用电源管理 :ref:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或禁用时钟源,从而导致 GPTimer 的计时出错。
|
||||
当启用电源管理 :menuitem:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或禁用时钟源,从而导致 GPTimer 的计时出错。
|
||||
|
||||
为了防止这种情况发生, GPTimer 驱动内部创建了一个电源管理锁。当调用 :cpp:func:`gptimer_enable` 函数后,该锁将被激活,确保系统不会进入睡眠模式,从而保持定时器的正确工作。如果需要降低功耗,可以调用 :cpp:func:`gptimer_disable` 函数来释放电源管理锁,使系统能够进入睡眠模式。但是,这样做会导致定时器停止计数,因此在唤醒后需要重新启动定时器。
|
||||
|
||||
@@ -338,7 +338,7 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
|
||||
关于 Cache 安全
|
||||
---------------
|
||||
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 GPTimer 的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_GPTIMER_ISR_CACHE_SAFE` 选项。
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 GPTimer 的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :menuitem:`CONFIG_GPTIMER_ISR_CACHE_SAFE` 选项。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -347,18 +347,18 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
|
||||
关于性能
|
||||
--------
|
||||
|
||||
为了提升中断处理的实时响应能力, GPTimer 驱动提供了 :ref:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
为了提升中断处理的实时响应能力, GPTimer 驱动提供了 :menuitem:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
|
||||
.. note::
|
||||
|
||||
但是,中断处理程序调用的用户回调函数和用户上下文数据仍然可能位于 Flash 中,缓存缺失的问题还是会存在,这需要用户自己将回调函数和数据放入内部 RAM 中,比如使用 :c:macro:`IRAM_ATTR` 和 :c:macro:`DRAM_ATTR`。
|
||||
|
||||
前文还提到, GPTimer 驱动允许部分函数在中断上下文中使用。:ref:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` 选项可以将这些函数放入 IRAM 中,一来,可以避免缓存缺失带来的性能损失,二来,这些函数在 Cache 关闭期间也能使用。
|
||||
前文还提到, GPTimer 驱动允许部分函数在中断上下文中使用。:menuitem:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` 选项可以将这些函数放入 IRAM 中,一来,可以避免缓存缺失带来的性能损失,二来,这些函数在 Cache 关闭期间也能使用。
|
||||
|
||||
其他 Kconfig 选项
|
||||
-----------------
|
||||
|
||||
- :ref:`CONFIG_GPTIMER_ENABLE_DEBUG_LOG` 选项允许强制启用 GPTimer 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
|
||||
- :menuitem:`CONFIG_GPTIMER_ENABLE_DEBUG_LOG` 选项允许强制启用 GPTimer 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
|
||||
|
||||
关于资源消耗
|
||||
------------
|
||||
@@ -368,9 +368,9 @@ GPTimer 驱动支持在中断回调函数中调用 :cpp:func:`gptimer_set_alarm_
|
||||
- 编译器优化等级设置为 ``-Os``,以确保代码尺寸最小化。
|
||||
- 默认日志等级设置为 ``ESP_LOG_INFO``,以平衡调试信息和性能。
|
||||
- 关闭以下驱动优化选项:
|
||||
- :ref:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :ref:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` - 控制函数不放入 IRAM。
|
||||
- :ref:`CONFIG_GPTIMER_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
- :menuitem:`CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :menuitem:`CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` - 控制函数不放入 IRAM。
|
||||
- :menuitem:`CONFIG_GPTIMER_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
|
||||
**注意,以下数据不是精确值,仅供参考,在不同型号的芯片上,数据会有所出入。**
|
||||
|
||||
|
||||
@@ -625,7 +625,7 @@ I2C 从机事件回调函数列表见 :cpp:type:`i2c_slave_event_callbacks_t`。
|
||||
|
||||
.. only:: SOC_I2C_SUPPORT_APB
|
||||
|
||||
启用电源管理(即打开 :ref:`CONFIG_PM_ENABLE`),系统会在进入 Light-sleep 模式前调整或暂停 I2C FIFO 的时钟源,这可能会导致 I2C 信号改变,传输或接收到无效数据。
|
||||
启用电源管理(即打开 :menuitem:`CONFIG_PM_ENABLE`),系统会在进入 Light-sleep 模式前调整或暂停 I2C FIFO 的时钟源,这可能会导致 I2C 信号改变,传输或接收到无效数据。
|
||||
|
||||
但驱动程序可以通过获取 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 类型的电源管理锁来防止系统改变 APB 频率。每当用户创建一个以 :cpp:enumerator:`I2C_CLK_SRC_APB` 为时钟源的 I2C 总线,驱动程序将在开始 I2C 操作时获取电源管理锁,并在结束 I2C 操作时自动释放锁。
|
||||
|
||||
@@ -644,7 +644,7 @@ IRAM 安全
|
||||
|
||||
默认情况下,若 cache 因写入或擦除 flash 等原因而被禁用时,将推迟 I2C 中断。此时事件回调函数将无法按时执行,会影响实时应用的系统响应。
|
||||
|
||||
Kconfig 选项 :ref:`CONFIG_I2C_ISR_IRAM_SAFE` 能够做到以下几点:
|
||||
Kconfig 选项 :menuitem:`CONFIG_I2C_ISR_IRAM_SAFE` 能够做到以下几点:
|
||||
|
||||
1. 即使 cache 被禁用,I2C 中断依旧正常运行。
|
||||
2. 将 ISR 使用的所有函数放入 IRAM 中。
|
||||
@@ -678,8 +678,8 @@ I2C 从机操作函数也通过总线操作信号保证线程安全。
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_I2C_ISR_IRAM_SAFE` 将在 cache 被禁用时控制默认的 ISR 处理程序正常工作,详情请参阅 :ref:`i2c-iram-safe`。
|
||||
- :ref:`CONFIG_I2C_ENABLE_DEBUG_LOG` 可启用调试日志,但会增加固件二进制文件大小。
|
||||
- :menuitem:`CONFIG_I2C_ISR_IRAM_SAFE` 将在 cache 被禁用时控制默认的 ISR 处理程序正常工作,详情请参阅 :ref:`i2c-iram-safe`。
|
||||
- :menuitem:`CONFIG_I2C_ENABLE_DEBUG_LOG` 可启用调试日志,但会增加固件二进制文件大小。
|
||||
|
||||
应用示例
|
||||
--------
|
||||
|
||||
@@ -258,7 +258,7 @@ I2S 驱动中的资源可分为三个级别:
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
电源管理启用(即开启 :ref:`CONFIG_PM_ENABLE`)时,系统将在进入 Light-sleep 前调整或停止 I2S 时钟源,这可能会影响 I2S 信号,从而导致传输或接收的数据无效。
|
||||
电源管理启用(即开启 :menuitem:`CONFIG_PM_ENABLE`)时,系统将在进入 Light-sleep 前调整或停止 I2S 时钟源,这可能会影响 I2S 信号,从而导致传输或接收的数据无效。
|
||||
|
||||
I2S 驱动可以获取电源管理锁,从而防止系统设置更改或时钟源被禁用。时钟源为 APB 时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_APB_FREQ_MAX`。时钟源为 APLL(若支持)时,锁的类型将被设置为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_NO_LIGHT_SLEEP`。驱动程序将在调用 :cpp:func:`i2s_channel_enable` 启用通道时获取电源管理锁,并在调用 :cpp:func:`i2s_channel_disable` 禁用通道时释放锁,确保通道运行期间 I2S 时钟源保持稳定。
|
||||
|
||||
@@ -416,7 +416,7 @@ IRAM 安全
|
||||
|
||||
默认情况下,由于写入或擦除 flash 等原因导致 cache 被禁用时,I2S 中断将产生延迟,无法及时执行 EOF 中断。
|
||||
|
||||
在实时应用中,可通过启用 Kconfig 选项 :ref:`CONFIG_I2S_ISR_IRAM_SAFE` 来避免此种情况发生,启用后:
|
||||
在实时应用中,可通过启用 Kconfig 选项 :menuitem:`CONFIG_I2S_ISR_IRAM_SAFE` 来避免此种情况发生,启用后:
|
||||
|
||||
1. 即使在 cache 被禁用的情况下,中断仍可继续运行。
|
||||
|
||||
@@ -432,8 +432,8 @@ IRAM 安全
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_I2S_ISR_IRAM_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。更多信息可参考 :ref:`i2s-iram-safe`。
|
||||
- :ref:`CONFIG_I2S_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用该选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_I2S_ISR_IRAM_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。更多信息可参考 :ref:`i2s-iram-safe`。
|
||||
- :menuitem:`CONFIG_I2S_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用该选项将增加固件的二进制文件大小。
|
||||
|
||||
应用实例
|
||||
--------
|
||||
|
||||
@@ -538,7 +538,7 @@ Cache 安全
|
||||
关于低功耗
|
||||
------------
|
||||
|
||||
当启用电源管理 :ref:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或禁用时钟源,从而导致 I3C 传输出错。
|
||||
当启用电源管理 :menuitem:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或禁用时钟源,从而导致 I3C 传输出错。
|
||||
|
||||
为了防止这种情况发生, I3C 驱动内部创建了一个电源管理锁。当调用传输函数后,该锁将被激活,确保系统不会进入睡眠模式,从而保持定时器的正确工作,直至传输完成后,驱动自动释放该锁。使系统能够进入睡眠模式。
|
||||
|
||||
@@ -547,9 +547,9 @@ Kconfig 选项
|
||||
|
||||
以下 Kconfig 选项可用于配置 I3C 驱动程序:
|
||||
|
||||
- :ref:`CONFIG_I3C_MASTER_ISR_CACHE_SAFE`:确保 I3C 中断在缓存被禁用时也能正常工作(例如 SPI Flash 写入时)
|
||||
- :ref:`CONFIG_I3C_MASTER_ISR_HANDLER_IN_IRAM`:将 I3C 主机 ISR 处理程序放入 IRAM 以提高性能并减少缓存未命中
|
||||
- :ref:`CONFIG_I3C_MASTER_ENABLE_DEBUG_LOG`:启用 I3C 调试日志
|
||||
- :menuitem:`CONFIG_I3C_MASTER_ISR_CACHE_SAFE`:确保 I3C 中断在缓存被禁用时也能正常工作(例如 SPI Flash 写入时)
|
||||
- :menuitem:`CONFIG_I3C_MASTER_ISR_HANDLER_IN_IRAM`:将 I3C 主机 ISR 处理程序放入 IRAM 以提高性能并减少缓存未命中
|
||||
- :menuitem:`CONFIG_I3C_MASTER_ENABLE_DEBUG_LOG`:启用 I3C 调试日志
|
||||
|
||||
关于资源消耗
|
||||
------------
|
||||
@@ -559,8 +559,8 @@ Kconfig 选项
|
||||
- 编译器优化等级设置为 ``-Os``,以确保代码尺寸最小化。
|
||||
- 默认日志等级设置为 ``ESP_LOG_INFO``,以平衡调试信息和性能。
|
||||
- 关闭以下驱动优化选项:
|
||||
- :ref:`CONFIG_I3C_MASTER_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :ref:`CONFIG_I3C_MASTER_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
- :menuitem:`CONFIG_I3C_MASTER_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :menuitem:`CONFIG_I3C_MASTER_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
|
||||
**注意,以下数据不是精确值,仅供参考,在不同型号的芯片上,数据会有所出入。**
|
||||
|
||||
|
||||
@@ -1117,7 +1117,7 @@ ISP HIST 控制器完成亮度统计后,将动态生成特定事件。若想
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_ISP_ISR_IRAM_SAFE` 控制默认的 ISR 句柄在 cache 被禁用时是否可以正常工作。
|
||||
- :menuitem:`CONFIG_ISP_ISR_IRAM_SAFE` 控制默认的 ISR 句柄在 cache 被禁用时是否可以正常工作。
|
||||
|
||||
.. _isp-iram-safe:
|
||||
|
||||
@@ -1126,7 +1126,7 @@ IRAM 安全
|
||||
|
||||
默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时,ISP 的中断将会延迟。
|
||||
|
||||
Kconfig 选项 :ref:`CONFIG_ISP_ISR_IRAM_SAFE` 支持:
|
||||
Kconfig 选项 :menuitem:`CONFIG_ISP_ISR_IRAM_SAFE` 支持:
|
||||
|
||||
- 即使 cache 被禁用也能启用中断
|
||||
- 将 ISR 使用的所有函数放入 IRAM
|
||||
@@ -1134,7 +1134,7 @@ Kconfig 选项 :ref:`CONFIG_ISP_ISR_IRAM_SAFE` 支持:
|
||||
|
||||
启用上述 Kconfig 选项,保证 cache 被禁用时中断可以正常运行,但这会增加 IRAM 使用量。启用此选项后,当 cache 被禁用时,ISR 回调函数将继续运行。因此,必须确保回调函数及其上下文也是 IRAM 安全的。
|
||||
|
||||
Kconfig 选项 :ref:`CONFIG_ISP_CTRL_FUNC_IN_IRAM` 支持:
|
||||
Kconfig 选项 :menuitem:`CONFIG_ISP_CTRL_FUNC_IN_IRAM` 支持:
|
||||
|
||||
- 将一些 ISP 控制函数放入 IRAM,函数列表请参见:
|
||||
|
||||
|
||||
@@ -565,7 +565,7 @@ YUV420
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
当启用电源管理(即设置了 :ref:`CONFIG_PM_ENABLE`)时,系统需要调整或停止 JPEG 的源时钟以进入 Light-sleep 模式,这可能会改变 JPEG 解码器/编码器的处理过程,也可能会导致硬件计算出现意外。为防止以上问题出现,当 JPEG 编码器/解码器工作时,无法进入 Light-sleep 模式。
|
||||
当启用电源管理(即设置了 :menuitem:`CONFIG_PM_ENABLE`)时,系统需要调整或停止 JPEG 的源时钟以进入 Light-sleep 模式,这可能会改变 JPEG 解码器/编码器的处理过程,也可能会导致硬件计算出现意外。为防止以上问题出现,当 JPEG 编码器/解码器工作时,无法进入 Light-sleep 模式。
|
||||
|
||||
每当用户通过 JPEG 进行解码或编码(即调用 :cpp:func:`jpeg_encoder_process` 或 :cpp:func:`jpeg_decoder_process`)时,驱动程序会将电源管理设定为 :cpp:enumerator:`esp_pm_lock_type_t::ESP_PM_CPU_FREQ_MAX`,确保获取电源管理锁。一旦编码或解码完成,驱动程序将释放锁,则系统可以进入 Light-sleep 模式。
|
||||
|
||||
@@ -591,7 +591,7 @@ JPEG 编解码器通过 2D-DMA 搬运数据,而 JPEG 编解码器 **无法处
|
||||
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
- :ref:`CONFIG_JPEG_ENABLE_DEBUG_LOG` 可启用调试日志,但会增加固件二进制大小。
|
||||
- :menuitem:`CONFIG_JPEG_ENABLE_DEBUG_LOG` 可启用调试日志,但会增加固件二进制大小。
|
||||
|
||||
|
||||
维护者须知
|
||||
|
||||
@@ -256,7 +256,7 @@ bounce buffer 与 PSRAM frame buffer
|
||||
|
||||
.. note::
|
||||
|
||||
强烈建议在此模式下启用 Kconfig 选项::ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`,开启“PSRAM XIP(就地执行)”功能,使 CPU 能从 PSRAM 里而不是主 flash 中提取指令和只读数据。此外,即使想通过 SPI 1 写入主 flash,外部存储器 cache 也不会被禁用,应用程序便能正常显示 OTA 进度条。
|
||||
强烈建议在此模式下启用 Kconfig 选项::menuitem:`CONFIG_SPIRAM_XIP_FROM_PSRAM`,开启“PSRAM XIP(就地执行)”功能,使 CPU 能从 PSRAM 里而不是主 flash 中提取指令和只读数据。此外,即使想通过 SPI 1 写入主 flash,外部存储器 cache 也不会被禁用,应用程序便能正常显示 OTA 进度条。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -310,7 +310,7 @@ bounce buffer 与 PSRAM frame buffer
|
||||
.. note::
|
||||
|
||||
虽说在设计良好的嵌入式应用程序中, DMA 传递数据的速度不应该赶不上 LCD 读取数据的速度。但理论上,此种情况还是有可能出现的。在 {IDF_TARGET_NAME} 的硬件中,这种情况会导致 LCD 在 DMA 等待数据时单纯输出 dummy 字节。若以流式传输运行 DMA,则 DMA 会将读取到的数据传输到某个 LCD 地址,同时 LCD 也会将数据输出到某个 LCD 地址,但上述两个地址可能会不同步,导致图像 **永久** 偏移。
|
||||
为防止类似情况发生,可以启用 :ref:`CONFIG_LCD_RGB_RESTART_IN_VSYNC` 选项,以便驱动程序在 VBlank 中断时自动重启 DMA;或者也可以调用 :cpp:func:`esp_lcd_rgb_panel_restart`,手动重启 DMA。请注意,调用 :cpp:func:`esp_lcd_rgb_panel_restart` 不会立即重启 DMA,DMA 只会在下一个 VSYNC 事件中重启。
|
||||
为防止类似情况发生,可以启用 :menuitem:`CONFIG_LCD_RGB_RESTART_IN_VSYNC` 选项,以便驱动程序在 VBlank 中断时自动重启 DMA;或者也可以调用 :cpp:func:`esp_lcd_rgb_panel_restart`,手动重启 DMA。请注意,调用 :cpp:func:`esp_lcd_rgb_panel_restart` 不会立即重启 DMA,DMA 只会在下一个 VSYNC 事件中重启。
|
||||
|
||||
API 参考
|
||||
--------
|
||||
|
||||
@@ -983,7 +983,7 @@ MCPWM 捕获通道支持在信号上检测到有效边沿时发送通知。须
|
||||
电源管理
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
启用电源管理(即开启 :ref:`CONFIG_PM_ENABLE`)时,系统会在进入 Light-sleep 前调整 PLL 和 APB 频率。该操作有可能会改变 MCPWM 定时器的计数步长,导致计时偏差。
|
||||
启用电源管理(即开启 :menuitem:`CONFIG_PM_ENABLE`)时,系统会在进入 Light-sleep 前调整 PLL 和 APB 频率。该操作有可能会改变 MCPWM 定时器的计数步长,导致计时偏差。
|
||||
|
||||
不过,驱动程序可以获取 :cpp:enumerator:`ESP_PM_NO_LIGHT_SLEEP` 类型的电源管理锁,防止系统进入 Light-sleep。每当驱动创建以 PLL 作为时钟源的 MCPWM 定时器实例时,都会在通过 :cpp:func:`mcpwm_timer_enable` 启用定时器时获取电源管理锁。反之,调用 :cpp:func:`mcpwm_timer_disable` 时,驱动程序释放锁。
|
||||
|
||||
@@ -1014,7 +1014,7 @@ IRAM 安全
|
||||
|
||||
默认情况下,禁用 cache 时,写入/擦除 flash 等原因将导致 MCPWM 中断延迟,事件回调函数也将延迟执行。在实时应用程序中,应避免此类情况。
|
||||
|
||||
因此,可以启用 Kconfig 选项 :ref:`CONFIG_MCPWM_ISR_CACHE_SAFE`,该选项:
|
||||
因此,可以启用 Kconfig 选项 :menuitem:`CONFIG_MCPWM_ISR_CACHE_SAFE`,该选项:
|
||||
|
||||
* 支持在禁用 cache 时启用所需中断
|
||||
* 支持将 ISR 使用的所有函数存放在 IRAM 中 [2]_
|
||||
@@ -1022,7 +1022,7 @@ IRAM 安全
|
||||
|
||||
启用该选项可以保证 cache 禁用时的中断运行,但会相应增加 IRAM 占用。
|
||||
|
||||
另一个 Kconfig 选项 :ref:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` 也支持将常用的 IO 控制函数存放在 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:
|
||||
另一个 Kconfig 选项 :menuitem:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` 也支持将常用的 IO 控制函数存放在 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:
|
||||
|
||||
- :cpp:func:`mcpwm_comparator_set_compare_value`
|
||||
- :cpp:func:`mcpwm_timer_set_period`
|
||||
@@ -1048,9 +1048,9 @@ IRAM 安全
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_MCPWM_ISR_CACHE_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。更多信息请参见 :ref:`mcpwm-iram-safe`。
|
||||
- :ref:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` 控制 MCPWM 控制函数的存放位置(IRAM 或 flash)。更多信息请参见 :ref:`mcpwm-iram-safe`。
|
||||
- :ref:`CONFIG_MCPWM_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用此选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_MCPWM_ISR_CACHE_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。更多信息请参见 :ref:`mcpwm-iram-safe`。
|
||||
- :menuitem:`CONFIG_MCPWM_CTRL_FUNC_IN_IRAM` 控制 MCPWM 控制函数的存放位置(IRAM 或 flash)。更多信息请参见 :ref:`mcpwm-iram-safe`。
|
||||
- :menuitem:`CONFIG_MCPWM_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用此选项将增加固件的二进制文件大小。
|
||||
|
||||
应用示例
|
||||
--------------------
|
||||
|
||||
@@ -336,7 +336,7 @@ ISR 上下文接收
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
当电源管理 :ref:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源,会导致 RX 单元内部的时间基准无法按预期工作。
|
||||
当电源管理 :menuitem:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源,会导致 RX 单元内部的时间基准无法按预期工作。
|
||||
|
||||
为了防止这种情况发生,RX 单元驱动内部创建了一个电源管理锁。锁的类型会根据不同的时钟源来设置。驱动程序将在 :cpp:func:`parlio_rx_unit_enable` 中拿锁,并在 :cpp:func:`parlio_rx_unit_disable` 中释放锁。这意味着,无论电源管理策略如何,在这两个函数之间系统不会进入睡眠模式,时钟源也不会被禁用或调整频率,任何 RX 事务都可以保证正常工作。
|
||||
|
||||
@@ -352,7 +352,7 @@ ISR 上下文接收
|
||||
关于 Cache 安全
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 RX 单元的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE` 选项。
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 RX 单元的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :menuitem:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE` 选项。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -362,16 +362,16 @@ ISR 上下文接收
|
||||
|
||||
.. note::
|
||||
|
||||
当启用了以下选项时,系统在进行 Flash 读写操作时不会自动禁用 Cache, 因此无需启用 :ref:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE`。
|
||||
当启用了以下选项时,系统在进行 Flash 读写操作时不会自动禁用 Cache, 因此无需启用 :menuitem:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE`。
|
||||
|
||||
.. list::
|
||||
:SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND: - :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND`
|
||||
:SOC_SPIRAM_XIP_SUPPORTED: - :ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`
|
||||
:SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND: - :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND`
|
||||
:SOC_SPIRAM_XIP_SUPPORTED: - :menuitem:`CONFIG_SPIRAM_XIP_FROM_PSRAM`
|
||||
|
||||
关于性能
|
||||
^^^^^^^^
|
||||
|
||||
为了提升中断处理的实时响应能力,RX 单元驱动提供了 :ref:`CONFIG_PARLIO_RX_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
为了提升中断处理的实时响应能力,RX 单元驱动提供了 :menuitem:`CONFIG_PARLIO_RX_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -382,7 +382,7 @@ ISR 上下文接收
|
||||
其他 Kconfig 选项
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_PARLIO_ENABLE_DEBUG_LOG` 选项允许强制启用 RX 单元驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。此选项与 TX 单元驱动程序共用。
|
||||
- :menuitem:`CONFIG_PARLIO_ENABLE_DEBUG_LOG` 选项允许强制启用 RX 单元驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。此选项与 TX 单元驱动程序共用。
|
||||
|
||||
关于资源消耗
|
||||
^^^^^^^^^^^^
|
||||
@@ -392,8 +392,8 @@ ISR 上下文接收
|
||||
- 编译器优化等级设置为 ``-Os``,以确保代码尺寸最小化。
|
||||
- 默认日志等级设置为 ``ESP_LOG_INFO``,以平衡调试信息和性能。
|
||||
- 关闭以下驱动优化选项:
|
||||
- :ref:`CONFIG_PARLIO_RX_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :ref:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
- :menuitem:`CONFIG_PARLIO_RX_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :menuitem:`CONFIG_PARLIO_RX_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
|
||||
**注意,以下数据不是精确值,仅供参考,在不同型号的芯片和不同版本的 IDF 上,数据会有所出入。**
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
电源管理
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
当电源管理 :ref:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源,会导致 TX 单元内部的时间基准无法按预期工作。
|
||||
当电源管理 :menuitem:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源,会导致 TX 单元内部的时间基准无法按预期工作。
|
||||
|
||||
为了防止这种情况发生, TX 单元驱动内部创建了一个电源管理锁。锁的类型会根据不同的时钟源来设置。驱动程序将在 :cpp:func:`parlio_tx_unit_enable` 中拿锁,并在 :cpp:func:`parlio_tx_unit_disable` 中释放锁。这意味着,无论电源管理策略如何,在这两个函数之间系统不会进入睡眠模式,时钟源也不会被禁用或调整频率,任何 TX 事务都可以保证正常工作。
|
||||
|
||||
@@ -348,7 +348,7 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
关于 Cache 安全
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 TX 单元的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE` 选项。
|
||||
在文件系统进行 Flash 读写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致 TX 单元的中断处理程序在此期间无法响应,从而使用户的回调函数无法及时执行。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :menuitem:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE` 选项。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -358,16 +358,16 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
|
||||
.. note::
|
||||
|
||||
当启用了以下选项时,系统在进行 Flash 读写操作时不会自动禁用 Cache, 因此无需启用 :ref:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE`。
|
||||
当启用了以下选项时,系统在进行 Flash 读写操作时不会自动禁用 Cache, 因此无需启用 :menuitem:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE`。
|
||||
|
||||
.. list::
|
||||
:SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND: - :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND`
|
||||
:SOC_SPIRAM_XIP_SUPPORTED: - :ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`
|
||||
:SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND: - :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND`
|
||||
:SOC_SPIRAM_XIP_SUPPORTED: - :menuitem:`CONFIG_SPIRAM_XIP_FROM_PSRAM`
|
||||
|
||||
关于性能
|
||||
^^^^^^^^
|
||||
|
||||
为了提升中断处理的实时响应能力, TX 单元驱动提供了 :ref:`CONFIG_PARLIO_TX_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
为了提升中断处理的实时响应能力, TX 单元驱动提供了 :menuitem:`CONFIG_PARLIO_TX_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -376,7 +376,7 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
其他 Kconfig 选项
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_PARLIO_ENABLE_DEBUG_LOG` 选项允许强制启用 TX 单元驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。此选项与 RX 单元驱动程序共用。
|
||||
- :menuitem:`CONFIG_PARLIO_ENABLE_DEBUG_LOG` 选项允许强制启用 TX 单元驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。此选项与 RX 单元驱动程序共用。
|
||||
|
||||
关于资源消耗
|
||||
^^^^^^^^^^^^
|
||||
@@ -386,8 +386,8 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
- 编译器优化等级设置为 ``-Os``,以确保代码尺寸最小化。
|
||||
- 默认日志等级设置为 ``ESP_LOG_INFO``,以平衡调试信息和性能。
|
||||
- 关闭以下驱动优化选项:
|
||||
- :ref:`CONFIG_PARLIO_TX_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :ref:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
- :menuitem:`CONFIG_PARLIO_TX_ISR_HANDLER_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :menuitem:`CONFIG_PARLIO_TX_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
|
||||
**注意,以下数据不是精确值,仅供参考,在不同型号的芯片和不同版本的 IDF 上,数据会有所出入。**
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ PCNT 内部的硬件计数器会在计数达到高/低门限的时候自动清
|
||||
电源管理
|
||||
^^^^^^^^^^
|
||||
|
||||
当电源管理使能(即 :ref:`CONFIG_PM_ENABLE` 开启)时,系统会在进入 Light-sleep 模式之前调整 APB 的频率,这可能导致 PCNT 毛刺滤波器将有效信号误认为噪声。
|
||||
当电源管理使能(即 :menuitem:`CONFIG_PM_ENABLE` 开启)时,系统会在进入 Light-sleep 模式之前调整 APB 的频率,这可能导致 PCNT 毛刺滤波器将有效信号误认为噪声。
|
||||
|
||||
为了防止这种情况发生,驱动程序可以获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁,以确保 APB 频率保持不变。该锁在通过 :cpp:func:`pcnt_unit_enable` 使能 PCNT 单元时获取,并在通过 :cpp:func:`pcnt_unit_disable` 禁用单元时释放。
|
||||
|
||||
@@ -357,7 +357,7 @@ PCNT 内部的硬件计数器会在计数达到高/低门限的时候自动清
|
||||
|
||||
当缓存由于写入/擦除 flash 等原因被禁用时,PCNT 中断会默认被延迟。这会导致报警中断无法及时执行,从而无法满足实时性应用的要求。
|
||||
|
||||
Konfig 选项 :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
|
||||
Konfig 选项 :menuitem:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
|
||||
|
||||
1. 即使缓存被禁用也可以使能中断服务
|
||||
2. 将 ISR 使用的所有函数都放入 IRAM 中 [2]_
|
||||
@@ -365,7 +365,7 @@ Konfig 选项 :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
|
||||
|
||||
这样,在缓存被禁用时,中断也可运行,但是这也会增加 IRAM 的消耗。
|
||||
|
||||
另外一个 Konfig 选项 :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 也可以把常用的 IO 控制函数放在 IRAM 中。这样,当缓存禁用时,这些函数仍然可以执行。这些 IO 控制函数如下所示:
|
||||
另外一个 Konfig 选项 :menuitem:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 也可以把常用的 IO 控制函数放在 IRAM 中。这样,当缓存禁用时,这些函数仍然可以执行。这些 IO 控制函数如下所示:
|
||||
|
||||
- :cpp:func:`pcnt_unit_start`
|
||||
- :cpp:func:`pcnt_unit_stop`
|
||||
@@ -393,9 +393,9 @@ Konfig 选项 :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 可以实现以下功能:
|
||||
支持的 Kconfig 选项
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 用于确定 PCNT 控制函数的位置(放在 IRAM 还是 flash 中),请参考 :ref:`pcnt-iram-safe` 获取更多信息。
|
||||
- :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` 用于控制当缓存禁用时,默认的 ISR 句柄是否可以工作,请参考 :ref:`pcnt-iram-safe` 获取更多信息。
|
||||
- :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` 用于使能调试日志输出,而这会增大固件二进制文件。
|
||||
- :menuitem:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` 用于确定 PCNT 控制函数的位置(放在 IRAM 还是 flash 中),请参考 :ref:`pcnt-iram-safe` 获取更多信息。
|
||||
- :menuitem:`CONFIG_PCNT_ISR_IRAM_SAFE` 用于控制当缓存禁用时,默认的 ISR 句柄是否可以工作,请参考 :ref:`pcnt-iram-safe` 获取更多信息。
|
||||
- :menuitem:`CONFIG_PCNT_ENABLE_DEBUG_LOG` 用于使能调试日志输出,而这会增大固件二进制文件。
|
||||
|
||||
应用示例
|
||||
------------
|
||||
|
||||
@@ -571,7 +571,7 @@ RMT 编码器是 RMT TX 事务的一部分,用于在特定时间生成正确
|
||||
电源管理
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
当电源管理 :ref:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源。结果是,RMT 内部的时间基准无法按预期工作。
|
||||
当电源管理 :menuitem:`CONFIG_PM_ENABLE` 被启用的时候,系统在进入睡眠前可能会调整或禁用时钟源。结果是,RMT 内部的时间基准无法按预期工作。
|
||||
|
||||
驱动程序可以通过创建一个电源管理锁来防止上述问题。锁的类型会根据不同的时钟源来设置。驱动程序将在 :cpp:func:`rmt_enable` 中拿锁,并在 :cpp:func:`rmt_disable` 中释放锁。这意味着,无论电源管理策略如何,在这两个函数之间的任何 RMT 事务都可以保证正常工作。在此期间,时钟源不会被禁用或调整频率。
|
||||
|
||||
@@ -586,7 +586,7 @@ Cache 安全
|
||||
|
||||
默认情况下,禁用 cache 时,写入/擦除主 flash 等原因将导致 RMT 中断延迟,事件回调函数也将延迟执行。在实时应用程序中,应避免此类情况。此外,当 RMT 事务依赖 **交替** 中断连续编码或复制 RMT 符号时,上述中断延迟将导致不可预测的结果。
|
||||
|
||||
因此,可以启用 Kconfig 选项 :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 和 :ref:`CONFIG_RMT_RX_ISR_CACHE_SAFE`,该选项:
|
||||
因此,可以启用 Kconfig 选项 :menuitem:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 和 :menuitem:`CONFIG_RMT_RX_ISR_CACHE_SAFE`,该选项:
|
||||
|
||||
1. 支持在禁用 cache 时启用所需中断
|
||||
2. 支持将 ISR 使用的所有函数存放在 IRAM 中 [2]_
|
||||
@@ -594,9 +594,9 @@ Cache 安全
|
||||
|
||||
启用该选项可以保证 cache 禁用时的中断运行,但会相应增加 IRAM 占用。
|
||||
|
||||
请注意,当 :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 使能后,你必须将编码器函数(主要是 :cpp:member:`rmt_encoder_t::encode` 和 :cpp:member:`rmt_encoder_t::reset`)放进 IRAM 中。建议你使用 :c:macro:`RMT_ENCODER_FUNC_ATTR` 来装饰你的编码器函数。
|
||||
请注意,当 :menuitem:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 使能后,你必须将编码器函数(主要是 :cpp:member:`rmt_encoder_t::encode` 和 :cpp:member:`rmt_encoder_t::reset`)放进 IRAM 中。建议你使用 :c:macro:`RMT_ENCODER_FUNC_ATTR` 来装饰你的编码器函数。
|
||||
|
||||
另外一个 Kconfig 选项 :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 可以将 :cpp:func:`rmt_receive` 函数放进内部的 IRAM 中,从而当 flash cache 被关闭的时候,这个函数也能够被使用。
|
||||
另外一个 Kconfig 选项 :menuitem:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 可以将 :cpp:func:`rmt_receive` 函数放进内部的 IRAM 中,从而当 flash cache 被关闭的时候,这个函数也能够被使用。
|
||||
|
||||
.. _rmt-thread-safety:
|
||||
|
||||
@@ -615,9 +615,9 @@ RMT 驱动程序会确保工厂函数 :cpp:func:`rmt_new_tx_channel`、:cpp:func
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 和 :ref:`CONFIG_RMT_RX_ISR_CACHE_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。详情请参阅 :ref:`rmt-cache-safe`。
|
||||
- :ref:`CONFIG_RMT_ENABLE_DEBUG_LOG` 用于启用调试日志输出,启用此选项将增加固件的二进制文件大小。
|
||||
- :ref:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 用于控制 RMT 接收函数被链接到系统存储的哪个位置(IRAM 还是 Flash)。详情请参阅 :ref:`rmt-cache-safe`。
|
||||
- :menuitem:`CONFIG_RMT_TX_ISR_CACHE_SAFE` 和 :menuitem:`CONFIG_RMT_RX_ISR_CACHE_SAFE` 控制默认 ISR 处理程序能否在禁用 cache 的情况下工作。详情请参阅 :ref:`rmt-cache-safe`。
|
||||
- :menuitem:`CONFIG_RMT_ENABLE_DEBUG_LOG` 用于启用调试日志输出,启用此选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_RMT_RECV_FUNC_IN_IRAM` 用于控制 RMT 接收函数被链接到系统存储的哪个位置(IRAM 还是 Flash)。详情请参阅 :ref:`rmt-cache-safe`。
|
||||
|
||||
应用示例
|
||||
--------------------
|
||||
|
||||
@@ -84,7 +84,7 @@ SDM 通道完成任务后,请调用 :cpp:func:`sdm_del_channel` 回收相应
|
||||
电源管理
|
||||
^^^^^^^^
|
||||
|
||||
启用电源管理(即启用 :ref:`CONFIG_PM_ENABLE`)时,在进入 Light-sleep 模式前,系统会调整 APB 频率,这可能会改变 Sigma-Delta 调制器的采样率。
|
||||
启用电源管理(即启用 :menuitem:`CONFIG_PM_ENABLE`)时,在进入 Light-sleep 模式前,系统会调整 APB 频率,这可能会改变 Sigma-Delta 调制器的采样率。
|
||||
|
||||
但是,通过获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁,驱动程序可以防止系统改变 APB 频率。每当驱动程序创建 SDM 通道,且该通道选择 :cpp:enumerator:`SDM_CLK_SRC_APB` 作为其时钟源时,在通过 :cpp:func:`sdm_channel_enable` 启用通道的过程中,驱动程序会确保获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁。反之,调用 :cpp:func:`sdm_channel_disable` 禁用通道时,驱动程序释放该锁。
|
||||
|
||||
@@ -93,7 +93,7 @@ SDM 通道完成任务后,请调用 :cpp:func:`sdm_del_channel` 回收相应
|
||||
IRAM 安全
|
||||
^^^^^^^^^
|
||||
|
||||
Kconfig 选项 :ref:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` 支持将常用的 IO 控制函数存放在 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:
|
||||
Kconfig 选项 :menuitem:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` 支持将常用的 IO 控制函数存放在 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:
|
||||
|
||||
- :cpp:func:`sdm_channel_set_pulse_density`
|
||||
|
||||
@@ -115,8 +115,8 @@ Kconfig 选项 :ref:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` 支持将常用的 IO 控制
|
||||
Kconfig 选项
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` 控制 SDM 通道控制函数的存放位置(IRAM 或 flash)。更多信息请参阅 :ref:`sdm-iram-safe`。
|
||||
- :ref:`CONFIG_SDM_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用此选项将增加固件的二进制文件大小。
|
||||
- :menuitem:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` 控制 SDM 通道控制函数的存放位置(IRAM 或 flash)。更多信息请参阅 :ref:`sdm-iram-safe`。
|
||||
- :menuitem:`CONFIG_SDM_ENABLE_DEBUG_LOG` 用于启用调试日志输出。启用此选项将增加固件的二进制文件大小。
|
||||
|
||||
.. _convert_to_analog_signal:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ flash 自动暂停功能
|
||||
|
||||
4. flash 从暂停模式恢复后,支持立即下达另一个暂停命令。
|
||||
|
||||
启用 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 后,缓存将保持启用状态,禁用该选项即可禁用缓存。SPI0 和 SPI1 之间的仲裁由硬件决定。当 SPI1 进行读取等耗时较短的操作时,CPU 和缓存将等待至 SPI1 操作完成。然而,在擦除、页面写入或状态寄存器写入等过程中,如 ``SE``、``PP`` 和 ``WRSR``,自动暂停功能将中断正在进行的 flash 操作,使 CPU 得以在有限的时间内读取缓存及 flash 中的数据。
|
||||
启用 :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 后,缓存将保持启用状态,禁用该选项即可禁用缓存。SPI0 和 SPI1 之间的仲裁由硬件决定。当 SPI1 进行读取等耗时较短的操作时,CPU 和缓存将等待至 SPI1 操作完成。然而,在擦除、页面写入或状态寄存器写入等过程中,如 ``SE``、``PP`` 和 ``WRSR``,自动暂停功能将中断正在进行的 flash 操作,使 CPU 得以在有限的时间内读取缓存及 flash 中的数据。
|
||||
|
||||
基于此功能,部分的代码及变量现可存放在 flash/PSRAM 中,同时仍能保证在 flash 擦除期间的正常执行,减少了 IRAM/DRAM 的消耗。
|
||||
|
||||
@@ -47,7 +47,7 @@ flash 自动暂停功能
|
||||
|
||||
2. ISR 间隔时间 (ISR interval):由于不能频繁触发 ISR,需格外注意 **ISR 间隔时间减去 ISR 时间后的剩余时间** (图中 b 点至 c 点的距离)。在此期间,SPI1 会发送恢复命令重新启动操作,所需准备时间 ``tsus`` 的典型值约为 **40 us**。如果在 SPI1 完成恢复操作前接收到了新的暂停命令,可能导致 CPU 饥饿,触发 ``TWDT``。
|
||||
|
||||
对于第 2 点中所提到的 ``tsus`` 时间可以通过翻阅 flash datasheets 查找,通常在 AC CHARACTERISTICS 章节中。用户需要保证从 datasheets 获得的 ``tsus`` 值不大于 :ref:`CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US` 值。
|
||||
对于第 2 点中所提到的 ``tsus`` 时间可以通过翻阅 flash datasheets 查找,通常在 AC CHARACTERISTICS 章节中。用户需要保证从 datasheets 获得的 ``tsus`` 值不大于 :menuitem:`CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US` 值。
|
||||
|
||||
此外,flash 暂停可能延迟。CPU 和缓存通过 SPI0 频繁访问 flash,且 SPI1 频繁发送暂停命令时,会导致 MSPI 数据传输效率下降。可以通过在内部使用 **锁** 来避免此种情况。当 SPI1 发送暂停命令时,SPI0 将接管内存 SPI 总线并启用锁。SPI0 完成数据传输后,在锁延迟时间结束前,都将保有对内存 SPI 总线的控制权。在此锁延迟期间,如果接收到其他 SPI0 事务,则该 SPI0 事务将正常进行,并开启新一轮锁延迟周期。如无其他 SPI0 事务,则 SPI0 释放内存总线并启动 SPI0/1 仲裁。
|
||||
|
||||
@@ -60,7 +60,7 @@ suspend-resume 进阶用法
|
||||
|
||||
通常情况下,硬件在发出暂停命令后,会按 ``tsus`` 设定的时间延迟一段时间,再开放内存总线给 SPI0/CPU 使用。该延迟必须按 datasheet 中的最坏情况进行设置,因此在大多数情况下都偏保守。
|
||||
|
||||
通过启用 :ref:`CONFIG_SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS` 后,硬件将通过读取 flash 状态寄存器中的 ``WIP`` 位,来判断暂停命令是否真正生效,而不再依据 :ref:`CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US` 给出的固定时间进行等待。由于实际的暂停建立时间通常远小于 datasheet 给出的最大值,所以这种方式可以显著降低暂停过程中的开销,提升整体性能。
|
||||
通过启用 :menuitem:`CONFIG_SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS` 后,硬件将通过读取 flash 状态寄存器中的 ``WIP`` 位,来判断暂停命令是否真正生效,而不再依据 :menuitem:`CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US` 给出的固定时间进行等待。由于实际的暂停建立时间通常远小于 datasheet 给出的最大值,所以这种方式可以显著降低暂停过程中的开销,提升整体性能。
|
||||
|
||||
.. important::
|
||||
|
||||
@@ -70,10 +70,10 @@ suspend-resume 进阶用法
|
||||
|
||||
通常情况下,硬件在 flash 被暂停后,会自动安排合适的时机发送 resume 命令,让 flash 继续完成原有的擦除/写入操作。这种实现对软件透明,但存在一个副作用:在高优先级任务/中断仍在运行时,硬件可能再次发起 suspend/resume 流程,从而打断这些任务,影响其执行的连续性与时序。
|
||||
|
||||
通过启用 :ref:`CONFIG_SPI_FLASH_SOFTWARE_RESUME` 后,硬件自动 resume 功能将被关闭,flash 的恢复操作改由软件在合适的时机主动发出。此时,flash 在被暂停后将一直保持暂停状态,直到软件显式恢复。在 SPI1 的等待空闲流程中,软件会主动检查 flash 的 suspend 状态,若发现处于暂停状态则调用驱动的 resume 接口让 flash 重新开始原有操作。这意味着只有当高优先级任务或中断真正完成、软件回到 SPI1 操作上下文时,才会发出 resume,从而避免 suspend-resume 行为在高优先级路径上反复抢占总线。
|
||||
通过启用 :menuitem:`CONFIG_SPI_FLASH_SOFTWARE_RESUME` 后,硬件自动 resume 功能将被关闭,flash 的恢复操作改由软件在合适的时机主动发出。此时,flash 在被暂停后将一直保持暂停状态,直到软件显式恢复。在 SPI1 的等待空闲流程中,软件会主动检查 flash 的 suspend 状态,若发现处于暂停状态则调用驱动的 resume 接口让 flash 重新开始原有操作。这意味着只有当高优先级任务或中断真正完成、软件回到 SPI1 操作上下文时,才会发出 resume,从而避免 suspend-resume 行为在高优先级路径上反复抢占总线。
|
||||
|
||||
由于该机制依赖软件层在确定的执行点完成 resume,且当前实现没有针对多核做相应保护,因此该选项有以下限制:
|
||||
|
||||
- 仅支持单核场景,需要使能 :ref:`CONFIG_FREERTOS_UNICORE`。
|
||||
- 属于实验性功能,需要使能 :ref:`CONFIG_IDF_EXPERIMENTAL_FEATURES` 后才能可见。
|
||||
- 仅支持单核场景,需要使能 :menuitem:`CONFIG_FREERTOS_UNICORE`。
|
||||
- 属于实验性功能,需要使能 :menuitem:`CONFIG_IDF_EXPERIMENTAL_FEATURES` 后才能可见。
|
||||
- 该功能会提升中断响应的连续性,提升应用的性能。但同时,单次操作 flash 的耗时会上升。
|
||||
|
||||
@@ -118,7 +118,7 @@ SPI flash 容量
|
||||
|
||||
SPI flash 容量由引导加载程序镜像头部(烧录偏移量为 0x1000)的一个字段进行配置。
|
||||
|
||||
默认情况下,引导加载程序被写入 flash 时,``esptool`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导加载程序的头部。也可以在工程配置中设置 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
默认情况下,引导加载程序被写入 flash 时,``esptool`` 会自动检测 SPI flash 容量,同时使用正确容量更新引导加载程序的头部。也可以在工程配置中设置 :menuitem:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||
|
||||
如需在运行时覆盖已配置的 flash 容量,请配置 ``g_rom_flashchip`` 结构中的 ``chip_size``。``esp_flash_*`` 函数使用此容量(于软件和 ROM 中)进行边界检查。
|
||||
|
||||
@@ -254,16 +254,16 @@ OS 函数层目前支持访问锁和延迟的方法。
|
||||
|
||||
顶层 API 将芯片驱动和 OS 函数封装成一个完整的组件,并提供参数检查。
|
||||
|
||||
使用 OS 函数还可以在一定程度上避免在擦除大块 flash 区域时出现看门狗超时的情况。在这段时间内,CPU 将被 flash 擦除任务占用,从而阻止其他任务的执行,包括为看门狗定时器 (WDT) 供电的空闲任务。若已选中配置选项 :ref:`CONFIG_ESP_TASK_WDT_PANIC`,并且 flash 操作时间长于看门狗的超时时间,系统将重新启动。
|
||||
使用 OS 函数还可以在一定程度上避免在擦除大块 flash 区域时出现看门狗超时的情况。在这段时间内,CPU 将被 flash 擦除任务占用,从而阻止其他任务的执行,包括为看门狗定时器 (WDT) 供电的空闲任务。若已选中配置选项 :menuitem:`CONFIG_ESP_TASK_WDT_PANIC`,并且 flash 操作时间长于看门狗的超时时间,系统将重新启动。
|
||||
|
||||
不过,由于不同的 flash 芯片擦除时间不同,flash 驱动几乎无法兼容,很难完全规避超时的风险,这一点需要格外注意。请遵照以下指南:
|
||||
|
||||
1. 建议启用 :ref:`CONFIG_SPI_FLASH_YIELD_DURING_ERASE` 选项,允许调度器在擦除 flash 时进行重新调度。此外,还可以使用下列参数。
|
||||
1. 建议启用 :menuitem:`CONFIG_SPI_FLASH_YIELD_DURING_ERASE` 选项,允许调度器在擦除 flash 时进行重新调度。此外,还可以使用下列参数。
|
||||
|
||||
- 在 menuconfig 中增加 :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_TICKS` 或减少 :ref:`CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS` 的时间。
|
||||
- 在 menuconfig 中增加 :ref:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 的时间,以设置更长的看门狗超时周期。然而,看门狗超时周期拉长后,可能无法再检测到以前可检测到的超时。
|
||||
- 在 menuconfig 中增加 :menuitem:`CONFIG_SPI_FLASH_ERASE_YIELD_TICKS` 或减少 :menuitem:`CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS` 的时间。
|
||||
- 在 menuconfig 中增加 :menuitem:`CONFIG_ESP_TASK_WDT_TIMEOUT_S` 的时间,以设置更长的看门狗超时周期。然而,看门狗超时周期拉长后,可能无法再检测到以前可检测到的超时。
|
||||
|
||||
1. 请注意,在进行长时间的 SPI flash 操作时,启用 :ref:`CONFIG_ESP_TASK_WDT_PANIC` 选项将会在超时时触发紧急处理程序。不过,启用该选项也可以帮助处理应用程序中的意外异常,请根据实际情况决定是否需要启用这个选项。
|
||||
1. 请注意,在进行长时间的 SPI flash 操作时,启用 :menuitem:`CONFIG_ESP_TASK_WDT_PANIC` 选项将会在超时时触发紧急处理程序。不过,启用该选项也可以帮助处理应用程序中的意外异常,请根据实际情况决定是否需要启用这个选项。
|
||||
|
||||
2. 在开发过程中,请根据项目对擦除 flash 的具体要求和时间限制,谨慎进行 flash 操作。在配置 flash 擦除超时周期时,请在实际产品要求的基础上留出合理的冗余时间,从而提高产品的可靠性。
|
||||
|
||||
@@ -285,7 +285,7 @@ flash 操作完成后,CPU A 上的函数将设置另一标志位,即 ``s_fla
|
||||
|
||||
另外,所有 API 函数均受互斥量 ``s_flash_op_mutex`` 保护。
|
||||
|
||||
在单核环境中(启用 :ref:`CONFIG_FREERTOS_UNICORE`),需要禁用上述两个 cache,以防发生 CPU 间通信。
|
||||
在单核环境中(启用 :menuitem:`CONFIG_FREERTOS_UNICORE`),需要禁用上述两个 cache,以防发生 CPU 间通信。
|
||||
|
||||
.. only:: SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
|
||||
@@ -294,13 +294,13 @@ flash 操作完成后,CPU A 上的函数将设置另一标志位,即 ``s_fla
|
||||
flash 驱动的内部存储优化
|
||||
-----------------------------
|
||||
|
||||
ESP-IDF 提供了优化 IRAM 使用的选项。通过禁用 :ref:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 选项,可以选择性地将某些函数地放入 flash,使 SPI flash 操作函数在 flash 中执行,而不是从 IRAM 中执行。这种方式能够节省 IRAM 内存,用于其他对时间敏感的函数或任务。
|
||||
ESP-IDF 提供了优化 IRAM 使用的选项。通过禁用 :menuitem:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 选项,可以选择性地将某些函数地放入 flash,使 SPI flash 操作函数在 flash 中执行,而不是从 IRAM 中执行。这种方式能够节省 IRAM 内存,用于其他对时间敏感的函数或任务。
|
||||
|
||||
然而,这种方式对 flash 性能具有一定的影响。与 IRAM 中的函数相比,放在 flash 中的函数执行时间可能略有增加。因此对于具有严格时序要求或严重依赖 SPI flash 操作的应用程序,采取此方式前需进行权衡。
|
||||
|
||||
.. note::
|
||||
|
||||
未启用 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 时,不应禁用 :ref:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM`,否则会导致严重崩溃。关于 flash 挂起功能,请参阅 :ref:`auto-suspend`。
|
||||
未启用 :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 时,不应禁用 :menuitem:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM`,否则会导致严重崩溃。关于 flash 挂起功能,请参阅 :ref:`auto-suspend`。
|
||||
|
||||
资源消耗
|
||||
^^^^^^^^^^^^
|
||||
@@ -309,7 +309,7 @@ flash 操作完成后,CPU A 上的函数将设置另一标志位,即 ``s_fla
|
||||
|
||||
**请注意,以下数据并非精确值,仅供参考;不同芯片型号可能会有所差异。**
|
||||
|
||||
启用 :ref:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 时的资源消耗如下表所示:
|
||||
启用 :menuitem:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 时的资源消耗如下表所示:
|
||||
|
||||
.. list-table:: 选项启用时的资源消耗
|
||||
:widths: 20 10 10 10 10 10 10 10 10 10
|
||||
@@ -346,7 +346,7 @@ flash 操作完成后,CPU A 上的函数将设置另一标志位,即 ``s_fla
|
||||
- 247
|
||||
- 247
|
||||
|
||||
禁用 :ref:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 时的资源消耗如下表所示:
|
||||
禁用 :menuitem:`CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM` 时的资源消耗如下表所示:
|
||||
|
||||
.. list-table:: 选项禁用时的资源消耗
|
||||
:widths: 20 10 10 10 10 10 10 10 10 10
|
||||
|
||||
@@ -19,7 +19,7 @@ SPI0/1 总线上可能发生三种活动:
|
||||
.. list::
|
||||
|
||||
- 调用非加密 SPI flash 读取 API(:cpp:func:`esp_flash_read` 等)
|
||||
:esp32: - 或 SPI1 总线上的其他驱动程序用于用户定义的 SPI 操作(启用实验性功能 :ref:`CONFIG_SPI_FLASH_SHARE_SPI1_BUS`)
|
||||
:esp32: - 或 SPI1 总线上的其他驱动程序用于用户定义的 SPI 操作(启用实验性功能 :menuitem:`CONFIG_SPI_FLASH_SHARE_SPI1_BUS`)
|
||||
|
||||
- 缓存读取(通过 SPI0)。以下 API 和操作可以触发缓存读取:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ SPI Flash API ESP-IDF 版本与芯片 ROM 版本的对比
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
芯片 ROM 中有一组 SPI flash 驱动程序,可以通过启用 :ref:`CONFIG_SPI_FLASH_ROM_IMPL` 来使用。大多数 ESP-IDF SPI flash 驱动程序的代码都在内部 RAM 中,因此启用此选项可以释放一些内部 RAM 的占用量。请注意,如果启用此选项,一些 ESP-IDF 中的 SPI flash 驱动程序功能和错误修复可能不会体现在芯片 ROM 版本中。
|
||||
芯片 ROM 中有一组 SPI flash 驱动程序,可以通过启用 :menuitem:`CONFIG_SPI_FLASH_ROM_IMPL` 来使用。大多数 ESP-IDF SPI flash 驱动程序的代码都在内部 RAM 中,因此启用此选项可以释放一些内部 RAM 的占用量。请注意,如果启用此选项,一些 ESP-IDF 中的 SPI flash 驱动程序功能和错误修复可能不会体现在芯片 ROM 版本中。
|
||||
|
||||
|
||||
ESP-IDF 支持但不包含在芯片 ROM 中的功能
|
||||
@@ -17,16 +17,16 @@ ESP-IDF 支持但不包含在芯片 ROM 中的功能
|
||||
- 八线 flash 芯片。详情请参阅 :ref:`oct-flash-doc`。
|
||||
- Flash 的 32 位地址。请注意,此功能为可选功能,详情请参阅 :ref:`32-bit-flash-doc`。
|
||||
- TH flash 芯片。
|
||||
- Kconfig 选项 :ref:`CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED`。
|
||||
- :ref:`CONFIG_SPI_FLASH_VERIFY_WRITE`,启用此选项可检测错误写入。
|
||||
- :ref:`CONFIG_SPI_FLASH_LOG_FAILED_WRITE`,启用此选项会打印错误写入。
|
||||
- :ref:`CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE`,启用此选项会检查是否将 0 写入为 1。
|
||||
- :ref:`CONFIG_SPI_FLASH_DANGEROUS_WRITE`,启用此选项会检查是否对某些受保护的区域(如引导加载程序、分区表或应用程序本身)进行了 flash 编程。
|
||||
- :ref:`CONFIG_SPI_FLASH_ENABLE_COUNTERS`,启用此选项以收集 ESP-IDF SPI flash 驱动程序 API 的性能数据。
|
||||
- :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND`,启用此选项可在 flash 短时操作时自动挂起或恢复 flash 长时操作。请注意,此功能为可选功能,详情请参阅 :ref:`auto-suspend-intro`。
|
||||
- :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`,启用此选项可在休眠时配置 flash 进入 deep power-down 模式以降低功耗。请注意,此功能为可选功能,详情请参阅 :ref:`deep-power-down-mode`。
|
||||
:ESP_ROM_HAS_SPI_FLASH_MMAP and SOC_SPIRAM_XIP_SUPPORTED and not esp32s3: - :ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM`,启用该选项后,可将外部 PSRAM 用作指令 cache 和只读数据 cache。但请注意,ROM 中的某些函数不支持此用法,而 ESP-IDF 提供了这些 ROM 函数的替代版本。
|
||||
:esp32s3: - 启用 :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` 和 :ref:`CONFIG_SPIRAM_RODATA` 后,可将外部 PSRAM 用作指令 cache 和只读数据 cache。但请注意,ROM 中的某些函数不支持此用法,而 ESP-IDF 提供了这些 ROM 函数的替代版本。
|
||||
- Kconfig 选项 :menuitem:`CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED`。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_VERIFY_WRITE`,启用此选项可检测错误写入。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_LOG_FAILED_WRITE`,启用此选项会打印错误写入。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE`,启用此选项会检查是否将 0 写入为 1。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_DANGEROUS_WRITE`,启用此选项会检查是否对某些受保护的区域(如引导加载程序、分区表或应用程序本身)进行了 flash 编程。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_ENABLE_COUNTERS`,启用此选项以收集 ESP-IDF SPI flash 驱动程序 API 的性能数据。
|
||||
- :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND`,启用此选项可在 flash 短时操作时自动挂起或恢复 flash 长时操作。请注意,此功能为可选功能,详情请参阅 :ref:`auto-suspend-intro`。
|
||||
- :menuitem:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`,启用此选项可在休眠时配置 flash 进入 deep power-down 模式以降低功耗。请注意,此功能为可选功能,详情请参阅 :ref:`deep-power-down-mode`。
|
||||
:ESP_ROM_HAS_SPI_FLASH_MMAP and SOC_SPIRAM_XIP_SUPPORTED and not esp32s3: - :menuitem:`CONFIG_SPIRAM_XIP_FROM_PSRAM`,启用该选项后,可将外部 PSRAM 用作指令 cache 和只读数据 cache。但请注意,ROM 中的某些函数不支持此用法,而 ESP-IDF 提供了这些 ROM 函数的替代版本。
|
||||
:esp32s3: - 启用 :menuitem:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` 和 :menuitem:`CONFIG_SPIRAM_RODATA` 后,可将外部 PSRAM 用作指令 cache 和只读数据 cache。但请注意,ROM 中的某些函数不支持此用法,而 ESP-IDF 提供了这些 ROM 函数的替代版本。
|
||||
|
||||
在 ESP-IDF 中引入,但不包含在芯片 ROM 中的错误修复
|
||||
--------------------------------------------------
|
||||
|
||||
@@ -94,7 +94,7 @@ QSPI flash 芯片的高性能模式
|
||||
|
||||
启用高性能模式的方法:
|
||||
|
||||
1. 取消选择 :ref:`CONFIG_ESPTOOLPY_OCT_FLASH` 和 :ref:`CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT`。高性能模式不用于八线 flash,启用相关选项可能会导致无法使用高性能模式。
|
||||
1. 取消选择 :menuitem:`CONFIG_ESPTOOLPY_OCT_FLASH` 和 :menuitem:`CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT`。高性能模式不用于八线 flash,启用相关选项可能会导致无法使用高性能模式。
|
||||
|
||||
2. 启用 ``CONFIG_SPI_FLASH_HPM_ENA`` 选项。
|
||||
|
||||
@@ -108,13 +108,13 @@ QSPI flash 芯片的高性能模式
|
||||
|
||||
通过以下方式检查引导加载程序是否支持 `DC Aware`:
|
||||
|
||||
- 如果启动了新项目,建议通过在引导加载程序菜单中选择 :ref:`CONFIG_BOOTLOADER_FLASH_DC_AWARE` 选项来启用 `DC Aware`。请注意,此选项无法通过 OTA 修改,因为支持代码在引导加载程序中。
|
||||
- 如果启动了新项目,建议通过在引导加载程序菜单中选择 :menuitem:`CONFIG_BOOTLOADER_FLASH_DC_AWARE` 选项来启用 `DC Aware`。请注意,此选项无法通过 OTA 修改,因为支持代码在引导加载程序中。
|
||||
|
||||
- 如果想在现有项目中通过 OTA 来更新 `HPM-DC` 配置选项,请检查用于构建引导加载程序的 sdkconfig 文件(升级 ESP-IDF 版本可能会使此文件与用于构建引导加载程序的文件不同):
|
||||
|
||||
- 对于最新版本的 ESP-IDF(v4.4.7+、v5.0.7+、v5.1.4+、v5.2 及以上),如果选择了 :ref:`CONFIG_BOOTLOADER_FLASH_DC_AWARE`,则引导加载程序支持 `DC Aware`。
|
||||
- 对于最新版本的 ESP-IDF(v4.4.7+、v5.0.7+、v5.1.4+、v5.2 及以上),如果选择了 :menuitem:`CONFIG_BOOTLOADER_FLASH_DC_AWARE`,则引导加载程序支持 `DC Aware`。
|
||||
|
||||
- 对于某些范围内的 ESP-IDF 版本(v4.4.4-v4.4.6、v5.0-v5.0.6 和 v5.1-v5.1.3),如果选择了 ``CONFIG_ESPTOOLPY_FLASHFREQ_120M``,则引导加载程序支持 `DC Aware`。此时,可启用 :ref:`CONFIG_BOOTLOADER_FLASH_DC_AWARE` 进行确认(不会影响实际应用中的引导加载程序)。
|
||||
- 对于某些范围内的 ESP-IDF 版本(v4.4.4-v4.4.6、v5.0-v5.0.6 和 v5.1-v5.1.3),如果选择了 ``CONFIG_ESPTOOLPY_FLASHFREQ_120M``,则引导加载程序支持 `DC Aware`。此时,可启用 :menuitem:`CONFIG_BOOTLOADER_FLASH_DC_AWARE` 进行确认(不会影响实际应用中的引导加载程序)。
|
||||
|
||||
- 对于低于 v4.4.4 的 ESP-IDF 版本,引导加载程序不支持 `DC Aware`。
|
||||
|
||||
@@ -185,12 +185,12 @@ QSPI flash 芯片的 32 位地址支持
|
||||
默认情况下,上述超过 16 MB 内存的 flash 区域可用于数据存储,例如使用文件系统。
|
||||
|
||||
*实验性功能*:如需在超过 16 MB 的四线 flash 区域实现完整支持(包括代码执行和数据访问),请启用以下实验性配置选项:
|
||||
- :ref:`CONFIG_IDF_EXPERIMENTAL_FEATURES`
|
||||
- :ref:`CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH`
|
||||
- :menuitem:`CONFIG_IDF_EXPERIMENTAL_FEATURES`
|
||||
- :menuitem:`CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH`
|
||||
|
||||
请注意,此选项为实验性功能,无法在所有四线 flash 芯片上稳定使用。详情请咨询 `乐鑫商务部 <https://www.espressif.com/zh-hans/contact-us/sales-questions>`_。
|
||||
|
||||
对于八线 flash 芯片,如果启用了 :ref:`CONFIG_ESPTOOLPY_OCT_FLASH`,则该功能默认启用。
|
||||
对于八线 flash 芯片,如果启用了 :menuitem:`CONFIG_ESPTOOLPY_OCT_FLASH`,则该功能默认启用。
|
||||
|
||||
.. _oct-flash-doc:
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
|
||||
.. important::
|
||||
|
||||
flash 芯片的硬件设计各不相同,因此启用 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 选项暂停 flash 时应仔细且系统地进行测试。如果想在量产过程中使用挂起功能,请联系 `乐鑫商务部 <https://www.espressif.com/zh-hans/contact-us/sales-questions>`_。
|
||||
flash 芯片的硬件设计各不相同,因此启用 :menuitem:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 选项暂停 flash 时应仔细且系统地进行测试。如果想在量产过程中使用挂起功能,请联系 `乐鑫商务部 <https://www.espressif.com/zh-hans/contact-us/sales-questions>`_。
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
|
||||
- 步骤 5:在 cache 被禁用时,通过 ``linker.lf`` 文件把要使用的所有芯片驱动程序放入内部 RAM 中。详情请参阅 :doc:`/api-guides/linker-script-generation`。请确保 ``linker.lf`` 包含了你添加的所有源文件。
|
||||
|
||||
- 步骤 6:在项目中添加一个新的组件,例如 ``custom_chip_driver``。在 ``custom_chip_driver/chip_drivers.c`` 文件中将芯片对象列在 ``default_registered_chips`` 下。启用 :ref:`CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST` 配置选项,防止编译和链接由 ESP-IDF 提供的默认芯片驱动程序列表 ``default_registered_chips``;相反,链接器会搜索由你自定义的同名结构体 ``default_registered_chips``。详情请参阅 :example_file:`storage/custom_flash_driver/components/custom_chip_driver/chip_drivers.c`。
|
||||
- 步骤 6:在项目中添加一个新的组件,例如 ``custom_chip_driver``。在 ``custom_chip_driver/chip_drivers.c`` 文件中将芯片对象列在 ``default_registered_chips`` 下。启用 :menuitem:`CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST` 配置选项,防止编译和链接由 ESP-IDF 提供的默认芯片驱动程序列表 ``default_registered_chips``;相反,链接器会搜索由你自定义的同名结构体 ``default_registered_chips``。详情请参阅 :example_file:`storage/custom_flash_driver/components/custom_chip_driver/chip_drivers.c`。
|
||||
|
||||
- 步骤 7:构建项目,你将看到新的 flash 驱动程序。
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
从 PSRAM 执行代码功能
|
||||
----------------------
|
||||
|
||||
选择 :ref:`CONFIG_SPIRAM_XIP_FROM_PSRAM` 配置以启用此模式。在此模式下,代码从 PSRAM 执行,在大多数情况下,缓存不会在写入 API 期间被禁用。
|
||||
选择 :menuitem:`CONFIG_SPIRAM_XIP_FROM_PSRAM` 配置以启用此模式。在此模式下,代码从 PSRAM 执行,在大多数情况下,缓存不会在写入 API 期间被禁用。
|
||||
|
||||
在此模式下,flash ``.text`` 段(用于指令)和 flash ``.rodata`` 段(用于只读数据)将在启动时加载到 PSRAM。相应的虚拟地址将映射到 PSRAM。您无需确保在 flash 被擦除/编程时执行的代码/数据位于 IRAM 中。
|
||||
|
||||
|
||||
@@ -580,7 +580,7 @@ GPIO 矩阵与 IO_MUX 管脚
|
||||
- 使用 DMA 的轮询传输事务:{IDF_TARGET_MAX_TRANS_TIME_POLL_DMA} µs。
|
||||
- 使用 CPU 的轮询传输事务:{IDF_TARGET_MAX_TRANS_TIME_POLL_CPU} µs。
|
||||
|
||||
请注意,以上数据测试时,:ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` 选项处于启用状态,SPI 传输事务相关的代码放置在 IRAM 中。若关闭此选项(例如为了节省 IRAM),可能影响传输事务持续时间。
|
||||
请注意,以上数据测试时,:menuitem:`CONFIG_SPI_MASTER_ISR_IN_IRAM` 选项处于启用状态,SPI 传输事务相关的代码放置在 IRAM 中。若关闭此选项(例如为了节省 IRAM),可能影响传输事务持续时间。
|
||||
|
||||
SPI 时钟频率
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
@@ -636,11 +636,11 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_interface_con
|
||||
缓存缺失
|
||||
^^^^^^^^^^
|
||||
|
||||
默认配置只将 ISR 置于 IRAM 中。其他 SPI 相关功能,包括驱动本身和回调都可能发生缓存缺失,需等待代码从 flash 中读取。为避免缓存缺失,可参考 :ref:`CONFIG_SPI_MASTER_IN_IRAM`,将整个 SPI 驱动置入 IRAM,并将整个回调及其 callee 函数一起置入 IRAM。
|
||||
默认配置只将 ISR 置于 IRAM 中。其他 SPI 相关功能,包括驱动本身和回调都可能发生缓存缺失,需等待代码从 flash 中读取。为避免缓存缺失,可参考 :menuitem:`CONFIG_SPI_MASTER_IN_IRAM`,将整个 SPI 驱动置入 IRAM,并将整个回调及其 callee 函数一起置入 IRAM。
|
||||
|
||||
.. note::
|
||||
|
||||
SPI 驱动是基于 FreeRTOS 的 API 实现的,在使用 :ref:`CONFIG_SPI_MASTER_IN_IRAM` 时,应启用 :ref:`CONFIG_FREERTOS_IN_IRAM`。
|
||||
SPI 驱动是基于 FreeRTOS 的 API 实现的,在使用 :menuitem:`CONFIG_SPI_MASTER_IN_IRAM` 时,应启用 :menuitem:`CONFIG_FREERTOS_IN_IRAM`。
|
||||
|
||||
单个中断传输事务传输 n 字节的总成本为 **20+8n/Fspi[MHz]** [µs],故传输速度为 **n/(20+8n/Fspi)**。8 MHz 时钟速度的传输速度见下表。
|
||||
|
||||
@@ -681,7 +681,7 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_interface_con
|
||||
|
||||
传输事务长度较短时将提高传输事务间隔成本,因此应尽可能将几个短传输事务压缩成一个传输事务,以提升传输速度。
|
||||
|
||||
注意,ISR 在 flash 操作期间默认处于禁用状态。要在 flash 操作期间继续发送传输事务,请启用 :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM`,并在 :cpp:member:`spi_bus_config_t::intr_flags` 中设置 :c:macro:`ESP_INTR_FLAG_IRAM`。此时,flash 操作前列队的传输事务将由 ISR 并行处理。此外,每个设备的回调和它们的 ``callee`` 函数都应该在 IRAM 中,避免回调因缓存丢失而崩溃。详情请参阅 :ref:`iram-safe-interrupt-handlers`。
|
||||
注意,ISR 在 flash 操作期间默认处于禁用状态。要在 flash 操作期间继续发送传输事务,请启用 :menuitem:`CONFIG_SPI_MASTER_ISR_IN_IRAM`,并在 :cpp:member:`spi_bus_config_t::intr_flags` 中设置 :c:macro:`ESP_INTR_FLAG_IRAM`。此时,flash 操作前列队的传输事务将由 ISR 并行处理。此外,每个设备的回调和它们的 ``callee`` 函数都应该在 IRAM 中,避免回调因缓存丢失而崩溃。详情请参阅 :ref:`iram-safe-interrupt-handlers`。
|
||||
|
||||
.. only:: esp32h2
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
|
||||
默认情况下,禁用 cache 时,写入/擦除 flash 等原因将导致温度传感器中断延迟,事件回调函数也将延迟执行。在实时应用程序中,应避免此类情况。
|
||||
|
||||
因此,可以启用 Kconfig 选项 :ref:`CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE`,该选项:
|
||||
因此,可以启用 Kconfig 选项 :menuitem:`CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE`,该选项:
|
||||
|
||||
1. 支持在禁用 cache 时启用所需中断
|
||||
2. 支持将 ISR 使用的所有函数存放在 IRAM 中
|
||||
|
||||
@@ -371,7 +371,7 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
关于低功耗
|
||||
----------
|
||||
|
||||
当启用电源管理 :ref:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或关闭时钟源,从而导致 TWAI 出错。为了防止这种情况发生,驱动内部使用电源锁管理。当调用 :cpp:func:`twai_node_enable` 函数后,该锁将被激活,确保系统不会进入睡眠模式,从而保持 TWAI 功能正常。如果需要降低功耗,可以调用 :cpp:func:`twai_node_disable` 函数来释放电源管理锁,使系统能够进入睡眠模式,睡眠期间 TWAI 控制器也将停止工作。
|
||||
当启用电源管理 :menuitem:`CONFIG_PM_ENABLE` 时,系统在进入睡眠模式前可能会调整或关闭时钟源,从而导致 TWAI 出错。为了防止这种情况发生,驱动内部使用电源锁管理。当调用 :cpp:func:`twai_node_enable` 函数后,该锁将被激活,确保系统不会进入睡眠模式,从而保持 TWAI 功能正常。如果需要降低功耗,可以调用 :cpp:func:`twai_node_disable` 函数来释放电源管理锁,使系统能够进入睡眠模式,睡眠期间 TWAI 控制器也将停止工作。
|
||||
|
||||
.. only:: SOC_TWAI_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
@@ -380,12 +380,12 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
|
||||
{IDF_TARGET_NAME} 支持在 **Light Sleep** 期间将 TWAI 控制器断电以进一步降低功耗,并在唤醒后自动恢复。即程序不需要在 **Light Sleep** 唤醒后重新配置 TWAI。
|
||||
|
||||
启用选项 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,并在初始化 TWAI 节点时,将 :cpp:member:`twai_onchip_node_config_t::flags::sleep_allow_pd` 设置为 ``true`` 即可启用该功能,否则 TWAI 控制器在 **Light Sleep** 期间将保持供电。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。
|
||||
启用选项 :menuitem:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP`,并在初始化 TWAI 节点时,将 :cpp:member:`twai_onchip_node_config_t::flags::sleep_allow_pd` 设置为 ``true`` 即可启用该功能,否则 TWAI 控制器在 **Light Sleep** 期间将保持供电。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。
|
||||
|
||||
关于 Cache 安全
|
||||
---------------
|
||||
|
||||
在进行 Flash 写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致存放在 Flash 上的中断处理程序在此期间无法响应。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :ref:`CONFIG_TWAI_ISR_CACHE_SAFE` 选项。
|
||||
在进行 Flash 写操作时,为了避免 Cache 从 Flash 加载指令和数据时出现错误,系统会暂时禁用 Cache 功能。这会导致存放在 Flash 上的中断处理程序在此期间无法响应。如果希望在 Cache 被禁用期间,中断处理程序仍能正常运行,可以启用 :menuitem:`CONFIG_TWAI_ISR_CACHE_SAFE` 选项。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -399,9 +399,9 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
关于性能
|
||||
--------
|
||||
|
||||
为了提升中断处理的实时响应能力, 驱动提供了 :ref:`CONFIG_TWAI_ISR_IN_IRAM` 选项。启用该选项后,中断处理程序和接收操作将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令带来的延迟。
|
||||
为了提升中断处理的实时响应能力, 驱动提供了 :menuitem:`CONFIG_TWAI_ISR_IN_IRAM` 选项。启用该选项后,中断处理程序和接收操作将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令带来的延迟。
|
||||
|
||||
对于需要高性能发送操作的应用,驱动还提供了 :ref:`CONFIG_TWAI_IO_FUNC_IN_IRAM` 选项,用于将发送函数放置在 IRAM 中。这对于在用户任务中频繁调用 :cpp:func:`twai_node_transmit` 的时间关键应用特别有效。
|
||||
对于需要高性能发送操作的应用,驱动还提供了 :menuitem:`CONFIG_TWAI_IO_FUNC_IN_IRAM` 选项,用于将发送函数放置在 IRAM 中。这对于在用户任务中频繁调用 :cpp:func:`twai_node_transmit` 的时间关键应用特别有效。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -416,8 +416,8 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
- 默认日志等级设置为 ``ESP_LOG_INFO``,以平衡调试信息和性能。
|
||||
- 关闭以下驱动优化选项:
|
||||
|
||||
- :ref:`CONFIG_TWAI_ISR_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :ref:`CONFIG_TWAI_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
- :menuitem:`CONFIG_TWAI_ISR_IN_IRAM` - 中断处理程序不放入 IRAM。
|
||||
- :menuitem:`CONFIG_TWAI_ISR_CACHE_SAFE` - 不启用 Cache 安全选项。
|
||||
|
||||
**注意,以下数据仅供参考,不是精确值,在不同芯片上会有所出入。**
|
||||
|
||||
@@ -431,7 +431,7 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
| soc | 64 | 0 | 0 | 0 | 0 | 64 | 64 | 0 |
|
||||
+-----------------+------------+-------+------+-------+-------+-------+---------+-------+
|
||||
|
||||
打开 :ref:`CONFIG_TWAI_ISR_IN_IRAM` 优化选项的消耗情况:
|
||||
打开 :menuitem:`CONFIG_TWAI_ISR_IN_IRAM` 优化选项的消耗情况:
|
||||
|
||||
+-----------------+------------+-------+------+-------+-------+-------+---------+-------+
|
||||
| Component Layer | Total Size | DIRAM | .bss | .data | .text | Flash | .rodata | .text |
|
||||
@@ -448,7 +448,7 @@ TWAI控制器能够检测由于总线干扰产生的/损坏的不符合帧格式
|
||||
其他 Kconfig 选项
|
||||
-----------------
|
||||
|
||||
- :ref:`CONFIG_TWAI_ENABLE_DEBUG_LOG` 选项允许强制启用 TWAI 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
|
||||
- :menuitem:`CONFIG_TWAI_ENABLE_DEBUG_LOG` 选项允许强制启用 TWAI 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题。
|
||||
|
||||
应用示例
|
||||
========
|
||||
|
||||
@@ -241,7 +241,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
关于低功耗
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
当启用电源管理时(即开启 :ref:`CONFIG_PM_ENABLE`),系统在进入睡眠前可能会调整或禁用时钟源。因此,UHCI 内部的 FIFO 可能无法正常工作。
|
||||
当启用电源管理时(即开启 :menuitem:`CONFIG_PM_ENABLE`),系统在进入睡眠前可能会调整或禁用时钟源。因此,UHCI 内部的 FIFO 可能无法正常工作。
|
||||
|
||||
通过创建电源管理锁,驱动程序可以避免上述问题. 驱动会根据不同的时钟源设置锁的类型. 驱动程序将在 :cpp:func:`uhci_receive` 或 :cpp:func:`uhci_transmit` 中获取锁,并在事务完成中断中释放锁。这意味着,这两个函数之间的任何 UHCI 事务都能保证正常稳定运行。
|
||||
|
||||
@@ -250,7 +250,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
|
||||
默认情况下,当由于写入或擦除主 Flash 导致缓存被禁用时,UHCI 所依赖的中断会被延迟. 因此,事务完成中断可能无法及时处理,这在实时应用中是不可接受的。更糟糕的是,当 UHCI 事务依赖 **乒乓** 中断来连续编码或复制 UHCI 缓冲区时,延迟的中断可能会导致不可预测的结果。
|
||||
|
||||
通过启用 Kconfig 选项 :ref:`CONFIG_UHCI_ISR_CACHE_SAFE`,可实现以下功能:
|
||||
通过启用 Kconfig 选项 :menuitem:`CONFIG_UHCI_ISR_CACHE_SAFE`,可实现以下功能:
|
||||
|
||||
1. 即使缓存被禁用,中断也能被及时处理。
|
||||
2. 将 ISR 使用的所有函数放入 IRAM [1]_
|
||||
@@ -265,7 +265,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
|
||||
**请注意以下数据仅供参考,不同芯片型号可能会有所不同.**
|
||||
|
||||
启用 :ref:`CONFIG_UHCI_ISR_CACHE_SAFE` 时的资源消耗:
|
||||
启用 :menuitem:`CONFIG_UHCI_ISR_CACHE_SAFE` 时的资源消耗:
|
||||
|
||||
.. list-table:: 资源消耗
|
||||
:widths: 10 10 10 10 10 10 10 10 10
|
||||
@@ -290,7 +290,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
- 175
|
||||
- 175
|
||||
|
||||
禁用 :ref:`CONFIG_UHCI_ISR_CACHE_SAFE` 时的资源消耗:
|
||||
禁用 :menuitem:`CONFIG_UHCI_ISR_CACHE_SAFE` 时的资源消耗:
|
||||
|
||||
.. list-table:: 资源消耗
|
||||
:widths: 10 10 10 10 10 10 10 10 10 10
|
||||
@@ -320,7 +320,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
关于性能
|
||||
^^^^^^^^
|
||||
|
||||
为了提升中断处理的实时响应能力, UHCI 驱动提供了 :ref:`CONFIG_UHCI_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
为了提升中断处理的实时响应能力, UHCI 驱动提供了 :menuitem:`CONFIG_UHCI_ISR_HANDLER_IN_IRAM` 选项。启用该选项后,中断处理程序将被放置在内部 RAM 中运行,从而减少了从 Flash 加载指令时可能出现的缓存丢失带来的延迟。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -334,7 +334,7 @@ RX 事件数据在 :cpp:type:`uhci_rx_event_data_t` 中定义:
|
||||
其他 Kconfig 选项
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_UHCI_ENABLE_DEBUG_LOG` 选项允许强制启用 UHCI 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题,但会增加固件二进制文件的大小。
|
||||
- :menuitem:`CONFIG_UHCI_ENABLE_DEBUG_LOG` 选项允许强制启用 UHCI 驱动的所有调试日志,无论全局日志级别设置如何。启用此选项可以帮助开发人员在调试过程中获取更详细的日志信息,从而更容易定位和解决问题,但会增加固件二进制文件的大小。
|
||||
|
||||
应用示例
|
||||
--------------------
|
||||
|
||||
@@ -26,9 +26,9 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义
|
||||
|
||||
多数配置可通过 menuconfig 完成。CMake 会根据配置信息生成及嵌入证书包。
|
||||
|
||||
* :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`:自动创建并附加证书包。
|
||||
* :ref:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`:决定添加证书列表中的哪些证书。
|
||||
* :ref:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`:指定要在证书包中嵌入的其他证书的路径。
|
||||
* :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`:自动创建并附加证书包。
|
||||
* :menuitem:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`:决定添加证书列表中的哪些证书。
|
||||
* :menuitem:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`:指定要在证书包中嵌入的其他证书的路径。
|
||||
|
||||
要在使用 ESP-TLS 时启用证书包,将函数指针指向证书包的 attach 函数:
|
||||
|
||||
@@ -75,7 +75,7 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义
|
||||
定期同步
|
||||
-------------
|
||||
|
||||
证书包会与 Mozilla 的 NSS 根证书商店定期同步。在 ESP-IDF 的次要版本或补丁版本中,为了保证兼容性,会将上游证书包中已弃用的证书添加到弃用列表。如有需要,可以通过 :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST` 将弃用证书加入默认证书包。这些弃用证书将在下一个 ESP-IDF 主要版本中移除。
|
||||
证书包会与 Mozilla 的 NSS 根证书商店定期同步。在 ESP-IDF 的次要版本或补丁版本中,为了保证兼容性,会将上游证书包中已弃用的证书添加到弃用列表。如有需要,可以通过 :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST` 将弃用证书加入默认证书包。这些弃用证书将在下一个 ESP-IDF 主要版本中移除。
|
||||
|
||||
交叉签名证书支持
|
||||
----------------
|
||||
@@ -83,7 +83,7 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义
|
||||
概述
|
||||
^^^^
|
||||
|
||||
启用配置选项 :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 时,ESP x509 证书包 API 将支持验证包含交叉签名根证书的证书链。
|
||||
启用配置选项 :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 时,ESP x509 证书包 API 将支持验证包含交叉签名根证书的证书链。
|
||||
|
||||
即使证书链中包含交叉签名根证书,验证过程中也能从证书包中智能匹配候选的证书颁发机构 (CA),从而提高与各类服务器证书的互操作性。
|
||||
|
||||
@@ -102,11 +102,11 @@ ESP x509 证书包 API 提供了一种简便的方法,帮助你安装自定义
|
||||
使用方法
|
||||
^^^^^^^^
|
||||
|
||||
除了在项目配置中启用 :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 外,应用无需额外更改。握手过程中,证书包会自动提供候选的 CA。
|
||||
除了在项目配置中启用 :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 外,应用无需额外更改。握手过程中,证书包会自动提供候选的 CA。
|
||||
|
||||
.. note::
|
||||
|
||||
如果启用了 :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY`,其内部会使用 ``MBEDTLS_X509_TRUSTED_CERT_CALLBACK``。在此情况下,用户 **不应** 自行提供受信任证书回调函数,因为证书包会自动处理。
|
||||
如果启用了 :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY`,其内部会使用 ``MBEDTLS_X509_TRUSTED_CERT_CALLBACK``。在此情况下,用户 **不应** 自行提供受信任证书回调函数,因为证书包会自动处理。
|
||||
|
||||
应用示例
|
||||
---------
|
||||
|
||||
@@ -70,7 +70,7 @@ HTTP 基本请求
|
||||
HTTPS 请求
|
||||
-----------
|
||||
|
||||
ESP HTTP 客户端支持使用 **mbedTLS** 的 SSL 连接,需将 ``url`` 配置为以 ``https`` 开头,或将 ``transport_type`` 设置为 ``HTTP_TRANSPORT_OVER_SSL``。可以通过 :ref:`CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS` 来配置 HTTPS 支持(默认启用)。
|
||||
ESP HTTP 客户端支持使用 **mbedTLS** 的 SSL 连接,需将 ``url`` 配置为以 ``https`` 开头,或将 ``transport_type`` 设置为 ``HTTP_TRANSPORT_OVER_SSL``。可以通过 :menuitem:`CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS` 来配置 HTTPS 支持(默认启用)。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -146,9 +146,9 @@ ESP HTTP 客户端具有保存和检索来自服务器的 HTTP 响应头的功
|
||||
|
||||
要启用响应头保存功能,必须配置以下 Kconfig 选项:
|
||||
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS`:启用响应头保存(默认禁用以节省内存)。
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_MAX_SAVED_RESPONSE_HEADERS`:要保存的响应头的最大数量(默认值:10)。
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_MAX_RESPONSE_HEADER_SIZE`:响应头键和值的最大大小(单位:字节,默认值:各 128 字节)。
|
||||
* :menuitem:`CONFIG_ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS`:启用响应头保存(默认禁用以节省内存)。
|
||||
* :menuitem:`CONFIG_ESP_HTTP_CLIENT_MAX_SAVED_RESPONSE_HEADERS`:要保存的响应头的最大数量(默认值:10)。
|
||||
* :menuitem:`CONFIG_ESP_HTTP_CLIENT_MAX_RESPONSE_HEADER_SIZE`:响应头键和值的最大大小(单位:字节,默认值:各 128 字节)。
|
||||
|
||||
用法
|
||||
^^^^^
|
||||
|
||||
@@ -93,7 +93,7 @@ HTTP 服务器具有长连接的功能,允许重复使用同一个连接(会
|
||||
WebSocket 服务器
|
||||
----------------
|
||||
|
||||
HTTP 服务器组件提供 websocket 支持。可以在 menuconfig 中使用 :ref:`CONFIG_HTTPD_WS_SUPPORT` 选项启用 websocket 功能。
|
||||
HTTP 服务器组件提供 websocket 支持。可以在 menuconfig 中使用 :menuitem:`CONFIG_HTTPD_WS_SUPPORT` 选项启用 websocket 功能。
|
||||
|
||||
:example:`protocols/http_server/ws_echo_server` 演示了如何使用 HTTP 服务器创建一个 WebSocket 回显服务器,该服务器在本地网络上启动,与 WebSocket 客户端进行交互,回显接收到的 WebSocket 帧。
|
||||
|
||||
@@ -105,7 +105,7 @@ HTTP 服务器组件为 WebSocket 端点提供了握手前回调 (pre-handshake
|
||||
|
||||
握手前回调函数可用于身份认证、权限校验及其他检查。如果回调返回 :c:macro:`ESP_OK`,WebSocket 握手将继续进行;如果返回其他值,则握手中止,连接也会关闭。
|
||||
|
||||
要使用 WebSocket 握手前回调,需在项目配置中启用 :ref:`CONFIG_HTTPD_WS_PRE_HANDSHAKE_CB_SUPPORT` 选项。
|
||||
要使用 WebSocket 握手前回调,需在项目配置中启用 :menuitem:`CONFIG_HTTPD_WS_PRE_HANDSHAKE_CB_SUPPORT` 选项。
|
||||
|
||||
WebSocket 握手后回调
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -114,7 +114,7 @@ WebSocket 握手后回调
|
||||
|
||||
此时连接已升级为 WebSocket,服务器已返回 WebSocket 握手响应。该握手后回调可用于记录日志、发送初始消息或执行其他初始化任务。
|
||||
|
||||
要使用 WebSocket 握手后回调功能,需在项目配置中启用 :ref:`CONFIG_HTTPD_WS_POST_HANDSHAKE_CB_SUPPORT` 选项。
|
||||
要使用 WebSocket 握手后回调功能,需在项目配置中启用 :menuitem:`CONFIG_HTTPD_WS_POST_HANDSHAKE_CB_SUPPORT` 选项。
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ HTTPS 服务器证书选择钩子
|
||||
|
||||
ESP HTTPS 服务器组件提供了设置服务器证书选择钩子的选项。启用此功能后,在服务器握手过程中,可以配置并使用证书选择回调函数。该回调函数会根据客户端 hello 消息中提供的 TLS 扩展(如 ALPN 和 SNI),动态选择合适的证书发送给客户端。
|
||||
|
||||
要启用此功能,请先在 ESP HTTPS 服务器的 menuconfig 中启用 :ref:`CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK`。请注意,只有当 Mbedtls 被用作 ESP-TLS 的 TLS 协议栈(默认行为)时,ESP-TLS 选项才可使用。
|
||||
要启用此功能,请先在 ESP HTTPS 服务器的 menuconfig 中启用 :menuitem:`CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK`。请注意,只有当 Mbedtls 被用作 ESP-TLS 的 TLS 协议栈(默认行为)时,ESP-TLS 选项才可使用。
|
||||
|
||||
启用此功能后,请使用 :cpp:type:`httpd_ssl_config_t` 结构体中的 :cpp:member:`httpd_ssl_config::cert_select_cb` 成员,设置证书选择回调函数。
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ ESP-TLS 在客户端提供了多种验证 TLS 服务器的选项,如验证对
|
||||
* ``cacert_bytes`` - CA 证书大小(以字节为单位)。
|
||||
* **use_global_ca_store**: ``global_ca_store`` 可一次性完成初始化及设置,并用于验证 ESP-TLS 连接的服务器,注意需要在这些服务器各自的 :cpp:type:`esp_tls_cfg_t` 结构体中设置 ``use_global_ca_store = true``。有关初始化和设置 ``global_ca_store`` 的不同 API,请参阅文末的 API 参考。
|
||||
* **crt_bundle_attach**:ESP x509 证书包 API 提供了便捷的服务器验证方法,即打包一组自定义的 x509 根证书,用于 TLS 服务器验证,详情请参阅 :doc:`ESP x509 证书包 </api-reference/protocols/esp_crt_bundle>`。
|
||||
* **psk_hint_key**:要使用预共享密钥验证服务器,必须在 ESP-TLS menuconfig 中启用 :ref:`CONFIG_ESP_TLS_PSK_VERIFICATION`,然后向结构体 :cpp:type:`esp_tls_cfg_t` 提供指向 PSK 提示和密钥的指针。若未选择有关服务器验证的其他选项,ESP-TLS 将仅用 PSK 验证服务器。
|
||||
* **跳过服务器验证**:该选项并不安全,仅供测试使用。在 ESP-TLS menuconfig 中启用 :ref:`CONFIG_ESP_TLS_INSECURE` 和 :ref:`CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY` 可启用该选项,此时,若未在 :cpp:type:`esp_tls_cfg_t` 结构体选择其他服务器验证选项,ESP-TLS 将默认跳过服务器验证。
|
||||
* **psk_hint_key**:要使用预共享密钥验证服务器,必须在 ESP-TLS menuconfig 中启用 :menuitem:`CONFIG_ESP_TLS_PSK_VERIFICATION`,然后向结构体 :cpp:type:`esp_tls_cfg_t` 提供指向 PSK 提示和密钥的指针。若未选择有关服务器验证的其他选项,ESP-TLS 将仅用 PSK 验证服务器。
|
||||
* **跳过服务器验证**:该选项并不安全,仅供测试使用。在 ESP-TLS menuconfig 中启用 :menuitem:`CONFIG_ESP_TLS_INSECURE` 和 :menuitem:`CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY` 可启用该选项,此时,若未在 :cpp:type:`esp_tls_cfg_t` 结构体选择其他服务器验证选项,ESP-TLS 将默认跳过服务器验证。
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -83,7 +83,7 @@ SNI 是 TLS 协议的一个扩展,它能让客户端在 TLS 握手过程中,
|
||||
ESP-TLS 服务器证书选择回调
|
||||
----------------------------------
|
||||
|
||||
使用 MbedTLS 协议栈时,ESP-TLS 组件支持设置服务器证书选择回调函数。此时,在服务器握手期间可选择使用哪个服务器证书,该回调可获取客户端发送的 "Client Hello" 消息中提供的 TLS 扩展(ALPN、SPI 等),并基于此选择传输哪个服务器证书给客户端。要启用此功能,请在 ESP-TLS menuconfig 中启用 :ref:`CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK`。
|
||||
使用 MbedTLS 协议栈时,ESP-TLS 组件支持设置服务器证书选择回调函数。此时,在服务器握手期间可选择使用哪个服务器证书,该回调可获取客户端发送的 "Client Hello" 消息中提供的 TLS 扩展(ALPN、SPI 等),并基于此选择传输哪个服务器证书给客户端。要启用此功能,请在 ESP-TLS menuconfig 中启用 :menuitem:`CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK`。
|
||||
|
||||
证书选择回调可在结构体 :cpp:type:`esp_tls_cfg_t` 中配置,具体如下:
|
||||
|
||||
@@ -135,10 +135,10 @@ ESP-TLS 组件支持通过 :cpp:func:`esp_tls_register_stack` API 注册自定
|
||||
|
||||
可选函数(如果不支持,可以为 NULL):
|
||||
|
||||
* ``get_client_session`` - 获取客户端会话票据(须启用 :ref:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`)
|
||||
* ``free_client_session`` - 释放客户端会话(须启用 :ref:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`)
|
||||
* ``server_session_ticket_ctx_init`` - 初始化服务器会话票据上下文(须启用 :ref:`CONFIG_ESP_TLS_SERVER_SESSION_TICKETS`)
|
||||
* ``server_session_ticket_ctx_free`` - 释放服务器会话票据上下文(须启用 :ref:`CONFIG_ESP_TLS_SERVER_SESSION_TICKETS`)
|
||||
* ``get_client_session`` - 获取客户端会话票据(须启用 :menuitem:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`)
|
||||
* ``free_client_session`` - 释放客户端会话(须启用 :menuitem:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`)
|
||||
* ``server_session_ticket_ctx_init`` - 初始化服务器会话票据上下文(须启用 :menuitem:`CONFIG_ESP_TLS_SERVER_SESSION_TICKETS`)
|
||||
* ``server_session_ticket_ctx_free`` - 释放服务器会话票据上下文(须启用 :menuitem:`CONFIG_ESP_TLS_SERVER_SESSION_TICKETS`)
|
||||
* ``server_session_create`` - 创建服务器会话(服务器端,如果提供了 server_session_init,该接口可以为 NULL)
|
||||
* ``server_session_init`` - 初始化服务器会话(服务器端,如果提供了 server_session_create,该接口可以为 NULL)
|
||||
* ``server_session_continue_async`` - 继续服务器端的异步握手(服务器端,如果提供了 server_session_create,该接口可以为 NULL)
|
||||
@@ -219,7 +219,7 @@ ESP-TLS 支持通过 PSA Crypto 不透明驱动接口在 ESP32 系列芯片上
|
||||
|
||||
1) 在工程中添加 `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_ 作为依赖,详情请参阅 `如何在 ESP-IDF 中使用 esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_。
|
||||
|
||||
2) 启用 menuconfig 选项 :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`:
|
||||
2) 启用 menuconfig 选项 :menuitem:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
@@ -343,7 +343,7 @@ ESP-TLS 支持客户端会话恢复,可以在后续与同一服务器连接时
|
||||
|
||||
要启用和使用客户端会话票据的步骤如下:
|
||||
|
||||
1. 启用 Kconfig 选项 :ref:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`。
|
||||
1. 启用 Kconfig 选项 :menuitem:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`。
|
||||
2. 在成功建立 TLS 连接(并完成握手)后,使用 :cpp:func:`esp_tls_get_client_session` 获取会话票据。
|
||||
|
||||
* **对于 TLS 1.3**:会话票据可能在握手后由服务器随时发送,因此应用程序应定期或在特定的应用层交互之后调用 :cpp:func:`esp_tls_get_client_session`,确保获取最新的票据。TLS 协议栈接收并处理的每个新票据都会覆盖之前的票据,用于后续的会话恢复。
|
||||
|
||||
@@ -183,9 +183,9 @@ ESP-IDF 的 PSA 内部可信存储 (Internal Trusted Storage, ITS) 实现默认
|
||||
|
||||
通过 ``menuconfig`` 在 ``Component Config`` > ``mbedTLS`` 中启用该功能:
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_STORAGE_BACKEND`:启用自定义存储后端
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MIN`:自定义密钥 ID 范围的起始值(默认 ``0x30000000``)
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MAX`:自定义密钥 ID 范围的结束值(默认 ``0x3FFFFFFF``)
|
||||
- :menuitem:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_STORAGE_BACKEND`:启用自定义存储后端
|
||||
- :menuitem:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MIN`:自定义密钥 ID 范围的起始值(默认 ``0x30000000``)
|
||||
- :menuitem:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MAX`:自定义密钥 ID 范围的结束值(默认 ``0x3FFFFFFF``)
|
||||
|
||||
配置范围内的 PSA 密钥 ID 会被路由到已注册的后端。其他所有密钥 ID(以及随机种子等 PSA 内部数据)继续使用默认的 NVS 后端。
|
||||
|
||||
@@ -290,57 +290,57 @@ ESP-IDF 中的示例使用 :doc:`/api-reference/protocols/esp_tls`,为访问
|
||||
重要配置
|
||||
--------
|
||||
|
||||
Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中的部分重要配置选项如下所示。点击 :ref:`此处 <CONFIG_MBEDTLS_MEM_ALLOC_MODE>` 获取完整配置选项列表。
|
||||
Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中的部分重要配置选项如下所示。点击 :menuitem:`此处 <CONFIG_MBEDTLS_MEM_ALLOC_MODE>` 获取完整配置选项列表。
|
||||
|
||||
**核心配置:**
|
||||
|
||||
.. list::
|
||||
|
||||
:SOC_SHA_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_SHA`:支持硬件 SHA 加速
|
||||
:SOC_AES_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_AES`:支持硬件 AES 加速
|
||||
:SOC_MPI_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_MPI`:支持硬件 MPI(大数)加速
|
||||
:SOC_ECC_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_ECC`:支持硬件 ECC 加速
|
||||
- :ref:`CONFIG_MBEDTLS_MEM_ALLOC_MODE`:内存分配策略(内部/外部/自定义)
|
||||
- :ref:`CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN`:用于内存优化的非对称输入/输出片段长度
|
||||
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`:启用动态 TX/RX buffer 分配
|
||||
- :ref:`CONFIG_MBEDTLS_DEBUG`:启用 mbedTLS 调试(有助于调试)
|
||||
:SOC_SHA_SUPPORTED: - :menuitem:`CONFIG_MBEDTLS_HARDWARE_SHA`:支持硬件 SHA 加速
|
||||
:SOC_AES_SUPPORTED: - :menuitem:`CONFIG_MBEDTLS_HARDWARE_AES`:支持硬件 AES 加速
|
||||
:SOC_MPI_SUPPORTED: - :menuitem:`CONFIG_MBEDTLS_HARDWARE_MPI`:支持硬件 MPI(大数)加速
|
||||
:SOC_ECC_SUPPORTED: - :menuitem:`CONFIG_MBEDTLS_HARDWARE_ECC`:支持硬件 ECC 加速
|
||||
- :menuitem:`CONFIG_MBEDTLS_MEM_ALLOC_MODE`:内存分配策略(内部/外部/自定义)
|
||||
- :menuitem:`CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN`:用于内存优化的非对称输入/输出片段长度
|
||||
- :menuitem:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`:启用动态 TX/RX buffer 分配
|
||||
- :menuitem:`CONFIG_MBEDTLS_DEBUG`:启用 mbedTLS 调试(有助于调试)
|
||||
|
||||
**TLS 协议配置:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_TLS_ENABLED`:启用 TLS 协议支持
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_2`:支持 TLS 1.2(推荐)
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_3`:支持 TLS 1.3(最新标准)
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_DTLS`:支持基于 UDP 的 DTLS
|
||||
- :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(客户端会话票据)
|
||||
- :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(服务器会话票据)
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_ALPN`:支持应用层协议协商
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION`:支持服务器名称指示 (SNI)
|
||||
- :menuitem:`CONFIG_MBEDTLS_TLS_ENABLED`:启用 TLS 协议支持
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_2`:支持 TLS 1.2(推荐)
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_3`:支持 TLS 1.3(最新标准)
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_PROTO_DTLS`:支持基于 UDP 的 DTLS
|
||||
- :menuitem:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(客户端会话票据)
|
||||
- :menuitem:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS`:支持 TLS 会话恢复(服务器会话票据)
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_ALPN`:支持应用层协议协商
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION`:支持服务器名称指示 (SNI)
|
||||
|
||||
**证书支持:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`:支持受信任的根证书包(详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`)
|
||||
- :ref:`CONFIG_MBEDTLS_X509_USE_C`:启用 X.509 证书支持
|
||||
- :ref:`CONFIG_MBEDTLS_PEM_PARSE_C`:读取并解析 PEM 格式的证书
|
||||
- :ref:`CONFIG_MBEDTLS_PEM_WRITE_C`:编写 PEM 格式的证书
|
||||
- :ref:`CONFIG_MBEDTLS_X509_CRT_PARSE_C`:解析 X.509 证书
|
||||
- :ref:`CONFIG_MBEDTLS_X509_CRL_PARSE_C`:解析 X.509 证书吊销列表
|
||||
- :menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`:支持受信任的根证书包(详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`)
|
||||
- :menuitem:`CONFIG_MBEDTLS_X509_USE_C`:启用 X.509 证书支持
|
||||
- :menuitem:`CONFIG_MBEDTLS_PEM_PARSE_C`:读取并解析 PEM 格式的证书
|
||||
- :menuitem:`CONFIG_MBEDTLS_PEM_WRITE_C`:编写 PEM 格式的证书
|
||||
- :menuitem:`CONFIG_MBEDTLS_X509_CRT_PARSE_C`:解析 X.509 证书
|
||||
- :menuitem:`CONFIG_MBEDTLS_X509_CRL_PARSE_C`:解析 X.509 证书吊销列表
|
||||
|
||||
**加密算法:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_AES_C`:支持 AES 块密码
|
||||
- :ref:`CONFIG_MBEDTLS_RSA_C`:RSA 公钥密码系统
|
||||
- :ref:`CONFIG_MBEDTLS_ECP_C`:支持椭圆曲线密码学
|
||||
- :ref:`CONFIG_MBEDTLS_ECDSA_C`:椭圆曲线数字签名算法
|
||||
- :ref:`CONFIG_MBEDTLS_ECDH_C`:椭圆曲线 Diffie-Hellman 密钥交换
|
||||
- :ref:`CONFIG_MBEDTLS_SHA256_C`:SHA-256 哈希函数
|
||||
- :ref:`CONFIG_MBEDTLS_SHA512_C`:SHA-512 哈希函数
|
||||
- :ref:`CONFIG_MBEDTLS_GCM_C`:Galois/Counter 模式用于认证加密
|
||||
- :menuitem:`CONFIG_MBEDTLS_AES_C`:支持 AES 块密码
|
||||
- :menuitem:`CONFIG_MBEDTLS_RSA_C`:RSA 公钥密码系统
|
||||
- :menuitem:`CONFIG_MBEDTLS_ECP_C`:支持椭圆曲线密码学
|
||||
- :menuitem:`CONFIG_MBEDTLS_ECDSA_C`:椭圆曲线数字签名算法
|
||||
- :menuitem:`CONFIG_MBEDTLS_ECDH_C`:椭圆曲线 Diffie-Hellman 密钥交换
|
||||
- :menuitem:`CONFIG_MBEDTLS_SHA256_C`:SHA-256 哈希函数
|
||||
- :menuitem:`CONFIG_MBEDTLS_SHA512_C`:SHA-512 哈希函数
|
||||
- :menuitem:`CONFIG_MBEDTLS_GCM_C`:Galois/Counter 模式用于认证加密
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -391,15 +391,15 @@ Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中
|
||||
- NA
|
||||
- 42196 B
|
||||
* - 启用 SSL 动态 buffer 长度
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH`
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH`
|
||||
- 42120 B
|
||||
* - 禁用保留对端证书
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE`
|
||||
- :menuitem:`CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE`
|
||||
- 38533 B
|
||||
* - 启用动态 TX/RX buffer
|
||||
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`
|
||||
:ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA`
|
||||
::ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT`
|
||||
- :menuitem:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`
|
||||
:menuitem:`CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA`
|
||||
::menuitem:`CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT`
|
||||
- 22013 B
|
||||
|
||||
.. note::
|
||||
@@ -408,7 +408,7 @@ Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中
|
||||
|
||||
.. note::
|
||||
|
||||
:ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 默认启用。如果无需支持交叉签名证书链,禁用该选项可将 TLS 握手期间的堆内存峰值降低约 1 KB,但代价是 flash 中的证书包体积会增大。详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`。
|
||||
:menuitem:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` 默认启用。如果无需支持交叉签名证书链,禁用该选项可将 TLS 握手期间的堆内存峰值降低约 1 KB,但代价是 flash 中的证书包体积会增大。详情请参阅 :doc:`/api-reference/protocols/esp_crt_bundle`。
|
||||
|
||||
|
||||
减小固件大小
|
||||
|
||||
@@ -41,9 +41,9 @@ Protocomm 为以下各种传输提供框架:
|
||||
|
||||
关于启用/禁用相应的安全版本,请参阅 protocomm 组件的项目配置菜单。相应配置选项如下:
|
||||
|
||||
* 支持 ``protocomm_security0``,该版本无安全功能::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0`,该选项默认启用。
|
||||
* 支持 ``protocomm_security1``,使用 Curve25519 密钥交换和 AES-CTR 加密/解密::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1`,该选项默认启用。
|
||||
* 支持 ``protocomm_security2``,使用基于 SRP6a 的密钥交换和 AES-GCM 加密/解密::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2`。
|
||||
* 支持 ``protocomm_security0``,该版本无安全功能::menuitem:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0`,该选项默认启用。
|
||||
* 支持 ``protocomm_security1``,使用 Curve25519 密钥交换和 AES-CTR 加密/解密::menuitem:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1`,该选项默认启用。
|
||||
* 支持 ``protocomm_security2``,使用基于 SRP6a 的密钥交换和 AES-GCM 加密/解密::menuitem:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2`。
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -81,23 +81,23 @@ FatFs 组件提供了便利的封装函数,用于通过 VFS 层挂载文件系
|
||||
|
||||
FatFs 组件提供以下配置选项:
|
||||
|
||||
* ``CONFIG_FATFS_LONG_FILENAMES`` - 选择 FatFs 库如何处理长文件名 (LFN) 支持。可用选项包括 :ref:`CONFIG_FATFS_LFN_NONE <CONFIG_FATFS_LFN_NONE>` 以禁用 LFN 支持并将名称限制为 `8.3 格式 <https://en.wikipedia.org/wiki/8.3_filename>`_ (仅 SFN), :ref:`CONFIG_FATFS_LFN_HEAP <CONFIG_FATFS_LFN_HEAP>` 以启用 LFN 支持并将 LFN 工作缓冲区存储在堆上(默认),以及 :ref:`CONFIG_FATFS_LFN_STACK <CONFIG_FATFS_LFN_STACK>` 以启用 LFN 支持并将 LFN 工作缓冲区存储在栈上。详细信息请参阅 `FatFs 文件名 <http://elm-chan.org/fsw/ff/doc/filename.html>`_。
|
||||
* :ref:`CONFIG_FATFS_VOLUME_COUNT` - 设置逻辑 FatFs 卷的数量。增加此值可能会增加基础内存使用量。
|
||||
* :ref:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM` - 如果启用,FatFs 库在分配内部缓冲区时优先使用外部 RAM。如果外部 RAM 分配失败,则回退到内部 RAM。这可能会对热 I/O 路径产生明显的性能开销。禁用此选项可优先考虑性能;启用可减少内部 RAM 使用量。
|
||||
* :ref:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS` - 如果启用,FatFs 库首先尝试在支持 DMA、缓存对齐的内存中分配堆工作缓冲区,以便 SDMMC 传输避免额外的拷贝。此选项在使用 PSRAM 和 SDMMC DMA 的目标芯片上(例如 ESP32-P4)非常有用。如果同时启用此选项和 :ref:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`,FatFs 库会先尝试支持 DMA 的 RAM,然后是外部 RAM,最后是内部 RAM。
|
||||
* :ref:`CONFIG_FATFS_USE_DYN_BUFFERS` - 如果启用,FatFs 库会单独分配实例缓冲区,并根据每个已挂载卷的逻辑扇区大小调整其大小。当多个 FatFs 实例使用不同的逻辑扇区大小时,此选项非常有用,因为它可以减少内存使用量。如果禁用,所有实例都使用为最大配置逻辑扇区大小调整大小的缓冲区。
|
||||
* :ref:`CONFIG_FATFS_PER_FILE_CACHE` - 如果启用,每个打开的文件使用单独的缓存缓冲区。这提高了 I/O 性能,但当多个文件打开时会增加 RAM 使用量。如果禁用,则使用单个共享缓存,这减少了 RAM 使用量,但可能会增加存储读写操作。
|
||||
* :ref:`CONFIG_FATFS_USE_FASTSEEK` - 如果启用,POSIX :cpp:func:`lseek` 运行更快。快速定位不适用于以写入模式打开的文件。要使用快速查找,请以只读模式打开文件,或关闭后以只读模式重新打开。
|
||||
* :ref:`CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE` - 设置当 :ref:`CONFIG_FATFS_USE_FASTSEEK` 启用时快速查找使用的 CLMT(簇链接映射表)缓冲区大小。较大的缓冲区可以改善较大文件上的查找行为,但会使用更多 RAM。
|
||||
* :ref:`CONFIG_FATFS_VFS_FSTAT_BLKSIZE` - 设置通过 VFS 使用的默认 stdio 文件缓冲区块大小。此选项主要与基于 stdio 的 I/O(例如 ``fread``/``fgets``)相关,不是直接 POSIX ``read``/``write`` 路径的主要调整参数。较大的值可以提高缓冲读取吞吐量,但会增加堆使用量。
|
||||
* :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC` - 如果启用,FatFs 库会在每次调用 :cpp:func:`write`、:cpp:func:`pwrite`、:cpp:func:`link`、:cpp:func:`truncate` 和 :cpp:func:`ftruncate` 后自动调用 :cpp:func:`f_sync`。此选项提高了文件一致性和大小报告的准确性,但由于会触发频繁的磁盘操作而降低了性能。
|
||||
* :ref:`CONFIG_FATFS_LINK_LOCK` - 如果启用,此选项保证 :cpp:func:`link` 函数的 API 线程安全。禁用此选项可以帮助执行频繁小文件操作(例如文件日志记录)的应用程序。禁用时,:cpp:func:`link` 执行的拷贝是非原子的。在这种情况下,从另一个任务在同一卷上对大文件使用 :cpp:func:`link` 不保证线程安全。
|
||||
* 其他相关选项包括 :ref:`CONFIG_FATFS_FS_LOCK`、:ref:`CONFIG_FATFS_TIMEOUT_MS` 和 ``CONFIG_FATFS_CHOOSE_CODEPAGE`` (特别是 ``CONFIG_FATFS_CODEPAGE_DYNAMIC`` 对代码大小的影响)。其他选项包括 ``CONFIG_FATFS_SECTOR_SIZE``、``CONFIG_FATFS_MAX_LFN``、``CONFIG_FATFS_API_ENCODING`` 和 ``CONFIG_FATFS_USE_STRFUNC_CHOICE``。
|
||||
* ``CONFIG_FATFS_LONG_FILENAMES`` - 选择 FatFs 库如何处理长文件名 (LFN) 支持。可用选项包括 :menuitem:`CONFIG_FATFS_LFN_NONE <CONFIG_FATFS_LFN_NONE>` 以禁用 LFN 支持并将名称限制为 `8.3 格式 <https://en.wikipedia.org/wiki/8.3_filename>`_ (仅 SFN), :menuitem:`CONFIG_FATFS_LFN_HEAP <CONFIG_FATFS_LFN_HEAP>` 以启用 LFN 支持并将 LFN 工作缓冲区存储在堆上(默认),以及 :menuitem:`CONFIG_FATFS_LFN_STACK <CONFIG_FATFS_LFN_STACK>` 以启用 LFN 支持并将 LFN 工作缓冲区存储在栈上。详细信息请参阅 `FatFs 文件名 <http://elm-chan.org/fsw/ff/doc/filename.html>`_。
|
||||
* :menuitem:`CONFIG_FATFS_VOLUME_COUNT` - 设置逻辑 FatFs 卷的数量。增加此值可能会增加基础内存使用量。
|
||||
* :menuitem:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM` - 如果启用,FatFs 库在分配内部缓冲区时优先使用外部 RAM。如果外部 RAM 分配失败,则回退到内部 RAM。这可能会对热 I/O 路径产生明显的性能开销。禁用此选项可优先考虑性能;启用可减少内部 RAM 使用量。
|
||||
* :menuitem:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS` - 如果启用,FatFs 库首先尝试在支持 DMA、缓存对齐的内存中分配堆工作缓冲区,以便 SDMMC 传输避免额外的拷贝。此选项在使用 PSRAM 和 SDMMC DMA 的目标芯片上(例如 ESP32-P4)非常有用。如果同时启用此选项和 :menuitem:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`,FatFs 库会先尝试支持 DMA 的 RAM,然后是外部 RAM,最后是内部 RAM。
|
||||
* :menuitem:`CONFIG_FATFS_USE_DYN_BUFFERS` - 如果启用,FatFs 库会单独分配实例缓冲区,并根据每个已挂载卷的逻辑扇区大小调整其大小。当多个 FatFs 实例使用不同的逻辑扇区大小时,此选项非常有用,因为它可以减少内存使用量。如果禁用,所有实例都使用为最大配置逻辑扇区大小调整大小的缓冲区。
|
||||
* :menuitem:`CONFIG_FATFS_PER_FILE_CACHE` - 如果启用,每个打开的文件使用单独的缓存缓冲区。这提高了 I/O 性能,但当多个文件打开时会增加 RAM 使用量。如果禁用,则使用单个共享缓存,这减少了 RAM 使用量,但可能会增加存储读写操作。
|
||||
* :menuitem:`CONFIG_FATFS_USE_FASTSEEK` - 如果启用,POSIX :cpp:func:`lseek` 运行更快。快速定位不适用于以写入模式打开的文件。要使用快速查找,请以只读模式打开文件,或关闭后以只读模式重新打开。
|
||||
* :menuitem:`CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE` - 设置当 :menuitem:`CONFIG_FATFS_USE_FASTSEEK` 启用时快速查找使用的 CLMT(簇链接映射表)缓冲区大小。较大的缓冲区可以改善较大文件上的查找行为,但会使用更多 RAM。
|
||||
* :menuitem:`CONFIG_FATFS_VFS_FSTAT_BLKSIZE` - 设置通过 VFS 使用的默认 stdio 文件缓冲区块大小。此选项主要与基于 stdio 的 I/O(例如 ``fread``/``fgets``)相关,不是直接 POSIX ``read``/``write`` 路径的主要调整参数。较大的值可以提高缓冲读取吞吐量,但会增加堆使用量。
|
||||
* :menuitem:`CONFIG_FATFS_IMMEDIATE_FSYNC` - 如果启用,FatFs 库会在每次调用 :cpp:func:`write`、:cpp:func:`pwrite`、:cpp:func:`link`、:cpp:func:`truncate` 和 :cpp:func:`ftruncate` 后自动调用 :cpp:func:`f_sync`。此选项提高了文件一致性和大小报告的准确性,但由于会触发频繁的磁盘操作而降低了性能。
|
||||
* :menuitem:`CONFIG_FATFS_LINK_LOCK` - 如果启用,此选项保证 :cpp:func:`link` 函数的 API 线程安全。禁用此选项可以帮助执行频繁小文件操作(例如文件日志记录)的应用程序。禁用时,:cpp:func:`link` 执行的拷贝是非原子的。在这种情况下,从另一个任务在同一卷上对大文件使用 :cpp:func:`link` 不保证线程安全。
|
||||
* 其他相关选项包括 :menuitem:`CONFIG_FATFS_FS_LOCK`、:menuitem:`CONFIG_FATFS_TIMEOUT_MS` 和 ``CONFIG_FATFS_CHOOSE_CODEPAGE`` (特别是 ``CONFIG_FATFS_CODEPAGE_DYNAMIC`` 对代码大小的影响)。其他选项包括 ``CONFIG_FATFS_SECTOR_SIZE``、``CONFIG_FATFS_MAX_LFN``、``CONFIG_FATFS_API_ENCODING`` 和 ``CONFIG_FATFS_USE_STRFUNC_CHOICE``。
|
||||
|
||||
这些选项控制 FatFs 库如何计算和报告可用空间:
|
||||
|
||||
* :ref:`CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT` - 如果设置为 1,FatFs 库忽略空闲簇计数。默认值为 0。
|
||||
* :ref:`CONFIG_FATFS_DONT_TRUST_LAST_ALLOC` - 如果设置为 1,FatFs 库忽略上次分配编号。默认值为 0。
|
||||
* :menuitem:`CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT` - 如果设置为 1,FatFs 库忽略空闲簇计数。默认值为 0。
|
||||
* :menuitem:`CONFIG_FATFS_DONT_TRUST_LAST_ALLOC` - 如果设置为 1,FatFs 库忽略上次分配编号。默认值为 0。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -324,9 +324,9 @@ exFAT 使用不同的元数据布局。除了 FAT 区域外,它还需要一个
|
||||
|
||||
影响行为的主要变量是:
|
||||
|
||||
* 缓冲区位置和大小(:ref:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS`、:ref:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`、:ref:`CONFIG_FATFS_USE_DYN_BUFFERS`、:ref:`CONFIG_FATFS_PER_FILE_CACHE` 和应用程序 I/O 缓冲区大小)。
|
||||
* 缓冲区位置和大小(:menuitem:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS`、:menuitem:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`、:menuitem:`CONFIG_FATFS_USE_DYN_BUFFERS`、:menuitem:`CONFIG_FATFS_PER_FILE_CACHE` 和应用程序 I/O 缓冲区大小)。
|
||||
* 磨损均衡逻辑扇区大小和模式(``CONFIG_WL_SECTOR_SIZE_*`` 和 ``CONFIG_WL_SECTOR_MODE_*``)。
|
||||
* 同步策略(:ref:`CONFIG_FATFS_IMMEDIATE_FSYNC`)。
|
||||
* 同步策略(:menuitem:`CONFIG_FATFS_IMMEDIATE_FSYNC`)。
|
||||
* 工作负载模式(事务大小、顺序访问与随机访问、读取与写入比率)。
|
||||
|
||||
优化 I/O 性能
|
||||
@@ -334,15 +334,15 @@ exFAT 使用不同的元数据布局。除了 FAT 区域外,它还需要一个
|
||||
|
||||
对于面向吞吐量的工作负载:
|
||||
|
||||
* 除非一致性要求需要,否则保持禁用 :ref:`CONFIG_FATFS_IMMEDIATE_FSYNC`。
|
||||
* 如果峰值速度是最高优先级,请禁用 :ref:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`,以便缓冲区保留在内部 RAM 中。
|
||||
* 除非一致性要求需要,否则保持禁用 :menuitem:`CONFIG_FATFS_IMMEDIATE_FSYNC`。
|
||||
* 如果峰值速度是最高优先级,请禁用 :menuitem:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM`,以便缓冲区保留在内部 RAM 中。
|
||||
* 优先选择较大的读写事务大小,而不是许多小操作。
|
||||
* 尽可能将事务大小与活动扇区大小(例如 512 B 或 4096 B)对齐,并在需要时填充写入以减少部分扇区开销。
|
||||
* 对于带磨损均衡的 SPI flash,当 RAM 预算允许时,优先选择 ``CONFIG_WL_SECTOR_SIZE_4096``,因为它通常更高效。
|
||||
* 如果使用 512 字节的 WL 扇区,当应用程序可以接受 flash 扇区擦除期间更高的断电风险时,请使用 ``CONFIG_WL_SECTOR_MODE_PERF``。
|
||||
* 在热路径上尽可能优先选择 POSIX ``read``/``write`` 而不是 ``fread``/``fwrite``。有关更广泛的速度指导,请参阅 :doc:`最大化执行速度 <../../api-guides/performance/speed>`。
|
||||
* 在 SDMMC DMA 目标(例如带有 PSRAM 的 ESP32-P4)上,启用 :ref:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS` 以减少额外的缓冲区拷贝。
|
||||
* 对于具有长反向查找的读取密集型工作负载,启用 :ref:`CONFIG_FATFS_USE_FASTSEEK`。
|
||||
* 在 SDMMC DMA 目标(例如带有 PSRAM 的 ESP32-P4)上,启用 :menuitem:`CONFIG_FATFS_ALLOC_PREFER_ALIGNED_WORK_BUFFERS` 以减少额外的缓冲区拷贝。
|
||||
* 对于具有长反向查找的读取密集型工作负载,启用 :menuitem:`CONFIG_FATFS_USE_FASTSEEK`。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -351,14 +351,14 @@ exFAT 使用不同的元数据布局。除了 FAT 区域外,它还需要一个
|
||||
优化内存使用
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* 当减少 RAM 使用是优先事项时,禁用 :ref:`CONFIG_FATFS_PER_FILE_CACHE` 以使用单个共享缓存。
|
||||
* 当减少 RAM 使用是优先事项时,禁用 :menuitem:`CONFIG_FATFS_PER_FILE_CACHE` 以使用单个共享缓存。
|
||||
* 尽可能低地调整 ``esp_vfs_fat_mount_config_t.max_files`` (参见 :ref:`挂载和使用 FatFs <fatfs-mount-and-use>`);每个同时打开的文件都会增加 RAM 使用量。
|
||||
* 如果启用了 :ref:`CONFIG_FATFS_PER_FILE_CACHE`,优先选择 ``CONFIG_WL_SECTOR_SIZE_512`` 以减少每文件缓存大小。
|
||||
* 如果禁用了 :ref:`CONFIG_FATFS_PER_FILE_CACHE`,``CONFIG_WL_SECTOR_SIZE_4096`` 可能是更好的权衡。
|
||||
* 在支持外部 RAM 的目标上启用 :ref:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM` 以减少内部 RAM 压力,但预计 I/O 性能会降低。
|
||||
* 如果启用了 :menuitem:`CONFIG_FATFS_PER_FILE_CACHE`,优先选择 ``CONFIG_WL_SECTOR_SIZE_512`` 以减少每文件缓存大小。
|
||||
* 如果禁用了 :menuitem:`CONFIG_FATFS_PER_FILE_CACHE`,``CONFIG_WL_SECTOR_SIZE_4096`` 可能是更好的权衡。
|
||||
* 在支持外部 RAM 的目标上启用 :menuitem:`CONFIG_FATFS_ALLOC_PREFER_EXTRAM` 以减少内部 RAM 压力,但预计 I/O 性能会降低。
|
||||
* 当 SFN (8.3) 文件名可接受时,考虑使用 ``CONFIG_FATFS_LONG_FILENAMES = CONFIG_FATFS_LFN_NONE``。
|
||||
* 如果需要长文件名,将 ``CONFIG_FATFS_MAX_LFN`` 减小到满足需求的最小值。
|
||||
* 启用 :ref:`CONFIG_FATFS_USE_DYN_BUFFERS`,以便每个挂载的卷使用根据其实际扇区大小调整大小的缓冲区。
|
||||
* 启用 :menuitem:`CONFIG_FATFS_USE_DYN_BUFFERS`,以便每个挂载的卷使用根据其实际扇区大小调整大小的缓冲区。
|
||||
|
||||
优化存储效率
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
.. note::
|
||||
|
||||
在使用基于 HMAC 的方案进行上述流程时,可以直接调用 :cpp:func:`nvs_flash_secure_init` API 对默认和自定义 NVS 分区进行加密,而无需启用 NVS 加密相关配置选项(如 :ref:`CONFIG_NVS_ENCRYPTION`, :ref:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> ``CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC``, :ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID`)。
|
||||
在使用基于 HMAC 的方案进行上述流程时,可以直接调用 :cpp:func:`nvs_flash_secure_init` API 对默认和自定义 NVS 分区进行加密,而无需启用 NVS 加密相关配置选项(如 :menuitem:`CONFIG_NVS_ENCRYPTION`, :menuitem:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> ``CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC``, :menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID`)。
|
||||
|
||||
|
||||
应用示例
|
||||
|
||||
@@ -12,7 +12,7 @@ NVS 加密
|
||||
|
||||
.. only:: SOC_HMAC_SUPPORTED
|
||||
|
||||
根据要使用的具体方案,可以选择启用 :ref:`CONFIG_NVS_ENCRYPTION` 和 :ref:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` > ``CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC`` 或 ``CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC`` 实现 NVS 加密。
|
||||
根据要使用的具体方案,可以选择启用 :menuitem:`CONFIG_NVS_ENCRYPTION` 和 :menuitem:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` > ``CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC`` 或 ``CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC`` 实现 NVS 加密。
|
||||
|
||||
.. _nvs_encr_flash_enc_scheme:
|
||||
|
||||
@@ -120,13 +120,13 @@ NVS 密钥分区
|
||||
|
||||
注意,此方案使用一个 eFuse 块来存储获取加密密钥所需的 HMAC 密钥。
|
||||
|
||||
- NVS 加密启用时后,可用 API 函数 :cpp:func:`nvs_flash_init` 来初始化加密的默认 NVS 分区。该 API 函数首先检查 :ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 处是否存在一个 HMAC 密钥。
|
||||
- NVS 加密启用时后,可用 API 函数 :cpp:func:`nvs_flash_init` 来初始化加密的默认 NVS 分区。该 API 函数首先检查 :menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 处是否存在一个 HMAC 密钥。
|
||||
|
||||
.. note::
|
||||
|
||||
:ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 配置的有效范围为 ``0`` (:cpp:enumerator:`hmac_key_id_t::HMAC_KEY0`) 到 ``5`` (:cpp:enumerator:`hmac_key_id_t::HMAC_KEY5`)。默认情况下该配置为 ``-1``,须在构建用户应用程序之前进行修改。
|
||||
:menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 配置的有效范围为 ``0`` (:cpp:enumerator:`hmac_key_id_t::HMAC_KEY0`) 到 ``5`` (:cpp:enumerator:`hmac_key_id_t::HMAC_KEY5`)。默认情况下该配置为 ``-1``,须在构建用户应用程序之前进行修改。
|
||||
|
||||
- 如果找不到密钥,会内部生成一个密钥,并储存在 :ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 指定的 eFuse 块中。
|
||||
- 如果找不到密钥,会内部生成一个密钥,并储存在 :menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 指定的 eFuse 块中。
|
||||
- 如果找到用于 :cpp:enumerator:`esp_efuse_purpose_t::ESP_EFUSE_KEY_PURPOSE_HMAC_UP` 的密钥,该密钥也会用于 XTS 加密密钥的生成。
|
||||
- 如果指定的 eFuse 块被 :cpp:enumerator:`esp_efuse_purpose_t::ESP_EFUSE_KEY_PURPOSE_HMAC_UP` 以外目的的密钥占用,则会引发错误。
|
||||
|
||||
@@ -146,13 +146,13 @@ NVS API 函数 ``nvs_get_*`` 或 ``nvs_set_*`` 也可用于读取和写入加密
|
||||
|
||||
**加密默认的 NVS 分区**
|
||||
|
||||
- 要为默认 NVS 分区启用加密,无需额外的步骤。在启用 :ref:`CONFIG_NVS_ENCRYPTION` 时,API 函数 :cpp:func:`nvs_flash_init` 会根据使用的方案(由 :ref:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` 设置)在内部执行一些额外步骤,为默认的 NVS 分区启用加密。
|
||||
- 要为默认 NVS 分区启用加密,无需额外的步骤。在启用 :menuitem:`CONFIG_NVS_ENCRYPTION` 时,API 函数 :cpp:func:`nvs_flash_init` 会根据使用的方案(由 :menuitem:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` 设置)在内部执行一些额外步骤,为默认的 NVS 分区启用加密。
|
||||
|
||||
- 在基于 flash 加密的方案中,加密密钥由找到的第一个 :ref:`nvs_encr_key_partition` 生成。
|
||||
|
||||
.. only:: SOC_HMAC_SUPPORTED
|
||||
|
||||
在 HMAC 方案中,密钥由 :ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 中烧录的 HMAC 密钥生成(参考 API 文档以了解更多详细信息)。
|
||||
在 HMAC 方案中,密钥由 :menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID` 中烧录的 HMAC 密钥生成(参考 API 文档以了解更多详细信息)。
|
||||
|
||||
另外,还可使用 API 函数 :cpp:func:`nvs_flash_secure_init` 为默认 NVS 分区启用加密。
|
||||
|
||||
@@ -211,7 +211,7 @@ NVS API 函数 ``nvs_get_*`` 或 ``nvs_set_*`` 也可用于读取和写入加密
|
||||
.. only:: SOC_HMAC_SUPPORTED
|
||||
|
||||
.. note::
|
||||
在采用基于 HMAC 的方案时,可以在不启用任何 NVS 加密的配置选项的情况下开始上述工作流::ref:`CONFIG_NVS_ENCRYPTION`,:ref:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> `CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC` 和 :ref:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID`,以使用 :cpp:func:`nvs_flash_secure_init` API 加密默认分区及自定义的 NVS 分区。
|
||||
在采用基于 HMAC 的方案时,可以在不启用任何 NVS 加密的配置选项的情况下开始上述工作流::menuitem:`CONFIG_NVS_ENCRYPTION`,:menuitem:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> `CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC` 和 :menuitem:`CONFIG_NVS_SEC_HMAC_EFUSE_KEY_ID`,以使用 :cpp:func:`nvs_flash_secure_init` API 加密默认分区及自定义的 NVS 分区。
|
||||
|
||||
|
||||
NVS Security Provider
|
||||
@@ -225,7 +225,7 @@ NVS Security Provider
|
||||
|
||||
.. note::
|
||||
|
||||
如果不希望使用 :component: `nvs_sec_provider` 组件的默认实现,而使用自定义方式生成或者保护 NVS 加密密钥,请选择 :ref:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> ``CONFIG_NVS_SEC_KEY_PROTECT_NONE`` 配置项。
|
||||
如果不希望使用 :component: `nvs_sec_provider` 组件的默认实现,而使用自定义方式生成或者保护 NVS 加密密钥,请选择 :menuitem:`CONFIG_NVS_SEC_KEY_PROTECTION_SCHEME` -> ``CONFIG_NVS_SEC_KEY_PROTECT_NONE`` 配置项。
|
||||
|
||||
API 参考
|
||||
-------------
|
||||
|
||||
@@ -21,7 +21,7 @@ NVS 使用分区表中类型为 ``data``、子类型为 ``nvs`` 的分区。该
|
||||
|
||||
.. note::
|
||||
|
||||
启用 :ref:`CONFIG_NVS_BDL_STACK` 后,NVS 也可以通过块设备层 (BDL) 运行,从而支持标准 flash 分区以外的其他存储后端。在 BDL 模式下,:cpp:func:`nvs_flash_init_partition_ptr` 不可用,但 :cpp:func:`nvs_flash_init_partition_bdl` 可用于自定义块设备初始化。详情见 :ref:`nvs_internals` > :ref:`nvs_underlying_storage`。
|
||||
启用 :menuitem:`CONFIG_NVS_BDL_STACK` 后,NVS 也可以通过块设备层 (BDL) 运行,从而支持标准 flash 分区以外的其他存储后端。在 BDL 模式下,:cpp:func:`nvs_flash_init_partition_ptr` 不可用,但 :cpp:func:`nvs_flash_init_partition_bdl` 可用于自定义块设备初始化。详情见 :ref:`nvs_internals` > :ref:`nvs_underlying_storage`。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -167,9 +167,9 @@ NVS 中的大量数据
|
||||
|
||||
默认情况下,内部 NVS 会在内部 RAM 中分配堆内存。对于较大的 NVS 分区或大量键,应用程序可能仅因 NVS 的开销就耗尽内部 RAM 的堆内存。
|
||||
|
||||
如果应用程序所使用的模组配备了通过 SPI 连接的 PSRAM,则可通过启用 Kconfig 选项 :ref:`CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM` 来克服这一限制。该选项会将 RAM 分配重定向到通过 SPI 连接的 PSRAM。
|
||||
如果应用程序所使用的模组配备了通过 SPI 连接的 PSRAM,则可通过启用 Kconfig 选项 :menuitem:`CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM` 来克服这一限制。该选项会将 RAM 分配重定向到通过 SPI 连接的 PSRAM。
|
||||
|
||||
当启用 SPIRAM 且 :ref:`CONFIG_SPIRAM_USE` 设为 ``CONFIG_SPIRAM_USE_CAPS_ALLOC`` 时,此选项可在 menuconfig 菜单的 nvs_flash 组件中使用。
|
||||
当启用 SPIRAM 且 :menuitem:`CONFIG_SPIRAM_USE` 设为 ``CONFIG_SPIRAM_USE_CAPS_ALLOC`` 时,此选项可在 menuconfig 菜单的 nvs_flash 组件中使用。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -180,7 +180,7 @@ NVS 中的大量数据
|
||||
|
||||
当 NVS 用于弱电源或不稳定电源系统(如太阳能或电池供电系统)时,flash 擦除操作可能偶尔无法彻底完成,而应用程序无法检测到这一问题。这会导致实际 flash 内容与预留页面的预期布局不一致。在极少数情况下(特别是在意外断电时),可能造成可用 NVS 页面耗尽,导致分区初始化失败并返回 ``ESP_ERR_NVS_NO_FREE_PAGES`` 错误。
|
||||
|
||||
为解决此问题,可通过 Kconfig 选项 :ref:`CONFIG_NVS_FLASH_VERIFY_ERASE` 启用 flash 擦除操作的验证机制,通过回读受影响页面进行检测。若在 ``flash_erase`` 操作后页面未完全擦除为 ``0xFF``,系统将重试擦除操作直至页面被正确清空。包括首次尝试在内的擦除尝试总次数可通过 Kconfig 选项 :ref:`CONFIG_NVS_FLASH_ERASE_ATTEMPTS` 进行配置。
|
||||
为解决此问题,可通过 Kconfig 选项 :menuitem:`CONFIG_NVS_FLASH_VERIFY_ERASE` 启用 flash 擦除操作的验证机制,通过回读受影响页面进行检测。若在 ``flash_erase`` 操作后页面未完全擦除为 ``0xFF``,系统将重试擦除操作直至页面被正确清空。包括首次尝试在内的擦除尝试总次数可通过 Kconfig 选项 :menuitem:`CONFIG_NVS_FLASH_ERASE_ATTEMPTS` 进行配置。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -526,7 +526,7 @@ NVS 正常运行所需的默认最小空间为 12 KiB (``0x3000``),即至少
|
||||
底层存储
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
在构建时,可以配置 NVS 访问其底层存储的模式。menuconfig 选项 :ref:`CONFIG_NVS_BDL_STACK` 提供了两种模式。
|
||||
在构建时,可以配置 NVS 访问其底层存储的模式。menuconfig 选项 :menuitem:`CONFIG_NVS_BDL_STACK` 提供了两种模式。
|
||||
|
||||
**ESP 分区 API(默认)**:NVS 使用 :ref:`esp_partition <flash-partition-apis>` 访问存储。这是默认运行模式,其中 NVS 使用由分区表定义的 SPI flash 分区。在此模式下:
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ VFS 组件支持通过 :cpp:func:`select` 进行同步输入/输出多路复用
|
||||
|
||||
.. note::
|
||||
|
||||
如果 :cpp:func:`select` 用于套接字文件描述符,可以禁用 :ref:`CONFIG_VFS_SUPPORT_SELECT` 选项来减少代码量,提高性能。
|
||||
如果 :cpp:func:`select` 用于套接字文件描述符,可以禁用 :menuitem:`CONFIG_VFS_SUPPORT_SELECT` 选项来减少代码量,提高性能。
|
||||
|
||||
不要在 :cpp:func:`select` 调用过程中更改套接字驱动,否则会出现一些未定义行为。
|
||||
|
||||
@@ -232,8 +232,8 @@ VFS 对文件路径长度没有限制,但文件系统路径前缀受 ``ESP_VFS
|
||||
IDF 定义了多个可供应用程序使用的 VFS 设备。这些设备包括:
|
||||
|
||||
* ``/dev/uart/<UART NUMBER>`` - 此文件映射到使用 VFS 驱动程序打开的 UART 中。UART 编号是 UART 外设的编号。
|
||||
* ``/dev/null`` - 此文件丢弃所有写入的数据,并在读取时返回 EOF。启用 :ref:`CONFIG_VFS_INITIALIZE_DEV_NULL` 会自动创建此文件。
|
||||
* ``/dev/console`` - 此文件连接到在 menuconfig 中由 :ref:`CONFIG_ESP_CONSOLE_UART` 和 :ref:`CONFIG_ESP_CONSOLE_SECONDARY` 指定的主输出和次输出。更多信息请参考 :doc:`../../api-guides/stdio`。
|
||||
* ``/dev/null`` - 此文件丢弃所有写入的数据,并在读取时返回 EOF。启用 :menuitem:`CONFIG_VFS_INITIALIZE_DEV_NULL` 会自动创建此文件。
|
||||
* ``/dev/console`` - 此文件连接到在 menuconfig 中由 :menuitem:`CONFIG_ESP_CONSOLE_UART` 和 :menuitem:`CONFIG_ESP_CONSOLE_SECONDARY` 指定的主输出和次输出。更多信息请参考 :doc:`../../api-guides/stdio`。
|
||||
|
||||
|
||||
应用示例
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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 未来使用
|
||||
|
||||
@@ -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 块版本相关的字段:
|
||||
|
||||
@@ -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 级别),不包含颜色、标签或时间戳。
|
||||
|
||||
|
||||
@@ -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 参考。
|
||||
|
||||
应用示例
|
||||
-------------------
|
||||
|
||||
@@ -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 内存。
|
||||
|
||||
|
||||
@@ -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 定时器任务栈的大小。
|
||||
|
||||
|
||||
应用示例
|
||||
|
||||
@@ -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 定时器 API,FreeRTOS 会创建定时器服务或守护任务
|
||||
- :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``
|
||||
|
||||
|
||||
@@ -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 钩子有以下不足:
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ FreeRTOS (IDF)
|
||||
|
||||
原始 FreeRTOS(下文称 Vanilla FreeRTOS)是一款小巧高效的实时操作系统,适用于许多单核 MCU 和 SoC。但为了支持双核 ESP 芯片,如 ESP32、ESP32-S3、ESP32-P4,ESP-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 具有以下特点:
|
||||
|
||||
|
||||
@@ -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 在开发和调试阶段最为有用:
|
||||
- 影子内存会占用约 42–64 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`。
|
||||
|
||||
内存泄漏误报
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -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”),以及一个或多个需映射到此范围的内存存储体。
|
||||
|
||||
|
||||
@@ -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 用法
|
||||
^^^^^^^^^
|
||||
|
||||
@@ -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 将日志记录到主机
|
||||
------------------------------
|
||||
|
||||
@@ -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-Fi,BT 偏移不会生效,因此不需要第二个全局 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-Fi,BT 偏移不会生效,因此不需要第二个全局 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` 函数来获取应用程序的版本信息。
|
||||
|
||||
应用示例
|
||||
--------------
|
||||
|
||||
@@ -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`` 的数据分区。
|
||||
|
||||
使用以下命令对数据分区镜像进行签名:
|
||||
|
||||
|
||||
@@ -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 上下文备份,它们的上下文会自动恢复,或者提供了相关的选项允许用户进入外设下电模式:
|
||||
|
||||
|
||||
@@ -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()`` 时,任何新创建的线程都会继承该线程的配置,否则新线程将采用默认配置。
|
||||
|
||||
|
||||
@@ -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 电源域供电的 GPIO(RTC 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-Down(DPD)**:通过启用配置项 :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD`,令 SPI Flash 在供电保持开启的前提下进入器件内部的深度休眠指令状态。多数 SPI Flash 在 DPD 下电流可降至极低水平(常低于 1 µA),同时可避免反复上下电带来的唤醒延迟。
|
||||
为降低 Light-sleep 期间 SPI Flash 的功耗,ESP-IDF **优先推荐**采用 **Deep Power-Down(DPD)**:通过启用配置项 :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-down(DPD)模式
|
||||
""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
若待机功耗仍偏高,应优先采用 **Deep Power-Down(DPD)**,通过 :ref:`CONFIG_ESP_SLEEP_SET_FLASH_DPD` 降低休眠电流;功耗数据、时序及启用方式参见前文 :ref:`spi_flash_power_down_dpd`。
|
||||
若待机功耗仍偏高,应优先采用 **Deep Power-Down(DPD)**,通过 :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 中积压数据过多,冲刷时间可能超过中断看门狗超时,会在进入睡眠过程中触发看门狗复位。
|
||||
|
||||
示例:在每次睡眠前确保所有调试输出已发出::
|
||||
|
||||
|
||||
@@ -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.5~17.5 MHz 振荡器(频率取决于芯片型号)的 256 分频时钟``:频率稳定性优于 ``内置 90~150 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 库实现时间同步。
|
||||
|
||||
|
||||
@@ -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 一直处于唤醒状态,可能会掩盖某些问题,因为部分问题只会在特定电源域断电时发生。
|
||||
|
||||
|
||||
@@ -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``):
|
||||
|
||||
|
||||
@@ -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 内部的问题引起。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user