Merge branch 'fix/heap-allocate-in-rtc-iram_v5.4' into 'release/v5.4'

fix(heap): MALLOC_CAP_EXEC does not allocate in RTC IRAM (backport v5.4)

See merge request espressif/esp-idf!35623
This commit is contained in:
Jiang Jiang Jian 2025-01-09 11:36:16 +08:00
commit dd00aa1776
4 changed files with 59 additions and 13 deletions

View File

@ -28,7 +28,12 @@ extern "C" {
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
inline static bool esp_dram_match_iram(void) { inline static bool esp_dram_match_iram(void) {
return (SOC_DRAM_LOW == SOC_IRAM_LOW && SOC_DRAM_HIGH == SOC_IRAM_HIGH); bool dram_match_iram = (SOC_DRAM_LOW == SOC_IRAM_LOW) &&
(SOC_DRAM_HIGH == SOC_IRAM_HIGH);
#if SOC_RTC_FAST_MEM_SUPPORTED
dram_match_iram &= (SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW);
#endif
return dram_match_iram;
} }
/** /**
@ -97,7 +102,7 @@ inline static bool esp_ptr_in_diram_iram(const void *p) {
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
inline static bool esp_ptr_in_rtc_iram_fast(const void *p) { inline static bool esp_ptr_in_rtc_iram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED #if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH); return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
#else #else
return false; return false;
@ -151,6 +156,21 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
#endif #endif
} }
/* Convert a RTC DRAM pointer to equivalent word address in RTC IRAM
- Address must be word aligned
- Address must pass esp_ptr_in_rtc_dram_fast() test, or result will be invalid pointer
*/
__attribute__((always_inline))
inline static void * esp_ptr_rtc_dram_to_iram(const void *p) {
intptr_t ptr = (intptr_t)p;
#if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
return (void *) ( SOC_RTC_IRAM_LOW + (ptr - SOC_RTC_DRAM_LOW) );
#else
return (void *) ptr;
#endif
}
/* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM /* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
- Address must be word aligned - Address must be word aligned

View File

@ -27,7 +27,12 @@ extern "C" {
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
inline static bool esp_dram_match_iram(void) { inline static bool esp_dram_match_iram(void) {
return (SOC_DRAM_LOW == SOC_IRAM_LOW && SOC_DRAM_HIGH == SOC_IRAM_HIGH); bool dram_match_iram = (SOC_DRAM_LOW == SOC_IRAM_LOW) &&
(SOC_DRAM_HIGH == SOC_IRAM_HIGH);
#if SOC_RTC_FAST_MEM_SUPPORTED
dram_match_iram &= (SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW);
#endif
return dram_match_iram;
} }
/** /**
@ -96,7 +101,7 @@ inline static bool esp_ptr_in_diram_iram(const void *p) {
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
inline static bool esp_ptr_in_rtc_iram_fast(const void *p) { inline static bool esp_ptr_in_rtc_iram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED #if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH); return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
#else #else
return false; return false;
@ -150,6 +155,21 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
#endif #endif
} }
/* Convert a RTC DRAM pointer to equivalent word address in RTC IRAM
- Address must be word aligned
- Address must pass esp_ptr_in_rtc_dram_fast() test, or result will be invalid pointer
*/
__attribute__((always_inline))
inline static void * esp_ptr_rtc_dram_to_iram(const void *p) {
intptr_t ptr = (intptr_t)p;
#if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
return (void *) ( SOC_RTC_IRAM_LOW + (ptr - SOC_RTC_DRAM_LOW) );
#else
return (void *) ptr;
#endif
}
/* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM /* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
- Address must be word aligned - Address must be word aligned

View File

@ -38,14 +38,19 @@ HEAP_IRAM_ATTR static void *dram_alloc_to_iram_addr(void *addr, size_t len)
{ {
uintptr_t dstart = (uintptr_t)addr; //First word uintptr_t dstart = (uintptr_t)addr; //First word
uintptr_t dend __attribute__((unused)) = dstart + len - 4; //Last word uintptr_t dend __attribute__((unused)) = dstart + len - 4; //Last word
assert(esp_ptr_in_diram_dram((void *)dstart)); assert(esp_ptr_in_diram_dram((void *)dstart) || esp_ptr_in_rtc_dram_fast((void *)dstart));
assert(esp_ptr_in_diram_dram((void *)dend)); assert(esp_ptr_in_diram_dram((void *)dend) || esp_ptr_in_rtc_dram_fast((void *)dend));
assert((dstart & 3) == 0); assert((dstart & 3) == 0);
assert((dend & 3) == 0); assert((dend & 3) == 0);
#if SOC_DIRAM_INVERTED // We want the word before the result to hold the DRAM address #if SOC_DIRAM_INVERTED // We want the word before the result to hold the DRAM address
uint32_t *iptr = esp_ptr_diram_dram_to_iram((void *)dend); uint32_t *iptr = esp_ptr_diram_dram_to_iram((void *)dend);
#else #else
uint32_t *iptr = esp_ptr_diram_dram_to_iram((void *)dstart); uint32_t *iptr = NULL;
if (esp_ptr_in_rtc_dram_fast((void *)dstart)) {
iptr = esp_ptr_rtc_dram_to_iram((void *)dstart);
} else {
iptr = esp_ptr_diram_dram_to_iram((void *)dstart);
}
#endif #endif
*iptr = dstart; *iptr = dstart;
return iptr + 1; return iptr + 1;
@ -57,7 +62,7 @@ HEAP_IRAM_ATTR void heap_caps_free( void *ptr)
return; return;
} }
if (esp_ptr_in_diram_iram(ptr)) { if (esp_ptr_in_diram_iram(ptr) || esp_ptr_in_rtc_iram_fast(ptr)) {
//Memory allocated here is actually allocated in the DRAM alias region and //Memory allocated here is actually allocated in the DRAM alias region and
//cannot be de-allocated as usual. dram_alloc_to_iram_addr stores a pointer to //cannot be de-allocated as usual. dram_alloc_to_iram_addr stores a pointer to
//the equivalent DRAM address, though; free that. //the equivalent DRAM address, though; free that.
@ -132,7 +137,8 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_aligned_alloc_base(size_t alignment
//This heap can satisfy all the requested capabilities. See if we can grab some memory using it. //This heap can satisfy all the requested capabilities. See if we can grab some memory using it.
// If MALLOC_CAP_EXEC is requested but the DRAM and IRAM are on the same addresses (like on esp32c6) // If MALLOC_CAP_EXEC is requested but the DRAM and IRAM are on the same addresses (like on esp32c6)
// proceed as for a default allocation. // proceed as for a default allocation.
if ((caps & MALLOC_CAP_EXEC) && !esp_dram_match_iram() && esp_ptr_in_diram_dram((void *)heap->start)) { if (((caps & MALLOC_CAP_EXEC) && !esp_dram_match_iram()) &&
(esp_ptr_in_diram_dram((void *)heap->start) || esp_ptr_in_rtc_dram_fast((void *)heap->start))) {
//This is special, insofar that what we're going to get back is a DRAM address. If so, //This is special, insofar that what we're going to get back is a DRAM address. If so,
//we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and //we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and
//add a pointer to the DRAM equivalent before the address we're going to return. //add a pointer to the DRAM equivalent before the address we're going to return.

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -51,11 +51,11 @@ enum {
/** /**
* Defined the attributes and allocation priority of each memory on the chip, * Defined the attributes and allocation priority of each memory on the chip,
* The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first, * The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first,
* if no memory caps matched or the allocation is failed, it will go to columns Medium Priorty Matching and Low Priority Matching * if no memory caps matched or the allocation is failed, it will go to columns Medium Priority Matching and Low Priority Matching
* in turn to continue matching. * in turn to continue matching.
*/ */
const soc_memory_type_desc_t soc_memory_types[] = { const soc_memory_type_desc_t soc_memory_types[] = {
/* Mem Type Name | High Priority Matching | Medium Priorty Matching | Low Priority Matching */ /* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */
[SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS, 0, 0 }}, [SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS, 0, 0 }},
//TODO, in fact, part of them support EDMA, to be supported. //TODO, in fact, part of them support EDMA, to be supported.
[SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S2_MEM_COMMON_CAPS, 0 }}, [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S2_MEM_COMMON_CAPS, 0 }},
@ -113,7 +113,7 @@ const soc_memory_region_t soc_memory_regions[] = {
{ 0x3FFF8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40068000, false}, //Block 20, can be used for MAC dump, can be used as trace memory { 0x3FFF8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40068000, false}, //Block 20, can be used for MAC dump, can be used as trace memory
{ 0x3FFFC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4006C000, true}, //Block 21, can be used for MAC dump, can be used as trace memory, used for startup stack { 0x3FFFC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4006C000, true}, //Block 21, can be used for MAC dump, can be used as trace memory, used for startup stack
#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
{ SOC_RTC_DRAM_LOW, 0x2000, SOC_MEMORY_TYPE_RTCRAM, 0, false}, //RTC Fast Memory { SOC_RTC_DRAM_LOW, 0x2000, SOC_MEMORY_TYPE_RTCRAM, SOC_RTC_IRAM_LOW, false}, //RTC Fast Memory
#endif #endif
}; };