Skip to content

Commit 9fcf14f

Browse files
authored
Fix VM Address mask (#8440)
* Fix VM Address mask Adjust VM Address mask to allow up to 8M Byte parts. Allow for free heap size values over 64K ESP.getHeapStats(, uint32_t,) uint32_t getMaxFreeBlockSize(); * Fix example * Update MockEsp.cpp for uint32_t on EspClass::getMaxFreeBlockSize() * Added comment about heap size limitation and static_assert to verify. Updated boards.txt to show correct External memory size and Heap size.
1 parent 378fcfc commit 9fcf14f

File tree

10 files changed

+178
-138
lines changed

10 files changed

+178
-138
lines changed

boards.txt

+111-111
Large diffs are not rendered by default.

cores/esp8266/Esp-frag.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,18 @@
2323
#include "coredecls.h"
2424
#include "Esp.h"
2525

26-
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
26+
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag)
2727
{
2828
// L2 / Euclidean norm of free block sizes.
2929
// Having getFreeHeap()=sum(hole-size), fragmentation is given by
3030
// 100 * (1 - sqrt(sum(hole-size²)) / sum(hole-size))
31-
3231
umm_info(NULL, false);
3332

3433
uint32_t free_size = umm_free_heap_size_core(umm_get_current_heap());
3534
if (hfree)
3635
*hfree = free_size;
3736
if (hmax)
38-
*hmax = (uint16_t)umm_max_block_size_core(umm_get_current_heap());
37+
*hmax = umm_max_block_size_core(umm_get_current_heap());
3938
if (hfrag) {
4039
if (free_size) {
4140
*hfrag = umm_fragmentation_metric_core(umm_get_current_heap());
@@ -45,6 +44,18 @@ void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
4544
}
4645
}
4746

47+
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
48+
{
49+
uint32_t hmax32;
50+
getHeapStats(hfree, &hmax32, hfrag);
51+
if (hmax) {
52+
// With the MMU_EXTERNAL_HEAP option, hmax could overflow for heaps larger
53+
// then 64KB. return UINT16_MAX (saturation) for those cases.
54+
// Added deprecated attribute and message.
55+
*hmax = (hmax32 > UINT16_MAX) ? UINT16_MAX : hmax32;
56+
}
57+
}
58+
4859
uint8_t EspClass::getHeapFragmentation()
4960
{
5061
return (uint8_t)umm_fragmentation_metric();

cores/esp8266/Esp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ uint32_t EspClass::getFreeHeap(void)
222222
return system_get_free_heap_size();
223223
}
224224

225-
uint16_t EspClass::getMaxFreeBlockSize(void)
225+
uint32_t EspClass::getMaxFreeBlockSize(void)
226226
{
227227
return umm_max_block_size();
228228
}

cores/esp8266/Esp.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ class EspClass {
114114
static uint32_t getChipId();
115115

116116
static uint32_t getFreeHeap();
117-
static uint16_t getMaxFreeBlockSize();
117+
static uint32_t getMaxFreeBlockSize();
118118
static uint8_t getHeapFragmentation(); // in %
119-
static void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr);
119+
static void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr) __attribute__((deprecated("Use 'uint32_t*' on max, 2nd argument")));
120+
static void getHeapStats(uint32_t* free = nullptr, uint32_t* max = nullptr, uint8_t* frag = nullptr);
120121

121122
static uint32_t getFreeContStack();
122123
static void resetFreeContStack();

cores/esp8266/core_esp8266_vm.cpp

+14-7
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
* Higher density PSRAM (ESP-PSRAM64H/etc.) works as well, but may be too
5757
large to effectively use with UMM. Only 256K is available vial malloc,
5858
but addresses above 256K do work and can be used for fixed buffers.
59-
59+
6060
*/
6161

6262
#ifdef MMU_EXTERNAL_HEAP
@@ -71,6 +71,8 @@
7171

7272
extern "C" {
7373

74+
#define VM_OFFSET_MASK 0x007fffffu
75+
7476
#define SHORT_MASK 0x000008u
7577
#define LOAD_MASK 0x00f00fu
7678
#define L8UI_MATCH 0x000002u
@@ -324,21 +326,21 @@ static IRAM_ATTR void loadstore_exception_handler(struct __exception_frame *ef,
324326
uint32_t val = ef->a_reg[regno];
325327
uint32_t what = insn & STORE_MASK;
326328
if (what == S8I_MATCH) {
327-
spi_ramwrite(spi1, excvaddr & 0x1ffff, 8-1, val);
329+
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 8-1, val);
328330
} else if (what == S16I_MATCH) {
329-
spi_ramwrite(spi1, excvaddr & 0x1ffff, 16-1, val);
331+
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 16-1, val);
330332
} else {
331-
spi_ramwrite(spi1, excvaddr & 0x1ffff, 32-1, val);
333+
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 32-1, val);
332334
}
333335
} else {
334336
if (insn & L32_MASK) {
335-
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 32-1);
337+
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 32-1);
336338
} else if (insn & L16_MASK) {
337-
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 16-1);
339+
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 16-1);
338340
if ((insn & SIGNED_MASK ) && (ef->a_reg[regno] & 0x8000))
339341
ef->a_reg[regno] |= 0xffff0000;
340342
} else {
341-
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 8-1);
343+
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 8-1);
342344
}
343345
}
344346
}
@@ -389,6 +391,11 @@ void install_vm_exception_handler()
389391
__vm_cache_line[cache_ways - 1].next = NULL;
390392
}
391393

394+
// Our umm_malloc configuration can only support a maximum of 256K RAM. A
395+
// change would affect the block size of all heaps, and a larger block size
396+
// would result in wasted space in the smaller heaps.
397+
static_assert(MMU_EXTERNAL_HEAP <= 256, "Heap size must not exceed 256K");
398+
392399
// Hook into memory manager
393400
umm_init_vm( (void *)0x10000000, MMU_EXTERNAL_HEAP * 1024);
394401
}

cores/esp8266/umm_malloc/umm_local.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,15 @@ void umm_print_stats(int force) {
192192
umm_heap_context_t *_context = umm_get_current_heap();
193193

194194
DBGLOG_FORCE(force, "umm heap statistics:\n");
195-
DBGLOG_FORCE(force, " Heap ID %5u\n", _context->id);
196-
DBGLOG_FORCE(force, " Free Space %5u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block));
197-
DBGLOG_FORCE(force, " OOM Count %5u\n", _context->UMM_OOM_COUNT);
195+
DBGLOG_FORCE(force, " Heap ID %7u\n", _context->id);
196+
DBGLOG_FORCE(force, " Free Space %7u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block));
197+
DBGLOG_FORCE(force, " OOM Count %7u\n", _context->UMM_OOM_COUNT);
198198
#if defined(UMM_STATS_FULL)
199-
DBGLOG_FORCE(force, " Low Watermark %5u\n", _context->stats.free_blocks_min * sizeof(umm_block));
200-
DBGLOG_FORCE(force, " Low Watermark ISR %5u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block));
201-
DBGLOG_FORCE(force, " MAX Alloc Request %5u\n", _context->stats.alloc_max_size);
199+
DBGLOG_FORCE(force, " Low Watermark %7u\n", _context->stats.free_blocks_min * sizeof(umm_block));
200+
DBGLOG_FORCE(force, " Low Watermark ISR %7u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block));
201+
DBGLOG_FORCE(force, " MAX Alloc Request %7u\n", _context->stats.alloc_max_size);
202202
#endif
203-
DBGLOG_FORCE(force, " Size of umm_block %5u\n", sizeof(umm_block));
203+
DBGLOG_FORCE(force, " Size of umm_block %7u\n", sizeof(umm_block));
204204
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
205205
}
206206
#endif

libraries/esp8266/examples/HeapMetric/HeapMetric.ino

+23-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ void stats(const char* what) {
1010
// we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation()
1111
// or all at once:
1212
uint32_t free;
13-
uint16_t max;
13+
uint32_t max;
1414
uint8_t frag;
1515
ESP.getHeapStats(&free, &max, &frag);
1616

17-
Serial.printf("free: %5d - max: %5d - frag: %3d%% <- ", free, max, frag);
17+
Serial.printf("free: %7u - max: %7u - frag: %3d%% <- ", free, max, frag);
1818
// %s requires a malloc that could fail, using println instead:
1919
Serial.println(what);
2020
}
@@ -109,6 +109,7 @@ void tryit(int blocksize) {
109109
void setup() {
110110
Serial.begin(115200);
111111
WiFi.mode(WIFI_OFF);
112+
delay(50);
112113

113114
Serial.printf("\r\nDemo Heap Metrics for DRAM\r\n");
114115
tryit(8000);
@@ -135,6 +136,26 @@ void setup() {
135136
tryit(15);
136137
}
137138
#endif
139+
#ifdef MMU_EXTERNAL_HEAP
140+
{
141+
HeapSelect ephemeral = HeapSelect(UMM_HEAP_EXTERNAL);
142+
Serial.printf("\r\nDemo Heap Metrics for External RAM\r\n");
143+
#if (MMU_EXTERNAL_HEAP > 64)
144+
tryit(64000);
145+
tryit(32000);
146+
#endif
147+
tryit(16000);
148+
tryit(8000);
149+
tryit(4000);
150+
tryit(2000);
151+
tryit(1000);
152+
tryit(500);
153+
tryit(200);
154+
tryit(100);
155+
tryit(50);
156+
tryit(15);
157+
}
158+
#endif
138159
}
139160

140161
void loop() {

libraries/esp8266/examples/irammem/irammem.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ void setup() {
592592
size_t free_iram = ESP.getFreeHeap();
593593
ETS_PRINTF("IRAM free: %6d\n", free_iram);
594594
uint32_t hfree;
595-
uint16_t hmax;
595+
uint32_t hmax;
596596
uint8_t hfrag;
597597
ESP.getHeapStats(&hfree, &hmax, &hfrag);
598598
ETS_PRINTF("ESP.getHeapStats(free: %u, max: %u, frag: %u)\n",

tests/host/common/MockEsp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ uint32_t EspClass::getFreeHeap()
108108
return 30000;
109109
}
110110

111-
uint16_t EspClass::getMaxFreeBlockSize()
111+
uint32_t EspClass::getMaxFreeBlockSize()
112112
{
113113
return 20000;
114114
}

tools/boards.txt.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1270,10 +1270,10 @@
12701270
( '.menu.mmu.4816H.build.mmuflags', '-DMMU_IRAM_SIZE=0xC000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_IRAM_HEAP' ),
12711271
( '.menu.mmu.3216', '16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared)' ),
12721272
( '.menu.mmu.3216.build.mmuflags', '-DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x4000 -DMMU_SEC_HEAP=0x40108000 -DMMU_SEC_HEAP_SIZE=0x4000' ),
1273-
( '.menu.mmu.ext128k', '128K External 23LC1024' ),
1273+
( '.menu.mmu.ext128k', '128K Heap External 23LC1024' ),
12741274
( '.menu.mmu.ext128k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=128 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ),
1275-
( '.menu.mmu.ext1024k', '1M External 64 MBit PSRAM' ),
1276-
( '.menu.mmu.ext1024k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ),
1275+
( '.menu.mmu.ext8192k', '8M w/256K Heap External 64 MBit PSRAM' ),
1276+
( '.menu.mmu.ext8192k.build.mmuflags', '-DMMU_EXTERNAL_HEAP=256 -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000' ),
12771277
]),
12781278

12791279
######################## Non 32-bit load/store exception handler

0 commit comments

Comments
 (0)