Merge branch 'change/change_regdma_malloc_caps' into 'master'

change(heap): reserve DMA pool with low priority MALLOC_CAP_DEFAULT cap

See merge request espressif/esp-idf!50255
This commit is contained in:
Wu Zheng Hui
2026-07-09 19:32:56 +08:00
7 changed files with 26 additions and 26 deletions

View File

@@ -124,7 +124,7 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL
that the internal memory is entirely filled up. This causes allocations that are specifically done in
internal memory, for example the stack for new tasks or memory to service DMA or have memory that's
also available when SPI cache is down, to fail. This option reserves a pool specifically for requests
like that; the memory in this pool is not given out when a normal malloc() is called.
like that; a normal malloc() can fall back to the pool only after all other internal are exhausted.
Set this to 0 to disable this feature.

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -37,6 +37,11 @@ esp_err_t esp_psram_extram_add_to_heap_allocator(void);
/**
* @brief Reserve a pool of internal memory for specific DMA/internal allocations
*
* Carves out @p size bytes from the regular internal heaps and registers the
* region as separate heap pool with new priority-based caps: medium priority for
* MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, and low priority for MALLOC_CAP_DEFAULT.
* malloc() uses the pool only after other internal heaps are exhausted.
*
* @param size Size of reserved pool in bytes
*
* @return

View File

@@ -664,7 +664,7 @@ esp_err_t esp_psram_extram_reserve_dma_pool(size_t size)
return ESP_ERR_NO_MEM;
}
uint32_t caps[] = {0, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
uint32_t caps[] = {0, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
esp_err_t e = heap_caps_add_region_with_caps(caps, (intptr_t)dma_heap, (intptr_t)dma_heap + next_size - 1);
if (e != ESP_OK) {
return e;

View File

@@ -63,7 +63,7 @@ enum {
*/
const soc_memory_type_desc_t soc_memory_types[SOC_MEMORY_TYPE_NUM] = {
/* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */
[SOC_MEMORY_TYPE_RETENT_MEM] = { "RETENT_RAM", { MALLOC_L2MEM_BASE_CAPS | MALLOC_CAP_RETENTION | MALLOC_CAP_SIMD, 0, 0 }},
[SOC_MEMORY_TYPE_RETENT_MEM] = { "RETENT_RAM", { MALLOC_CAP_RETENTION | MALLOC_CAP_SIMD, MALLOC_L2MEM_BASE_CAPS, 0 }},
[SOC_MEMORY_TYPE_L2MEM] = { "RAM", { MALLOC_L2MEM_BASE_CAPS | MALLOC_CAP_SIMD, 0, 0 }},
[SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_SIMD }},
[SOC_MEMORY_TYPE_SPM] = { "SPM", { MALLOC_CAP_SPM, ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL, 0 }},

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -65,25 +65,6 @@ TEST_CASE("Malloc/overwrite, then free all available DRAM", "[heap]")
}
#if CONFIG_SPIRAM_USE_MALLOC && (CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL > 1024)
TEST_CASE("Check if reserved DMA pool still can allocate even when malloc()'ed memory is exhausted", "[heap][psram]")
{
char** dmaMem=malloc(sizeof(char*)*512);
assert(dmaMem);
int m=tryAllocMem();
int i=0;
for (i=0; i<512; i++) {
dmaMem[i]=heap_caps_malloc(1024, MALLOC_CAP_DMA);
if (dmaMem[i]==NULL) break;
}
for (int j=0; j<i; j++) free(dmaMem[j]);
free(dmaMem);
tryAllocMemFree();
printf("Could allocate %dK of DMA memory after allocating all of %dK of normal memory.\n", i, m);
TEST_ASSERT(i);
}
#endif
#if CONFIG_SPIRAM
TEST_CASE("Check if default cap allocates in external memory in priority", "[heap][psram]")
{

View File

@@ -114,7 +114,14 @@ An additional configuration item, :ref:`CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL`, ca
If a suitable block of preferred internal/external memory is not available, the allocator will try the other type of memory.
Because some buffers can only be allocated in internal memory, a second configuration item :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` defines a pool of internal memory which is reserved for *only* explicitly internal allocations (such as memory for DMA use). Regular ``malloc()`` will not allocate from this pool. The :ref:`MALLOC_CAP_DMA <dma-capable-memory>` and ``MALLOC_CAP_INTERNAL`` flags can be used to allocate memory from this pool.
Because some buffers can only be allocated in internal memory, a second configuration item :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` reserves a pool of internal DMA-capable memory at startup (in ``main_task``, after PSRAM is initialized). The pool is malloc from the regular internal heaps and re-registered as separate heap pool.
The reserved pool uses the heap capability priority mechanism:
- **Medium priority**``MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL``: explicit ``heap_caps_malloc()`` requests with these flags are preferentially served from this pool.
- **Low priority**``MALLOC_CAP_DEFAULT``: ``malloc()`` may use the pool only after other internal heaps with higher-priority ``MALLOC_CAP_DEFAULT`` are exhausted.
Therefore, under normal conditions ``malloc()`` does not allocate from this pool, but it can fall back to it as a last resort before allocation fails entirely.
.. _external_ram_config_bss:

View File

@@ -114,7 +114,14 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该
如果优先考虑的内部或外部存储器中没有可用的存储块,分配程序则会选择其他类型存储。
由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项 :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` 定义一个内部内存池,仅限显式的内部存储器分配使用(例如用于 DMA 的存储器)。常规 ``malloc()`` 将不会从该池中分配,但可以使用 :ref:`MALLOC_CAP_DMA <dma-capable-memory>```MALLOC_CAP_INTERNAL`` 标志从该池中分配存储器
由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项 :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` 在启动阶段PSRAM 初始化完成后,于 ``main_task`` 中)预留一块内部 DMA 可用内存池。该内存从常规内部堆中分配出,并重新注册为独立的内存池
预留池通过堆能力优先级机制管理:
- **中优先级**``MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL``:显式使用这些标志的 ``heap_caps_malloc()`` 请求会优先从此池分配。
- **低优先级**``MALLOC_CAP_DEFAULT``:仅当其他具有更高优先级 ``MALLOC_CAP_DEFAULT`` 的内部堆耗尽后,``malloc()`` 才会回退使用此池。
因此,在正常情况下 ``malloc()`` 不会从该池分配;仅当其他内部内存耗尽后,``malloc()`` 才会将其作为最后的回退来源以避免分配完全失败。
.. _external_ram_config_bss: