From d91ca719934a0a4bd0306553061f1d7f74583ec2 Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Tue, 28 Aug 2018 15:33:31 +0200 Subject: [PATCH 01/14] +Esp.getHeapUnfragness() --- cores/esp8266/Esp-unfragness.cpp | 37 +++++++++++++++++++++++++++ cores/esp8266/Esp.h | 1 + cores/esp8266/umm_malloc/umm_malloc.c | 8 ++++++ cores/esp8266/umm_malloc/umm_malloc.h | 2 ++ libraries/esp8266/keywords.txt | 1 + 5 files changed, 49 insertions(+) create mode 100644 cores/esp8266/Esp-unfragness.cpp diff --git a/cores/esp8266/Esp-unfragness.cpp b/cores/esp8266/Esp-unfragness.cpp new file mode 100644 index 0000000000..8340138677 --- /dev/null +++ b/cores/esp8266/Esp-unfragness.cpp @@ -0,0 +1,37 @@ +/* + Esp.cpp - ESP8266-specific APIs + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 + */ + +#include "umm_malloc/umm_malloc.h" +#include "umm_malloc/umm_malloc_cfg.h" +#include "coredecls.h" +#include "Esp.h" + +uint16_t EspClass::getHeapUnfragness(uint32_t* freeHeap) +{ + ummFreeSize2 = 1; // enable processing + umm_info(NULL, 0); + ummFreeSize2 -= 1; + uint32_t fh = ummHeapInfo.freeBlocks * umm_block_size(); + uint16_t ret = 1000.0 * sqrt(ummFreeSize2) / fh; + ummFreeSize2 = 0; // disable processing + if (freeHeap) + *freeHeap = fh; + return ret; +} diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 60747251cf..eae732d3e0 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -104,6 +104,7 @@ class EspClass { uint16_t getVcc(); uint32_t getFreeHeap(); + uint16_t getHeapUnfragness(uint32_t* freeHeap); uint32_t getChipId(); diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index d65eac781d..1cb56b38cf 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -976,6 +976,7 @@ static void *get_unpoisoned( unsigned char *ptr ) { */ UMM_HEAP_INFO ummHeapInfo; +uint64_t ummFreeSize2; void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { @@ -1024,6 +1025,8 @@ void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) { ++ummHeapInfo.freeEntries; ummHeapInfo.freeBlocks += curBlocks; + if (ummFreeSize2) + ummFreeSize2 += (uint64_t)curBlocks * (uint64_t)sizeof(umm_block) * (uint64_t)curBlocks * (uint64_t)sizeof(umm_block); if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) { ummHeapInfo.maxFreeContiguousBlocks = curBlocks; @@ -1204,6 +1207,7 @@ void umm_init( void ) { 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); + ummFreeSize2 = 0; /* setup initial blank heap structure */ { @@ -1761,4 +1765,8 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) { return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block); } +size_t ICACHE_FLASH_ATTR umm_block_size( void ) { + return sizeof(umm_block); +} + /* ------------------------------------------------------------------------ */ diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 0019b0ec50..d725bae9bd 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -29,6 +29,7 @@ typedef struct UMM_HEAP_INFO_t { } UMM_HEAP_INFO; +extern uint64_t ummFreeSize2; extern UMM_HEAP_INFO ummHeapInfo; void umm_init( void ); @@ -41,6 +42,7 @@ void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); +size_t umm_block_size ( void ); #ifdef __cplusplus } diff --git a/libraries/esp8266/keywords.txt b/libraries/esp8266/keywords.txt index 91d90b0ad6..a0163c7911 100644 --- a/libraries/esp8266/keywords.txt +++ b/libraries/esp8266/keywords.txt @@ -29,6 +29,7 @@ reset KEYWORD2 restart KEYWORD2 getVcc KEYWORD2 getFreeHeap KEYWORD2 +getHeapUnfragness KEYWORD2 getChipId KEYWORD2 getSdkVersion KEYWORD2 getCoreVersion KEYWORD2 From 83b44d79af67f3955f54cfa7f824f13188e3a4d9 Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Tue, 28 Aug 2018 18:44:31 +0200 Subject: [PATCH 02/14] only in debug mode --- cores/esp8266/Esp-unfragness.cpp | 4 ++++ cores/esp8266/umm_malloc/umm_malloc.c | 13 ++++++++++++- cores/esp8266/umm_malloc/umm_malloc.h | 5 ++++- libraries/esp8266/keywords.txt | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/Esp-unfragness.cpp b/cores/esp8266/Esp-unfragness.cpp index 8340138677..b80e0c27e2 100644 --- a/cores/esp8266/Esp-unfragness.cpp +++ b/cores/esp8266/Esp-unfragness.cpp @@ -18,6 +18,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef DEBUG_ESP_PORT + #include "umm_malloc/umm_malloc.h" #include "umm_malloc/umm_malloc_cfg.h" #include "coredecls.h" @@ -35,3 +37,5 @@ uint16_t EspClass::getHeapUnfragness(uint32_t* freeHeap) *freeHeap = fh; return ret; } + +#endif // defined(DEBUG_ESP_PORT) diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index 1cb56b38cf..75af0286ab 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -976,7 +976,10 @@ static void *get_unpoisoned( unsigned char *ptr ) { */ UMM_HEAP_INFO ummHeapInfo; + +#ifdef DEBUG_ESP_PORT uint64_t ummFreeSize2; +#endif void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { @@ -1025,8 +1028,11 @@ void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) { ++ummHeapInfo.freeEntries; ummHeapInfo.freeBlocks += curBlocks; + +#ifdef DEBUG_ESP_PORT if (ummFreeSize2) ummFreeSize2 += (uint64_t)curBlocks * (uint64_t)sizeof(umm_block) * (uint64_t)curBlocks * (uint64_t)sizeof(umm_block); +#endif if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) { ummHeapInfo.maxFreeContiguousBlocks = curBlocks; @@ -1207,8 +1213,9 @@ void umm_init( void ) { 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); +#ifdef DEBUG_ESP_PORT ummFreeSize2 = 0; - +#endif /* setup initial blank heap structure */ { /* index of the 0th `umm_block` */ @@ -1765,8 +1772,12 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) { return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block); } +#ifdef DEBUG_ESP_PORT + size_t ICACHE_FLASH_ATTR umm_block_size( void ) { return sizeof(umm_block); } +#endif + /* ------------------------------------------------------------------------ */ diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index d725bae9bd..f301f0b2f7 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -29,7 +29,6 @@ typedef struct UMM_HEAP_INFO_t { } UMM_HEAP_INFO; -extern uint64_t ummFreeSize2; extern UMM_HEAP_INFO ummHeapInfo; void umm_init( void ); @@ -42,7 +41,11 @@ void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); + +#ifdef DEBUG_ESP_PORT +extern uint64_t ummFreeSize2; size_t umm_block_size ( void ); +#endif #ifdef __cplusplus } diff --git a/libraries/esp8266/keywords.txt b/libraries/esp8266/keywords.txt index a0163c7911..aa4a273d00 100644 --- a/libraries/esp8266/keywords.txt +++ b/libraries/esp8266/keywords.txt @@ -33,6 +33,7 @@ getHeapUnfragness KEYWORD2 getChipId KEYWORD2 getSdkVersion KEYWORD2 getCoreVersion KEYWORD2 +getFullVersion KEYWORD2 getBootVersion KEYWORD2 getBootMode KEYWORD2 getCpuFreqMHz KEYWORD2 From 26d64a4086c975852cfed95532c8ece2e3a51520 Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Tue, 28 Aug 2018 18:50:03 +0200 Subject: [PATCH 03/14] default value --- cores/esp8266/Esp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index eae732d3e0..5bfdaa11c6 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -104,7 +104,7 @@ class EspClass { uint16_t getVcc(); uint32_t getFreeHeap(); - uint16_t getHeapUnfragness(uint32_t* freeHeap); + uint16_t getHeapUnfragness(uint32_t* freeHeap = nullptr); uint32_t getChipId(); From 8f22381b3d8c0f570bb60f734b7e862c0f72675b Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Wed, 29 Aug 2018 11:53:49 +0200 Subject: [PATCH 04/14] always enable, 64->32, light 32 integer square root, comments --- cores/esp8266/Esp-unfragness.cpp | 14 +++++--------- cores/esp8266/coredecls.h | 3 +++ cores/esp8266/isqrt.c | 21 +++++++++++++++++++++ cores/esp8266/umm_malloc/umm_malloc.c | 13 +------------ cores/esp8266/umm_malloc/umm_malloc.h | 3 ++- 5 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 cores/esp8266/isqrt.c diff --git a/cores/esp8266/Esp-unfragness.cpp b/cores/esp8266/Esp-unfragness.cpp index b80e0c27e2..d83c1f4b36 100644 --- a/cores/esp8266/Esp-unfragness.cpp +++ b/cores/esp8266/Esp-unfragness.cpp @@ -18,8 +18,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef DEBUG_ESP_PORT - #include "umm_malloc/umm_malloc.h" #include "umm_malloc/umm_malloc_cfg.h" #include "coredecls.h" @@ -27,15 +25,13 @@ uint16_t EspClass::getHeapUnfragness(uint32_t* freeHeap) { - ummFreeSize2 = 1; // enable processing + // L2 / Euclidian norm of free block sizes. + // Having getFreeHeap()=sum(hole-size), un-fragmentation is given by + // sqrt(sum(hole-size²)) / sum(hole-size) + umm_info(NULL, 0); - ummFreeSize2 -= 1; uint32_t fh = ummHeapInfo.freeBlocks * umm_block_size(); - uint16_t ret = 1000.0 * sqrt(ummFreeSize2) / fh; - ummFreeSize2 = 0; // disable processing if (freeHeap) *freeHeap = fh; - return ret; + return (isqrt32(ummHeapInfo.ummFreeSize2) * 1000) / fh; } - -#endif // defined(DEBUG_ESP_PORT) diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 39cedf557c..ed13da34ab 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -8,6 +8,7 @@ extern "C" { // TODO: put declarations here, get rid of -Wno-implicit-function-declaration +#include <stdint.h> #include <cont.h> // g_pcont declaration extern bool timeshift64_is_set; @@ -18,6 +19,8 @@ void tune_timeshift64 (uint64_t now_us); void settimeofday_cb (void (*cb)(void)); void disable_extra4k_at_link_time (void) __attribute__((noinline)); +uint32_t isqrt32 (uint32_t n); + #ifdef __cplusplus } #endif diff --git a/cores/esp8266/isqrt.c b/cores/esp8266/isqrt.c new file mode 100644 index 0000000000..1bd6753aa8 --- /dev/null +++ b/cores/esp8266/isqrt.c @@ -0,0 +1,21 @@ + +#include <coredecls.h> +#include <stdint.h> + +uint32_t isqrt32 (uint32_t n) +{ + // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C + + unsigned int c = 0x8000; + unsigned int g = 0x8000; + + for(;;) + { + if (g*g > n) + g ^= c; + c >>= 1; + if (!c) + return g; + g |= c; + } +} diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index 75af0286ab..91d0283afb 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -977,10 +977,6 @@ static void *get_unpoisoned( unsigned char *ptr ) { UMM_HEAP_INFO ummHeapInfo; -#ifdef DEBUG_ESP_PORT -uint64_t ummFreeSize2; -#endif - void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { unsigned short int blockNo = 0; @@ -1028,11 +1024,7 @@ void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) { ++ummHeapInfo.freeEntries; ummHeapInfo.freeBlocks += curBlocks; - -#ifdef DEBUG_ESP_PORT - if (ummFreeSize2) - ummFreeSize2 += (uint64_t)curBlocks * (uint64_t)sizeof(umm_block) * (uint64_t)curBlocks * (uint64_t)sizeof(umm_block); -#endif + ummHeapInfo.ummFreeSize2 += (uint32_t)curBlocks * (uint32_t)sizeof(umm_block) * (uint32_t)curBlocks * (uint32_t)sizeof(umm_block); if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) { ummHeapInfo.maxFreeContiguousBlocks = curBlocks; @@ -1213,9 +1205,6 @@ void umm_init( void ) { 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); -#ifdef DEBUG_ESP_PORT - ummFreeSize2 = 0; -#endif /* setup initial blank heap structure */ { /* index of the 0th `umm_block` */ diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index f301f0b2f7..95f5c6bbc9 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -26,6 +26,8 @@ typedef struct UMM_HEAP_INFO_t { unsigned short int freeBlocks; unsigned short int maxFreeContiguousBlocks; + + uint32_t ummFreeSize2; } UMM_HEAP_INFO; @@ -43,7 +45,6 @@ void umm_free( void *ptr ); size_t umm_free_heap_size( void ); #ifdef DEBUG_ESP_PORT -extern uint64_t ummFreeSize2; size_t umm_block_size ( void ); #endif From 9bce009ea181af66b445b09e74dda711481f0c1d Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Wed, 29 Aug 2018 12:05:27 +0200 Subject: [PATCH 05/14] fix when debugging is disabled --- cores/esp8266/umm_malloc/umm_malloc.c | 4 ---- cores/esp8266/umm_malloc/umm_malloc.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index 91d0283afb..bbcb506825 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -1761,12 +1761,8 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) { return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block); } -#ifdef DEBUG_ESP_PORT - size_t ICACHE_FLASH_ATTR umm_block_size( void ) { return sizeof(umm_block); } -#endif - /* ------------------------------------------------------------------------ */ diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 95f5c6bbc9..22fd05892d 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -43,10 +43,7 @@ void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); - -#ifdef DEBUG_ESP_PORT size_t umm_block_size ( void ); -#endif #ifdef __cplusplus } From 08b23042e94f70ef3c680f37b216042a11781ef8 Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Wed, 29 Aug 2018 12:13:30 +0200 Subject: [PATCH 06/14] give credits --- cores/esp8266/isqrt.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cores/esp8266/isqrt.c b/cores/esp8266/isqrt.c index 1bd6753aa8..90e6ae9cce 100644 --- a/cores/esp8266/isqrt.c +++ b/cores/esp8266/isqrt.c @@ -5,7 +5,12 @@ uint32_t isqrt32 (uint32_t n) { // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C + // Another very fast algorithm donated by Tristan Muntsinger + // (Tristan.Muntsinger@gmail.com) is below. + // (note: tested across the full 32 bits range, see comment below) + // 15 iterations (c=1<<15) + unsigned int c = 0x8000; unsigned int g = 0x8000; @@ -19,3 +24,30 @@ uint32_t isqrt32 (uint32_t n) g |= c; } } + +/* tested with: + +#include <stdio.h> +#include <stdint.h> +#include <math.h> + +int main (void) +{ + for (uint32_t i = 0; ++i; ) + { + uint32_t sr = isqrt32(i); + uint32_t ifsr = sqrt(i); + + if (ifsr != sr) + printf("%d: i%d f%d\n", i, sr, ifsr); + + if (!(i & 0xffffff)) + { + printf("%i%% (0x%08x)\r", ((i >> 16) * 100) >> 16, i); + fflush(stdout); + } + } + + printf("\n"); +} +*/ From f55f0bac036ebb81ed55ec695d7e03f7fafae4a4 Mon Sep 17 00:00:00 2001 From: David Gauchard <gauchard@laas.fr> Date: Wed, 29 Aug 2018 12:32:05 +0200 Subject: [PATCH 07/14] cosmetics --- cores/esp8266/umm_malloc/umm_malloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index bbcb506825..a3c6dd2756 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -1205,6 +1205,7 @@ void umm_init( void ) { 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); + /* setup initial blank heap structure */ { /* index of the 0th `umm_block` */ From 0d2f7a02bfe3515149ef17a2b2fce0f0552cb922 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 4 Sep 2018 22:32:52 +0200 Subject: [PATCH 08/14] fragmentation metric updates (doc, better api, added getMaxFreeBlockSize()) --- cores/esp8266/{Esp-unfragness.cpp => Esp-frag.cpp} | 9 ++++++--- cores/esp8266/Esp.cpp | 5 +++++ cores/esp8266/Esp.h | 3 ++- cores/esp8266/coredecls.h | 2 +- cores/esp8266/{isqrt.c => sqrt32.c} | 6 +++--- cores/esp8266/umm_malloc/umm_malloc.c | 5 +++++ cores/esp8266/umm_malloc/umm_malloc.h | 1 + doc/faq/a02-my-esp-crashes.rst | 9 ++++++--- doc/libraries.rst | 4 ++++ libraries/esp8266/keywords.txt | 3 ++- 10 files changed, 35 insertions(+), 12 deletions(-) rename cores/esp8266/{Esp-unfragness.cpp => Esp-frag.cpp} (78%) rename cores/esp8266/{isqrt.c => sqrt32.c} (93%) diff --git a/cores/esp8266/Esp-unfragness.cpp b/cores/esp8266/Esp-frag.cpp similarity index 78% rename from cores/esp8266/Esp-unfragness.cpp rename to cores/esp8266/Esp-frag.cpp index d83c1f4b36..13a3874e1a 100644 --- a/cores/esp8266/Esp-unfragness.cpp +++ b/cores/esp8266/Esp-frag.cpp @@ -23,15 +23,18 @@ #include "coredecls.h" #include "Esp.h" -uint16_t EspClass::getHeapUnfragness(uint32_t* freeHeap) +uint8_t EspClass::getHeapFragmentation (uint32_t* freeHeap, uint16_t* maxBlock) { // L2 / Euclidian norm of free block sizes. // Having getFreeHeap()=sum(hole-size), un-fragmentation is given by // sqrt(sum(hole-size²)) / sum(hole-size) umm_info(NULL, 0); - uint32_t fh = ummHeapInfo.freeBlocks * umm_block_size(); + uint32_t block_size = umm_block_size(); + uint32_t fh = ummHeapInfo.freeBlocks * block_size; if (freeHeap) *freeHeap = fh; - return (isqrt32(ummHeapInfo.ummFreeSize2) * 1000) / fh; + if (maxBlock) + *maxBlock = ummHeapInfo.maxFreeContiguousBlocks * block_size; + return 100 - (sqrt32(ummHeapInfo.ummFreeSize2) * 100) / fh; } diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 055ea74637..79e35c2bf2 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -171,6 +171,11 @@ uint32_t EspClass::getFreeHeap(void) return system_get_free_heap_size(); } +uint16_t EspClass::getMaxFreeBlockSize(void) +{ + return system_get_free_heap_size(); +} + uint32_t EspClass::getChipId(void) { return system_get_chip_id(); diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 5bfdaa11c6..3e92c89cce 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -104,7 +104,8 @@ class EspClass { uint16_t getVcc(); uint32_t getFreeHeap(); - uint16_t getHeapUnfragness(uint32_t* freeHeap = nullptr); + uint16_t getMaxFreeBlockSize(); + uint8_t getHeapFragmentation(uint32_t* freeHeap = nullptr, uint16_t* maxBlock = nullptr); // in % uint32_t getChipId(); diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index ed13da34ab..3ac87eee9f 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -19,7 +19,7 @@ void tune_timeshift64 (uint64_t now_us); void settimeofday_cb (void (*cb)(void)); void disable_extra4k_at_link_time (void) __attribute__((noinline)); -uint32_t isqrt32 (uint32_t n); +uint32_t sqrt32 (uint32_t n); #ifdef __cplusplus } diff --git a/cores/esp8266/isqrt.c b/cores/esp8266/sqrt32.c similarity index 93% rename from cores/esp8266/isqrt.c rename to cores/esp8266/sqrt32.c index 90e6ae9cce..697ccd3bec 100644 --- a/cores/esp8266/isqrt.c +++ b/cores/esp8266/sqrt32.c @@ -2,7 +2,7 @@ #include <coredecls.h> #include <stdint.h> -uint32_t isqrt32 (uint32_t n) +uint32_t sqrt32 (uint32_t n) { // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C // Another very fast algorithm donated by Tristan Muntsinger @@ -10,7 +10,7 @@ uint32_t isqrt32 (uint32_t n) // (note: tested across the full 32 bits range, see comment below) // 15 iterations (c=1<<15) - + unsigned int c = 0x8000; unsigned int g = 0x8000; @@ -35,7 +35,7 @@ int main (void) { for (uint32_t i = 0; ++i; ) { - uint32_t sr = isqrt32(i); + uint32_t sr = sqrt32(i); uint32_t ifsr = sqrt(i); if (ifsr != sr) diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index a3c6dd2756..9e22a4496f 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -1762,6 +1762,11 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) { return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block); } +uint16_t ICACHE_FLASH_ATTR umm_max_block_size( void ) { + umm_info(NULL, 0); + return ummHeapInfo.maxFreeContiguousBlocks * sizeof(umm_block); +} + size_t ICACHE_FLASH_ATTR umm_block_size( void ) { return sizeof(umm_block); } diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 22fd05892d..7ff0034d39 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -43,6 +43,7 @@ void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); +uint16_t umm_max_block_size( void ); size_t umm_block_size ( void ); #ifdef __cplusplus diff --git a/doc/faq/a02-my-esp-crashes.rst b/doc/faq/a02-my-esp-crashes.rst index cb60e6b32f..460b1a2946 100644 --- a/doc/faq/a02-my-esp-crashes.rst +++ b/doc/faq/a02-my-esp-crashes.rst @@ -291,9 +291,12 @@ Memory, memory, memory rely on exceptions for error handling, which is not available for the ESP, and in any case there is no access to the underlying code. - Instrumenting the code with the OOM debug option and calls to ``ESP.getFreeHeap()`` will - help the process of finding leaks. Now is time to re-read about the - `exception decoder <#exception-decoder>`__. + Instrumenting the code with the OOM debug option and calls to + ``ESP.getFreeHeap()`` / ``ESP.getHeapFragmentation()`` / + ``ESP.getMaxFreeBlockSize()`` will help the process of finding memory issues. + + Now is time to re-read about the `exception decoder + <#exception-decoder>`__. *Some techniques for reducing memory usage* diff --git a/doc/libraries.rst b/doc/libraries.rst index ce22cb23ac..0c21580165 100644 --- a/doc/libraries.rst +++ b/doc/libraries.rst @@ -83,6 +83,10 @@ Some ESP-specific APIs related to deep sleep, RTC and flash memories are availab ``ESP.getFreeHeap()`` returns the free heap size. +``ESP.getHeapFragmentation()`` returns the fragmentation metric (0% is clean, more than ~50% is not harmless) + +``ESP.getMaxFreeBlockSize()`` returns the maximum allocatable ram block regarding heap fragmentation + ``ESP.getChipId()`` returns the ESP8266 chip ID as a 32-bit integer. ``ESP.getCoreVersion()`` returns a String containing the core version. diff --git a/libraries/esp8266/keywords.txt b/libraries/esp8266/keywords.txt index aa4a273d00..f6bb96b5d7 100644 --- a/libraries/esp8266/keywords.txt +++ b/libraries/esp8266/keywords.txt @@ -29,7 +29,8 @@ reset KEYWORD2 restart KEYWORD2 getVcc KEYWORD2 getFreeHeap KEYWORD2 -getHeapUnfragness KEYWORD2 +getHeapFragmentation KEYWORD2 +getMaxFreeBlockSize KEYWORD2 getChipId KEYWORD2 getSdkVersion KEYWORD2 getCoreVersion KEYWORD2 From 84c92b5c4c5d3166cebaab4ca12d2471051eae5b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 6 Sep 2018 22:13:13 +0200 Subject: [PATCH 09/14] api reworked, +example --- cores/esp8266/Esp-frag.cpp | 26 +++--- cores/esp8266/Esp.cpp | 3 +- cores/esp8266/Esp.h | 7 +- cores/esp8266/sqrt32.c | 11 ++- .../examples/HeapMetric/HeapMetric.ino | 80 +++++++++++++++++++ 5 files changed, 110 insertions(+), 17 deletions(-) create mode 100644 libraries/esp8266/examples/HeapMetric/HeapMetric.ino diff --git a/cores/esp8266/Esp-frag.cpp b/cores/esp8266/Esp-frag.cpp index 13a3874e1a..d888d70b92 100644 --- a/cores/esp8266/Esp-frag.cpp +++ b/cores/esp8266/Esp-frag.cpp @@ -23,18 +23,26 @@ #include "coredecls.h" #include "Esp.h" -uint8_t EspClass::getHeapFragmentation (uint32_t* freeHeap, uint16_t* maxBlock) +void EspClass::getHeapStats(uint32_t* free, uint16_t* max, uint8_t* frag) { // L2 / Euclidian norm of free block sizes. - // Having getFreeHeap()=sum(hole-size), un-fragmentation is given by - // sqrt(sum(hole-size²)) / sum(hole-size) + // Having getFreeHeap()=sum(hole-size), fragmentation is given by + // 100 * (1 - sqrt(sum(hole-size²)) / sum(hole-size)) umm_info(NULL, 0); - uint32_t block_size = umm_block_size(); + uint8_t block_size = umm_block_size(); uint32_t fh = ummHeapInfo.freeBlocks * block_size; - if (freeHeap) - *freeHeap = fh; - if (maxBlock) - *maxBlock = ummHeapInfo.maxFreeContiguousBlocks * block_size; - return 100 - (sqrt32(ummHeapInfo.ummFreeSize2) * 100) / fh; + if (free) + *free = fh; + if (max) + *max = ummHeapInfo.maxFreeContiguousBlocks * block_size; + if (frag) + *frag = 100 - (sqrt32(ummHeapInfo.ummFreeSize2) * 100) / fh; +} + +uint8_t EspClass::getHeapFragmentation() +{ + uint8_t frag; + getHeapStats(nullptr, nullptr, &frag); + return frag; } diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 79e35c2bf2..bc90bb416c 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -24,6 +24,7 @@ #include <memory> #include "interrupts.h" #include "MD5Builder.h" +#include "umm_malloc/umm_malloc.h" extern "C" { #include "user_interface.h" @@ -173,7 +174,7 @@ uint32_t EspClass::getFreeHeap(void) uint16_t EspClass::getMaxFreeBlockSize(void) { - return system_get_free_heap_size(); + return umm_max_block_size(); } uint32_t EspClass::getChipId(void) diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 3e92c89cce..226119f071 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -103,11 +103,12 @@ class EspClass { void restart(); uint16_t getVcc(); + uint32_t getChipId(); + uint32_t getFreeHeap(); uint16_t getMaxFreeBlockSize(); - uint8_t getHeapFragmentation(uint32_t* freeHeap = nullptr, uint16_t* maxBlock = nullptr); // in % - - uint32_t getChipId(); + uint8_t getHeapFragmentation(); // in % + void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr); const char * getSdkVersion(); String getCoreVersion(); diff --git a/cores/esp8266/sqrt32.c b/cores/esp8266/sqrt32.c index 697ccd3bec..af6ffa495f 100644 --- a/cores/esp8266/sqrt32.c +++ b/cores/esp8266/sqrt32.c @@ -5,8 +5,7 @@ uint32_t sqrt32 (uint32_t n) { // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C - // Another very fast algorithm donated by Tristan Muntsinger - // (Tristan.Muntsinger@gmail.com) is below. + // Another very fast algorithm donated by Tristan.Muntsinger@gmail.com // (note: tested across the full 32 bits range, see comment below) // 15 iterations (c=1<<15) @@ -25,7 +24,9 @@ uint32_t sqrt32 (uint32_t n) } } -/* tested with: +/* + * tested with: + * #include <stdio.h> #include <stdint.h> @@ -50,4 +51,6 @@ int main (void) printf("\n"); } -*/ + + * + */ diff --git a/libraries/esp8266/examples/HeapMetric/HeapMetric.ino b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino new file mode 100644 index 0000000000..1d8ca97599 --- /dev/null +++ b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino @@ -0,0 +1,80 @@ + +// nothing else than showing heap metric usage +// released to public domain + +#include <ESP8266WiFi.h> + +void stats (const char* what) +{ + // we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation() + // or all at once: + uint32_t free; + uint16_t max; + uint8_t frag; + ESP.getHeapStats(&free, &max, &frag); + + Serial.printf("free: %5d - max: %5d - frag: %3d%% <- ", free, max, frag); + // %s requires a malloc that could fail, using println instead: + Serial.println(what); +} + +void tryit (int blocksize) +{ + void** p; + int blocks; + + // heap-used ~= blocks*sizeof(void*) + blocks*blocksize + blocks = ((ESP.getMaxFreeBlockSize() / (blocksize + sizeof(void*))) + 3) & ~3; // rounded up, multiple of 4 + + Serial.printf("\nFilling memory with blocks of %d bytes each\n", blocksize); + stats("before"); + + p = (void**)malloc(sizeof(void*) * blocks); + for (int i = 0; i < blocks; i++) + p[i] = malloc(blocksize); + stats("array and blocks allocation"); + + for (int i = 0; i < blocks; i += 2) + { + if (p[i]) + free(p[i]); + p[i] = nullptr; + } + stats("freeing every other blocks"); + + for (int i = 0; i < blocks; i += 4) + { + if (p[i + 1]) + free(p[i + 1]); + p[i + 1] = nullptr; + } + stats("freeing every other remaining blocks"); + + for (int i = 0; i < blocks; i++) + if (p[i]) + free(p[i]); + stats("freeing array"); + + free(p); + stats("after"); +} + +void setup() +{ + Serial.begin(115200); + WiFi.mode(WIFI_OFF); + + tryit(8000); + tryit(4000); + tryit(2000); + tryit(1000); + tryit(500); + tryit(200); + tryit(100); + tryit(50); + tryit(15); +} + +void loop () +{ +} From e93e9f6b5a7a44cbe953ae0b5743c1fa636bd52f Mon Sep 17 00:00:00 2001 From: Develo <deveyes@gmail.com> Date: Fri, 7 Sep 2018 15:07:59 -0300 Subject: [PATCH 10/14] read all lines from slow servers (#5113) Replaces #1829 --- libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino index 6634a53e6e..c0e3ee6d73 100644 --- a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino +++ b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino @@ -85,7 +85,7 @@ void loop() { } // Read all the lines of the reply from server and print them to Serial - while (client.available()) { + while (client.available() || client.connected()) { String line = client.readStringUntil('\r'); Serial.print(line); } From fc9631275b139bd3e58fe788f4b63d480a58ea03 Mon Sep 17 00:00:00 2001 From: yoursunny <sunnylandh@gmail.com> Date: Sat, 8 Sep 2018 23:34:20 -0400 Subject: [PATCH 11/14] ESP8266HTTPClient: allow getString() more than once (#5091) fixes #4951 --- .../src/ESP8266HTTPClient.cpp | 31 ++++++++++++++----- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 6 +++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 28a3503484..f04a1d7043 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -33,7 +33,7 @@ class TransportTraits { public: - virtual ~TransportTraits() + virtual ~TransportTraits() { } @@ -126,6 +126,7 @@ void HTTPClient::clear() _returnCode = 0; _size = -1; _headers = ""; + _payload.reset(); } @@ -281,6 +282,16 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, const uint8_t htt * called after the payload is handled */ void HTTPClient::end(void) +{ + disconnect(); + clear(); +} + +/** + * disconnect + * close the TCP socket + */ +void HTTPClient::disconnect() { if(connected()) { if(_tcp->available() > 0) { @@ -734,7 +745,7 @@ int HTTPClient::writeToStream(Stream * stream) return returnError(HTTPC_ERROR_ENCODING); } - end(); + disconnect(); return ret; } @@ -742,20 +753,24 @@ int HTTPClient::writeToStream(Stream * stream) * return all payload as String (may need lot of ram or trigger out of memory!) * @return String */ -String HTTPClient::getString(void) +const String& HTTPClient::getString(void) { - StreamString sstring; + if (_payload) { + return *_payload; + } + + _payload.reset(new StreamString()); if(_size) { // try to reserve needed memmory - if(!sstring.reserve((_size + 1))) { + if(!_payload->reserve((_size + 1))) { DEBUG_HTTPCLIENT("[HTTP-Client][getString] not enough memory to reserve a string! need: %d\n", (_size + 1)); - return ""; + return *_payload; } } - writeToStream(&sstring); - return sstring; + writeToStream(_payload.get()); + return *_payload; } /** diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 72b42853f7..c0332ffeda 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -127,6 +127,8 @@ typedef enum { class TransportTraits; typedef std::unique_ptr<TransportTraits> TransportTraitsPtr; +class StreamString; + class HTTPClient { public: @@ -185,7 +187,7 @@ class HTTPClient WiFiClient& getStream(void); WiFiClient* getStreamPtr(void); int writeToStream(Stream* stream); - String getString(void); + const String& getString(void); static String errorToString(int error); @@ -196,6 +198,7 @@ class HTTPClient }; bool beginInternal(String url, const char* expectedProtocol); + void disconnect(); void clear(); int returnError(int error); bool connect(void); @@ -228,6 +231,7 @@ class HTTPClient int _size = -1; bool _canReuse = false; transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; + std::unique_ptr<StreamString> _payload; }; From ab5a94d50baeb0f2f7b387ad13683fb1ed34a5a0 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 9 Sep 2018 23:16:35 +0200 Subject: [PATCH 12/14] fixe types, fix names --- cores/esp8266/Esp-frag.cpp | 20 ++++++++++---------- cores/esp8266/umm_malloc/umm_malloc.c | 7 +++++-- cores/esp8266/umm_malloc/umm_malloc.h | 6 +++--- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/cores/esp8266/Esp-frag.cpp b/cores/esp8266/Esp-frag.cpp index d888d70b92..34185a4727 100644 --- a/cores/esp8266/Esp-frag.cpp +++ b/cores/esp8266/Esp-frag.cpp @@ -23,7 +23,7 @@ #include "coredecls.h" #include "Esp.h" -void EspClass::getHeapStats(uint32_t* free, uint16_t* max, uint8_t* frag) +void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag) { // L2 / Euclidian norm of free block sizes. // Having getFreeHeap()=sum(hole-size), fragmentation is given by @@ -32,17 +32,17 @@ void EspClass::getHeapStats(uint32_t* free, uint16_t* max, uint8_t* frag) umm_info(NULL, 0); uint8_t block_size = umm_block_size(); uint32_t fh = ummHeapInfo.freeBlocks * block_size; - if (free) - *free = fh; - if (max) - *max = ummHeapInfo.maxFreeContiguousBlocks * block_size; - if (frag) - *frag = 100 - (sqrt32(ummHeapInfo.ummFreeSize2) * 100) / fh; + if (hfree) + *hfree = fh; + if (hmax) + *hmax = ummHeapInfo.maxFreeContiguousBlocks * block_size; + if (hfrag) + *hfrag = 100 - (sqrt32(ummHeapInfo.freeSize2) * 100) / fh; } uint8_t EspClass::getHeapFragmentation() { - uint8_t frag; - getHeapStats(nullptr, nullptr, &frag); - return frag; + uint8_t hfrag; + getHeapStats(nullptr, nullptr, &hfrag); + return hfrag; } diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index 9e22a4496f..c86142b27e 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -1024,7 +1024,10 @@ void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) { if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) { ++ummHeapInfo.freeEntries; ummHeapInfo.freeBlocks += curBlocks; - ummHeapInfo.ummFreeSize2 += (uint32_t)curBlocks * (uint32_t)sizeof(umm_block) * (uint32_t)curBlocks * (uint32_t)sizeof(umm_block); + ummHeapInfo.freeSize2 += (unsigned int)curBlocks + * (unsigned int)sizeof(umm_block) + * (unsigned int)curBlocks + * (unsigned int)sizeof(umm_block); if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) { ummHeapInfo.maxFreeContiguousBlocks = curBlocks; @@ -1762,7 +1765,7 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) { return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block); } -uint16_t ICACHE_FLASH_ATTR umm_max_block_size( void ) { +size_t ICACHE_FLASH_ATTR umm_max_block_size( void ) { umm_info(NULL, 0); return ummHeapInfo.maxFreeContiguousBlocks * sizeof(umm_block); } diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 7ff0034d39..fcb1ade824 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -27,7 +27,7 @@ typedef struct UMM_HEAP_INFO_t { unsigned short int maxFreeContiguousBlocks; - uint32_t ummFreeSize2; + unsigned int freeSize2; } UMM_HEAP_INFO; @@ -43,8 +43,8 @@ void *umm_realloc( void *ptr, size_t size ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); -uint16_t umm_max_block_size( void ); -size_t umm_block_size ( void ); +size_t umm_max_block_size( void ); +size_t umm_block_size( void ); #ifdef __cplusplus } From 19a34884fa596ac59703b5489691aa8d1177599f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 9 Sep 2018 23:57:49 +0200 Subject: [PATCH 13/14] coding style fix --- .../examples/HeapMetric/HeapMetric.ino | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/esp8266/examples/HeapMetric/HeapMetric.ino b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino index 1d8ca97599..3aada4c2a7 100644 --- a/libraries/esp8266/examples/HeapMetric/HeapMetric.ino +++ b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino @@ -4,22 +4,20 @@ #include <ESP8266WiFi.h> -void stats (const char* what) -{ +void stats (const char* what) { // we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation() // or all at once: uint32_t free; uint16_t max; uint8_t frag; ESP.getHeapStats(&free, &max, &frag); - + Serial.printf("free: %5d - max: %5d - frag: %3d%% <- ", free, max, frag); // %s requires a malloc that could fail, using println instead: Serial.println(what); } -void tryit (int blocksize) -{ +void tryit (int blocksize) { void** p; int blocks; @@ -30,37 +28,39 @@ void tryit (int blocksize) stats("before"); p = (void**)malloc(sizeof(void*) * blocks); - for (int i = 0; i < blocks; i++) + for (int i = 0; i < blocks; i++) { p[i] = malloc(blocksize); + } stats("array and blocks allocation"); - for (int i = 0; i < blocks; i += 2) - { - if (p[i]) + for (int i = 0; i < blocks; i += 2) { + if (p[i]) { free(p[i]); + } p[i] = nullptr; } stats("freeing every other blocks"); - for (int i = 0; i < blocks; i += 4) - { - if (p[i + 1]) + for (int i = 0; i < blocks; i += 4) { + if (p[i + 1]) { free(p[i + 1]); + } p[i + 1] = nullptr; } stats("freeing every other remaining blocks"); - for (int i = 0; i < blocks; i++) - if (p[i]) + for (int i = 0; i < blocks; i++) { + if (p[i]) { free(p[i]); + } + } stats("freeing array"); free(p); stats("after"); } -void setup() -{ +void setup() { Serial.begin(115200); WiFi.mode(WIFI_OFF); @@ -75,6 +75,5 @@ void setup() tryit(15); } -void loop () -{ +void loop () { } From 469729a4f2deac21b90b291cd847ad35bd771fa5 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 10 Sep 2018 01:13:05 +0200 Subject: [PATCH 14/14] use astyle for example --- libraries/esp8266/examples/HeapMetric/HeapMetric.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/esp8266/examples/HeapMetric/HeapMetric.ino b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino index 3aada4c2a7..c9ad8abba4 100644 --- a/libraries/esp8266/examples/HeapMetric/HeapMetric.ino +++ b/libraries/esp8266/examples/HeapMetric/HeapMetric.ino @@ -4,7 +4,7 @@ #include <ESP8266WiFi.h> -void stats (const char* what) { +void stats(const char* what) { // we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation() // or all at once: uint32_t free; @@ -17,7 +17,7 @@ void stats (const char* what) { Serial.println(what); } -void tryit (int blocksize) { +void tryit(int blocksize) { void** p; int blocks; @@ -75,5 +75,5 @@ void setup() { tryit(15); } -void loop () { +void loop() { }