From 0db8b00b8aced2367d9226bccb1fa5210d034733 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Wed, 25 Jan 2017 17:25:50 +0800 Subject: [PATCH] tight 28k --- components/esp32/cpu_start.c | 15 +- components/esp32/heap_alloc_caps.c | 45 ++- .../esp32/include/esp_heap_alloc_caps.h | 11 + components/esp32/include/heap_alloc_caps.h | 34 -- components/esp32/ld/esp32.rom.ld | 343 +++++++++--------- 5 files changed, 243 insertions(+), 205 deletions(-) delete mode 100644 components/esp32/include/heap_alloc_caps.h diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index cf20083508..2dbfffd5a2 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -38,7 +38,7 @@ #include "tcpip_adapter.h" -#include "heap_alloc_caps.h" +#include "esp_heap_alloc_caps.h" #include "sdkconfig.h" #include "esp_system.h" #include "esp_spi_flash.h" @@ -106,8 +106,6 @@ void IRAM_ATTR call_start_cpu0() memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start)); } - // Initialize heap allocator - heap_alloc_caps_init(); ESP_EARLY_LOGI(TAG, "Pro cpu up."); @@ -131,6 +129,15 @@ void IRAM_ATTR call_start_cpu0() ESP_EARLY_LOGI(TAG, "Single core mode"); CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN); #endif + + /* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted. + If the heap allocator is initialized first, it will put free memory linked list items into + memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory, + corrupting those linked lists. Initializing the allocator *after* the app cpu has booted + works around this problem. */ + heap_alloc_caps_init(); + + ESP_EARLY_LOGI(TAG, "Pro cpu start user code"); start_cpu0(); } @@ -250,6 +257,8 @@ static void main_task(void* args) // Now that the application is about to start, disable boot watchdogs REG_CLR_BIT(TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN_S); REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN); + //Enable allocation in region where the startup stacks were located. + heap_alloc_enable_nonos_stack_tag(); app_main(); vTaskDelete(NULL); } diff --git a/components/esp32/heap_alloc_caps.c b/components/esp32/heap_alloc_caps.c index 7d2a26e64e..565dd9b8fd 100644 --- a/components/esp32/heap_alloc_caps.c +++ b/components/esp32/heap_alloc_caps.c @@ -36,6 +36,7 @@ hardwiring addresses. //Amount of priority slots for the tag descriptors. #define NO_PRIOS 3 + typedef struct { const char *name; uint32_t prio[NO_PRIOS]; @@ -46,6 +47,9 @@ typedef struct { Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table. Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request. Make sure there are never more than HEAPREGIONS_MAX_TAGCOUNT (in heap_regions.h) tags (ex the last empty marker) + +WARNING: The current code assumes the ROM stacks are located in tag 1; no allocation from this tag can be done until +the FreeRTOS scheduler has started. */ static const tag_desc_t tag_desc[]={ { "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, false}, //Tag 0: Plain ole D-port RAM @@ -89,8 +93,8 @@ This array is *NOT* const because it gets modified depending on what pools are/a static HeapRegionTagged_t regions[]={ { (uint8_t *)0x3F800000, 0x20000, 15, 0}, //SPI SRAM, if available { (uint8_t *)0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code - { (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- can be used for BT - { (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- can be used for BT + { (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory + { (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions. { (uint8_t *)0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0 { (uint8_t *)0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1 { (uint8_t *)0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2 @@ -134,6 +138,16 @@ static HeapRegionTagged_t regions[]={ { NULL, 0, 0, 0} //end }; +/* For the startup code, the stacks live in memory tagged by this tag. Hence, we only enable allocating from this tag + once FreeRTOS has started up completely. */ +#define NONOS_STACK_TAG 1 + +static bool nonos_stack_in_use=true; + +void heap_alloc_enable_nonos_stack_tag() +{ + nonos_stack_in_use=false; +} //Modify regions array to disable the given range of memory. static void disable_mem_region(void *from, void *to) { @@ -185,12 +199,24 @@ void heap_alloc_caps_init() { //Disable the bits of memory where this code is loaded. disable_mem_region(&_data_start, &_heap_start); //DRAM used by bss/data static variables disable_mem_region(&_init_start, &_iram_text_end); //IRAM used by code - disable_mem_region((void*)0x3ffae000, (void*)0x3ffb0000); //knock out ROM data region disable_mem_region((void*)0x40070000, (void*)0x40078000); //CPU0 cache region disable_mem_region((void*)0x40078000, (void*)0x40080000); //CPU1 cache region - // TODO: this region should be checked, since we don't need to knock out all region finally - disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe8000); //knock out ROM data region + /* Warning: The ROM stack is located in the 0x3ffe0000 area. We do not specifically disable that area here because + after the scheduler has started, the ROM stack is not used anymore by anything. We handle it instead by not allowing + any mallocs from tag 1 (the IRAM/DRAM region) until the scheduler has started. + + The 0x3ffe0000 region also contains static RAM for various ROM functions. The following lines knocks + out the regions for UART and ETSC, so these functions are usable. Libraries like xtos, which are + not usable in FreeRTOS anyway, are commented out in the linker script so they cannot be used; we + do not disable their memory regions here and they will be used as general purpose heap memory. + + Enabling the heap allocator for this region but disabling allocation here until FreeRTOS is started up + is a somewhat risky action in theory, because on initializing the allocator, it will go and write linked + list entries at the start and end of all regions. For the ESP32, these linked list entries happen to end + up in a region that is not touched by the stack; they can be placed safely there.*/ + disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe0440); //knock out ROM PRO data region + disable_mem_region((void*)0x3ffe4000, (void*)0x3ffe4350); //knock out ROM APP data region #if CONFIG_BT_ENABLED #if CONFIG_BT_DRAM_RELEASE @@ -198,8 +224,11 @@ void heap_alloc_caps_init() { disable_mem_region((void*)0x3ffb8000, (void*)0x3ffbbb28); //knock out BT data region disable_mem_region((void*)0x3ffbdb28, (void*)0x3ffc0000); //knock out BT data region #else - disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //knock out BT data region + disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //knock out BT hardware shared memory & BT data region #endif + disable_mem_region((void*)0x3ffae000, (void*)0x3ffaff10); //knock out ROM data region, inc region needed for BT ROM routines +#else + disable_mem_region((void*)0x3ffae000, (void*)0x3ffae2a0); //knock out ROM data region #endif #if CONFIG_MEMMAP_TRACEMEM @@ -317,6 +346,10 @@ void *pvPortMallocCaps( size_t xWantedSize, uint32_t caps ) for (prio=0; prio>>>> btdm data */ +