diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index 2357638..6694244 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -123,15 +123,13 @@ void loop() LCDDisplay::loop(); // ignored if LCD not in use -// Optionally report any decrease in memory (will automatically trigger on first call) -#if ENABLE_FREE_MEM_WARNING - static int ramLowWatermark = 32767; // replaced on first loop + // Report any decrease in memory (will automatically trigger on first call) + static int ramLowWatermark = __INT_MAX__; // replaced on first loop - int freeNow = updateMinimumFreeMemory(); + int freeNow = minimumFreeMemory(); if (freeNow < ramLowWatermark) { ramLowWatermark = freeNow; LCD(2,F("Free RAM=%5db"), ramLowWatermark); } -#endif } diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index e0496cc..2556cc2 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -720,7 +720,7 @@ bool DCCEXParser::parseD(Print *stream, int params, int p[]) return true; case HASH_KEYWORD_RAM: // - StringFormatter::send(stream, F("\nFree memory=%d\n"), freeMemory()); + StringFormatter::send(stream, F("\nFree memory=%d\n"), minimumFreeMemory()); break; case HASH_KEYWORD_ACK: // diff --git a/config.example.h b/config.example.h index f528b3e..b4751b5 100644 --- a/config.example.h +++ b/config.example.h @@ -111,6 +111,4 @@ The configuration file for DCC-EX Command Station // #define OLED_DRIVER 128,32 ///////////////////////////////////////////////////////////////////////////////////// -// -// Enable warning as memory gets depleted -#define ENABLE_FREE_MEM_WARNING false + diff --git a/freeMemory.cpp b/freeMemory.cpp index 6735ac1..f640abe 100644 --- a/freeMemory.cpp +++ b/freeMemory.cpp @@ -18,6 +18,7 @@ * along with CommandStation. If not, see . */ +#include #include "freeMemory.h" // thanks go to https://github.com/mpflaga/Arduino-MemoryFree @@ -31,25 +32,40 @@ extern char *__malloc_heap_start; #endif -static volatile int minimum_free_memory = 32767; +static volatile int minimum_free_memory = __INT_MAX__; -int freeMemory() { +static inline int freeMemory() { char top; #if defined(__arm__) return &top - reinterpret_cast(sbrk(0)); #elif defined(__AVR__) return __brkval ? &top - __brkval : &top - __malloc_heap_start; #else -#error bailed out alredy above +#error bailed out already above #endif } // Update low ram level. Allow for extra bytes to be specified // by estimation or inspection, that may be used by other -// called subroutines. -int updateMinimumFreeMemory(unsigned char extraBytes) { +// called subroutines. Must be called with interrupts disabled. +// +// Although __brkval may go up and down as heap memory is allocated +// and freed, this function records only the worst case encountered. +// So even if all of the heap is freed, the reported minimum free +// memory will not increase. +// +void updateMinimumFreeMemory(unsigned char extraBytes) { int spare = freeMemory()-extraBytes; + if (spare < 0) spare = 0; if (spare < minimum_free_memory) minimum_free_memory = spare; - return minimum_free_memory; +} + +// Return low memory value. +int minimumFreeMemory() { + byte sreg_save = SREG; + noInterrupts(); // Disable interrupts + int retval = minimum_free_memory; + SREG = sreg_save; // Restore interrupt state + return retval; } diff --git a/freeMemory.h b/freeMemory.h index bf93189..3d1fe40 100644 --- a/freeMemory.h +++ b/freeMemory.h @@ -20,6 +20,6 @@ #ifndef freeMemory_h #define freeMemory_h -int freeMemory(); -int updateMinimumFreeMemory(unsigned char extraBytes=0); +void updateMinimumFreeMemory(unsigned char extraBytes=0); +int minimumFreeMemory(); #endif