1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-07 06:01:35 +03:00

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.
This commit is contained in:
M Hightower
2022-01-11 14:35:46 -08:00
committed by GitHub
parent 378fcfcda4
commit 9fcf14f81f
10 changed files with 178 additions and 138 deletions

View File

@ -23,19 +23,18 @@
#include "coredecls.h"
#include "Esp.h"
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
void EspClass::getHeapStats(uint32_t* hfree, uint32_t* hmax, uint8_t* hfrag)
{
// L2 / Euclidean norm of free block sizes.
// Having getFreeHeap()=sum(hole-size), fragmentation is given by
// 100 * (1 - sqrt(sum(hole-size²)) / sum(hole-size))
umm_info(NULL, false);
uint32_t free_size = umm_free_heap_size_core(umm_get_current_heap());
if (hfree)
*hfree = free_size;
if (hmax)
*hmax = (uint16_t)umm_max_block_size_core(umm_get_current_heap());
*hmax = umm_max_block_size_core(umm_get_current_heap());
if (hfrag) {
if (free_size) {
*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)
}
}
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
{
uint32_t hmax32;
getHeapStats(hfree, &hmax32, hfrag);
if (hmax) {
// With the MMU_EXTERNAL_HEAP option, hmax could overflow for heaps larger
// then 64KB. return UINT16_MAX (saturation) for those cases.
// Added deprecated attribute and message.
*hmax = (hmax32 > UINT16_MAX) ? UINT16_MAX : hmax32;
}
}
uint8_t EspClass::getHeapFragmentation()
{
return (uint8_t)umm_fragmentation_metric();

View File

@ -222,7 +222,7 @@ uint32_t EspClass::getFreeHeap(void)
return system_get_free_heap_size();
}
uint16_t EspClass::getMaxFreeBlockSize(void)
uint32_t EspClass::getMaxFreeBlockSize(void)
{
return umm_max_block_size();
}

View File

@ -114,9 +114,10 @@ class EspClass {
static uint32_t getChipId();
static uint32_t getFreeHeap();
static uint16_t getMaxFreeBlockSize();
static uint32_t getMaxFreeBlockSize();
static uint8_t getHeapFragmentation(); // in %
static void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr);
static void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr) __attribute__((deprecated("Use 'uint32_t*' on max, 2nd argument")));
static void getHeapStats(uint32_t* free = nullptr, uint32_t* max = nullptr, uint8_t* frag = nullptr);
static uint32_t getFreeContStack();
static void resetFreeContStack();

View File

@ -56,7 +56,7 @@
* Higher density PSRAM (ESP-PSRAM64H/etc.) works as well, but may be too
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.
*/
#ifdef MMU_EXTERNAL_HEAP
@ -71,6 +71,8 @@
extern "C" {
#define VM_OFFSET_MASK 0x007fffffu
#define SHORT_MASK 0x000008u
#define LOAD_MASK 0x00f00fu
#define L8UI_MATCH 0x000002u
@ -324,21 +326,21 @@ static IRAM_ATTR void loadstore_exception_handler(struct __exception_frame *ef,
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);
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 8-1, val);
} else if (what == S16I_MATCH) {
spi_ramwrite(spi1, excvaddr & 0x1ffff, 16-1, val);
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 16-1, val);
} else {
spi_ramwrite(spi1, excvaddr & 0x1ffff, 32-1, val);
spi_ramwrite(spi1, excvaddr & VM_OFFSET_MASK, 32-1, val);
}
} else {
if (insn & L32_MASK) {
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 32-1);
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 32-1);
} else if (insn & L16_MASK) {
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & 0x1ffff, 16-1);
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 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);
ef->a_reg[regno] = spi_ramread(spi1, excvaddr & VM_OFFSET_MASK, 8-1);
}
}
}
@ -389,6 +391,11 @@ void install_vm_exception_handler()
__vm_cache_line[cache_ways - 1].next = NULL;
}
// Our umm_malloc configuration can only support a maximum of 256K RAM. A
// change would affect the block size of all heaps, and a larger block size
// would result in wasted space in the smaller heaps.
static_assert(MMU_EXTERNAL_HEAP <= 256, "Heap size must not exceed 256K");
// Hook into memory manager
umm_init_vm( (void *)0x10000000, MMU_EXTERNAL_HEAP * 1024);
}

View File

@ -192,15 +192,15 @@ void umm_print_stats(int force) {
umm_heap_context_t *_context = umm_get_current_heap();
DBGLOG_FORCE(force, "umm heap statistics:\n");
DBGLOG_FORCE(force, " Heap ID %5u\n", _context->id);
DBGLOG_FORCE(force, " Free Space %5u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block));
DBGLOG_FORCE(force, " OOM Count %5u\n", _context->UMM_OOM_COUNT);
DBGLOG_FORCE(force, " Heap ID %7u\n", _context->id);
DBGLOG_FORCE(force, " Free Space %7u\n", _context->UMM_FREE_BLOCKS * sizeof(umm_block));
DBGLOG_FORCE(force, " OOM Count %7u\n", _context->UMM_OOM_COUNT);
#if defined(UMM_STATS_FULL)
DBGLOG_FORCE(force, " Low Watermark %5u\n", _context->stats.free_blocks_min * sizeof(umm_block));
DBGLOG_FORCE(force, " Low Watermark ISR %5u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block));
DBGLOG_FORCE(force, " MAX Alloc Request %5u\n", _context->stats.alloc_max_size);
DBGLOG_FORCE(force, " Low Watermark %7u\n", _context->stats.free_blocks_min * sizeof(umm_block));
DBGLOG_FORCE(force, " Low Watermark ISR %7u\n", _context->stats.free_blocks_isr_min * sizeof(umm_block));
DBGLOG_FORCE(force, " MAX Alloc Request %7u\n", _context->stats.alloc_max_size);
#endif
DBGLOG_FORCE(force, " Size of umm_block %5u\n", sizeof(umm_block));
DBGLOG_FORCE(force, " Size of umm_block %7u\n", sizeof(umm_block));
DBGLOG_FORCE(force, "+--------------------------------------------------------------+\n");
}
#endif