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() {
 }