diff --git a/cores/esp8266/core_esp8266_app_entry_noextra4k.cpp b/cores/esp8266/core_esp8266_app_entry_noextra4k.cpp index 58f615c784..0c0eac4d48 100644 --- a/cores/esp8266/core_esp8266_app_entry_noextra4k.cpp +++ b/cores/esp8266/core_esp8266_app_entry_noextra4k.cpp @@ -39,7 +39,19 @@ extern "C" void app_entry_redefinable(void) { g_pcont = &g_cont; + #ifdef UMM_INIT_USE_IRAM + /* + * Legacy option: the umm_init() call path must reside in IRAM. + */ umm_init(); + #else + /* + * Instruction cache is enabled/disabled around running umm_init(). + * Allows the use of IROM (flash) to store umm_init(). + */ + mmu_wrap_irom_fn(umm_init); + #endif + /* Call the entry point of the SDK code. */ call_user_start(); } diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 39decfb12f..430808f19d 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -365,7 +365,12 @@ extern "C" void app_entry_redefinable(void) /* Doing umm_init just once before starting the SDK, allowed us to remove test and init calls at each malloc API entry point, saving IRAM. */ +#ifdef UMM_INIT_USE_IRAM umm_init(); +#else + // umm_init() is in IROM + mmu_wrap_irom_fn(umm_init); +#endif /* Call the entry point of the SDK code. */ call_user_start(); } diff --git a/cores/esp8266/hwdt_app_entry.cpp b/cores/esp8266/hwdt_app_entry.cpp index 22a91a6bee..8177832b9e 100644 --- a/cores/esp8266/hwdt_app_entry.cpp +++ b/cores/esp8266/hwdt_app_entry.cpp @@ -275,6 +275,7 @@ #include #include #include +#include "mmu_iram.h" extern "C" { #include @@ -1007,6 +1008,18 @@ STATIC void IRAM_MAYBE handle_hwdt(void) { #endif } +#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM) +static void printSanityCheck() { + ETS_PRINTF("\n\nsys_stack_first: %p\n", sys_stack_first); + ETS_PRINTF( "CONT_STACK: %p\n", CONT_STACK); + ETS_PRINTF( "g_pcont: %p\n", g_pcont); + ETS_PRINTF( "ROM_STACK: %p\n", ROM_STACK); + ETS_PRINTF( "get_noextra4k_g_pcont(): %p\n", get_noextra4k_g_pcont()); + ETS_PRINTF( "g_rom_stack: %p\n", g_rom_stack); + ETS_PRINTF( "g_rom_stack_A16_sz: 0x%08X\n\n", g_rom_stack_A16_sz); +} +#endif //DEBUG_ESP_HWDT_DEV_DEBUG + /* * Using Cache_Read_Enable/Cache_Read_Disable to reduce IRAM usage. Moved * strings and most functions to flash. At this phase of the startup, "C++" has @@ -1019,34 +1032,11 @@ STATIC void IRAM_MAYBE handle_hwdt(void) { * https://richard.burtons.org/2015/06/12/esp8266-cache_read_enable/. * Additional insight can be gleemed from reviewing the ESP8266_RTOS_SDK. * (eg. ../components/bootloader_support/src/bootloader_utility.c) + * + * The logic to use Cache_Read_Enable and Cache_Read_Disable has been + * generalized into a wrapper function, mmu_wrap_irom_fn, and moved to + * mmu_iram.cpp. */ -#define ICACHE_SIZE_32 1 -#define ICACHE_SIZE_16 0 - -extern "C" void Cache_Read_Disable(void); -extern "C" void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); - -#ifndef USE_IRAM -static void IRAM_ATTR __attribute__((noinline)) handle_hwdt_icache() __attribute__((used)); -void handle_hwdt_icache() { - Cache_Read_Enable(0, 0, ICACHE_SIZE_16); - handle_hwdt(); - Cache_Read_Disable(); -} -#endif // USE_IRAM - - -#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM) -static void printSanityCheck() { - ETS_PRINTF("\n\nsys_stack_first: %p\n", sys_stack_first); - ETS_PRINTF( "CONT_STACK: %p\n", CONT_STACK); - ETS_PRINTF( "g_pcont: %p\n", g_pcont); - ETS_PRINTF( "ROM_STACK: %p\n", ROM_STACK); - ETS_PRINTF( "get_noextra4k_g_pcont(): %p\n", get_noextra4k_g_pcont()); - ETS_PRINTF( "g_rom_stack: %p\n", g_rom_stack); - ETS_PRINTF( "g_rom_stack_A16_sz: 0x%08X\n\n", g_rom_stack_A16_sz); -} -#endif //DEBUG_ESP_HWDT_DEV_DEBUG /* hwdt_pre_sdk_init() is the result of a hook for development diagnotics which @@ -1071,9 +1061,8 @@ void hwdt_pre_sdk_init(void) { #endif } -static void IRAM_ATTR __attribute__((noinline)) hwdt_pre_sdk_init_icache(void) __attribute__((used)); +static void __attribute__((noinline)) hwdt_pre_sdk_init_icache(void) __attribute__((used)); void hwdt_pre_sdk_init_icache(void) { - Cache_Read_Enable(0, 0, ICACHE_SIZE_16); #ifdef DEBUG_ESP_HWDT_UART_SPEED const uint32_t uart_divisor = set_uart_speed(0, DEBUG_ESP_HWDT_UART_SPEED); #endif @@ -1085,7 +1074,6 @@ void hwdt_pre_sdk_init_icache(void) { adjust_uart_speed(uart_divisor); } #endif - Cache_Read_Disable(); } /* @@ -1106,6 +1094,7 @@ asm ( ".literal .umm_init, umm_init\n\t" ".literal .call_user_start, call_user_start\n\t" ".literal .get_noextra4k_g_pcont, get_noextra4k_g_pcont\n\t" + ".literal .mmu_wrap_irom_fn, mmu_wrap_irom_fn\n\t" ".align 4\n\t" ".global app_entry_redefinable\n\t" ".type app_entry_redefinable, @function\n\t" @@ -1129,7 +1118,9 @@ asm ( #ifdef USE_IRAM "call0 handle_hwdt\n\t" #else - "call0 handle_hwdt_icache\n\t" + "l32r a0, .mmu_wrap_irom_fn\n\t" + "movi a2, handle_hwdt\n\t" + "callx0 a0\n\t" #endif /* * Use new calculated SYS stack from top. @@ -1160,7 +1151,9 @@ asm ( /* * Allow for running additional diagnotics supplied at link time. */ - "call0 hwdt_pre_sdk_init_icache\n\t" + "l32r a0, .mmu_wrap_irom_fn\n\t" + "movi a2, hwdt_pre_sdk_init_icache\n\t" + "callx0 a0\n\t" // In case somebody cares, leave things as we found them // - Restore ROM BSS zeros. @@ -1174,7 +1167,12 @@ asm ( * improvements could possibly use hwdt_pre_sdk_init() to run other early * diagnostic tools. */ +#ifdef UMM_INIT_USE_IRAM "l32r a0, .umm_init\n\t" +#else + "l32r a0, .mmu_wrap_irom_fn\n\t" + "l32r a2, .umm_init\n\t" +#endif "callx0 a0\n\t" "l32r a3, .call_user_start\n\t" diff --git a/cores/esp8266/mmu_iram.cpp b/cores/esp8266/mmu_iram.cpp index 7a3548e4a3..9f1b05d455 100644 --- a/cores/esp8266/mmu_iram.cpp +++ b/cores/esp8266/mmu_iram.cpp @@ -19,13 +19,16 @@ #include "mmu_iram.h" #include +#define ICACHE_SIZE_32 1 +#define ICACHE_SIZE_16 0 + extern "C" { #if (MMU_ICACHE_SIZE == 0x4000) -#define SOC_CACHE_SIZE 0 // 16KB +#define SOC_CACHE_SIZE ICACHE_SIZE_16 #pragma message("ICACHE size 16K") #else -#define SOC_CACHE_SIZE 1 // 32KB +#define SOC_CACHE_SIZE ICACHE_SIZE_32 #endif #if (MMU_ICACHE_SIZE == 0x4000) @@ -185,8 +188,21 @@ extern "C" void pinMode( uint8_t pin, uint8_t mode ) { __pinMode( pin, mode ); } +#else // #ifdef DEV_DEBUG_PRINT +extern void Cache_Read_Disable(void); #endif // #ifdef DEV_DEBUG_PRINT +#else // #if (MMU_ICACHE_SIZE == 0x4000) +extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); #endif // #if (MMU_ICACHE_SIZE == 0x4000) +/* + * This wrapper is for running code from IROM (flash) before the SDK starts. + */ +void IRAM_ATTR mmu_wrap_irom_fn(void (*fn)(void)) { + Cache_Read_Enable(0, 0, ICACHE_SIZE_16); + fn(); + Cache_Read_Disable(); +} + }; diff --git a/cores/esp8266/mmu_iram.h b/cores/esp8266/mmu_iram.h index f7b62ba8c2..121226bd4c 100644 --- a/cores/esp8266/mmu_iram.h +++ b/cores/esp8266/mmu_iram.h @@ -80,6 +80,24 @@ DBG_MMU_FLUSH(0) #define DBG_MMU_PRINTF(...) do {} while(false) #endif // defined(DEV_DEBUG_PRINT) || defined(DEBUG_ESP_MMU) +/* + * This wrapper is for running code from IROM (flash) before the SDK starts. + * + * Wraps a `void fn(void)` call with calls to enable and disable iCACHE. + * Allows a function that resides in IROM to run before the SDK starts. + * + * Do not use once the SDK has started. + * + * Because the SDK initialization code has not run, nearly all the SDK functions + * are not safe to call. + * + * Note printing at this early stage is complicated. To gain more insight, + * review DEV_DEBUG_PRINT build path in mmu_iram.cpp. To handle strings stored + * in IROM, review printing method and comments in hwdt_app_entry.cpp. + * + */ +void IRAM_ATTR mmu_wrap_irom_fn(void (*fn)(void)); + static inline __attribute__((always_inline)) bool mmu_is_iram(const void *addr) { const uintptr_t iram_start = (uintptr_t)XCHAL_INSTRAM1_VADDR; diff --git a/cores/esp8266/umm_malloc/umm_info.c b/cores/esp8266/umm_malloc/umm_info.c index bd3280baed..4a95e994c3 100644 --- a/cores/esp8266/umm_malloc/umm_info.c +++ b/cores/esp8266/umm_malloc/umm_info.c @@ -28,7 +28,7 @@ void *umm_info(void *ptr, bool force) { UMM_CRITICAL_DECL(id_info); - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); uint16_t blockNo = 0; diff --git a/cores/esp8266/umm_malloc/umm_integrity.c b/cores/esp8266/umm_malloc/umm_integrity.c index c66ec3bb00..c652562f99 100644 --- a/cores/esp8266/umm_malloc/umm_integrity.c +++ b/cores/esp8266/umm_malloc/umm_integrity.c @@ -33,7 +33,7 @@ bool umm_integrity_check(void) { uint16_t prev; uint16_t cur; - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); /* Iterate through all free blocks */ prev = 0; diff --git a/cores/esp8266/umm_malloc/umm_local.c b/cores/esp8266/umm_malloc/umm_local.c index 24ddf8ce06..035d8a0d55 100644 --- a/cores/esp8266/umm_malloc/umm_local.c +++ b/cores/esp8266/umm_malloc/umm_local.c @@ -166,7 +166,7 @@ size_t umm_block_size(void) { #if defined(UMM_STATS) || defined(UMM_STATS_FULL) // Keep complete call path in IRAM size_t umm_free_heap_size_lw(void) { - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); umm_heap_context_t *_context = umm_get_current_heap(); return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block); diff --git a/cores/esp8266/umm_malloc/umm_malloc.cpp b/cores/esp8266/umm_malloc/umm_malloc.cpp index d3f4c92c66..78d20c98d0 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.cpp +++ b/cores/esp8266/umm_malloc/umm_malloc.cpp @@ -63,24 +63,26 @@ extern "C" { #define DBGLOG_LEVEL 0 #endif -// Save 104 bytes by calling umm_init() early once from app_entry() -// Some minor UMM_CRITICAL_METRICS counts will be lost through CRT0 init. -// #define UMM_INIT_HEAP if (!umm_heap) { umm_init(); } -#define UMM_INIT_HEAP (void)0 - #include "dbglog/dbglog.h" -// C This change is new in upstream umm_malloc.I think this would have created a -// C breaking change. Keeping the old #define method in umm_malloc_cfg.h. -// C I don't see a simple way of making it work. We would have to run code before -// C the SDK has run to set a value for uint32_t UMM_MALLOC_CFG_HEAP_SIZE. -// C On the other hand, a manual call to umm_init() before anything else has had a -// C chance to run would mean that all those calls testing to see if the heap has -// C been initialized at every umm_malloc API could be removed. -// C -// C before starting the NON OS SDK -// C extern void *UMM_MALLOC_CFG_HEAP_ADDR; -// C extern uint32_t UMM_MALLOC_CFG_HEAP_SIZE; +/* + * These variables are used in upstream umm_malloc for initializing the heap. + * Our port initialization is different and does not use them at this time. +extern void *UMM_MALLOC_CFG_HEAP_ADDR; +extern uint32_t UMM_MALLOC_CFG_HEAP_SIZE; + */ +/* + * In our port, we leave UMM_CHECK_INITIALIZED unset. Since we initialize the + * heap before CRT0 init has run, commonly used testing methods for heap init + * may not work. Not using UMM_CHECK_INITIALIZED saves about 104 bytes of IRAM. + * + * In our configuration app_entry_redefinable() must call umm_init(), before + * calling the SDK's app_entry_custom(). The DRAM Heap must be available before + * the SDK starts. + * + * If building with UMM_CRITICAL_METRICS, some minor counts will be lost through + * CRT0 init. + */ #include "umm_local.h" // target-dependent supplemental @@ -91,7 +93,6 @@ UMM_H_ATTPACKPRE typedef struct umm_ptr_t { uint16_t prev; } UMM_H_ATTPACKSUF umm_ptr; - UMM_H_ATTPACKPRE typedef struct umm_block_t { union { umm_ptr used; @@ -425,21 +426,30 @@ static uint16_t umm_assimilate_down(umm_heap_context_t *_context, uint16_t c, ui } /* ------------------------------------------------------------------------- */ - -static void umm_init_stage_2(umm_heap_context_t *_context) { +#undef ICACHE_MAYBE +#ifdef UMM_INIT_USE_IRAM +// umm_init(), ... stays in IRAM +#define ICACHE_MAYBE +#else +// Freeup IRAM +#define ICACHE_MAYBE ICACHE_FLASH_ATTR +#endif +/* + * In this port, we split the upstream version of umm_init_heap() into two + * parts: _umm_init_heap and umm_init_heap. Then add multiple heap support. + */ +static void ICACHE_MAYBE _umm_init_heap(umm_heap_context_t *_context) { /* setup initial blank heap structure */ UMM_FRAGMENTATION_METRIC_INIT(); /* init stats.free_blocks */ - #if defined(UMM_STATS) || defined(UMM_STATS_FULL) #if defined(UMM_STATS_FULL) - _context->stats.free_blocks_min = - _context->stats.free_blocks_isr_min = UMM_NUMBLOCKS - 2; + _context->stats.free_blocks_min = UMM_NUMBLOCKS - 2; + _context->stats.free_blocks_isr_min = UMM_NUMBLOCKS - 2; #endif - #ifndef UMM_INLINE_METRICS + #if (defined(UMM_STATS) || defined(UMM_STATS_FULL)) && !defined(UMM_INLINE_METRICS) _context->stats.free_blocks = UMM_NUMBLOCKS - 2; #endif - #endif /* Set up umm_block[0], which just points to umm_block[1] */ UMM_NBLOCK(0) = 1; @@ -478,78 +488,91 @@ static void umm_init_stage_2(umm_heap_context_t *_context) { UMM_PBLOCK(UMM_BLOCK_LAST) = 1; } - -void umm_init_common(size_t id, void *start_addr, size_t size, bool zero) { - /* Preserve internal setup */ +void ICACHE_MAYBE umm_init_heap(size_t id, void *start_addr, size_t size, bool full_init) { + /* Check for bad values and block duplicate init attempts. */ umm_heap_context_t *_context = umm_get_heap_by_id(id); if (NULL == start_addr || NULL == _context || _context->heap) { return; } /* init heap pointer and size, and memset it to 0 */ + _context->id = id; _context->heap = (umm_block *)start_addr; _context->heap_end = (void *)((uintptr_t)start_addr + size); _context->numblocks = (size / sizeof(umm_block)); - // An option for blocking the zeroing of extra heaps allows for performing - // post-crash discovery. - if (zero) { + // An option for blocking the zeroing of extra heaps. This allows for + // post-crash debugging after reboot. + if (full_init) { memset(_context->heap, 0x00, size); #if (!defined(UMM_INLINE_METRICS) && defined(UMM_STATS)) || defined(UMM_STATS_FULL) memset(&_context->stats, 0x00, sizeof(_context->stats)); #endif /* Set up internal data structures */ - umm_init_stage_2(_context); + _umm_init_heap(_context); } } -void umm_init(void) { - // if (umm_heap) { - // return; - // } +void ICACHE_MAYBE umm_init(void) { + + // We can get called before "C" runtime has run. Here we handles that + // beginning of time initialization. As such heap_context[] must be + // defined with attributes to prevent initialization by the "C" runtime. + // A late "C" runtime init would destroy our work. + + // Assume no "C" runtime zero init for (size_t i = 0; i < UMM_NUM_HEAPS; i++) { heap_context[i].heap = NULL; } memset(&heap_context[0], 0, sizeof(heap_context)); - umm_init_common(UMM_HEAP_DRAM, (void *)UMM_MALLOC_CFG_HEAP_ADDR, UMM_MALLOC_CFG_HEAP_SIZE, true); - // umm_heap = (void *)&heap_context; + // Note, full_init must be true for the primary heap, DRAM. + umm_init_heap(UMM_HEAP_DRAM, (void *)UMM_MALLOC_CFG_HEAP_ADDR, UMM_MALLOC_CFG_HEAP_SIZE, true); + + // upstream ref: + // Initialize the heap from linker supplied values */ + // umm_init_heap(UMM_MALLOC_CFG_HEAP_ADDR, UMM_MALLOC_CFG_HEAP_SIZE); } +/* + * Only the Internal DRAM init, needs (or maybe not) to be called from IRAM. + * umm_init_iram and umm_init_vm are called from user_init() after the SDK has + * inited and ICACHE has been enabled. + */ #ifdef UMM_HEAP_IRAM -void umm_init_iram_ex(void *addr, unsigned int size, bool zero) { +void ICACHE_FLASH_ATTR umm_init_iram_ex(void *addr, unsigned int size, bool full_init) { /* We need the main, internal heap set up first */ - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); - umm_init_common(UMM_HEAP_IRAM, addr, size, zero); + umm_init_heap(UMM_HEAP_IRAM, addr, size, full_init); } void _text_end(void); -void umm_init_iram(void) __attribute__((weak)); +void ICACHE_FLASH_ATTR umm_init_iram(void) __attribute__((weak)); /* By using a weak link, it is possible to reduce the IRAM heap size with a user-supplied init function. This would allow the creation of a block of IRAM dedicated to a sketch and possibly used/preserved across reboots. */ -void umm_init_iram(void) { +void ICACHE_FLASH_ATTR umm_init_iram(void) { umm_init_iram_ex(mmu_sec_heap(), mmu_sec_heap_size(), true); } #endif // #ifdef UMM_HEAP_IRAM #ifdef UMM_HEAP_EXTERNAL -void umm_init_vm(void *vmaddr, unsigned int vmsize) { +void ICACHE_FLASH_ATTR umm_init_vm(void *vmaddr, unsigned int vmsize) { /* We need the main, internal (DRAM) heap set up first */ - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); - umm_init_common(UMM_HEAP_EXTERNAL, vmaddr, vmsize, true); + umm_init_heap(UMM_HEAP_EXTERNAL, vmaddr, vmsize, true); } #endif /* ------------------------------------------------------------------------ * Must be called only from within critical sections guarded by - * UMM_CRITICAL_ENTRY() and UMM_CRITICAL_EXIT(). + * UMM_CRITICAL_ENTRY(id) and UMM_CRITICAL_EXIT(id). */ static void umm_free_core(umm_heap_context_t *_context, void *ptr) { @@ -614,7 +637,7 @@ static void umm_free_core(umm_heap_context_t *_context, void *ptr) { void umm_free(void *ptr) { UMM_CRITICAL_DECL(id_free); - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); /* If we're being asked to free a NULL pointer, well that's just silly! */ @@ -769,7 +792,7 @@ void *umm_malloc(size_t size) { void *ptr = NULL; - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); /* * "Is it safe" @@ -878,7 +901,7 @@ void *umm_realloc(void *ptr, size_t size) { size_t curSize; - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); /* * This code looks after the case of a NULL value for ptr. The ANSI C diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfg.h b/cores/esp8266/umm_malloc/umm_malloc_cfg.h index 3ec44c1f40..b7a090f7f2 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfg.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfg.h @@ -1,14 +1,16 @@ /* - * Configuration for umm_malloc - target Arduino ESP8266 core - * - * Changes specific to a target platform go here. - * - * This comment section changed to below in the upstream version, keeping old method for now. - * * Configuration for umm_malloc - DO NOT EDIT THIS FILE BY HAND! * - * Refer to the notes below for how to configure the build at compile time - * using -D to define non-default values + * NOTE WELL: Your project MUST have a umm_malloc_cfgport.h - even if + * it's empty!!! + * + * Refer to the notes below for details on the umm_malloc configuration + * options. + */ + +/* + * Minimized changes in umm_malloc_cfg.h, transition Arduino ESP8266 specific + * changes to umm_malloc_cfgport.h. */ #ifndef _UMM_MALLOC_CFG_H @@ -18,65 +20,10 @@ #include #include -#include -#include -#include "../debug.h" -#include "../esp8266_undocumented.h" - #ifdef __cplusplus extern "C" { #endif -#include -#include -#include - -#include "c_types.h" - -/* - * Define active Heaps - */ -#if defined(MMU_IRAM_HEAP) -#define UMM_HEAP_IRAM -#else -#undef UMM_HEAP_IRAM -#endif - -#if defined(MMU_EXTERNAL_HEAP) -#define UMM_HEAP_EXTERNAL -#else -#undef UMM_HEAP_EXTERNAL -#endif - -/* - * Assign IDs to active Heaps and tally. DRAM is always active. - */ -#define UMM_HEAP_DRAM 0 -#define UMM_HEAP_DRAM_DEFINED 1 - -#ifdef UMM_HEAP_IRAM -#undef UMM_HEAP_IRAM -#define UMM_HEAP_IRAM_DEFINED 1 -#define UMM_HEAP_IRAM UMM_HEAP_DRAM_DEFINED -#else -#define UMM_HEAP_IRAM_DEFINED 0 -#endif - -#ifdef UMM_HEAP_EXTERNAL -#undef UMM_HEAP_EXTERNAL -#define UMM_HEAP_EXTERNAL_DEFINED 1 -#define UMM_HEAP_EXTERNAL (UMM_HEAP_DRAM_DEFINED + UMM_HEAP_IRAM_DEFINED) -#else -#define UMM_HEAP_EXTERNAL_DEFINED 0 -#endif - -#define UMM_NUM_HEAPS (UMM_HEAP_DRAM_DEFINED + UMM_HEAP_IRAM_DEFINED + UMM_HEAP_EXTERNAL_DEFINED) - -#if (UMM_NUM_HEAPS == 1) -#else -#define UMM_HEAP_STACK_DEPTH 32 -#endif - /* * There are a number of defines you can set at compile time that affect how * the memory allocator will operate. @@ -116,6 +63,16 @@ extern "C" { * Setting this at compile time will automatically set UMM_INFO. * Note that enabling this define will add a slight runtime penalty. * + * UMM_CHECK_INITIALIZED + * + * Set if you want to be able to verify that the heap is intialized + * before any operation - the default is no check. You may set the + * UMM_CHECK_INITIALIZED macro to the following provided macros, or + * write your own handler: + * + * UMM_INIT_IF_UNINITIALIZED + * UMM_HANG_IF_UNINITIALIZED + * * UMM_INTEGRITY_CHECK * * Set if you want to be able to verify that the heap is semantically correct @@ -143,6 +100,12 @@ extern "C" { * ---------------------------------------------------------------------------- */ +#ifdef UMM_CFGFILE +#include UMM_CFGFILE +#else +#include "umm_malloc_cfgport.h" +#endif + #define UMM_BEST_FIT #define UMM_INFO // #define UMM_INLINE_METRICS @@ -168,22 +131,6 @@ extern "C" { */ -#ifdef UMM_TEST_BUILD -extern char test_umm_heap[]; -#endif - -#ifdef UMM_TEST_BUILD -/* Start addresses and the size of the heap */ -#define UMM_MALLOC_CFG_HEAP_ADDR (test_umm_heap) -#define UMM_MALLOC_CFG_HEAP_SIZE 0x10000 -#else -/* Start addresses and the size of the heap */ -extern char _heap_start[]; -#define UMM_HEAP_END_ADDR 0x3FFFC000UL -#define UMM_MALLOC_CFG_HEAP_ADDR ((uint32_t)&_heap_start[0]) -#define UMM_MALLOC_CFG_HEAP_SIZE ((size_t)(UMM_HEAP_END_ADDR - UMM_MALLOC_CFG_HEAP_ADDR)) -#endif - /* A couple of macros to make packing structures less compiler dependent */ #define UMM_H_ATTPACKPRE @@ -191,6 +138,20 @@ extern char _heap_start[]; /* -------------------------------------------------------------------------- */ +#ifndef UMM_INIT_IF_UNINITIALIZED + #define UMM_INIT_IF_UNINITIALIZED() do { if (UMM_HEAP == NULL) { umm_init(); } } while (0) +#endif + +#ifndef UMM_HANG_IF_UNINITIALIZED + #define UMM_HANG_IF_UNINITIALIZED() do { if (UMM_HEAP == NULL) { while (1) {} } } while (0) +#endif + +#ifndef UMM_CHECK_INITIALIZED + #define UMM_CHECK_INITIALIZED() +#endif + +/* -------------------------------------------------------------------------- */ + #ifdef UMM_BEST_FIT #ifdef UMM_FIRST_FIT #error Both UMM_BEST_FIT and UMM_FIRST_FIT are defined - pick one! diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfgport.h b/cores/esp8266/umm_malloc/umm_malloc_cfgport.h new file mode 100644 index 0000000000..02db6fc66c --- /dev/null +++ b/cores/esp8266/umm_malloc/umm_malloc_cfgport.h @@ -0,0 +1,91 @@ +#ifndef _UMM_MALLOC_CFGPORT_H +#define _UMM_MALLOC_CFGPORT_H + +#ifndef _UMM_MALLOC_CFG_H +#error "This include file must be used with umm_malloc_cfg.h" +#endif + +/* + * Arduino ESP8266 core umm_malloc port config + */ +#include +#include +#include "../debug.h" +#include "../esp8266_undocumented.h" + +#include +#include +#include + +#include "c_types.h" + +/* + * -DUMM_INIT_USE_IRAM + * + * Historically, the umm_init() call path has been in IRAM. The umm_init() call + * path is now in ICACHE (flash). Use the build option UMM_INIT_USE_IRAM to + * restore the legacy behavor. + * + * If you have your own app_entry_redefinable() function, see + * app_entry_redefinable() in core_esp8266_app_entry_noextra4k.cpp for an + * example of how to toggle between ICACHE and IRAM in your build. + * + * The default is to use ICACHE. + */ +// #define UMM_INIT_USE_IRAM 1 + + +/* + * Start addresses and the size of the heap + */ +extern char _heap_start[]; +#define UMM_HEAP_END_ADDR 0x3FFFC000UL +#define UMM_MALLOC_CFG_HEAP_ADDR ((uint32_t)&_heap_start[0]) +#define UMM_MALLOC_CFG_HEAP_SIZE ((size_t)(UMM_HEAP_END_ADDR - UMM_MALLOC_CFG_HEAP_ADDR)) + +/* + * Define active Heaps + */ +#if defined(MMU_IRAM_HEAP) +#define UMM_HEAP_IRAM +#else +#undef UMM_HEAP_IRAM +#endif + +#if defined(MMU_EXTERNAL_HEAP) +#define UMM_HEAP_EXTERNAL +#else +#undef UMM_HEAP_EXTERNAL +#endif + +/* + * Assign IDs to active Heaps and tally. DRAM is always active. + */ +#define UMM_HEAP_DRAM 0 +#define UMM_HEAP_DRAM_DEFINED 1 + +#ifdef UMM_HEAP_IRAM +#undef UMM_HEAP_IRAM +#define UMM_HEAP_IRAM_DEFINED 1 +#define UMM_HEAP_IRAM UMM_HEAP_DRAM_DEFINED +#else +#define UMM_HEAP_IRAM_DEFINED 0 +#endif + +#ifdef UMM_HEAP_EXTERNAL +#undef UMM_HEAP_EXTERNAL +#define UMM_HEAP_EXTERNAL_DEFINED 1 +#define UMM_HEAP_EXTERNAL (UMM_HEAP_DRAM_DEFINED + UMM_HEAP_IRAM_DEFINED) +#else +#define UMM_HEAP_EXTERNAL_DEFINED 0 +#endif + +#define UMM_NUM_HEAPS (UMM_HEAP_DRAM_DEFINED + UMM_HEAP_IRAM_DEFINED + UMM_HEAP_EXTERNAL_DEFINED) + +#if (UMM_NUM_HEAPS == 1) +#else +#define UMM_HEAP_STACK_DEPTH 32 +#endif + + +#endif diff --git a/cores/esp8266/umm_malloc/umm_poison.c b/cores/esp8266/umm_malloc/umm_poison.c index a7a3fa2179..802e580617 100644 --- a/cores/esp8266/umm_malloc/umm_poison.c +++ b/cores/esp8266/umm_malloc/umm_poison.c @@ -227,7 +227,7 @@ bool umm_poison_check(void) { bool ok = true; uint16_t cur; - UMM_INIT_HEAP; + UMM_CHECK_INITIALIZED(); UMM_CRITICAL_ENTRY(id_poison); umm_heap_context_t *_context = umm_get_current_heap();