Skip to content

Commit

Permalink
Heap init code improvements and updates (#8458)
Browse files Browse the repository at this point in the history
* Heap init code improvements and updates

Moved secondary heap init code to flash.
  External -24 IRAM, +32 IROM
  IRAM     -76 IRAM, +64 IROM

General updates to umm_init call path and DEFINES to better align with
upstream. Name changes: UMM_INIT_HEAP with UMM_CHECK_INITIALIZED,
umm_init_stage_2 with _umm_init_heap, and umm_init_common with umm_init_heap.

Add file umm_cfgport.h to hold port-specific values. Stay focused
on heap initialization only move-related defines.

Improved comments.

Created a wrapper function for running pre-SDK code from flash.
Updated hwdt_app_entry to use it.

Update umm_init with option to run from ICACHE.
Added build define UMM_INIT_USE_ICACHE to move umm_init call path to flash.
When used frees up 160 bytes of IRAM at a cost of 208 bytes of IROM

Defaults to no change, umm_init call path will be in IRAM.

* Changed default to use IROM for umm_init() and option to revert back to UMM_INIT_USE_IRAM.
  • Loading branch information
mhightower83 committed Feb 15, 2022
1 parent d7c3d7b commit 7356cd1
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 166 deletions.
12 changes: 12 additions & 0 deletions cores/esp8266/core_esp8266_app_entry_noextra4k.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
5 changes: 5 additions & 0 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
62 changes: 30 additions & 32 deletions cores/esp8266/hwdt_app_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
#include <esp8266_peri.h>
#include <uart.h>
#include <pgmspace.h>
#include "mmu_iram.h"

extern "C" {
#include <user_interface.h>
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -1085,7 +1074,6 @@ void hwdt_pre_sdk_init_icache(void) {
adjust_uart_speed(uart_divisor);
}
#endif
Cache_Read_Disable();
}

/*
Expand All @@ -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"
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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"
Expand Down
20 changes: 18 additions & 2 deletions cores/esp8266/mmu_iram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
#include "mmu_iram.h"
#include <user_interface.h>

#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)
Expand Down Expand Up @@ -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();
}

};
18 changes: 18 additions & 0 deletions cores/esp8266/mmu_iram.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/umm_malloc/umm_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/umm_malloc/umm_integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion cores/esp8266/umm_malloc/umm_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 7356cd1

Please sign in to comment.