Merge branch 'feature/ext_ram_allocatable_using_heap_alloc_cap' into 'master'
Make external RAM allocatable using heap_alloc_cap See merge request !1226
This commit is contained in:
commit
2a0e6c40d0
14 changed files with 164 additions and 45 deletions
|
@ -57,8 +57,7 @@ choice SPIRAM_USE
|
||||||
config SPIRAM_USE_MEMMAP
|
config SPIRAM_USE_MEMMAP
|
||||||
bool "Integrate RAM into ESP32 memory map"
|
bool "Integrate RAM into ESP32 memory map"
|
||||||
config SPIRAM_USE_CAPS_ALLOC
|
config SPIRAM_USE_CAPS_ALLOC
|
||||||
bool "Make RAM allocatable using heap_caps_malloc(..., MALLOC_CAP_SPISRAM)"
|
bool "Make RAM allocatable using heap_caps_malloc(..., MALLOC_CAP_SPIRAM)"
|
||||||
depends on TO_BE_DONE
|
|
||||||
config SPIRAM_USE_MALLOC
|
config SPIRAM_USE_MALLOC
|
||||||
bool "Make RAM allocatable using malloc as well"
|
bool "Make RAM allocatable using malloc as well"
|
||||||
depends on TO_BE_DONE
|
depends on TO_BE_DONE
|
||||||
|
|
|
@ -174,7 +174,10 @@ void esp_perip_clk_init(void)
|
||||||
DPORT_LEDC_CLK_EN |
|
DPORT_LEDC_CLK_EN |
|
||||||
DPORT_UHCI1_CLK_EN |
|
DPORT_UHCI1_CLK_EN |
|
||||||
DPORT_TIMERGROUP1_CLK_EN |
|
DPORT_TIMERGROUP1_CLK_EN |
|
||||||
|
//80MHz SPIRAM uses SPI2 as well; it's initialized before this is called. Do not disable the clock for that if this is enabled.
|
||||||
|
#if !CONFIG_SPIRAM_SPEED_80M
|
||||||
DPORT_SPI_CLK_EN_2 |
|
DPORT_SPI_CLK_EN_2 |
|
||||||
|
#endif
|
||||||
DPORT_PWM0_CLK_EN |
|
DPORT_PWM0_CLK_EN |
|
||||||
DPORT_I2C_EXT1_CLK_EN |
|
DPORT_I2C_EXT1_CLK_EN |
|
||||||
DPORT_CAN_CLK_EN |
|
DPORT_CAN_CLK_EN |
|
||||||
|
@ -196,6 +199,7 @@ void esp_perip_clk_init(void)
|
||||||
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
||||||
DPORT_WIFI_CLK_EMAC_EN;
|
DPORT_WIFI_CLK_EMAC_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||||
* the current is not reduced when disable I2S clock.
|
* the current is not reduced when disable I2S clock.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -255,6 +255,15 @@ void start_cpu0_default(void)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
esp_setup_syscall_table();
|
esp_setup_syscall_table();
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||||
|
esp_err_t r=esp_spiram_add_to_heapalloc();
|
||||||
|
if (r != ESP_OK) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//Enable trace memory and immediately start trace.
|
//Enable trace memory and immediately start trace.
|
||||||
#if CONFIG_ESP32_TRAX
|
#if CONFIG_ESP32_TRAX
|
||||||
#if CONFIG_ESP32_TRAX_TWOBANKS
|
#if CONFIG_ESP32_TRAX_TWOBANKS
|
||||||
|
|
|
@ -39,6 +39,12 @@ esp_err_t esp_spiram_init();
|
||||||
bool esp_spiram_test();
|
bool esp_spiram_test();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add the initialized SPI RAM to the heap allocator.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_spiram_add_to_heapalloc();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,6 +28,8 @@ we add more types of external RAM memory, this can be made into a more intellige
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/xtensa_api.h"
|
#include "freertos/xtensa_api.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
|
#include "esp_heap_caps_init.h"
|
||||||
|
#include "soc/soc_memory_layout.h"
|
||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
#include "rom/cache.h"
|
#include "rom/cache.h"
|
||||||
|
|
||||||
|
@ -120,6 +122,12 @@ esp_err_t esp_spiram_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_spiram_add_to_heapalloc()
|
||||||
|
{
|
||||||
|
//Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
|
||||||
|
//no need to explicitly specify them.
|
||||||
|
return heap_caps_add_region((intptr_t)SOC_EXTRAM_DATA_LOW, (intptr_t)SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE-1);
|
||||||
|
}
|
||||||
|
|
||||||
size_t esp_spiram_get_size()
|
size_t esp_spiram_get_size()
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,9 +94,6 @@ typedef enum {
|
||||||
|
|
||||||
static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
|
static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
|
||||||
|
|
||||||
//For now, we only use F40M + S40M, and we don't have to go through gpio matrix
|
|
||||||
#define ENABLE_GPIO_MATRIX_SPI 1
|
|
||||||
|
|
||||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||||
|
|
||||||
|
@ -528,9 +525,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
|
||||||
}
|
}
|
||||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M);
|
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M);
|
||||||
|
|
||||||
#if ENABLE_GPIO_MATRIX_SPI
|
|
||||||
psram_gpio_config(mode);
|
psram_gpio_config(mode);
|
||||||
#endif
|
|
||||||
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO));
|
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO));
|
||||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], 2);
|
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], 2);
|
||||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], 2);
|
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], 2);
|
||||||
|
|
|
@ -56,12 +56,15 @@ TEST_CASE("Spiram cache flush on mmap", "[spiram][ignore]")
|
||||||
void *mem[2];
|
void *mem[2];
|
||||||
res[0]=0; res[1]=0;
|
res[0]=0; res[1]=0;
|
||||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||||
mem[0]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
printf("Allocating SPI RAM chunk...\n");
|
||||||
mem[1]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||||
|
mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||||
#else
|
#else
|
||||||
mem[0]=(void*)0x3f800000;
|
mem[0]=(void*)0x3f800000;
|
||||||
mem[1]=(void*)0x3f800000+TSTSZ;
|
mem[1]=(void*)0x3f800000+TSTSZ;
|
||||||
#endif
|
#endif
|
||||||
|
assert(mem[0]);
|
||||||
|
assert(mem[1]);
|
||||||
TaskHandle_t th[2];
|
TaskHandle_t th[2];
|
||||||
err[0]=0; err[1]=0;
|
err[0]=0; err[1]=0;
|
||||||
printf("Creating tasks\n");
|
printf("Creating tasks\n");
|
||||||
|
@ -99,12 +102,15 @@ TEST_CASE("Spiram cache flush on write/read", "[spiram][ignore]")
|
||||||
void *mem[2];
|
void *mem[2];
|
||||||
res[0]=0; res[1]=0;
|
res[0]=0; res[1]=0;
|
||||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||||
mem[0]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
printf("Allocating SPI RAM chunk...\n");
|
||||||
mem[1]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||||
|
mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||||
#else
|
#else
|
||||||
mem[0]=(void*)0x3f800000;
|
mem[0]=(void*)0x3f800000;
|
||||||
mem[1]=(void*)0x3f800000+TSTSZ;
|
mem[1]=(void*)0x3f800000+TSTSZ;
|
||||||
#endif
|
#endif
|
||||||
|
assert(mem[0]);
|
||||||
|
assert(mem[1]);
|
||||||
TaskHandle_t th[2];
|
TaskHandle_t th[2];
|
||||||
const esp_partition_t* part = get_test_data_partition();
|
const esp_partition_t* part = get_test_data_partition();
|
||||||
assert(part!=NULL);
|
assert(part!=NULL);
|
||||||
|
@ -138,4 +144,40 @@ TEST_CASE("Spiram cache flush on write/read", "[spiram][ignore]")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR TEST_CASE("Spiram memcmp weirdness at 80MHz", "[spiram][ignore]") {
|
||||||
|
char *mem1=malloc(0x10000);
|
||||||
|
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||||
|
char *mem2=heap_caps_malloc(0x10000, MALLOC_CAP_SPIRAM);
|
||||||
|
#else
|
||||||
|
char *mem2=(void*)0x3f800000;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !CONFIG_SPIRAM_SPEED_80M
|
||||||
|
printf("**** WARNING **** Spi memory isn't running at 80MHz, so this test is somewhat meaningless.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("RAM: Got %p and %p\n", mem1, mem2);
|
||||||
|
assert(mem1);
|
||||||
|
assert(mem2);
|
||||||
|
for (int i=0; i<0x10000; i++) mem1[i]=i^0xAAAAAAAA;
|
||||||
|
|
||||||
|
for (int cycle=1; cycle<100; cycle++) {
|
||||||
|
memcpy(mem2, mem1, 0x10000);
|
||||||
|
if (memcmp(mem1, mem2, 0x10000)!=0) {
|
||||||
|
printf("Memcmp failed! Cycle %d\n", cycle);
|
||||||
|
for (int i=0; i<0x10000; i++) {
|
||||||
|
if (mem1[i]!=mem2[i]) {
|
||||||
|
printf("Found real difference at index %d: 0x%x vs 0x%x\n", i, mem1[i], mem2[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MEMMAP
|
#endif //CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MEMMAP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,24 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
return heap_caps_malloc( size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
return heap_caps_realloc( ptr, size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Find the heap which belongs to ptr, or return NULL if it's
|
/* Find the heap which belongs to ptr, or return NULL if it's
|
||||||
not in any heap.
|
not in any heap.
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ void heap_caps_init()
|
||||||
|
|
||||||
heap_t *heaps_array = NULL;
|
heap_t *heaps_array = NULL;
|
||||||
for (int i = 0; i < num_heaps; i++) {
|
for (int i = 0; i < num_heaps; i++) {
|
||||||
if (heap_caps_match(&temp_heaps[i], MALLOC_CAP_8BIT)) {
|
if (heap_caps_match(&temp_heaps[i], MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL)) {
|
||||||
/* use the first DRAM heap which can fit the data */
|
/* use the first DRAM heap which can fit the data */
|
||||||
heaps_array = multi_heap_malloc(temp_heaps[i].heap, sizeof(heap_t) * num_heaps);
|
heaps_array = multi_heap_malloc(temp_heaps[i].heap, sizeof(heap_t) * num_heaps);
|
||||||
if (heaps_array != NULL) {
|
if (heaps_array != NULL) {
|
||||||
|
|
|
@ -48,6 +48,16 @@ extern SLIST_HEAD(registered_heap_ll, heap_t_) registered_heaps;
|
||||||
|
|
||||||
bool heap_caps_match(const heap_t *heap, uint32_t caps);
|
bool heap_caps_match(const heap_t *heap, uint32_t caps);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Because we don't want to add _another_ known allocation method to the stack of functions to trace wrt memory tracing,
|
||||||
|
these are declared private. The newlib malloc()/realloc() implementation also calls these, so they are declared
|
||||||
|
separately in newlib/syscalls.c.
|
||||||
|
*/
|
||||||
|
void *heap_caps_realloc_default(void *p, size_t size);
|
||||||
|
void *heap_caps_malloc_default(size_t size);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "soc/soc_memory_layout.h"
|
#include "soc/soc_memory_layout.h"
|
||||||
|
|
||||||
|
#include "heap_private.h"
|
||||||
|
|
||||||
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||||
|
|
||||||
static portMUX_TYPE trace_mux = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE trace_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
@ -303,13 +305,25 @@ static IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **callers)
|
||||||
_Static_assert(STACK_DEPTH >= 0 && STACK_DEPTH <= 10, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-10");
|
_Static_assert(STACK_DEPTH >= 0 && STACK_DEPTH <= 10, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-10");
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TRACE_MALLOC_CAPS,
|
||||||
|
TRACE_MALLOC_DEFAULT
|
||||||
|
} trace_malloc_mode_t;
|
||||||
|
|
||||||
|
|
||||||
void *__real_heap_caps_malloc(size_t size, uint32_t caps);
|
void *__real_heap_caps_malloc(size_t size, uint32_t caps);
|
||||||
|
|
||||||
/* trace any 'malloc' event */
|
/* trace any 'malloc' event */
|
||||||
static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps)
|
static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
||||||
{
|
{
|
||||||
uint32_t ccount = get_ccount();
|
uint32_t ccount = get_ccount();
|
||||||
void *p = __real_heap_caps_malloc(size, caps);
|
void *p;
|
||||||
|
if ( mode == TRACE_MALLOC_CAPS ) {
|
||||||
|
p = __real_heap_caps_malloc(size, caps);
|
||||||
|
} else { //TRACE_MALLOC_DEFAULT
|
||||||
|
p = heap_caps_malloc_default(size);
|
||||||
|
}
|
||||||
|
|
||||||
if (tracing && p != NULL) {
|
if (tracing && p != NULL) {
|
||||||
heap_trace_record_t rec = {
|
heap_trace_record_t rec = {
|
||||||
.address = p,
|
.address = p,
|
||||||
|
@ -338,7 +352,7 @@ static IRAM_ATTR __attribute__((noinline)) void trace_free(void *p)
|
||||||
void * __real_heap_caps_realloc(void *p, size_t size, uint32_t caps);
|
void * __real_heap_caps_realloc(void *p, size_t size, uint32_t caps);
|
||||||
|
|
||||||
/* trace any 'realloc' event */
|
/* trace any 'realloc' event */
|
||||||
static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t size, uint32_t caps)
|
static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
||||||
{
|
{
|
||||||
void *callers[STACK_DEPTH];
|
void *callers[STACK_DEPTH];
|
||||||
uint32_t ccount = get_ccount();
|
uint32_t ccount = get_ccount();
|
||||||
|
@ -346,7 +360,12 @@ static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t s
|
||||||
get_call_stack(callers);
|
get_call_stack(callers);
|
||||||
record_free(p, callers);
|
record_free(p, callers);
|
||||||
}
|
}
|
||||||
void *r = __real_heap_caps_realloc(p, size, caps);
|
void *r;
|
||||||
|
if (mode == TRACE_MALLOC_CAPS ) {
|
||||||
|
r = __real_heap_caps_realloc(p, size, caps);
|
||||||
|
} else { //TRACE_MALLOC_DEFAULT
|
||||||
|
r = heap_caps_realloc_default(p, size);
|
||||||
|
}
|
||||||
if (tracing && r != NULL) {
|
if (tracing && r != NULL) {
|
||||||
get_call_stack(callers);
|
get_call_stack(callers);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
|
@ -370,7 +389,7 @@ static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t s
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_malloc(size_t size)
|
IRAM_ATTR void *__wrap_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return trace_malloc(size, MALLOC_CAP_8BIT);
|
return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR void __wrap_free(void *p)
|
IRAM_ATTR void __wrap_free(void *p)
|
||||||
|
@ -380,13 +399,13 @@ IRAM_ATTR void __wrap_free(void *p)
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_realloc(void *p, size_t size)
|
IRAM_ATTR void *__wrap_realloc(void *p, size_t size)
|
||||||
{
|
{
|
||||||
return trace_realloc(p, size, MALLOC_CAP_8BIT);
|
return trace_realloc(p, size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
|
IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
|
||||||
{
|
{
|
||||||
size = size * nmemb;
|
size = size * nmemb;
|
||||||
void *result = trace_malloc(size, MALLOC_CAP_8BIT);
|
void *result = trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
memset(result, 0, size);
|
memset(result, 0, size);
|
||||||
}
|
}
|
||||||
|
@ -395,12 +414,12 @@ IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_malloc(size_t size, uint32_t caps)
|
IRAM_ATTR void *__wrap_heap_caps_malloc(size_t size, uint32_t caps)
|
||||||
{
|
{
|
||||||
return trace_malloc(size, caps);
|
return trace_malloc(size, caps, TRACE_MALLOC_CAPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR void __wrap_heap_caps_free(void *p) __attribute__((alias("__wrap_free")));
|
IRAM_ATTR void __wrap_heap_caps_free(void *p) __attribute__((alias("__wrap_free")));
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps)
|
IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps)
|
||||||
{
|
{
|
||||||
return trace_realloc(p, size, caps);
|
return trace_realloc(p, size, caps, TRACE_MALLOC_CAPS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@
|
||||||
#define MALLOC_CAP_PID5 (1<<7) ///< Memory must be mapped to PID5 memory space (PIDs are not currently used)
|
#define MALLOC_CAP_PID5 (1<<7) ///< Memory must be mapped to PID5 memory space (PIDs are not currently used)
|
||||||
#define MALLOC_CAP_PID6 (1<<8) ///< Memory must be mapped to PID6 memory space (PIDs are not currently used)
|
#define MALLOC_CAP_PID6 (1<<8) ///< Memory must be mapped to PID6 memory space (PIDs are not currently used)
|
||||||
#define MALLOC_CAP_PID7 (1<<9) ///< Memory must be mapped to PID7 memory space (PIDs are not currently used)
|
#define MALLOC_CAP_PID7 (1<<9) ///< Memory must be mapped to PID7 memory space (PIDs are not currently used)
|
||||||
#define MALLOC_CAP_SPISRAM (1<<10) ///< Memory must be in SPI SRAM
|
#define MALLOC_CAP_SPIRAM (1<<10) ///< Memory must be in SPI RAM
|
||||||
|
#define MALLOC_CAP_INTERNAL (1<<11) ///< Memory must be internal; specifically it should not disappear when flash/spiram cache is switched off
|
||||||
#define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker
|
#define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
*/
|
*/
|
||||||
void *heap_caps_malloc(size_t size, uint32_t caps);
|
void *heap_caps_malloc(size_t size, uint32_t caps);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
|
* @brief Free memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,9 +23,18 @@
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
These contain the business logic for the malloc() and realloc() implementation. Because of heap tracing
|
||||||
|
wrapping reasons, we do not want these to be a public api, however, so they're not defined publicly.
|
||||||
|
*/
|
||||||
|
extern void *heap_caps_malloc_default( size_t size );
|
||||||
|
extern void *heap_caps_realloc_default( void *ptr, size_t size );
|
||||||
|
|
||||||
|
|
||||||
void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size)
|
void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size)
|
||||||
{
|
{
|
||||||
return heap_caps_malloc( size, MALLOC_CAP_8BIT );
|
return heap_caps_malloc_default( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR _free_r(struct _reent *r, void* ptr)
|
void IRAM_ATTR _free_r(struct _reent *r, void* ptr)
|
||||||
|
@ -35,12 +44,12 @@ void IRAM_ATTR _free_r(struct _reent *r, void* ptr)
|
||||||
|
|
||||||
void* IRAM_ATTR _realloc_r(struct _reent *r, void* ptr, size_t size)
|
void* IRAM_ATTR _realloc_r(struct _reent *r, void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
return heap_caps_realloc( ptr, size, MALLOC_CAP_8BIT );
|
return heap_caps_realloc_default( ptr, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IRAM_ATTR _calloc_r(struct _reent *r, size_t count, size_t size)
|
void* IRAM_ATTR _calloc_r(struct _reent *r, size_t count, size_t size)
|
||||||
{
|
{
|
||||||
void* result = heap_caps_malloc(count * size, MALLOC_CAP_8BIT);
|
void* result = heap_caps_malloc_default(count * size);
|
||||||
if (result) {
|
if (result) {
|
||||||
bzero(result, count * size);
|
bzero(result, count * size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,28 +40,28 @@ The prioritised capabilities work roughly like this:
|
||||||
*/
|
*/
|
||||||
const soc_memory_type_desc_t soc_memory_types[] = {
|
const soc_memory_type_desc_t soc_memory_types[] = {
|
||||||
//Type 0: Plain ole D-port RAM
|
//Type 0: Plain ole D-port RAM
|
||||||
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, false, false},
|
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL, MALLOC_CAP_32BIT, 0 }, false, false},
|
||||||
//Type 1: Plain ole D-port RAM which has an alias on the I-port
|
//Type 1: Plain ole D-port RAM which has an alias on the I-port
|
||||||
//(This DRAM is also the region used by ROM during startup)
|
//(This DRAM is also the region used by ROM during startup)
|
||||||
{ "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
|
{ "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
|
||||||
//Type 2: IRAM
|
//Type 2: IRAM
|
||||||
{ "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT, 0, 0 }, false, false},
|
{ "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL, 0, 0 }, false, false},
|
||||||
//Type 3-8: PID 2-7 IRAM
|
//Type 3-8: PID 2-7 IRAM
|
||||||
{ "PID2IRAM", { MALLOC_CAP_PID2, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID2IRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID3IRAM", { MALLOC_CAP_PID3, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID3IRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID4IRAM", { MALLOC_CAP_PID4, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID4IRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID5IRAM", { MALLOC_CAP_PID5, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID5IRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID6IRAM", { MALLOC_CAP_PID6, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID6IRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID7IRAM", { MALLOC_CAP_PID7, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
{ "PID7IRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||||
//Type 9-14: PID 2-7 DRAM
|
//Type 9-14: PID 2-7 DRAM
|
||||||
{ "PID2DRAM", { MALLOC_CAP_PID2, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID2DRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID3DRAM", { MALLOC_CAP_PID3, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID3DRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID4DRAM", { MALLOC_CAP_PID4, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID4DRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID5DRAM", { MALLOC_CAP_PID5, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID5DRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID6DRAM", { MALLOC_CAP_PID6, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID6DRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
{ "PID7DRAM", { MALLOC_CAP_PID7, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
{ "PID7DRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||||
//Type 15: SPI SRAM data
|
//Type 15: SPI SRAM data
|
||||||
{ "SPISRAM", { MALLOC_CAP_SPISRAM, 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
|
{ "SPIRAM", { MALLOC_CAP_SPIRAM, 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
|
const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
|
||||||
|
@ -73,7 +73,7 @@ Because of requirements in the coalescing code which merges adjacent regions, th
|
||||||
from low to high start address.
|
from low to high start address.
|
||||||
*/
|
*/
|
||||||
const soc_memory_region_t soc_memory_regions[] = {
|
const soc_memory_region_t soc_memory_regions[] = {
|
||||||
{ 0x3F800000, 0x20000, 15, 0}, //SPI SRAM, if available
|
{ 0x3F800000, 0x400000, 15, 0}, //SPI SRAM, if available
|
||||||
{ 0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
|
{ 0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
|
||||||
{ 0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
|
{ 0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
|
||||||
{ 0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
|
{ 0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
|
||||||
|
@ -170,9 +170,7 @@ const soc_reserved_region_t soc_reserved_regions[] = {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1 // SPI ram not supported yet
|
{ 0x3f800000, 0x3fC00000 }, //SPI RAM gets added later if needed, in spiram.c; reserve it for now
|
||||||
{ 0x3f800000, 0x3f820000 }, //SPI SRAM not installed
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t soc_reserved_region_count = sizeof(soc_reserved_regions)/sizeof(soc_reserved_region_t);
|
const size_t soc_reserved_region_count = sizeof(soc_reserved_regions)/sizeof(soc_reserved_region_t);
|
||||||
|
|
Loading…
Reference in a new issue