diff --git a/Marlin/M100_Free_Mem_Chk.cpp b/Marlin/M100_Free_Mem_Chk.cpp
index de61d5bb22e..08236ff95e1 100644
--- a/Marlin/M100_Free_Mem_Chk.cpp
+++ b/Marlin/M100_Free_Mem_Chk.cpp
@@ -38,6 +38,11 @@
  * M100 C x Corrupts x locations within the free memory block. This is useful to check the
  *          correctness of the M100 F and M100 D commands.
  *
+ * Also, there are two support functions that can be called from a developer's C code.
+ *
+ *    uint16_t check_for_free_memory_corruption(char * const ptr);
+ *    void M100_dump_free_memory(char *ptr, char *sp);
+ *
  * Initial version by Roxy-3D
  */
 #define M100_FREE_MEMORY_DUMPER     // Enable for the `M110 D` Dump sub-command
@@ -47,7 +52,7 @@
 
 #if ENABLED(M100_FREE_MEMORY_WATCHER)
 
-#define TEST_BYTE 0xE5
+#define TEST_BYTE ((uint8_t) 0xE5)
 
 extern char* __brkval;
 extern size_t  __heap_start, __heap_end, __flp;
@@ -61,6 +66,7 @@ extern char __bss_end;
 //
 
 #define END_OF_HEAP() (__brkval ? __brkval : &__bss_end)
+int check_for_free_memory_corruption(char *title);
 
 // Location of a variable on its stack frame. Returns a value above
 // the stack (once the function returns to the caller).
@@ -70,7 +76,7 @@ char* top_of_stack() {
 }
 
 // Count the number of test bytes at the specified location.
-int16_t count_test_bytes(const char * const ptr) {
+int16_t count_test_bytes(const uint8_t * const ptr) {
   for (uint16_t i = 0; i < 32000; i++)
     if (ptr[i] != TEST_BYTE)
       return i - 1;
@@ -78,27 +84,6 @@ int16_t count_test_bytes(const char * const ptr) {
   return -1;
 }
 
-// Return a count of free memory blocks.
-uint16_t free_memory_is_corrupted(char * const ptr, const uint16_t size) {
-  // Find the longest block of test bytes in the given buffer
-  uint16_t block_cnt = 0;
-  for (uint16_t i = 0; i < size; i++) {
-    if (ptr[i] == TEST_BYTE) {
-      const uint16_t j = count_test_bytes(ptr + i);
-      if (j > 8) {
-        //SERIAL_ECHOPAIR("Found ", j);
-        //SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)ptr + i));
-        i += j;
-        block_cnt++;
-      }
-    }
-  }
-  //if (block_cnt > 1) {
-  //  SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
-  //  SERIAL_ECHOLNPAIR("\nLargest free block is ", max_cnt);
-  //}
-  return block_cnt;
-}
 
 //
 // M100 sub-commands
@@ -114,13 +99,13 @@ uint16_t free_memory_is_corrupted(char * const ptr, const uint16_t size) {
    *  the block. If so, it may indicate memory corruption due to a bad pointer.
    *  Unexpected bytes are flagged in the right column.
    */
-  void dump_free_memory(char *ptr, char *sp) {
+  void dump_free_memory(uint8_t *ptr, uint8_t *sp) {
     //
     // Start and end the dump on a nice 16 byte boundary
     // (even though the values are not 16-byte aligned).
     //
-    ptr = (char*)((uint16_t)ptr & 0xFFF0); // Align to 16-byte boundary
-    sp  = (char*)((uint16_t)sp  | 0x000F); // Align sp to the 15th byte (at or above sp)
+    ptr = (uint8_t *)((uint16_t)ptr & 0xFFF0); // Align to 16-byte boundary
+    sp  = (uint8_t *)((uint16_t)sp  | 0x000F); // Align sp to the 15th byte (at or above sp)
 
     // Dump command main loop
     while (ptr < sp) {
@@ -131,14 +116,30 @@ uint16_t free_memory_is_corrupted(char * const ptr, const uint16_t size) {
         print_hex_byte(ptr[i]);
         SERIAL_CHAR(' ');
       }
+      safe_delay(25);
       SERIAL_CHAR('|');                   // Point out non test bytes
       for (uint8_t i = 0; i < 16; i++)
         SERIAL_CHAR(ptr[i] == TEST_BYTE ? ' ' : '?');
       SERIAL_EOL;
       ptr += 16;
+      safe_delay(25);
       idle();
     }
   }
+
+void M100_dump_routine( char *title, char *start, char *end) {
+unsigned char c;
+int i;
+
+//
+// Round the start and end locations to produce full lines of output
+//
+      start = (char*) ((uint16_t) start & 0xfff0);
+      end   = (char*) ((uint16_t) end   | 0x000f);
+
+      SERIAL_ECHOLN(title);
+      dump_free_memory( start, end );
+}
 #endif // M100_FREE_MEMORY_DUMPER
 
 /**
@@ -172,7 +173,7 @@ void free_memory_pool_report(const char * const ptr, const uint16_t size) {
     SERIAL_ECHOPAIR("\nLargest free block is ", max_cnt);
     SERIAL_ECHOLNPAIR(" bytes at 0x", hex_word((uint16_t)max_addr));
   }
-  SERIAL_ECHOLNPAIR("free_memory_is_corrupted() = ", free_memory_is_corrupted(ptr, size));
+  SERIAL_ECHOLNPAIR("check_for_free_memory_corruption() = ", check_for_free_memory_corruption("M100 F "));
 }
 
 #if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
@@ -202,13 +203,17 @@ void free_memory_pool_report(const char * const ptr, const uint16_t size) {
  * M100 I
  *  Init memory for the M100 tests. (Automatically applied on the first M100.)
  */
-void init_free_memory(char *ptr, int16_t size) {
+void init_free_memory(uint8_t *ptr, int16_t size) {
   SERIAL_ECHOLNPGM("Initializing free memory block.\n\n");
 
   size -= 250;    // -250 to avoid interrupt activity that's altered the stack.
-  if (size < 0) return;
+  if (size < 0) {
+    SERIAL_ECHOLNPGM("Unable to initialize.\n");
+    return;
+  }
 
-  ptr += 8;
+  ptr += 8;       // move a few bytes away from the heap just because we don't want
+                  // to be altering memory that close to it.
   memset(ptr, TEST_BYTE, size);
 
   SERIAL_ECHO(size);
@@ -217,8 +222,7 @@ void init_free_memory(char *ptr, int16_t size) {
   for (uint16_t i = 0; i < size; i++) {
     if (ptr[i] != TEST_BYTE) {
       SERIAL_ECHOPAIR("? address : 0x", hex_word((uint16_t)ptr + i));
-      SERIAL_ECHOPAIR("=", hex_byte(ptr[i]));
-      SERIAL_EOL; SERIAL_EOL;
+      SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
     }
   }
 }
@@ -228,9 +232,9 @@ void init_free_memory(char *ptr, int16_t size) {
  */
 void gcode_M100() {
   SERIAL_ECHOPAIR("\n__brkval : 0x", hex_word((uint16_t)__brkval));
-  SERIAL_ECHOPAIR("\n__bss_end : 0x", hex_word((uint16_t)&__bss_end));
+  SERIAL_ECHOPAIR("\n__bss_end: 0x", hex_word((uint16_t)&__bss_end));
 
-  char *ptr = END_OF_HEAP(), *sp = top_of_stack();
+  uint8_t *ptr = END_OF_HEAP(), *sp = top_of_stack();
 
   SERIAL_ECHOPAIR("\nstart of free space : 0x", hex_word((uint16_t)ptr));
   SERIAL_ECHOLNPAIR("\nStack Pointer : 0x", hex_word((uint16_t)sp));
@@ -243,10 +247,8 @@ void gcode_M100() {
   }
 
   #if ENABLED(M100_FREE_MEMORY_DUMPER)
-
     if (code_seen('D'))
       return dump_free_memory(ptr, sp);
-
   #endif
 
   if (code_seen('F'))
@@ -260,4 +262,67 @@ void gcode_M100() {
   #endif
 }
 
+int check_for_free_memory_corruption(char *title) {
+  char *sp, *ptr;
+  int block_cnt = 0, i, j, n;
+
+    SERIAL_ECHO(title);
+
+    ptr = __brkval ? __brkval : &__bss_end;    
+    sp = top_of_stack();
+
+    n = sp - ptr;
+    SERIAL_ECHOPAIR("\nfmc() n=", n);
+    SERIAL_ECHOPAIR("\n&__brkval: 0x", hex_word((uint16_t)&__brkval));
+    SERIAL_ECHOPAIR("=0x",             hex_word((uint16_t)__brkval));
+    SERIAL_ECHOPAIR("\n__bss_end: 0x", hex_word((uint16_t)&__bss_end));
+    SERIAL_ECHOPAIR(" sp=", hex_word(sp));
+
+    if (sp < ptr)  {
+        SERIAL_ECHOPGM(" sp < Heap ");
+//      SET_INPUT_PULLUP(63);		// if the developer has a switch wired up to their controller board
+//      safe_delay(5);                  // this code can be enabled to pause the display as soon as the 
+//      while ( READ(63))               // malfunction is detected.   It is currently defaulting to a switch
+//        idle();                       // being on pin-63 which is unassigend and available on most controller 
+//      safe_delay(20);                 // boards.
+//      while ( !READ(63))
+//        idle();
+        safe_delay(20);
+        M100_dump_routine( "   Memory corruption detected with sp<Heap\n", (char *)0x1b80,  0x21ff );
+    }
+
+    // Scan through the range looking for the biggest block of 0xE5's we can find
+    for (i = 0; i < n; i++) {
+      if (*(ptr + i) == (char)0xe5) {
+        j = count_test_bytes(ptr + i);
+        if (j > 8) {
+//        SERIAL_ECHOPAIR("Found ", j);
+//        SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i)));
+
+          i += j;
+          block_cnt++;
+          SERIAL_ECHOPAIR(" (", block_cnt);
+          SERIAL_ECHOPAIR(") found=", j);
+          SERIAL_ECHOPGM("   ");
+        }
+      }
+    }
+    SERIAL_ECHOPAIR("  block_found=", block_cnt);
+
+    if ((block_cnt!=1) || (__brkval != 0x0000)) 
+      SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
+
+    if ((block_cnt==0))		       // Make sure the special case of no free blocks shows up as an
+      block_cnt = -1;                  // error to the calling code!
+
+    if (block_cnt==1) {              
+      SERIAL_ECHOPGM(" return=0\n");  // if the block_cnt is 1, nothing has broken up the free memory
+      return 0;                       // area and it is appropriate to say 'no corruption'.
+    }
+    SERIAL_ECHOPGM(" return=true\n");
+    return block_cnt;
+  }
+
 #endif // M100_FREE_MEMORY_WATCHER
+
+