From 8788c7608c4a828781fcb31867c7235e8a036aee Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 2 Jan 2020 17:28:47 -0800 Subject: [PATCH 1/8] Enable virtual memory 128K+ via external SPI SRAM Provides a transparently accessible additional block of RAM of 128K to 8MB by using an external SPI SRAM. This memory is managed using the UMM memory manager and can be used by the core as if it were internal RAM (albiet much slower to read or write). The use case would be for things which are quite large but not particularly frequently used or compute intensive. For example, the SSL buffers of 16K++ are a good fit for this, as are the contents of Strings (both to avoid main heap fragmentation as well as allowing Strings of >30KB). A fully associative LRU cache is used to limit the SPI bus bottleneck, and background writeback is supported. Requires `ESP.enableVM()` call to actually add the VM subsystem. If this routine is not called, then the entire VM routines should not be linked in to user apps, so there should be no space penalty w/o it. UMM `malloc` and `new` are modified to support internal and external heap regions. By default, everything comes from the standard heap, but a call to `ESP.setExternalHeap()` before the allocation (followed by a call to `ESP.resetHeap()` will make the allocation come from external RAM. See the `virtualmem.ino` example for use. If there is no external RAM installed, the `setExternalHeap` call is a no-op. The String and BearSSL libraries have been modified to use this external RAM automatically. Theory of Operation: The Xtensa core generates a hardware exception (unrelated to C++ exceptions) when an address that's defined as invalid for load or store. The XTOS ROM routines capture the machine state and call a standard C exception handler routine (or the default one which resets the system). We hook into this exception callback and decode the EXCVADDR (the address being accessed) and use the exception PC to read out the faulting instruction. We decode that instruction and simulate it's behavior (i.e. either loading or storing some data to a register/external memory) and then return to the calling application. We use the hardware SPI interface to talk to an external SRAM/PSRAM, and implement a simple cache to minimize the amount of times we need to go out over the (slow) SPI bus. The SPI is set up in a DIO mode which uses no more pins than normal SPI, but provides for ~2X faster transfers. SIO mode is also supported. NOTE: This works fine for processor accesses, but cannot be used by any of the peripherals' DMA. For that, we'd need a real MMU. Hardware Configuration (only use 3.3V compatible SRAMs!): SPI byte-addressible SRAM/PSRAM: 23LC1024 or smaller CS -> GPIO15 SCK -> GPIO14 MOSI -> GPIO13 MISO -> GPIO12 (note these are GPIO numbers, not the Arduino Dxx pin names. Refer to your ESP8266 board schematic for the mapping of GPIO to pin.) Higher density PSRAM (ESP-PSRAM64H/etc.) should work as well, but I'm still waiting on my chips so haven't done any testing. Biggest concern is their command set and functionality in DIO mode. If DIO mode isn't supported, then a fallback to SIO is possible. This PR originated with code from @pvvx's esp8266web server at https://github.com/pvvx/esp8266web (licensed in the public domain) but doesn't resemble it much any more. Thanks, @pvvx! Keep a list of the last 8 lines in RAM (~.5KB of RAM) and use that to speed up things like memcpys and other operations where the source and destination addresses are inside VM RAM. A custom set of SPI routines is used in the VM system for speed and code size (and because the core cannot be dependent on a library). --- cores/esp8266/Esp.cpp | 27 ++ cores/esp8266/Esp.h | 7 + cores/esp8266/StackThunk.cpp | 3 + cores/esp8266/WString.cpp | 2 + cores/esp8266/core_esp8266_vm.cpp | 407 ++++++++++++++++++ cores/esp8266/core_esp8266_vm.h | 11 + cores/esp8266/esp8266_undocumented.h | 39 ++ cores/esp8266/umm_malloc/umm_malloc.cpp | 144 +++++++ cores/esp8266/umm_malloc/umm_malloc.h | 7 + .../src/WiFiClientSecureBearSSL.cpp | 7 + libraries/LittleFS/lib/littlefs | 2 +- .../examples/virtualmem/virtualmem.ino | 140 ++++++ libraries/esp8266/keywords.txt | 4 + tests/host/common/MockEsp.cpp | 12 + tools/sdk/ssl/bearssl | 2 +- 15 files changed, 812 insertions(+), 2 deletions(-) create mode 100644 cores/esp8266/core_esp8266_vm.cpp create mode 100644 cores/esp8266/core_esp8266_vm.h create mode 100644 libraries/esp8266/examples/virtualmem/virtualmem.ino diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 04c83518f6..0578dbff94 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -27,6 +27,8 @@ #include "umm_malloc/umm_malloc.h" #include "cont.h" #include "coredecls.h" +#include "umm_malloc/umm_malloc.h" +#include "core_esp8266_vm.h" extern "C" { #include "user_interface.h" @@ -695,3 +697,28 @@ String EspClass::getSketchMD5() result = md5.toString(); return result; } + +void EspClass::enableVM() +{ + if (!vmEnabled) + install_vm_exception_handler(); + vmEnabled = true; +} + +void EspClass::setExternalHeap() +{ + if (vmEnabled) + umm_push_heap(UMM_HEAP_EXTERNAL); +} + +void EspClass::setInternalHeap() +{ + if (vmEnabled) + umm_push_heap(UMM_HEAP_INTERNAL); +} + +void EspClass::resetHeap() +{ + if (vmEnabled) + umm_pop_heap(); +} diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index f4529c839a..5e3178195b 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -198,6 +198,13 @@ class EspClass { #else uint32_t getCycleCount(); #endif + + void enableVM(); + void setExternalHeap(); + void setInternalHeap(); + void resetHeap(); +private: + bool vmEnabled = false; }; #ifndef CORE_MOCK diff --git a/cores/esp8266/StackThunk.cpp b/cores/esp8266/StackThunk.cpp index 89294d3902..ed25282687 100644 --- a/cores/esp8266/StackThunk.cpp +++ b/cores/esp8266/StackThunk.cpp @@ -28,6 +28,7 @@ #include #include "StackThunk.h" #include +#include extern "C" { @@ -45,7 +46,9 @@ void stack_thunk_add_ref() { stack_thunk_refcnt++; if (stack_thunk_refcnt == 1) { + ESP.setInternalHeap(); stack_thunk_ptr = (uint32_t *)malloc(_stackSize * sizeof(uint32_t)); + ESP.resetHeap(); stack_thunk_top = stack_thunk_ptr + _stackSize - 1; stack_thunk_save = NULL; stack_thunk_repaint(); diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 7b9d9db934..ec67f574d8 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -179,7 +179,9 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) { return false; } uint16_t oldLen = len(); + ESP.setExternalHeap(); char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize); + ESP.resetHeap(); if (newbuffer) { size_t oldSize = capacity() + 1; // include NULL. if (isSSO()) { diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp new file mode 100644 index 0000000000..7416b8f466 --- /dev/null +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -0,0 +1,407 @@ +/* + core_esp8266_vm - Implements logic to enable external SRAM/PSRAM to be used + as if it were on-chip memory by code. + + Copyright (c) 2020 Earle F. Philhower, III All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + + The original exception handler idea was taken from @pvvx's public domain + misaligned-flash-read exception handler, available here: + https://github.com/pvvx/esp8266web/blob/master/app/sdklib/system/app_main.c + + + Theory of Operation: + + The Xtensa core generates a hardware exception (unrelated to C++ exceptions) + when an address that's defined as invalid for load or store. The XTOS ROM + routines capture the machine state and call a standard C exception handler + routine (or the default one which resets the system). + + We hook into this exception callback and decode the EXCVADDR (the address + being accessed) and use the exception PC to read out the faulting + instruction. We decode that instruction and simulate it's behavior + (i.e. either loading or storing some data to a register/external memory) + and then return to the calling application. + + We use the hardware SPI interface to talk to an external SRAM/PSRAM, and + implement a simple cache to minimize the amount of times we actually need + to go out over the (slow) SPI bus. The SPI is set up in a DIO mode which + uses no more pins than normal SPI, but provides for ~2X faster transfers. + + NOTE: This works fine for processor accesses, but cannot be used by any + of the peripherals' DMA. For that, we'd need a real MMU. + + Hardware Configuration (make sure you have 3.3V compatible SRAMs): + * SPI interfaced byte-addressible SRAM/PSRAM: 24LC1024 or smaller + CS -> GPIO15 + SCK -> GPIO14 + MOSI -> GPIO13 + MISO -> GPIO12 + (note these are GPIO numbers, not the Arduion Dxx ones. Refer to your + ESP8266 board schematic for the mapping of GPIO to pin.) + * Higher density PSRAM (ESP-PSRAM64H/etc.) should work as well, but I'm + still waiting on my chips so haven't done any testing. Biggest concern + is their command set and functionality in DIO mode. If DIO mode isn't + supported, then a fallback to SIO or moving to QIO is a possibility. + +*/ + + + +#include +#include +#include "esp8266_peri.h" +#include "core_esp8266_vm.h" +#include "umm_malloc/umm_malloc.h" + + +extern "C" { + +#define SHORT_MASK 0x000008u +#define LOAD_MASK 0x00f00fu +#define L8UI_MATCH 0x000002u +#define L16UI_MATCH 0x001002u +#define L16SI_MATCH 0x009002u +#define L16_MASK 0x001000u +#define SIGNED_MASK 0x008000u +#define L32IN_MATCH 0x000008u +#define L32I_MATCH 0x002002u +#define L32R_MATCH 0x000001u +#define L32_MASK 0x002009u + +#define STORE_MASK 0x00f00fu +#define S8I_MATCH 0x004002u +#define S16I_MATCH 0x005002u +#define S16_MASK 0x001000u +#define S32I_MATCH 0x006002u +#define S32IN_MATCH 0x000009u +#define S32_MASK 0x002001u + +#define EXCCAUSE_LOAD_PROHIBITED 28 // Cache Attribute does not allow Load +#define EXCCAUSE_STORE_PROHIBITED 29 // Cache Attribute does not allow Store +#define EXCCAUSE_STORE_MASK 1 // Fast way of deciding if it's a ld or s that faulted + +// MINI SPI implementation inlined to have max performance and minimum code +// bloat. Can't include a library (SPI) in the core, anyway. + +// Place in a struct so hopefully compiler will generate smaller, base+offset +// based code to access it +typedef struct { + volatile uint32_t spi_cmd; // The SPI can change this behind our backs, so volatile! + uint32_t spi_addr; + uint32_t spi_ctrl; + uint32_t spi_ctrl1; // undocumented? Not shown in the reg map + uint32_t spi_rd_status; + uint32_t spi_ctrl2; + uint32_t spi_clock; + uint32_t spi_user; + uint32_t spi_user1; + uint32_t spi_user2; + uint32_t spi_wr_status; + uint32_t spi_pin; + uint32_t spi_slave; + uint32_t spi_slave1; + uint32_t spi_slave2; + uint32_t spi_slave3; + uint32_t spi_w[16]; // NOTE: You need a memory barrier before reading these after a read xaction + uint32_t spi_ext3; +} spi_regs; + +// The standard HSPI bus pins are used +constexpr uint8_t cs = 15; +constexpr uint8_t miso = 12; +constexpr uint8_t mosi = 13; +constexpr uint8_t sck = 14; + +#define DECLARE_SPI1 spi_regs *spi1 = (spi_regs*)&SPI1CMD + +constexpr uint32_t spi_clkval = 0x00041001; // 5MHz = 0x001c1001 10 = 0x000c1001 20 = 0x00041001 30 = 0x00002001 40 = 0x00001001 + +typedef enum { sio = 0, dio = 1 } iotype; +constexpr iotype hspi_mode = dio; + +constexpr int read_delay = (hspi_mode == dio) ? 4-1 : 0; + +constexpr int cache_ways = 4; // N-way, fully associative cache +constexpr int cache_words = 16; // Must be 16 words or smaller to fit in SPI buffer + +static struct cache_line { + int32_t addr; // Address, lower bits masked off + int dirty; // Needs writeback + struct cache_line *next; // We'll keep linked list in MRU order + union { + uint32_t w[cache_words]; + uint16_t s[cache_words * 2]; + uint8_t b[cache_words * 4]; + }; +} __vm_cache_line[cache_ways]; +static struct cache_line *__vm_cache; // Always points to MRU (hence the line being read/written) + +constexpr int addrmask = ~(sizeof(__vm_cache[0].w)-1); // Helper to mask off bits present in cache entry + + +static void spi_init(spi_regs *spi1) +{ + pinMode(sck, SPECIAL); + pinMode(miso, SPECIAL); + pinMode(mosi, SPECIAL); + pinMode(cs, SPECIAL); + spi1->spi_cmd = 0; + GPMUX &= ~(1 << 9); + spi1->spi_clock = spi_clkval; + spi1->spi_ctrl = 0 ; // MSB first + plain SPI mode + spi1->spi_ctrl1 = 0; // undocumented, clear for safety? + spi1->spi_ctrl2 = 0; // No add'l delays on signals + spi1->spi_user2 = 0; // No insn or insn_bits to set +} + +// Note: GCC optimization -O2 and -O3 tried and returned *slower* code than the default + +// The SPI hardware cannot make the "command" portion dual or quad, only the addr and data +// So using the command portion of the cycle will not work. Comcatenate the address +// and command into a single 32-bit chunk "address" which will be sent across both bits. + +inline ICACHE_RAM_ATTR void spi_writetransaction(spi_regs *spi1, int addr, int addr_bits, int dummy_bits, int data_bits, iotype dual) +{ + // Ensure no writes are still ongoing + while (spi1->spi_cmd & SPIBUSY) { /* busywait */ } + + spi1->spi_addr = addr; + spi1->spi_user = (addr_bits? SPIUADDR : 0) | (dummy_bits ? SPIUDUMMY : 0) | (data_bits ? SPIUMOSI : 0) | (dual ? SPIUFWDIO : 0); + spi1->spi_user1 = (addr_bits << 26) | (data_bits << 17) | dummy_bits; + // No need to set spi_user2, insn field never used + __asm ( "" ::: "memory" ); + spi1->spi_cmd = SPIBUSY; + // The write may continue on in the background, letting core do useful work instead of waiting, unless we're in cacheless mode + if (cache_ways == 0) { + while (spi1->spi_cmd & SPIBUSY) { /* busywait */ } + } +} + +inline ICACHE_RAM_ATTR uint32_t spi_readtransaction(spi_regs *spi1, int addr, int addr_bits, int dummy_bits, int data_bits, iotype dual) +{ + // Ensure no writes are still ongoing + while (spi1->spi_cmd & SPIBUSY) { /* busywait */ } + + spi1->spi_addr = addr; + spi1->spi_user = (addr_bits? SPIUADDR : 0) | (dummy_bits ? SPIUDUMMY : 0) | SPIUMISO | (dual ? SPIUFWDIO : 0); + spi1->spi_user1 = (addr_bits << 26) | (data_bits << 8) | dummy_bits; + // No need to set spi_user2, insn field never used + __asm ( "" ::: "memory" ); + spi1->spi_cmd = SPIBUSY; + while (spi1->spi_cmd & SPIBUSY) { /* busywait */ } + __asm ( "" ::: "memory" ); + return spi1->spi_w[0]; +} + +static inline ICACHE_RAM_ATTR void cache_flushrefill(spi_regs *spi1, int addr) +{ + addr &= addrmask; + struct cache_line *way = __vm_cache; + + if (__vm_cache->addr == addr) return; // Fast case, it already is the MRU + struct cache_line *last = way; + way = way->next; + + for (auto i = 1; i < cache_ways; i++) { + if (way->addr == addr) { + last->next = way->next; + way->next = __vm_cache; + __vm_cache = way; + return; + } else { + last = way; + way = way->next; + } + } + + // At this point we know the line is not in the cache and way points to the LRU. + + // We allow reads to go before writes since the write can happen in the background. + // We need to keep the data to be written back since it will be overwritten with read data + uint32_t wb[cache_words]; + if (last->dirty) { + memcpy(wb, last->w, sizeof(last->w)); + } + + // Update MRU info, list + last->next = __vm_cache; + __vm_cache = last; + + // Do the actual read + spi_readtransaction(spi1, (0x03 << 24) | addr, 32-1, read_delay, sizeof(last->w) * 8 - 1, hspi_mode); + memcpy(last->w, spi1->spi_w, sizeof(last->w)); + + // We fire a background writeback now, if needed + if (last->dirty) { + memcpy(spi1->spi_w, wb, sizeof(wb)); + spi_writetransaction(spi1, (0x02 << 24) | last->addr, 32-1, 0, sizeof(last->w) * 8 - 1, hspi_mode); + last->dirty = 0; + } + + // Update the addr at this point since we no longer need the old one + last->addr = addr; +} + +static inline ICACHE_RAM_ATTR void spi_ramwrite(spi_regs *spi1, int addr, int data_bits, uint32_t val) +{ + if (cache_ways == 0) { + spi1->spi_w[0] = val; + spi_writetransaction(spi1, (0x02<<24) | addr, 32-1, 0, data_bits, hspi_mode); + } else { + cache_flushrefill(spi1, addr); + __vm_cache->dirty = 1; + addr -= __vm_cache->addr; + switch (data_bits) { + case 31: __vm_cache->w[addr >> 2] = val; break; + case 7: __vm_cache->b[addr] = val; break; + default: __vm_cache->s[addr >> 1] = val; break; + } + } +} + +static inline ICACHE_RAM_ATTR uint32_t spi_ramread(spi_regs *spi1, int addr, int data_bits) +{ + if (cache_ways == 0) { + spi1->spi_w[0] = 0; + return spi_readtransaction(spi1, (0x03 << 24) | addr, 32-1, read_delay, data_bits, hspi_mode); + } else { + cache_flushrefill(spi1, addr); + addr -= __vm_cache->addr; + switch (data_bits) { + case 31: return __vm_cache->w[addr >> 2]; + case 7: return __vm_cache->b[addr]; + default: return __vm_cache->s[addr >> 1]; + } + } +} + +static void (*__old_handler)(struct __exception_frame *ef, uint32_t cause); + +static ICACHE_RAM_ATTR void loadstore_exception_handler(struct __exception_frame *ef, uint32_t cause) +{ + uint32_t epc1 = ef->epc; + uint32_t excvaddr; + uint32_t insn; + + __asm ( + "rsr %0, EXCVADDR;" // read out the faulting address + "movi a4, ~3;" // prepare a mask for the EPC + "and a4, a4, %2;" // apply mask for 32bit aligned base + "l32i a5, a4, 0;" // load part 1 + "l32i a6, a4, 4;" // load part 2 + "ssa8l %2;" // set up shift register for src op + "src %1, a6, a5;" // right shift to get faulting instruction + :"=r"(excvaddr), "=r"(insn) + :"r"(epc1) + :"a4", "a5", "a6" + ); + + // Check that we're really accessing VM and not some other illegal range + if ((excvaddr >> 28) != 1) { + // Reinstall the old handler, and retry the instruction to keep us out of the stack dump + _xtos_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, __old_handler); + _xtos_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, __old_handler); + return; + } + + DECLARE_SPI1; + ef->epc += (insn & SHORT_MASK) ? 2 : 3; // resume at following instruction + + int regno = (insn & 0x0000f0u) >> 4; + if (regno != 0) --regno; // account for skipped a1 in exception_frame + + if (cause & EXCCAUSE_STORE_MASK) { + uint32_t val = ef->a_reg[regno]; + uint32_t what = insn & STORE_MASK; + if (what == S8I_MATCH) { + spi_ramwrite(spi1, excvaddr & 0x1ffff, 8-1, val); + } else if (what == S16I_MATCH) { + spi_ramwrite(spi1, excvaddr & 0x1ffff, 16-1, val); + } else { + spi_ramwrite(spi1, excvaddr & 0x1ffff, 32-1, val); + } + } else { + if (insn & L32_MASK) { + ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 32-1); + } else if (insn & L16_MASK) { + ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 16-1); + if ((insn & SIGNED_MASK ) && (ef->a_reg[regno] & 0x8000)) + ef->a_reg[regno] |= 0xffff0000; + } else { + ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 8-1); + } + } +} + +void install_vm_exception_handler() +{ + // There is no way to get the current exception handler via an API, so pull it + // out using the decoded ROM dump which points to 0x3fffc100 as the start of + // the XTOS exception table (of C-callable functions) + uint32_t old = *(uint32_t*)(0x3fffc100 + EXCCAUSE_LOAD_PROHIBITED * 4); + __old_handler = (void (*)(struct __exception_frame *ef, uint32_t cause))old; + _xtos_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, loadstore_exception_handler); + _xtos_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, loadstore_exception_handler); + + DECLARE_SPI1; + + // Manually reset chip from DIO to SIO mode (HW SPI has issues with <8 bits/clocks total output) + digitalWrite(cs, HIGH); + digitalWrite(mosi, HIGH); + digitalWrite(miso, HIGH); + digitalWrite(sck, LOW); + pinMode(cs, OUTPUT); + pinMode(miso, OUTPUT); + pinMode(mosi, OUTPUT); + pinMode(sck, OUTPUT); + digitalWrite(cs, LOW); + for (int i = 0; i < 4; i++) { + digitalWrite(sck, HIGH); + digitalWrite(sck, LOW); + } + digitalWrite(cs, HIGH); + + // Set up the SPI regs + spi_init(spi1); + + // Enable streaming read/write mode + spi1->spi_w[0] = 0x40; + spi_writetransaction(spi1, 0x01<<24, 8-1, 0, 8-1, sio); + + if (hspi_mode == dio) { + // Ramp up to DIO mode + spi_writetransaction(spi1, 0x3b<<24, 8-1, 0, 0, sio); + spi1->spi_ctrl |= SPICDIO | SPICFASTRD; + } + + // Bring cache structures to baseline + if (cache_ways > 0) { + for (auto i = 0; i < cache_ways; i++) { + __vm_cache_line[i].addr = -1; // Invalid, bits set in lower region so will never hatch + __vm_cache_line[i].next = &__vm_cache_line[i+1]; + } + __vm_cache = &__vm_cache_line[0]; + __vm_cache_line[cache_ways - 1].next = NULL; + } + + // Hook into memory manager + umm_init_vm( (void *)0x10000000, 0x20000); +} + + +}; diff --git a/cores/esp8266/core_esp8266_vm.h b/cores/esp8266/core_esp8266_vm.h new file mode 100644 index 0000000000..94681a7eeb --- /dev/null +++ b/cores/esp8266/core_esp8266_vm.h @@ -0,0 +1,11 @@ +#ifdef __cplusplus +extern "C" { +#endif + +extern void install_vm_exception_handler(); + + +#ifdef __cplusplus +}; +#endif + diff --git a/cores/esp8266/esp8266_undocumented.h b/cores/esp8266/esp8266_undocumented.h index 22216d962a..31f872c399 100644 --- a/cores/esp8266/esp8266_undocumented.h +++ b/cores/esp8266/esp8266_undocumented.h @@ -1,5 +1,8 @@ // ROM and blob calls without official headers available +#ifndef __ESP8266_UNDOCUMENTED_H +#define __ESP8266_UNDOCUMENTED_H + #ifdef __cplusplus extern "C" { #endif @@ -34,6 +37,42 @@ extern int ets_uart_printf(const char *format, ...) __attribute__ ((format (prin extern void ets_delay_us(uint32_t us); +/* The Xtensa OS code in ROM for handling hardware exceptions */ +struct __exception_frame +{ + uint32_t epc; + uint32_t ps; + uint32_t sar; + uint32_t unused; + union { + struct { + uint32_t a0; + // note: no a1 here! + uint32_t a2; + uint32_t a3; + uint32_t a4; + uint32_t a5; + uint32_t a6; + uint32_t a7; + uint32_t a8; + uint32_t a9; + uint32_t a10; + uint32_t a11; + uint32_t a12; + uint32_t a13; + uint32_t a14; + uint32_t a15; + }; + uint32_t a_reg[15]; + }; + uint32_t cause; +}; + +extern void _xtos_set_exception_handler(uint32_t reason, void (*fn)(struct __exception_frame *ef, uint32_t cause)); +extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause); + #ifdef __cplusplus }; #endif + +#endif diff --git a/cores/esp8266/umm_malloc/umm_malloc.cpp b/cores/esp8266/umm_malloc/umm_malloc.cpp index 5feaa2edea..a503a74ca5 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.cpp +++ b/cores/esp8266/umm_malloc/umm_malloc.cpp @@ -86,9 +86,112 @@ UMM_H_ATTPACKPRE typedef struct umm_block_t { /* ------------------------------------------------------------------------- */ +/* Points to the currently active heap */ umm_block *umm_heap = NULL; unsigned short int umm_numblocks = 0; +/* Copies of the globals from both heaps */ +static umm_block *umm_heap_internal = NULL; +static unsigned short int umm_numblocks_internal = 0; + +static umm_block *umm_heap_external = NULL; +static unsigned short int umm_numblocks_external = 0; + +#ifdef UMM_INFO +extern UMM_HEAP_INFO ummHeapInfo; +static UMM_HEAP_INFO ummHeapInfo_internal; +static UMM_HEAP_INFO ummHeapInfo_external; +#endif + +#if defined(UMM_STATS) || defined(UMM_STATS_FULL) +extern UMM_STATISTICS ummStats; +static UMM_STATISTICS ummStats_internal; +static UMM_STATISTICS ummStats_external; +#endif + +/* A stack allowing push/popping of heaps for library use */ +static int umm_heap_cur = UMM_HEAP_INTERNAL; +#define UMM_HEAP_STACK_DEPTH 32 +static int umm_heap_stack_ptr = 0; +static char umm_heap_stack[UMM_HEAP_STACK_DEPTH]; + +/* ------------------------------------------------------------------------ */ +/* + * Swap globals to a specific heap. No-op if we're already in that heap. + * + * Uses memcpy() instead of pointer assignment to minimize code changes + * elsewhere in this and other files. + */ + +void umm_set_heap( int which ) { + if (which != umm_heap_cur) { + if (umm_heap_cur == UMM_HEAP_INTERNAL) { /* Moving to external */ + umm_heap = umm_heap_external; + umm_numblocks = umm_numblocks_external; + +#ifdef UMM_INFO + memcpy(&ummHeapInfo_internal, &ummHeapInfo, sizeof(ummHeapInfo)); + memcpy(&ummHeapInfo, &ummHeapInfo_external, sizeof(ummHeapInfo)); +#endif + +#if defined(UMM_STATS) || defined(UMM_STATS_FULL) + memcpy(&ummStats_internal, &ummStats, sizeof(ummStats)); + memcpy(&ummStats, &ummStats_external, sizeof(ummStats)); +#endif + } else { /* Moving to internal */ + umm_heap = umm_heap_internal; + umm_numblocks = umm_numblocks_internal; + +#ifdef UMM_INFO + memcpy(&ummHeapInfo_external, &ummHeapInfo, sizeof(ummHeapInfo)); + memcpy(&ummHeapInfo, &ummHeapInfo_internal, sizeof(ummHeapInfo)); +#endif + +#if defined(UMM_STATS) || defined(UMM_STATS_FULL) + memcpy(&ummStats_external, &ummStats, sizeof(ummStats)); + memcpy(&ummStats, &ummStats_internal, sizeof(ummStats)); +#endif + } + umm_heap_cur = which; + } + +} + +/* ------------------------------------------------------------------------ */ + +void umm_push_heap( int which ) { + if (umm_heap_stack_ptr < UMM_HEAP_STACK_DEPTH) { + umm_heap_stack[umm_heap_stack_ptr++] = umm_heap_cur; + umm_set_heap( which ); + } +} + +/* ------------------------------------------------------------------------ */ + +void umm_pop_heap( void ) { + if (umm_heap_stack_ptr > 0 ) { + umm_set_heap(umm_heap_stack[--umm_heap_stack_ptr]); + } +} + +/* ------------------------------------------------------------------------ */ +/* + * Pushes a heap change to the right heap for a given pointer. Useful for + * realloc or free since you may not be in the right heap to handle it. + * + * After doing the required work, be sure to call umm_pop_heap() to return + * back to the original heap in use. + */ +void umm_push_heap_to_ptr( void *ptr ) { + if ( umm_heap_external && ( ptr >= (void *)umm_heap_external ) && + ( (umm_block *)ptr <= umm_heap_external + umm_numblocks_external ) ) { + umm_push_heap( UMM_HEAP_EXTERNAL ); + } else { + umm_push_heap( UMM_HEAP_INTERNAL ); + } +} + + #define UMM_NUMBLOCKS (umm_numblocks) /* ------------------------------------------------------------------------ */ @@ -214,12 +317,43 @@ static unsigned short int umm_assimilate_down( unsigned short int c, unsigned sh /* ------------------------------------------------------------------------- */ +static void umm_init_stage_2( void ); + void umm_init( void ) { /* init heap pointer and size, and memset it to 0 */ umm_heap = (umm_block *)UMM_MALLOC_CFG_HEAP_ADDR; umm_numblocks = (UMM_MALLOC_CFG_HEAP_SIZE / sizeof(umm_block)); memset(umm_heap, 0x00, UMM_MALLOC_CFG_HEAP_SIZE); + /* Save the current internal heap */ + umm_heap_internal = umm_heap; + umm_numblocks_internal = umm_numblocks; + /* Set up internal data structures */ + umm_init_stage_2(); +} + +void umm_init_vm( void *vmaddr, unsigned int vmsize ) { + /* We need the main, internal heap set up first */ + if (!umm_heap) + umm_init(); + + /* Preserve internal setup */ + umm_set_heap(UMM_HEAP_EXTERNAL); + + /* Init the external SRAM as heap */ + umm_heap = (umm_block *)vmaddr; + umm_numblocks = (vmsize / sizeof(umm_block)); + memset(umm_heap, 0x00, vmsize); + umm_init_stage_2(); + /* Save the newly generated external heap */ + umm_heap_external = umm_heap; + umm_numblocks_external = umm_numblocks; + + /* Return to the main heap until further notice */ + umm_set_heap(UMM_HEAP_INTERNAL); +} + +static void umm_init_stage_2( void ) { /* setup initial blank heap structure */ { /* index of the 0th `umm_block` */ @@ -357,8 +491,14 @@ void umm_free( void *ptr ) { UMM_CRITICAL_ENTRY(id_free); + /* Need to be in the heap in which this block lives */ + umm_push_heap_to_ptr( ptr); + umm_free_core( ptr ); + /* Restore to the old heap */ + umm_pop_heap(); + UMM_CRITICAL_EXIT(id_free); } @@ -563,6 +703,8 @@ void *umm_realloc( void *ptr, size_t size ) { STATS__ALLOC_REQUEST(id_realloc, size); + umm_push_heap_to_ptr( ptr ); + /* * Otherwise we need to actually do a reallocation. A naiive approach * would be to malloc() a new block of the correct size, copy the old data @@ -806,6 +948,8 @@ void *umm_realloc( void *ptr, size_t size ) { STATS__FREE_BLOCKS_MIN(); + umm_pop_heap(); + /* Release the critical section... */ UMM_CRITICAL_EXIT(id_realloc); diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 4c68b72027..71e0a69915 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -18,11 +18,18 @@ extern "C" { #endif void umm_init( void ); +void umm_init_vm( void *vmaddr, unsigned int vmsize ); void *umm_malloc( size_t size ); void *umm_calloc( size_t num, size_t size ); void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); +void umm_push_heap( int heap_number ); +void umm_pop_heap( void ); + +#define UMM_HEAP_INTERNAL 0 +#define UMM_HEAP_EXTERNAL 1 + #ifdef __cplusplus } #endif diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 773f68cfdc..baff2b9965 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -25,6 +25,7 @@ #include #include #include +#include extern "C" { #include "osapi.h" @@ -1067,8 +1068,10 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) { _sc = std::make_shared(); _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr + ESP.setExternalHeap(); _iobuf_in = std::shared_ptr(new unsigned char[_iobuf_in_size], std::default_delete()); _iobuf_out = std::shared_ptr(new unsigned char[_iobuf_out_size], std::default_delete()); + ESP.resetHeap(); if (!_sc || !_iobuf_in || !_iobuf_out) { _freeSSL(); // Frees _sc, _iobuf* @@ -1183,8 +1186,10 @@ bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain, _oom_err = false; _sc_svr = std::make_shared(); _eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr + ESP.setExternalHeap(); _iobuf_in = std::shared_ptr(new unsigned char[_iobuf_in_size], std::default_delete()); _iobuf_out = std::shared_ptr(new unsigned char[_iobuf_out_size], std::default_delete()); + ESP.resetHeap(); if (!_sc_svr || !_iobuf_in || !_iobuf_out) { _freeSSL(); @@ -1220,8 +1225,10 @@ bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain, _oom_err = false; _sc_svr = std::make_shared(); _eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr + ESP.setExternalHeap(); _iobuf_in = std::shared_ptr(new unsigned char[_iobuf_in_size], std::default_delete()); _iobuf_out = std::shared_ptr(new unsigned char[_iobuf_out_size], std::default_delete()); + ESP.resetHeap(); if (!_sc_svr || !_iobuf_in || !_iobuf_out) { _freeSSL(); diff --git a/libraries/LittleFS/lib/littlefs b/libraries/LittleFS/lib/littlefs index ce2c01f098..6b65737715 160000 --- a/libraries/LittleFS/lib/littlefs +++ b/libraries/LittleFS/lib/littlefs @@ -1 +1 @@ -Subproject commit ce2c01f098f4d2b9479de5a796c3bb531f1fe14c +Subproject commit 6b65737715039ef92d348014316b575b52547019 diff --git a/libraries/esp8266/examples/virtualmem/virtualmem.ino b/libraries/esp8266/examples/virtualmem/virtualmem.ino new file mode 100644 index 0000000000..c97d2cac33 --- /dev/null +++ b/libraries/esp8266/examples/virtualmem/virtualmem.ino @@ -0,0 +1,140 @@ + +uint32_t cyclesToRead1Kx32(unsigned int *x, uint32_t *res) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += *(x++); + } + *res = sum; + return ESP.getCycleCount() - b; +} + +uint32_t cyclesToWrite1Kx32(unsigned int *x) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += i; + *(x++) = sum; + } + return ESP.getCycleCount() - b; +} + + +uint32_t cyclesToRead1Kx16(unsigned short *x, uint32_t *res) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += *(x++); + } + *res = sum; + return ESP.getCycleCount() - b; +} + +uint32_t cyclesToWrite1Kx16(unsigned short *x) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += i; + *(x++) = sum; + } + return ESP.getCycleCount() - b; +} + +uint32_t cyclesToRead1Kx8(unsigned char*x, uint32_t *res) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += *(x++); + } + *res = sum; + return ESP.getCycleCount() - b; +} + +uint32_t cyclesToWrite1Kx8(unsigned char*x) { + uint32_t b = ESP.getCycleCount(); + uint32_t sum = 0; + for (int i = 0; i < 1024; i++) { + sum += i; + *(x++) = sum; + } + return ESP.getCycleCount() - b; +} + +void setup() { + Serial.begin(115200); + Serial.printf("\n"); + + ESP.enableVM(); // Start up the VM handler, set up the memory manager, etc. + + // Enabling VM does not change malloc to use the external region. It will continue to + // use the normal RAM until we request otherwise. + uint32_t *mem = (uint32_t *)malloc(1024 * sizeof(uint32_t)); + Serial.printf("Internal buffer: Address %p, free %d\n", mem, ESP.getFreeHeap()); + + // Now request from the VM heap + ESP.setExternalHeap(); + uint32_t *vm = (uint32_t *)malloc(1024 * sizeof(uint32_t)); + Serial.printf("External buffer: Address %p, free %d\n", vm, ESP.getFreeHeap()); + // Make sure we go back to the internal heap for other allocations. Don't forget to ESP.resetHeap()! + ESP.resetHeap(); + + uint32_t res; + uint32_t t; + t = cyclesToWrite1Kx32(vm); + Serial.printf("Virtual Memory Write: %d cycles for 4K\n", t); + t = cyclesToWrite1Kx32(mem); + Serial.printf("Physical Memory Write: %d cycles for 4K\n", t); + + t = cyclesToRead1Kx32(vm, &res); + Serial.printf("Virtual Memory Read: %d cycles for 4K (sum %08x)\n", t, res); + t = cyclesToRead1Kx32(mem, &res); + Serial.printf("Physical Memory Read: %d cycles for 4K (sum %08x)\n", t, res); + + t = cyclesToWrite1Kx16((uint16_t*)vm); + Serial.printf("Virtual Memory Write: %d cycles for 2K by 16\n", t); + t = cyclesToWrite1Kx16((uint16_t*)mem); + Serial.printf("Physical Memory Write: %d cycles for 2K by 16\n", t); + + t = cyclesToRead1Kx16((uint16_t*)vm, &res); + Serial.printf("Virtual Memory Read: %d cycles for 2K by 16 (sum %08x)\n", t, res); + t = cyclesToRead1Kx16((uint16_t*)mem, &res); + Serial.printf("Physical Memory Read: %d cycles for 2K by 16 (sum %08x)\n", t, res); + + t = cyclesToWrite1Kx8((uint8_t*)vm); + Serial.printf("Virtual Memory Write: %d cycles for 1K by 8\n", t); + t = cyclesToWrite1Kx8((uint8_t*)mem); + Serial.printf("Physical Memory Write: %d cycles for 1K by 8\n", t); + + t = cyclesToRead1Kx8((uint8_t*)vm, &res); + Serial.printf("Virtual Memory Read: %d cycles for 1K by 8 (sum %08x)\n", t, res); + t = cyclesToRead1Kx8((uint8_t*)mem, &res); + Serial.printf("Physical Memory Read: %d cycles for 1K by 8 (sum %08x)\n", t, res); + + // Let's use external heap to make a big ole' String + ESP.setExternalHeap(); + String s = ""; + for (int i = 0; i < 100; i++) { + s += i; + s += ' '; + } + ESP.resetHeap(); + Serial.printf("Internal free: %d\n", ESP.getFreeHeap()); + ESP.setExternalHeap(); + Serial.printf("External free: %d\n", ESP.getFreeHeap()); + ESP.resetHeap(); + Serial.printf("String: %s\n", s.c_str()); + + // Note that free/realloc will all use the heap specified when the pointer was created. + // No need to change heaps to delete an object, only to create it. + free(vm); + free(mem); + + Serial.printf("Internal free: %d\n", ESP.getFreeHeap()); + ESP.setExternalHeap(); + Serial.printf("External free: %d\n", ESP.getFreeHeap()); + ESP.resetHeap(); +} + +void loop() { + +} diff --git a/libraries/esp8266/keywords.txt b/libraries/esp8266/keywords.txt index 902db205c9..a703496544 100644 --- a/libraries/esp8266/keywords.txt +++ b/libraries/esp8266/keywords.txt @@ -60,6 +60,10 @@ getResetInfo KEYWORD2 getResetInfoPtr KEYWORD2 eraseConfig KEYWORD2 getCycleCount KEYWORD2 +enableVM KEYWORD2 +setExternalHeap KEYWORD2 +setInternalHeap KEYWORD2 +resetHeap KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp index c5ca502eda..ad34971189 100644 --- a/tests/host/common/MockEsp.cpp +++ b/tests/host/common/MockEsp.cpp @@ -226,3 +226,15 @@ uint32_t EspClass::getCycleCount() gettimeofday(&t, NULL); return (((uint64_t)t.tv_sec) * 1000000 + t.tv_usec) * (F_CPU / 1000000); } + +void EspClass::setInternalHeap() +{ +} + +void EspClass::setExternalHeap() +{ +} + +void EspClass::resetHeap() +{ +} diff --git a/tools/sdk/ssl/bearssl b/tools/sdk/ssl/bearssl index 0645c68c36..89454af34e 160000 --- a/tools/sdk/ssl/bearssl +++ b/tools/sdk/ssl/bearssl @@ -1 +1 @@ -Subproject commit 0645c68c3653233c4d0e59252cd591a664f808fd +Subproject commit 89454af34e3e61ddfc9837f3da5a0bc8ed44c3aa From e333d504582e14e378bd950a49448315a5b77b17 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Tue, 22 Dec 2020 13:33:23 -0800 Subject: [PATCH 2/8] Don't compile VM code unless using external heap --- cores/esp8266/core_esp8266_vm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index 35ad7db665..ecba57ab38 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -60,7 +60,7 @@ */ - +#ifdef UMM_HEAP_EXTERNAL #include #include @@ -405,3 +405,5 @@ void install_vm_exception_handler() }; + +#endif // ifdef(UMM_HEAP_EXTERNAL) From 5bb31a0ea7283f3e4f266ae287e3d655616d690a Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 9 Jan 2021 12:30:06 -0800 Subject: [PATCH 3/8] Tested and running with latest UMM IRAM heap changes Ran sanity tests successfully on 23LC1024 128K SRAM. Adjusted defines to ensure UMM knows about our heap. --- boards.txt | 136 +++++++++++----------- cores/esp8266/Esp.h | 2 +- cores/esp8266/core_esp8266_vm.cpp | 10 +- cores/esp8266/umm_malloc/umm_malloc_cfg.h | 6 +- tools/boards.txt.py | 4 +- 5 files changed, 82 insertions(+), 76 deletions(-) diff --git a/boards.txt b/boards.txt index 3d394d50f4..d4da3e5563 100644 --- a/boards.txt +++ b/boards.txt @@ -79,9 +79,9 @@ generic.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 generic.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) generic.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 generic.menu.mmu.ext128k=128K External 23LC1024 -generic.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +generic.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 generic.menu.mmu.ext1024k=1M External 64 MBit PSRAM -generic.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +generic.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 generic.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM generic.menu.non32xfer.fast.build.non32xferflags= generic.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -568,9 +568,9 @@ esp8285.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 esp8285.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) esp8285.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 esp8285.menu.mmu.ext128k=128K External 23LC1024 -esp8285.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp8285.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp8285.menu.mmu.ext1024k=1M External 64 MBit PSRAM -esp8285.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp8285.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp8285.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM esp8285.menu.non32xfer.fast.build.non32xferflags= esp8285.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -927,9 +927,9 @@ gen4iod.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 gen4iod.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) gen4iod.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 gen4iod.menu.mmu.ext128k=128K External 23LC1024 -gen4iod.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +gen4iod.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 gen4iod.menu.mmu.ext1024k=1M External 64 MBit PSRAM -gen4iod.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +gen4iod.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 gen4iod.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM gen4iod.menu.non32xfer.fast.build.non32xferflags= gen4iod.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1201,9 +1201,9 @@ huzzah.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x huzzah.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) huzzah.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 huzzah.menu.mmu.ext128k=128K External 23LC1024 -huzzah.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +huzzah.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 huzzah.menu.mmu.ext1024k=1M External 64 MBit PSRAM -huzzah.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +huzzah.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 huzzah.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM huzzah.menu.non32xfer.fast.build.non32xferflags= huzzah.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1408,9 +1408,9 @@ wifi_slot.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE wifi_slot.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) wifi_slot.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 wifi_slot.menu.mmu.ext128k=128K External 23LC1024 -wifi_slot.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifi_slot.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifi_slot.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifi_slot.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifi_slot.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifi_slot.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifi_slot.menu.non32xfer.fast.build.non32xferflags= wifi_slot.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1741,9 +1741,9 @@ arduino-esp8266.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACH arduino-esp8266.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) arduino-esp8266.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 arduino-esp8266.menu.mmu.ext128k=128K External 23LC1024 -arduino-esp8266.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +arduino-esp8266.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 arduino-esp8266.menu.mmu.ext1024k=1M External 64 MBit PSRAM -arduino-esp8266.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +arduino-esp8266.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 arduino-esp8266.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM arduino-esp8266.menu.non32xfer.fast.build.non32xferflags= arduino-esp8266.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1949,9 +1949,9 @@ espmxdevkit.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SI espmxdevkit.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espmxdevkit.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espmxdevkit.menu.mmu.ext128k=128K External 23LC1024 -espmxdevkit.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espmxdevkit.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espmxdevkit.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espmxdevkit.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espmxdevkit.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espmxdevkit.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espmxdevkit.menu.non32xfer.fast.build.non32xferflags= espmxdevkit.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2197,9 +2197,9 @@ oak.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x400 oak.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) oak.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 oak.menu.mmu.ext128k=128K External 23LC1024 -oak.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +oak.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 oak.menu.mmu.ext1024k=1M External 64 MBit PSRAM -oak.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +oak.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 oak.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM oak.menu.non32xfer.fast.build.non32xferflags= oak.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2413,9 +2413,9 @@ espduino.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE= espduino.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espduino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espduino.menu.mmu.ext128k=128K External 23LC1024 -espduino.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espduino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espduino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espduino.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espduino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espduino.menu.non32xfer.fast.build.non32xferflags= espduino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2619,9 +2619,9 @@ espectro.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE= espectro.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espectro.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espectro.menu.mmu.ext128k=128K External 23LC1024 -espectro.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espectro.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espectro.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espectro.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espectro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espectro.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espectro.menu.non32xfer.fast.build.non32xferflags= espectro.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2826,9 +2826,9 @@ espino.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x espino.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espino.menu.mmu.ext128k=128K External 23LC1024 -espino.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espino.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espino.menu.non32xfer.fast.build.non32xferflags= espino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3036,9 +3036,9 @@ espresso_lite_v1.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICAC espresso_lite_v1.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espresso_lite_v1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espresso_lite_v1.menu.mmu.ext128k=128K External 23LC1024 -espresso_lite_v1.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espresso_lite_v1.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espresso_lite_v1.menu.non32xfer.fast.build.non32xferflags= espresso_lite_v1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3246,9 +3246,9 @@ espresso_lite_v2.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICAC espresso_lite_v2.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espresso_lite_v2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espresso_lite_v2.menu.mmu.ext128k=128K External 23LC1024 -espresso_lite_v2.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espresso_lite_v2.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espresso_lite_v2.menu.non32xfer.fast.build.non32xferflags= espresso_lite_v2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3466,9 +3466,9 @@ sonoff.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x sonoff.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) sonoff.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 sonoff.menu.mmu.ext128k=128K External 23LC1024 -sonoff.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +sonoff.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 sonoff.menu.mmu.ext1024k=1M External 64 MBit PSRAM -sonoff.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +sonoff.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 sonoff.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM sonoff.menu.non32xfer.fast.build.non32xferflags= sonoff.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3713,9 +3713,9 @@ inventone.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE inventone.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) inventone.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 inventone.menu.mmu.ext128k=128K External 23LC1024 -inventone.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +inventone.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 inventone.menu.mmu.ext1024k=1M External 64 MBit PSRAM -inventone.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +inventone.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 inventone.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM inventone.menu.non32xfer.fast.build.non32xferflags= inventone.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3920,9 +3920,9 @@ d1_mini.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 d1_mini.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) d1_mini.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 d1_mini.menu.mmu.ext128k=128K External 23LC1024 -d1_mini.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini.menu.non32xfer.fast.build.non32xferflags= d1_mini.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4127,9 +4127,9 @@ d1_mini_lite.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_S d1_mini_lite.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) d1_mini_lite.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 d1_mini_lite.menu.mmu.ext128k=128K External 23LC1024 -d1_mini_lite.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_lite.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_lite.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini_lite.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_lite.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_lite.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini_lite.menu.non32xfer.fast.build.non32xferflags= d1_mini_lite.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4374,9 +4374,9 @@ d1_mini_pro.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SI d1_mini_pro.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) d1_mini_pro.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 d1_mini_pro.menu.mmu.ext128k=128K External 23LC1024 -d1_mini_pro.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_pro.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_pro.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini_pro.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_pro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_pro.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini_pro.menu.non32xfer.fast.build.non32xferflags= d1_mini_pro.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4564,9 +4564,9 @@ d1.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x4000 d1.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) d1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 d1.menu.mmu.ext128k=128K External 23LC1024 -d1.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1.menu.non32xfer.fast.build.non32xferflags= d1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4771,9 +4771,9 @@ nodemcu.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 nodemcu.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) nodemcu.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 nodemcu.menu.mmu.ext128k=128K External 23LC1024 -nodemcu.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcu.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcu.menu.mmu.ext1024k=1M External 64 MBit PSRAM -nodemcu.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcu.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcu.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM nodemcu.menu.non32xfer.fast.build.non32xferflags= nodemcu.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4978,9 +4978,9 @@ nodemcuv2.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE nodemcuv2.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) nodemcuv2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 nodemcuv2.menu.mmu.ext128k=128K External 23LC1024 -nodemcuv2.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcuv2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcuv2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -nodemcuv2.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcuv2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcuv2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM nodemcuv2.menu.non32xfer.fast.build.non32xferflags= nodemcuv2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5189,9 +5189,9 @@ modwifi.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 modwifi.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) modwifi.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 modwifi.menu.mmu.ext128k=128K External 23LC1024 -modwifi.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +modwifi.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 modwifi.menu.mmu.ext1024k=1M External 64 MBit PSRAM -modwifi.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +modwifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 modwifi.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM modwifi.menu.non32xfer.fast.build.non32xferflags= modwifi.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5416,9 +5416,9 @@ phoenix_v1.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZ phoenix_v1.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) phoenix_v1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 phoenix_v1.menu.mmu.ext128k=128K External 23LC1024 -phoenix_v1.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -phoenix_v1.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM phoenix_v1.menu.non32xfer.fast.build.non32xferflags= phoenix_v1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5626,9 +5626,9 @@ phoenix_v2.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZ phoenix_v2.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) phoenix_v2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 phoenix_v2.menu.mmu.ext128k=128K External 23LC1024 -phoenix_v2.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -phoenix_v2.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM phoenix_v2.menu.non32xfer.fast.build.non32xferflags= phoenix_v2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5836,9 +5836,9 @@ eduinowifi.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZ eduinowifi.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) eduinowifi.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 eduinowifi.menu.mmu.ext128k=128K External 23LC1024 -eduinowifi.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +eduinowifi.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 eduinowifi.menu.mmu.ext1024k=1M External 64 MBit PSRAM -eduinowifi.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +eduinowifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 eduinowifi.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM eduinowifi.menu.non32xfer.fast.build.non32xferflags= eduinowifi.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6043,9 +6043,9 @@ wiolink.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 wiolink.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) wiolink.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 wiolink.menu.mmu.ext128k=128K External 23LC1024 -wiolink.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wiolink.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wiolink.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wiolink.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wiolink.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wiolink.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wiolink.menu.non32xfer.fast.build.non32xferflags= wiolink.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6250,9 +6250,9 @@ blynk.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x4 blynk.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) blynk.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 blynk.menu.mmu.ext128k=128K External 23LC1024 -blynk.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +blynk.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 blynk.menu.mmu.ext1024k=1M External 64 MBit PSRAM -blynk.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +blynk.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 blynk.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM blynk.menu.non32xfer.fast.build.non32xferflags= blynk.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6457,9 +6457,9 @@ thing.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x4 thing.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) thing.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 thing.menu.mmu.ext128k=128K External 23LC1024 -thing.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thing.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thing.menu.mmu.ext1024k=1M External 64 MBit PSRAM -thing.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thing.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thing.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM thing.menu.non32xfer.fast.build.non32xferflags= thing.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6664,9 +6664,9 @@ thingdev.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE= thingdev.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) thingdev.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 thingdev.menu.mmu.ext128k=128K External 23LC1024 -thingdev.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thingdev.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thingdev.menu.mmu.ext1024k=1M External 64 MBit PSRAM -thingdev.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thingdev.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thingdev.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM thingdev.menu.non32xfer.fast.build.non32xferflags= thingdev.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6871,9 +6871,9 @@ esp210.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x esp210.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) esp210.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 esp210.menu.mmu.ext128k=128K External 23LC1024 -esp210.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp210.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp210.menu.mmu.ext1024k=1M External 64 MBit PSRAM -esp210.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp210.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp210.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM esp210.menu.non32xfer.fast.build.non32xferflags= esp210.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7078,9 +7078,9 @@ espinotee.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE espinotee.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) espinotee.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 espinotee.menu.mmu.ext128k=128K External 23LC1024 -espinotee.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espinotee.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espinotee.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espinotee.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espinotee.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espinotee.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espinotee.menu.non32xfer.fast.build.non32xferflags= espinotee.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7285,9 +7285,9 @@ wifiduino.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE wifiduino.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) wifiduino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 wifiduino.menu.mmu.ext128k=128K External 23LC1024 -wifiduino.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifiduino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifiduino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifiduino.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifiduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifiduino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifiduino.menu.non32xfer.fast.build.non32xferflags= wifiduino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7509,9 +7509,9 @@ wifinfo.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0 wifinfo.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) wifinfo.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 wifinfo.menu.mmu.ext128k=128K External 23LC1024 -wifinfo.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifinfo.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifinfo.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifinfo.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifinfo.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifinfo.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifinfo.menu.non32xfer.fast.build.non32xferflags= wifinfo.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7763,9 +7763,9 @@ cw01.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x40 cw01.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) cw01.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 cw01.menu.mmu.ext128k=128K External 23LC1024 -cw01.menu.mmu.ext128k.build.mmuflags=-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +cw01.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 cw01.menu.mmu.ext1024k=1M External 64 MBit PSRAM -cw01.menu.mmu.ext1024k.build.mmuflags=-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +cw01.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 cw01.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM cw01.menu.non32xfer.fast.build.non32xferflags= cw01.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 6d990e876b..e2a83ab9cc 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -252,7 +252,7 @@ class EspClass { */ void resetHeap(); private: -#ifdef UMM_HEAP_EXTERNAL +#ifdef MMU_EXTERNAL_HEAP bool vmEnabled = false; #endif /** diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index ecba57ab38..00ba4135a1 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -60,7 +60,7 @@ */ -#ifdef UMM_HEAP_EXTERNAL +#ifdef MMU_EXTERNAL_HEAP #include #include @@ -129,7 +129,9 @@ constexpr uint8_t sck = 14; #define DECLARE_SPI1 spi_regs *spi1 = (spi_regs*)&SPI1CMD -constexpr uint32_t spi_clkval = 0x00041001; // 5MHz = 0x001c1001 10 = 0x000c1001 20 = 0x00041001 30 = 0x00002001 40 = 0x00001001 +typedef enum { spi_5mhz = 0x001c1001, spi_10mhz = 0x000c1001, spi_20mhz = 0x00041001, spi_30mhz = 0x00002001, spi_40mhz = 0x00001001 } spi_clocking; + +constexpr uint32_t spi_clkval = spi_20mhz; typedef enum { sio = 0, dio = 1 } iotype; constexpr iotype hspi_mode = dio; @@ -400,10 +402,10 @@ void install_vm_exception_handler() } // Hook into memory manager - umm_init_vm( (void *)0x10000000, UMM_HEAP_EXTERNAL * 1024); + umm_init_vm( (void *)0x10000000, MMU_EXTERNAL_HEAP * 1024); } }; -#endif // ifdef(UMM_HEAP_EXTERNAL) +#endif diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfg.h b/cores/esp8266/umm_malloc/umm_malloc_cfg.h index 1e5d7f8003..2b038cb2a1 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfg.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfg.h @@ -42,7 +42,11 @@ extern "C" { #undef UMM_HEAP_IRAM #endif -// #define UMM_HEAP_EXTERNAL +#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. diff --git a/tools/boards.txt.py b/tools/boards.txt.py index 592608a19b..ada2fe25de 100755 --- a/tools/boards.txt.py +++ b/tools/boards.txt.py @@ -1212,9 +1212,9 @@ ( '.menu.mmu.3216', '16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared)' ), ( '.menu.mmu.3216.build.mmuflags', '-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000' ), ( '.menu.mmu.ext128k', '128K External 23LC1024' ), - ( '.menu.mmu.ext128k.build.mmuflags', '-DUMM_HEAP_EXTERNAL=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), + ( '.menu.mmu.ext128k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), ( '.menu.mmu.ext1024k', '1M External 64 MBit PSRAM' ), - ( '.menu.mmu.ext1024k.build.mmuflags', '-DUMM_HEAP_EXTERNAL=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), + ( '.menu.mmu.ext1024k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), ]), ######################## Non 32-bit load/store exception handler From 76198586fff795252a5d8f1f78c7f1951ababc5a Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 9 Jan 2021 15:02:47 -0800 Subject: [PATCH 4/8] Unify exception handler logic between non32xfer/vm Use same ASM macro from @mhightower83's non32xfer handler in the VM handler, avoid potential GCC optimization issues. --- cores/esp8266/core_esp8266_non32xfer.cpp | 45 +--------------------- cores/esp8266/core_esp8266_non32xfer.h | 48 ++++++++++++++++++++++++ cores/esp8266/core_esp8266_vm.cpp | 18 ++------- 3 files changed, 54 insertions(+), 57 deletions(-) diff --git a/cores/esp8266/core_esp8266_non32xfer.cpp b/cores/esp8266/core_esp8266_non32xfer.cpp index 0d7bb19196..249af591be 100644 --- a/cores/esp8266/core_esp8266_non32xfer.cpp +++ b/cores/esp8266/core_esp8266_non32xfer.cpp @@ -64,51 +64,10 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cause) { do { - /* - In adapting the public domain version, a crash would come or go away with - the slightest unrelated changes elsewhere in the function. Observed that - register a15 was used for epc1, then clobbered by `rsr.` I now believe a - "&" on the output register would have resolved the problem. - - However, I have refactored the Extended ASM to reduce and consolidate - register usage and corrected the issue. - - The positioning of the Extended ASM block (as early as possible in the - compiled function) is in part controlled by the immediate need for - output variable `insn`. This placement aids in getting excvaddr read as - early as possible. - */ uint32_t insn, excvaddr; -#if 1 - { - uint32_t tmp; - __asm__ ( - "rsr.excvaddr %[vaddr]\n\t" /* Read faulting address as early as possible */ - "movi.n %[tmp], ~3\n\t" /* prepare a mask for the EPC */ - "and %[tmp], %[tmp], %[epc]\n\t" /* apply mask for 32-bit aligned base */ - "ssa8l %[epc]\n\t" /* set up shift register for src op */ - "l32i %[insn], %[tmp], 0\n\t" /* load part 1 */ - "l32i %[tmp], %[tmp], 4\n\t" /* load part 2 */ - "src %[insn], %[tmp], %[insn]\n\t" /* right shift to get faulting instruction */ - : [vaddr]"=&r"(excvaddr), [insn]"=&r"(insn), [tmp]"=&r"(tmp) - : [epc]"r"(ef->epc) :); - } -#else - { - __asm__ __volatile__ ("rsr.excvaddr %0;" : "=r"(excvaddr):: "memory"); - /* - "C" reference code for the ASM to document intent. - May also prove useful when issolating possible issues with Extended ASM, - optimizations, new compilers, etc. - */ - uint32_t epc = ef->epc; - uint32_t *pWord = (uint32_t *)(epc & ~3); - uint64_t big_word = ((uint64_t)pWord[1] << 32) | pWord[0]; - uint32_t pos = (epc & 3) * 8; - insn = (uint32_t)(big_word >>= pos); - } -#endif + /* Extract instruction and faulting data address */ + __EXCEPTION_HANDLER_PREAMBLE(ef, excvaddr, insn); uint32_t what = insn & LOAD_MASK; uint32_t valmask = 0; diff --git a/cores/esp8266/core_esp8266_non32xfer.h b/cores/esp8266/core_esp8266_non32xfer.h index 93151239c4..83f8a06cf7 100644 --- a/cores/esp8266/core_esp8266_non32xfer.h +++ b/cores/esp8266/core_esp8266_non32xfer.h @@ -7,6 +7,54 @@ extern "C" { extern void install_non32xfer_exception_handler(); + + /* + In adapting the public domain version, a crash would come or go away with + the slightest unrelated changes elsewhere in the function. Observed that + register a15 was used for epc1, then clobbered by `rsr.` I now believe a + "&" on the output register would have resolved the problem. + + However, I have refactored the Extended ASM to reduce and consolidate + register usage and corrected the issue. + + The positioning of the Extended ASM block (as early as possible in the + compiled function) is in part controlled by the immediate need for + output variable `insn`. This placement aids in getting excvaddr read as + early as possible. + */ + +#if 0 + { + __asm__ __volatile__ ("rsr.excvaddr %0;" : "=r"(excvaddr):: "memory"); + /* + "C" reference code for the ASM to document intent. + May also prove useful when issolating possible issues with Extended ASM, + optimizations, new compilers, etc. + */ + uint32_t epc = ef->epc; + uint32_t *pWord = (uint32_t *)(epc & ~3); + uint64_t big_word = ((uint64_t)pWord[1] << 32) | pWord[0]; + uint32_t pos = (epc & 3) * 8; + insn = (uint32_t)(big_word >>= pos); + } +#endif + +#define __EXCEPTION_HANDLER_PREAMBLE(ef, excvaddr, insn) \ + { \ + uint32_t tmp; \ + __asm__ ( \ + "rsr.excvaddr %[vaddr]\n\t" /* Read faulting address as early as possible */ \ + "movi.n %[tmp], ~3\n\t" /* prepare a mask for the EPC */ \ + "and %[tmp], %[tmp], %[epc]\n\t" /* apply mask for 32-bit aligned base */ \ + "ssa8l %[epc]\n\t" /* set up shift register for src op */ \ + "l32i %[insn], %[tmp], 0\n\t" /* load part 1 */ \ + "l32i %[tmp], %[tmp], 4\n\t" /* load part 2 */ \ + "src %[insn], %[tmp], %[insn]\n\t" /* right shift to get faulting instruction */ \ + : [vaddr]"=&r"(excvaddr), [insn]"=&r"(insn), [tmp]"=&r"(tmp) \ + : [epc]"r"(ef->epc) :); \ + } + + #ifdef __cplusplus } #endif diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index 00ba4135a1..60dde187b2 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -66,6 +66,7 @@ #include #include "esp8266_peri.h" #include "core_esp8266_vm.h" +#include "core_esp8266_non32xfer.h" #include "umm_malloc/umm_malloc.h" @@ -296,22 +297,11 @@ static void (*__old_handler)(struct __exception_frame *ef, int cause); static ICACHE_RAM_ATTR void loadstore_exception_handler(struct __exception_frame *ef, int cause) { - uint32_t epc1 = ef->epc; uint32_t excvaddr; uint32_t insn; - __asm ( - "rsr %0, EXCVADDR;" // read out the faulting address - "movi a4, ~3;" // prepare a mask for the EPC - "and a4, a4, %2;" // apply mask for 32bit aligned base - "l32i a5, a4, 0;" // load part 1 - "l32i a6, a4, 4;" // load part 2 - "ssa8l %2;" // set up shift register for src op - "src %1, a6, a5;" // right shift to get faulting instruction - :"=r"(excvaddr), "=r"(insn) - :"r"(epc1) - :"a4", "a5", "a6" - ); + /* Extract instruction and faulting data address */ + __EXCEPTION_HANDLER_PREAMBLE(ef, excvaddr, insn); // Check that we're really accessing VM and not some other illegal range if ((excvaddr >> 28) != 1) { @@ -394,7 +384,7 @@ void install_vm_exception_handler() // Bring cache structures to baseline if (cache_ways > 0) { for (auto i = 0; i < cache_ways; i++) { - __vm_cache_line[i].addr = -1; // Invalid, bits set in lower region so will never hatch + __vm_cache_line[i].addr = -1; // Invalid, bits set in lower region so will never match __vm_cache_line[i].next = &__vm_cache_line[i+1]; } __vm_cache = &__vm_cache_line[0]; From 8474edf85f2843a33a9165d2c95e63b9636b1510 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Mon, 11 Jan 2021 17:24:07 -0800 Subject: [PATCH 5/8] Init VM heap automatically, like IRAM heap --- cores/esp8266/Esp.cpp | 30 ++++--------------- cores/esp8266/Esp.h | 10 ------- cores/esp8266/core_esp8266_main.cpp | 6 +++- cores/esp8266/core_esp8266_vm.cpp | 6 ++-- .../examples/virtualmem/virtualmem.ino | 2 -- 5 files changed, 13 insertions(+), 41 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 6aa875846b..9411b9586f 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -29,9 +29,6 @@ #include "coredecls.h" #include "umm_malloc/umm_malloc.h" -#ifdef UMM_HEAP_EXTERNAL -#include "core_esp8266_vm.h" -#endif #include extern "C" { @@ -974,22 +971,11 @@ String EspClass::getSketchMD5() return result; } -void EspClass::enableVM() -{ -#ifdef UMM_HEAP_EXTERNAL - if (!vmEnabled) - install_vm_exception_handler(); - vmEnabled = true; -#endif -} - void EspClass::setExternalHeap() { #ifdef UMM_HEAP_EXTERNAL - if (vmEnabled) { - if (!umm_push_heap(UMM_HEAP_EXTERNAL)) { - panic(); - } + if (!umm_push_heap(UMM_HEAP_EXTERNAL)) { + panic(); } #endif } @@ -1006,10 +992,8 @@ void EspClass::setIramHeap() void EspClass::setDramHeap() { #if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM) - if (vmEnabled) { - if (!umm_push_heap(UMM_HEAP_DRAM)) { - panic(); - } + if (!umm_push_heap(UMM_HEAP_DRAM)) { + panic(); } #elif defined(UMM_HEAP_IRAM) if (!umm_push_heap(UMM_HEAP_DRAM)) { @@ -1021,10 +1005,8 @@ void EspClass::setDramHeap() void EspClass::resetHeap() { #if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM) - if (vmEnabled) { - if (!umm_pop_heap()) { - panic(); - } + if (!umm_pop_heap()) { + panic(); } #elif defined(UMM_HEAP_IRAM) if (!umm_pop_heap()) { diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index e2a83ab9cc..f136bb4428 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -215,13 +215,6 @@ class EspClass { #else uint32_t getCycleCount(); #endif // !defined(CORE_MOCK) - /** - * @brief Installs VM exception handler to support External memory (Experimental) - * - * @param none - * @return none - */ - void enableVM(); /** * @brief Push current Heap selection and set Heap selection to DRAM. * @@ -252,9 +245,6 @@ class EspClass { */ void resetHeap(); private: -#ifdef MMU_EXTERNAL_HEAP - bool vmEnabled = false; -#endif /** * @brief Replaces @a byteCount bytes of a 4 byte block on flash * diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 417c3f26e8..1142a329e6 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -37,6 +37,7 @@ extern "C" { #include "flash_quirks.h" #include #include +#include "core_esp8266_vm.h" #define LOOP_TASK_PRIORITY 1 @@ -348,9 +349,12 @@ extern "C" void user_init(void) { cont_init(g_pcont); -#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) +#if defined(UMM_HEAP_EXTERNAL) + install_vm_exception_handler(); +#elif defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) install_non32xfer_exception_handler(); #endif + #if defined(MMU_IRAM_HEAP) umm_init_iram(); #endif diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index 60dde187b2..1674b76d2b 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -53,10 +53,8 @@ MISO -> GPIO12 (note these are GPIO numbers, not the Arduion Dxx ones. Refer to your ESP8266 board schematic for the mapping of GPIO to pin.) - * Higher density PSRAM (ESP-PSRAM64H/etc.) should work as well, but I'm - still waiting on my chips so haven't done any testing. Biggest concern - is their command set and functionality in DIO mode. If DIO mode isn't - supported, then a fallback to SIO or moving to QIO is a possibility. + * Higher density PSRAM (ESP-PSRAM64H/etc.) works as well, but may be too + large to effectively use with UMM */ diff --git a/libraries/esp8266/examples/virtualmem/virtualmem.ino b/libraries/esp8266/examples/virtualmem/virtualmem.ino index c97d2cac33..47b9396cc7 100644 --- a/libraries/esp8266/examples/virtualmem/virtualmem.ino +++ b/libraries/esp8266/examples/virtualmem/virtualmem.ino @@ -64,8 +64,6 @@ void setup() { Serial.begin(115200); Serial.printf("\n"); - ESP.enableVM(); // Start up the VM handler, set up the memory manager, etc. - // Enabling VM does not change malloc to use the external region. It will continue to // use the normal RAM until we request otherwise. uint32_t *mem = (uint32_t *)malloc(1024 * sizeof(uint32_t)); From a129c015bc5fa9ef85ec00919c0a0b3b850c13ef Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 13 Jan 2021 07:59:36 -0800 Subject: [PATCH 6/8] Include updated/fixes exception handler override --- cores/esp8266/core_esp8266_main.cpp | 4 +++- cores/esp8266/core_esp8266_vm.cpp | 7 +------ cores/esp8266/exc-sethandler.cpp | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 1142a329e6..a3e140ef80 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -351,7 +351,9 @@ extern "C" void user_init(void) { #if defined(UMM_HEAP_EXTERNAL) install_vm_exception_handler(); -#elif defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) +#endif + +#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) install_non32xfer_exception_handler(); #endif diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index 1674b76d2b..ff0cdde290 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -340,12 +340,7 @@ static ICACHE_RAM_ATTR void loadstore_exception_handler(struct __exception_frame void install_vm_exception_handler() { - // There is no way to get the current exception handler via an API, so pull it - // out using the decoded ROM dump which points to 0x3fffc100 as the start of - // the XTOS exception table (of C-callable functions) - uint32_t old = *(uint32_t*)(0x3fffc100 + EXCCAUSE_LOAD_PROHIBITED * 4); - __old_handler = (void (*)(struct __exception_frame *ef, int cause))old; - _xtos_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, loadstore_exception_handler); + __old_handler = _xtos_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, loadstore_exception_handler); _xtos_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, loadstore_exception_handler); DECLARE_SPI1; diff --git a/cores/esp8266/exc-sethandler.cpp b/cores/esp8266/exc-sethandler.cpp index 82f8293944..1551d2446c 100644 --- a/cores/esp8266/exc-sethandler.cpp +++ b/cores/esp8266/exc-sethandler.cpp @@ -40,7 +40,7 @@ * */ -#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || defined(NEW_EXC_C_WRAPPER) +#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || defined(NEW_EXC_C_WRAPPER) || defined(MMU_EXTERNAL_HEAP) /* * The original module source code came from: From fc85d183cfc83622efd4be624726d201681ca1c6 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Mon, 25 Jan 2021 12:34:24 -0800 Subject: [PATCH 7/8] Adjust UMM to only map 256K of 1M PSRAM Because UMM manages RAM in 8 byte chunks, attempting to manage the entire 1M available space on a 1M PSRAM causes the block IDs to overflow, crashing things at some point. Limit the UMM allocation to only 256K in this case. The remaining space can manually be assigned to buffers/etc. managed by the application, not malloc()/free(). --- boards.txt | 68 +++++++++++++++---------------- cores/esp8266/core_esp8266_vm.cpp | 15 ++++--- tools/boards.txt.py | 2 +- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/boards.txt b/boards.txt index 87a30b1036..f65b4f8cb3 100644 --- a/boards.txt +++ b/boards.txt @@ -76,7 +76,7 @@ generic.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x generic.menu.mmu.ext128k=128K External 23LC1024 generic.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 generic.menu.mmu.ext1024k=1M External 64 MBit PSRAM -generic.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +generic.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 generic.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM generic.menu.non32xfer.fast.build.non32xferflags= generic.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -561,7 +561,7 @@ esp8285.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x esp8285.menu.mmu.ext128k=128K External 23LC1024 esp8285.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp8285.menu.mmu.ext1024k=1M External 64 MBit PSRAM -esp8285.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp8285.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp8285.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM esp8285.menu.non32xfer.fast.build.non32xferflags= esp8285.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -916,7 +916,7 @@ gen4iod.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x gen4iod.menu.mmu.ext128k=128K External 23LC1024 gen4iod.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 gen4iod.menu.mmu.ext1024k=1M External 64 MBit PSRAM -gen4iod.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +gen4iod.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 gen4iod.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM gen4iod.menu.non32xfer.fast.build.non32xferflags= gen4iod.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1186,7 +1186,7 @@ huzzah.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4 huzzah.menu.mmu.ext128k=128K External 23LC1024 huzzah.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 huzzah.menu.mmu.ext1024k=1M External 64 MBit PSRAM -huzzah.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +huzzah.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 huzzah.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM huzzah.menu.non32xfer.fast.build.non32xferflags= huzzah.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1389,7 +1389,7 @@ wifi_slot.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE= wifi_slot.menu.mmu.ext128k=128K External 23LC1024 wifi_slot.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifi_slot.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifi_slot.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifi_slot.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifi_slot.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifi_slot.menu.non32xfer.fast.build.non32xferflags= wifi_slot.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1718,7 +1718,7 @@ arduino-esp8266.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE arduino-esp8266.menu.mmu.ext128k=128K External 23LC1024 arduino-esp8266.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 arduino-esp8266.menu.mmu.ext1024k=1M External 64 MBit PSRAM -arduino-esp8266.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +arduino-esp8266.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 arduino-esp8266.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM arduino-esp8266.menu.non32xfer.fast.build.non32xferflags= arduino-esp8266.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -1922,7 +1922,7 @@ espmxdevkit.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZ espmxdevkit.menu.mmu.ext128k=128K External 23LC1024 espmxdevkit.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espmxdevkit.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espmxdevkit.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espmxdevkit.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espmxdevkit.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espmxdevkit.menu.non32xfer.fast.build.non32xferflags= espmxdevkit.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2166,7 +2166,7 @@ oak.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 oak.menu.mmu.ext128k=128K External 23LC1024 oak.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 oak.menu.mmu.ext1024k=1M External 64 MBit PSRAM -oak.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +oak.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 oak.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM oak.menu.non32xfer.fast.build.non32xferflags= oak.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2378,7 +2378,7 @@ espduino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0 espduino.menu.mmu.ext128k=128K External 23LC1024 espduino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espduino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espduino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espduino.menu.non32xfer.fast.build.non32xferflags= espduino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2580,7 +2580,7 @@ espectro.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0 espectro.menu.mmu.ext128k=128K External 23LC1024 espectro.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espectro.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espectro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espectro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espectro.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espectro.menu.non32xfer.fast.build.non32xferflags= espectro.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2783,7 +2783,7 @@ espino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4 espino.menu.mmu.ext128k=128K External 23LC1024 espino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espino.menu.non32xfer.fast.build.non32xferflags= espino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -2989,7 +2989,7 @@ espresso_lite_v1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACH espresso_lite_v1.menu.mmu.ext128k=128K External 23LC1024 espresso_lite_v1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espresso_lite_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espresso_lite_v1.menu.non32xfer.fast.build.non32xferflags= espresso_lite_v1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3195,7 +3195,7 @@ espresso_lite_v2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACH espresso_lite_v2.menu.mmu.ext128k=128K External 23LC1024 espresso_lite_v2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espresso_lite_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espresso_lite_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espresso_lite_v2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espresso_lite_v2.menu.non32xfer.fast.build.non32xferflags= espresso_lite_v2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3411,7 +3411,7 @@ sonoff.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4 sonoff.menu.mmu.ext128k=128K External 23LC1024 sonoff.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 sonoff.menu.mmu.ext1024k=1M External 64 MBit PSRAM -sonoff.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +sonoff.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 sonoff.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM sonoff.menu.non32xfer.fast.build.non32xferflags= sonoff.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3654,7 +3654,7 @@ inventone.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE= inventone.menu.mmu.ext128k=128K External 23LC1024 inventone.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 inventone.menu.mmu.ext1024k=1M External 64 MBit PSRAM -inventone.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +inventone.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 inventone.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM inventone.menu.non32xfer.fast.build.non32xferflags= inventone.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -3857,7 +3857,7 @@ d1_mini.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x d1_mini.menu.mmu.ext128k=128K External 23LC1024 d1_mini.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini.menu.non32xfer.fast.build.non32xferflags= d1_mini.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4060,7 +4060,7 @@ d1_mini_lite.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SI d1_mini_lite.menu.mmu.ext128k=128K External 23LC1024 d1_mini_lite.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_lite.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini_lite.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_lite.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_lite.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini_lite.menu.non32xfer.fast.build.non32xferflags= d1_mini_lite.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4303,7 +4303,7 @@ d1_mini_pro.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZ d1_mini_pro.menu.mmu.ext128k=128K External 23LC1024 d1_mini_pro.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_pro.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1_mini_pro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1_mini_pro.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1_mini_pro.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1_mini_pro.menu.non32xfer.fast.build.non32xferflags= d1_mini_pro.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4489,7 +4489,7 @@ d1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 d1.menu.mmu.ext128k=128K External 23LC1024 d1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -d1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +d1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 d1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM d1.menu.non32xfer.fast.build.non32xferflags= d1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4692,7 +4692,7 @@ nodemcu.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x nodemcu.menu.mmu.ext128k=128K External 23LC1024 nodemcu.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcu.menu.mmu.ext1024k=1M External 64 MBit PSRAM -nodemcu.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcu.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcu.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM nodemcu.menu.non32xfer.fast.build.non32xferflags= nodemcu.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -4895,7 +4895,7 @@ nodemcuv2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE= nodemcuv2.menu.mmu.ext128k=128K External 23LC1024 nodemcuv2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcuv2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -nodemcuv2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +nodemcuv2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 nodemcuv2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM nodemcuv2.menu.non32xfer.fast.build.non32xferflags= nodemcuv2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5102,7 +5102,7 @@ modwifi.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x modwifi.menu.mmu.ext128k=128K External 23LC1024 modwifi.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 modwifi.menu.mmu.ext1024k=1M External 64 MBit PSRAM -modwifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +modwifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 modwifi.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM modwifi.menu.non32xfer.fast.build.non32xferflags= modwifi.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5325,7 +5325,7 @@ phoenix_v1.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE phoenix_v1.menu.mmu.ext128k=128K External 23LC1024 phoenix_v1.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v1.menu.mmu.ext1024k=1M External 64 MBit PSRAM -phoenix_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v1.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v1.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM phoenix_v1.menu.non32xfer.fast.build.non32xferflags= phoenix_v1.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5531,7 +5531,7 @@ phoenix_v2.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE phoenix_v2.menu.mmu.ext128k=128K External 23LC1024 phoenix_v2.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v2.menu.mmu.ext1024k=1M External 64 MBit PSRAM -phoenix_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +phoenix_v2.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 phoenix_v2.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM phoenix_v2.menu.non32xfer.fast.build.non32xferflags= phoenix_v2.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5737,7 +5737,7 @@ eduinowifi.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE eduinowifi.menu.mmu.ext128k=128K External 23LC1024 eduinowifi.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 eduinowifi.menu.mmu.ext1024k=1M External 64 MBit PSRAM -eduinowifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +eduinowifi.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 eduinowifi.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM eduinowifi.menu.non32xfer.fast.build.non32xferflags= eduinowifi.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -5940,7 +5940,7 @@ wiolink.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x wiolink.menu.mmu.ext128k=128K External 23LC1024 wiolink.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wiolink.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wiolink.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wiolink.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wiolink.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wiolink.menu.non32xfer.fast.build.non32xferflags= wiolink.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6143,7 +6143,7 @@ blynk.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x40 blynk.menu.mmu.ext128k=128K External 23LC1024 blynk.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 blynk.menu.mmu.ext1024k=1M External 64 MBit PSRAM -blynk.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +blynk.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 blynk.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM blynk.menu.non32xfer.fast.build.non32xferflags= blynk.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6346,7 +6346,7 @@ thing.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x40 thing.menu.mmu.ext128k=128K External 23LC1024 thing.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thing.menu.mmu.ext1024k=1M External 64 MBit PSRAM -thing.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thing.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thing.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM thing.menu.non32xfer.fast.build.non32xferflags= thing.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6549,7 +6549,7 @@ thingdev.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0 thingdev.menu.mmu.ext128k=128K External 23LC1024 thingdev.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thingdev.menu.mmu.ext1024k=1M External 64 MBit PSRAM -thingdev.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +thingdev.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 thingdev.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM thingdev.menu.non32xfer.fast.build.non32xferflags= thingdev.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6752,7 +6752,7 @@ esp210.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4 esp210.menu.mmu.ext128k=128K External 23LC1024 esp210.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp210.menu.mmu.ext1024k=1M External 64 MBit PSRAM -esp210.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +esp210.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 esp210.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM esp210.menu.non32xfer.fast.build.non32xferflags= esp210.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -6955,7 +6955,7 @@ espinotee.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE= espinotee.menu.mmu.ext128k=128K External 23LC1024 espinotee.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espinotee.menu.mmu.ext1024k=1M External 64 MBit PSRAM -espinotee.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +espinotee.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 espinotee.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM espinotee.menu.non32xfer.fast.build.non32xferflags= espinotee.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7158,7 +7158,7 @@ wifiduino.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE= wifiduino.menu.mmu.ext128k=128K External 23LC1024 wifiduino.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifiduino.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifiduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifiduino.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifiduino.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifiduino.menu.non32xfer.fast.build.non32xferflags= wifiduino.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7378,7 +7378,7 @@ wifinfo.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x wifinfo.menu.mmu.ext128k=128K External 23LC1024 wifinfo.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifinfo.menu.mmu.ext1024k=1M External 64 MBit PSRAM -wifinfo.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +wifinfo.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 wifinfo.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM wifinfo.menu.non32xfer.fast.build.non32xferflags= wifinfo.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) @@ -7628,7 +7628,7 @@ cw01.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x400 cw01.menu.mmu.ext128k=128K External 23LC1024 cw01.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 cw01.menu.mmu.ext1024k=1M External 64 MBit PSRAM -cw01.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +cw01.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 cw01.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM cw01.menu.non32xfer.fast.build.non32xferflags= cw01.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow) diff --git a/cores/esp8266/core_esp8266_vm.cpp b/cores/esp8266/core_esp8266_vm.cpp index ff0cdde290..b19360e87f 100644 --- a/cores/esp8266/core_esp8266_vm.cpp +++ b/cores/esp8266/core_esp8266_vm.cpp @@ -54,7 +54,8 @@ (note these are GPIO numbers, not the Arduion Dxx ones. Refer to your ESP8266 board schematic for the mapping of GPIO to pin.) * Higher density PSRAM (ESP-PSRAM64H/etc.) works as well, but may be too - large to effectively use with UMM + large to effectively use with UMM. Only 256K is available vial malloc, + but addresses above 256K do work and can be used for fixed buffers. */ @@ -129,11 +130,15 @@ constexpr uint8_t sck = 14; #define DECLARE_SPI1 spi_regs *spi1 = (spi_regs*)&SPI1CMD typedef enum { spi_5mhz = 0x001c1001, spi_10mhz = 0x000c1001, spi_20mhz = 0x00041001, spi_30mhz = 0x00002001, spi_40mhz = 0x00001001 } spi_clocking; - -constexpr uint32_t spi_clkval = spi_20mhz; - typedef enum { sio = 0, dio = 1 } iotype; -constexpr iotype hspi_mode = dio; + +#if MMU_EXTERNAL_HEAP > 128 + constexpr uint32_t spi_clkval = spi_40mhz; + constexpr iotype hspi_mode = sio; +#else + constexpr uint32_t spi_clkval = spi_20mhz; + constexpr iotype hspi_mode = dio; +#endif constexpr int read_delay = (hspi_mode == dio) ? 4-1 : 0; diff --git a/tools/boards.txt.py b/tools/boards.txt.py index 1aa46174f1..9b6f712e57 100755 --- a/tools/boards.txt.py +++ b/tools/boards.txt.py @@ -1214,7 +1214,7 @@ ( '.menu.mmu.ext128k', '128K External 23LC1024' ), ( '.menu.mmu.ext128k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), ( '.menu.mmu.ext1024k', '1M External 64 MBit PSRAM' ), - ( '.menu.mmu.ext1024k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=1024 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), + ( '.menu.mmu.ext1024k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ), ]), ######################## Non 32-bit load/store exception handler From bd302caa692e21c25cc8e1a39431e4912df84715 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sun, 14 Mar 2021 14:03:31 -0700 Subject: [PATCH 8/8] Update boards.txt --- boards.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boards.txt b/boards.txt index a8711bd715..e6b222a9e5 100644 --- a/boards.txt +++ b/boards.txt @@ -4689,6 +4689,10 @@ agruminolemon.menu.mmu.4816H=16KB cache + 48KB IRAM and 2nd Heap (shared) agruminolemon.menu.mmu.4816H.build.mmuflags=-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_IRAM_HEAP agruminolemon.menu.mmu.3216=16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) agruminolemon.menu.mmu.3216.build.mmuflags=-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000 +agruminolemon.menu.mmu.ext128k=128K External 23LC1024 +agruminolemon.menu.mmu.ext128k.build.mmuflags=-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 +agruminolemon.menu.mmu.ext1024k=1M External 64 MBit PSRAM +agruminolemon.menu.mmu.ext1024k.build.mmuflags=-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 agruminolemon.menu.non32xfer.fast=Use pgm_read macros for IRAM/PROGMEM agruminolemon.menu.non32xfer.fast.build.non32xferflags= agruminolemon.menu.non32xfer.safe=Byte/Word access to IRAM/PROGMEM (very slow)