Skip to content

Commit

Permalink
Merge branch 'feature/heap-in-flash' into 'master'
Browse files Browse the repository at this point in the history
heap: Add a configuration that places all the heap component in flash

Closes IDF-7143 and IDF-2853

See merge request espressif/esp-idf!23050
  • Loading branch information
SoucheSouche committed Apr 13, 2023
2 parents d8b8ab5 + 110aac2 commit 48932ce
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 100 deletions.
6 changes: 3 additions & 3 deletions components/app_trace/heap_trace_tohost.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
#include "esp_heap_trace.h"
#undef HEAP_TRACE_SRCFILE

#include "esp_heap_caps.h"
#if CONFIG_APPTRACE_SV_ENABLE
#include "esp_app_trace.h"
#include "esp_sysview_trace.h"
Expand Down Expand Up @@ -85,7 +85,7 @@ void heap_trace_dump_caps(__attribute__((unused)) const uint32_t caps)
}

/* Add a new allocation to the heap trace records */
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
{
if (!s_tracing) {
return;
Expand All @@ -100,7 +100,7 @@ static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
For HEAP_TRACE_LEAKS, this means removing the record from the log.
*/
static IRAM_ATTR void record_free(void *p, void **callers)
static HEAP_IRAM_ATTR void record_free(void *p, void **callers)
{
if (!s_tracing) {
return;
Expand Down
5 changes: 5 additions & 0 deletions components/driver/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,15 @@ menu "Driver Configurations"
config SPI_MASTER_ISR_IN_IRAM
bool "Place SPI master ISR function into IRAM"
default y
depends on !HEAP_PLACE_FUNCTION_INTO_FLASH
select PERIPH_CTRL_FUNC_IN_IRAM
help
Place the SPI master ISR in to IRAM to avoid possible cache miss.

Enabling this configuration is possible only when HEAP_PLACE_FUNCTION_INTO_FLASH
is disabled since the spi master uses can allocate transactions buffers into DMA
memory section using the heap component API that ipso facto has to be placed in IRAM.

Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver.

Expand Down
9 changes: 9 additions & 0 deletions components/heap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,13 @@ menu "Heap memory debugging"
features will be added and bugs will be fixed in the IDF source
but cannot be synced to ROM.

config HEAP_PLACE_FUNCTION_INTO_FLASH
bool "Force the entire heap component to be placed in flash memory"
depends on !HEAP_TLSF_USE_ROM_IMPL
default n
help
Enable this flag to save up RAM space by placing the heap component in the flash memory

Note that it is only safe to enable this configuration if no functions from esp_heap_caps.h
or esp_heap_trace.h are called from ISR.
endmenu
38 changes: 19 additions & 19 deletions components/heap/heap_caps.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ possible. This should optimize the amount of RAM accessible to the code without
static esp_alloc_failed_hook_t alloc_failed_callback;

#ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
IRAM_ATTR static void hex_to_str(char buf[8], uint32_t n)
HEAP_IRAM_ATTR static void hex_to_str(char buf[8], uint32_t n)
{
for (int i = 0; i < 8; i++) {
uint8_t b4 = (n >> (28 - i * 4)) & 0b1111;
buf[i] = b4 <= 9 ? '0' + b4 : 'a' + b4 - 10;
}
}
IRAM_ATTR static void fmt_abort_str(char dest[48], size_t size, uint32_t caps)
HEAP_IRAM_ATTR static void fmt_abort_str(char dest[48], size_t size, uint32_t caps)
{
char sSize[8];
char sCaps[8];
Expand All @@ -67,7 +67,7 @@ IRAM_ATTR static void fmt_abort_str(char dest[48], size_t size, uint32_t caps)
IRAM in such a way that it can be later freed. It assumes both the address as well as the length to be word-aligned.
It returns a region that's 1 word smaller than the region given because it stores the original Dram address there.
*/
IRAM_ATTR static void *dram_alloc_to_iram_addr(void *addr, size_t len)
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
Expand All @@ -84,7 +84,7 @@ IRAM_ATTR static void *dram_alloc_to_iram_addr(void *addr, size_t len)
return iptr + 1;
}

IRAM_ATTR NOINLINE_ATTR static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name)
HEAP_IRAM_ATTR NOINLINE_ATTR static void heap_caps_alloc_failed(size_t requested_size, uint32_t caps, const char *function_name)
{
if (alloc_failed_callback) {
alloc_failed_callback(requested_size, caps, function_name);
Expand Down Expand Up @@ -118,7 +118,7 @@ bool heap_caps_match(const heap_t *heap, uint32_t caps)
This function should not be called directly as it does not
check for failure / call heap_caps_alloc_failed()
*/
IRAM_ATTR static void *heap_caps_malloc_base( size_t size, uint32_t caps)
HEAP_IRAM_ATTR static void *heap_caps_malloc_base( size_t size, uint32_t caps)
{
void *ret = NULL;

Expand Down Expand Up @@ -192,7 +192,7 @@ IRAM_ATTR static void *heap_caps_malloc_base( size_t size, uint32_t caps)
/*
Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits.
*/
IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps){
HEAP_IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps){

void* ptr = heap_caps_malloc_base(size, caps);

Expand All @@ -217,7 +217,7 @@ void heap_caps_malloc_extmem_enable(size_t limit)
/*
Default memory allocation implementation. Should return standard 8-bit memory. malloc() essentially resolves to this function.
*/
IRAM_ATTR void *heap_caps_malloc_default( size_t size )
HEAP_IRAM_ATTR void *heap_caps_malloc_default( size_t size )
{
if (malloc_alwaysinternal_limit==MALLOC_DISABLE_EXTERNAL_ALLOCS) {
return heap_caps_malloc( size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
Expand Down Expand Up @@ -250,7 +250,7 @@ IRAM_ATTR void *heap_caps_malloc_default( size_t size )
Same for realloc()
Note: keep the logic in here the same as in heap_caps_malloc_default (or merge the two as soon as this gets more complex...)
*/
IRAM_ATTR void *heap_caps_realloc_default( void *ptr, size_t size )
HEAP_IRAM_ATTR void *heap_caps_realloc_default( void *ptr, size_t size )
{
if (malloc_alwaysinternal_limit==MALLOC_DISABLE_EXTERNAL_ALLOCS) {
return heap_caps_realloc( ptr, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL );
Expand Down Expand Up @@ -282,7 +282,7 @@ IRAM_ATTR void *heap_caps_realloc_default( void *ptr, size_t size )
/*
Memory allocation as preference in decreasing order.
*/
IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
HEAP_IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
{
va_list argp;
va_start( argp, num );
Expand All @@ -306,7 +306,7 @@ IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
/*
Memory reallocation as preference in decreasing order.
*/
IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... )
HEAP_IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... )
{
va_list argp;
va_start( argp, num );
Expand All @@ -330,7 +330,7 @@ IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ..
/*
Memory callocation as preference in decreasing order.
*/
IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... )
HEAP_IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... )
{
va_list argp;
va_start( argp, num );
Expand All @@ -357,7 +357,7 @@ IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ...
(This confirms if ptr is inside the heap's region, doesn't confirm if 'ptr'
is an allocated block or is some other random address inside the heap.)
*/
IRAM_ATTR static heap_t *find_containing_heap(void *ptr )
HEAP_IRAM_ATTR static heap_t *find_containing_heap(void *ptr )
{
intptr_t p = (intptr_t)ptr;
heap_t *heap;
Expand All @@ -369,7 +369,7 @@ IRAM_ATTR static heap_t *find_containing_heap(void *ptr )
return NULL;
}

IRAM_ATTR void heap_caps_free( void *ptr)
HEAP_IRAM_ATTR void heap_caps_free( void *ptr)
{
if (ptr == NULL) {
return;
Expand All @@ -394,7 +394,7 @@ IRAM_ATTR void heap_caps_free( void *ptr)
This function should not be called directly as it does not
check for failure / call heap_caps_alloc_failed()
*/
IRAM_ATTR static void *heap_caps_realloc_base( void *ptr, size_t size, uint32_t caps)
HEAP_IRAM_ATTR static void *heap_caps_realloc_base( void *ptr, size_t size, uint32_t caps)
{
bool ptr_in_diram_case = false;
heap_t *heap = NULL;
Expand Down Expand Up @@ -469,7 +469,7 @@ IRAM_ATTR static void *heap_caps_realloc_base( void *ptr, size_t size, uint32_t
return NULL;
}

IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps)
HEAP_IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps)
{
ptr = heap_caps_realloc_base(ptr, size, caps);

Expand All @@ -485,7 +485,7 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, uint32_t caps)
This function should not be called directly as it does not
check for failure / call heap_caps_alloc_failed()
*/
IRAM_ATTR static void *heap_caps_calloc_base( size_t n, size_t size, uint32_t caps)
HEAP_IRAM_ATTR static void *heap_caps_calloc_base( size_t n, size_t size, uint32_t caps)
{
void *result;
size_t size_bytes;
Expand All @@ -501,7 +501,7 @@ IRAM_ATTR static void *heap_caps_calloc_base( size_t n, size_t size, uint32_t ca
return result;
}

IRAM_ATTR void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
HEAP_IRAM_ATTR void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
{
void* ptr = heap_caps_calloc_base(n, size, caps);

Expand Down Expand Up @@ -655,7 +655,7 @@ size_t heap_caps_get_allocated_size( void *ptr )
return size;
}

IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
HEAP_IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t caps)
{
void *ret = NULL;

Expand Down Expand Up @@ -708,7 +708,7 @@ IRAM_ATTR void *heap_caps_aligned_alloc(size_t alignment, size_t size, uint32_t
return NULL;
}

IRAM_ATTR void heap_caps_aligned_free(void *ptr)
HEAP_IRAM_ATTR void heap_caps_aligned_free(void *ptr)
{
heap_caps_free(ptr);
}
Expand Down
25 changes: 12 additions & 13 deletions components/heap/heap_trace_standalone.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
#include "esp_heap_trace.h"
#undef HEAP_TRACE_SRCFILE

#include "esp_heap_caps.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_memory_utils.h"
#include "sys/queue.h"


#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH

#if CONFIG_HEAP_TRACING_STANDALONE
Expand Down Expand Up @@ -89,7 +88,7 @@ static heap_trace_hash_list_t hash_map[(size_t)CONFIG_HEAP_TRACE_HASH_MAP_SIZE];
static size_t total_hashmap_hits;
static size_t total_hashmap_miss;

static size_t hash_idx(void* p)
static HEAP_IRAM_ATTR size_t hash_idx(void* p)
{
static const uint32_t fnv_prime = 16777619UL; // expression 2^24 + 2^8 + 0x93 (32 bits size)
// since all the addresses are 4 bytes aligned, computing address * fnv_prime always gives
Expand All @@ -100,19 +99,19 @@ static size_t hash_idx(void* p)
((uint32_t)p >> 7)) * fnv_prime) % (uint32_t)CONFIG_HEAP_TRACE_HASH_MAP_SIZE;
}

static void map_add(heap_trace_record_t *r_add)
static HEAP_IRAM_ATTR void map_add(heap_trace_record_t *r_add)
{
size_t idx = hash_idx(r_add->address);
TAILQ_INSERT_TAIL(&hash_map[idx], r_add, tailq_hashmap);
}

static void map_remove(heap_trace_record_t *r_remove)
static HEAP_IRAM_ATTR void map_remove(heap_trace_record_t *r_remove)
{
size_t idx = hash_idx(r_remove->address);
TAILQ_REMOVE(&hash_map[idx], r_remove, tailq_hashmap);
}

static heap_trace_record_t* map_find(void *p)
static HEAP_IRAM_ATTR heap_trace_record_t* map_find(void *p)
{
size_t idx = hash_idx(p);
heap_trace_record_t *r_cur = NULL;
Expand Down Expand Up @@ -385,7 +384,7 @@ static void heap_trace_dump_base(bool internal_ram, bool psram)
}

/* Add a new allocation to the heap trace records */
static IRAM_ATTR void record_allocation(const heap_trace_record_t *r_allocation)
static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *r_allocation)
{
if (!tracing || r_allocation->address == NULL) {
return;
Expand Down Expand Up @@ -420,7 +419,7 @@ static IRAM_ATTR void record_allocation(const heap_trace_record_t *r_allocation)
callers is an array of STACK_DEPTH function pointer from the call stack
leading to the call of record_free.
*/
static IRAM_ATTR void record_free(void *p, void **callers)
static HEAP_IRAM_ATTR void record_free(void *p, void **callers)
{
if (!tracing || p == NULL) {
return;
Expand Down Expand Up @@ -473,7 +472,7 @@ static void list_setup(void)

/* 1. removes record r_remove from records.list,
2. places it into records.unused */
static IRAM_ATTR void list_remove(heap_trace_record_t *r_remove)
static HEAP_IRAM_ATTR void list_remove(heap_trace_record_t* r_remove)
{
assert(records.count > 0);

Expand All @@ -497,7 +496,7 @@ static IRAM_ATTR void list_remove(heap_trace_record_t *r_remove)


// pop record from unused list
static IRAM_ATTR heap_trace_record_t* list_pop_unused(void)
static HEAP_IRAM_ATTR heap_trace_record_t* list_pop_unused(void)
{
// no records left?
if (records.count >= records.capacity) {
Expand All @@ -517,7 +516,7 @@ static IRAM_ATTR heap_trace_record_t* list_pop_unused(void)

// deep copy a record.
// Note: only copies the *allocation data*, not the next & prev ptrs
static IRAM_ATTR void record_deep_copy(heap_trace_record_t *r_dest, const heap_trace_record_t *r_src)
static HEAP_IRAM_ATTR void record_deep_copy(heap_trace_record_t *r_dest, const heap_trace_record_t *r_src)
{
r_dest->ccount = r_src->ccount;
r_dest->address = r_src->address;
Expand All @@ -528,7 +527,7 @@ static IRAM_ATTR void record_deep_copy(heap_trace_record_t *r_dest, const heap_t

// Append a record to records.list
// Note: This deep copies r_append
static IRAM_ATTR heap_trace_record_t* list_add(const heap_trace_record_t *r_append)
static HEAP_IRAM_ATTR heap_trace_record_t* list_add(const heap_trace_record_t *r_append)
{
if (records.count < records.capacity) {

Expand Down Expand Up @@ -566,7 +565,7 @@ static IRAM_ATTR heap_trace_record_t* list_add(const heap_trace_record_t *r_appe
}

// search records.list backwards for the allocation record matching this address
static IRAM_ATTR heap_trace_record_t* list_find_address_reverse(void *p)
static HEAP_IRAM_ATTR heap_trace_record_t* list_find_address_reverse(void* p)
{
heap_trace_record_t *r_found = NULL;

Expand Down
10 changes: 8 additions & 2 deletions components/heap/include/esp_heap_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
extern "C" {
#endif

#if CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH
#define HEAP_IRAM_ATTR
#else
#define HEAP_IRAM_ATTR IRAM_ATTR
#endif

/**
* @brief Flags to indicate the capabilities of the various memory systems
*/
Expand Down Expand Up @@ -63,15 +69,15 @@ esp_err_t heap_caps_register_failed_alloc_callback(esp_alloc_failed_hook_t callb
* @note this hook is called on the same thread as the allocation, which may be within a low level operation.
* You should refrain from doing heavy work, logging, flash writes, or any locking.
*/
__attribute__((weak)) IRAM_ATTR void esp_heap_trace_alloc_hook(void* ptr, size_t size, uint32_t caps);
__attribute__((weak)) HEAP_IRAM_ATTR void esp_heap_trace_alloc_hook(void* ptr, size_t size, uint32_t caps);

/**
* @brief callback called after every free
* @param ptr the memory that was freed
* @note this hook is called on the same thread as the allocation, which may be within a low level operation.
* You should refrain from doing heavy work, logging, flash writes, or any locking.
*/
__attribute__((weak)) IRAM_ATTR void esp_heap_trace_free_hook(void* ptr);
__attribute__((weak)) HEAP_IRAM_ATTR void esp_heap_trace_free_hook(void* ptr);
#endif

/**
Expand Down
Loading

0 comments on commit 48932ce

Please sign in to comment.