feat(freertos): added option for automatically placing task stacks in PSRAM

When CONFIG_FREERTOS_PLACE_TASK_STACKS_IN_EXT_RAM is enabled freertos will
now automatically allocate task stacks to PSRAM.
This commit is contained in:
Marius Vikhammer
2026-05-27 16:11:36 +08:00
parent 4a0c14dc7d
commit d21dc8ca2e
26 changed files with 560 additions and 7 deletions

View File

@@ -221,9 +221,29 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该
- 片外 RAM 与片外 flash 使用相同的 cache 区域,这意味着频繁在片外 RAM 访问的变量可以像在片上 RAM 中一样快速读取和修改。但访问大块数据时(大于 32 KBcache 空间可能会不足,访问速度将降低到片外 RAM 的访问速度。此外,访问大块数据会挤出 flash cache可能在之后降低代码的执行速度。
- 一般来说,片外 RAM 不会用作任务堆栈存储器。:cpp:func:`xTaskCreate` 及类似函数始终会为堆栈和任务 TCB 分配片上储存器。
- 一般来说,片外 RAM 不会用作任务堆栈存储器。:cpp:func:`xTaskCreate` 及类似函数始终会为堆栈和任务 TCB 分配片上储存器。任务堆栈也可选择放入片外 RAM——详见下方 :ref:`task-stack-in-external-ram`
可以使用 :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM` 选项将任务堆栈放入片外存储器。这时,必须使用 :cpp:func:`xTaskCreateStatic` 指定从片外存储器分配的任务堆栈缓冲区,否则任务堆栈将仍从片上存储器分配。
.. _task-stack-in-external-ram:
将任务堆栈放入片外存储器
-------------------------------
有三种方式可将任务堆栈放入片外 RAM
1. **单任务(显式)** 使用 ``MALLOC_CAP_SPIRAM`` 标志调用 :cpp:func:`xTaskCreateWithCaps`。需要启用 :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM`
2. **单任务(静态)** 使用 :cpp:func:`xTaskCreateStatic`,提供位于片外 RAM 的调用方自定义缓冲区。需要启用 :ref:`CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM`
3. **全局默认(自动)** 启用 :ref:`CONFIG_FREERTOS_PLACE_TASK_STACKS_IN_EXT_RAM`。启用后,:cpp:func:`xTaskCreate` / :cpp:func:`xTaskCreatePinnedToCore` 的每次调用都会优先从 PSRAM 分配任务堆栈,若 PSRAM 耗尽则回退到片上 RAM。TCB 始终保留在片上 DRAM 中。
启用 :ref:`CONFIG_FREERTOS_PLACE_TASK_STACKS_IN_EXT_RAM` 后,还需注意以下额外限制:
- **Flash 操作** 任何会暂时禁用 CPU cache 的代码路径flash 擦除/写入、NVS、OTA必须在堆栈位于片上 RAM 的任务中运行,或通过 `espressif/esp_flash_dispatcher <https://components.espressif.com/components/espressif/esp_flash_dispatcher>`__ 组件路由,该组件会在专用片上 RAM 任务中执行 flash 操作。
- **深度睡眠** 从堆栈位于 PSRAM 的任务中调用 :cpp:func:`esp_deep_sleep_start` 会记录错误日志并继续执行,但在睡眠过程中禁用 cache 时极有可能发生崩溃。建议改用 :cpp:func:`esp_deep_sleep_try_to_start`:当从 PSRAM 堆栈任务中调用时,该函数会返回 :c:macro:`ESP_ERR_NOT_ALLOWED` 而不会崩溃。若应用程序需要深度睡眠,请从堆栈位于片上 RAM 的任务中发起调用。
- **浅睡眠** 从堆栈位于 PSRAM 的任务中直接调用 :cpp:func:`esp_light_sleep_start` 同样会返回 :c:macro:`ESP_ERR_NOT_ALLOWED`。Tickless idle 自动浅睡眠是安全的,因为它由 idle 任务发起,而 idle 任务的堆栈始终位于片上 RAM堆栈在 PSRAM 中的任务在唤醒后可正常恢复执行。
- **pthread** :cpp:func:`pthread_create` 委托给 :cpp:func:`xTaskCreate`因此启用此选项后pthread 堆栈也会移至 PSRAM。
相关演示请参考 :example:`system/freertos/psram_stack` 示例。
初始化失败