Skip to content

Commit

Permalink
Merge branch 'fix/heap-allocate-in-rtc-iram_v5.2' into 'release/v5.2'
Browse files Browse the repository at this point in the history
fix(heap): MALLOC_CAP_EXEC does not allocate in RTC IRAM (backport v5.2)

See merge request espressif/esp-idf!35621
  • Loading branch information
Jiang Jiang Jian committed Jan 16, 2025
2 parents 5c627d9 + 7fac9e4 commit 5c235ff
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 15 deletions.
29 changes: 26 additions & 3 deletions components/bootloader_support/include/bootloader_memory_utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -27,7 +27,12 @@ extern "C" {
*/
__attribute__((always_inline))
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;
}

/**
Expand Down Expand Up @@ -81,6 +86,7 @@ __attribute__((always_inline))
inline static bool esp_ptr_in_diram_iram(const void *p) {
// TODO: IDF-5980 esp32c6 D/I RAM share the same address
#if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW
(void)p;
return false;
#else
return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
Expand All @@ -96,9 +102,10 @@ inline static bool esp_ptr_in_diram_iram(const void *p) {
*/
__attribute__((always_inline))
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);
#else
(void)p;
return false;
#endif
}
Expand All @@ -115,6 +122,7 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED
return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
#else
(void)p;
return false;
#endif
}
Expand Down Expand Up @@ -150,6 +158,21 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
#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
- Address must be word aligned
Expand Down
29 changes: 26 additions & 3 deletions components/esp_hw_support/include/esp_memory_utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -27,7 +27,12 @@ extern "C" {
*/
__attribute__((always_inline))
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;
}

/**
Expand Down Expand Up @@ -81,6 +86,7 @@ __attribute__((always_inline))
inline static bool esp_ptr_in_diram_iram(const void *p) {
// TODO: IDF-5980 esp32c6 D/I RAM share the same address
#if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW
(void)p;
return false;
#else
return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
Expand All @@ -96,9 +102,10 @@ inline static bool esp_ptr_in_diram_iram(const void *p) {
*/
__attribute__((always_inline))
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);
#else
(void)p;
return false;
#endif
}
Expand All @@ -115,6 +122,7 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED
return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
#else
(void)p;
return false;
#endif
}
Expand Down Expand Up @@ -150,6 +158,21 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
#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
- Address must be word aligned
Expand Down
16 changes: 11 additions & 5 deletions components/heap/heap_caps_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,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 dend __attribute__((unused)) = dstart + len - 4; //Last word
assert(esp_ptr_in_diram_dram((void *)dstart));
assert(esp_ptr_in_diram_dram((void *)dend));
assert(esp_ptr_in_diram_dram((void *)dstart) || esp_ptr_in_rtc_dram_fast((void *)dstart));
assert(esp_ptr_in_diram_dram((void *)dend) || esp_ptr_in_rtc_dram_fast((void *)dend));
assert((dstart & 3) == 0);
assert((dend & 3) == 0);
#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);
#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
*iptr = dstart;
return iptr + 1;
Expand All @@ -51,7 +56,7 @@ HEAP_IRAM_ATTR void heap_caps_free( void *ptr)
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
//cannot be de-allocated as usual. dram_alloc_to_iram_addr stores a pointer to
//the equivalent DRAM address, though; free that.
Expand Down Expand Up @@ -114,7 +119,8 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_malloc_base( size_t size, uint32_t
//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)
// 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,
//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.
Expand Down
8 changes: 4 additions & 4 deletions components/heap/port/esp32s2/memory_layout.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -51,11 +51,11 @@ enum {
/**
* 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,
* 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.
*/
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 }},
//TODO, in fact, part of them support EDMA, to be supported.
[SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S2_MEM_COMMON_CAPS, 0 }},
Expand Down Expand Up @@ -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
{ 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
{ 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
};

Expand Down

0 comments on commit 5c235ff

Please sign in to comment.