From 907aed57db9a8242312ddee3267fe2d46f907f7c Mon Sep 17 00:00:00 2001
From: gralco <kuzmenko@alephobjects.com>
Date: Fri, 8 Apr 2016 14:27:08 -0600
Subject: [PATCH 1/2] Fix bug which can cause an infinite M109 loop

Since residency_start_ms is -1 when entering the heatup while loop whilst the hotend temp is close to the target them already then it may not escape.

Hence "Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time."
---
 Marlin/Marlin_main.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index f9bb9de309f..100c6364859 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -4325,7 +4325,8 @@ inline void gcode_M109() {
     #ifdef TEMP_RESIDENCY_TIME
       // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
       // Restart the timer whenever the temperature falls outside the hysteresis.
-      if (labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) > ((residency_start_ms < 0) ? TEMP_WINDOW : TEMP_HYSTERESIS))
+      if ((residency_start_ms <= 0 && labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) < TEMP_WINDOW) ||
+          (labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) > ((residency_start_ms < 0) ? TEMP_WINDOW : TEMP_HYSTERESIS)))
         residency_start_ms = millis();
     #endif //TEMP_RESIDENCY_TIME
 

From 1acf901b63272cc8eb4ad7a4126868320bfb0176 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <sourcetree@thinkyhead.com>
Date: Fri, 8 Apr 2016 21:18:40 -0700
Subject: [PATCH 2/2] Adjustments to residency_start_ms handling

---
 Marlin/Marlin_main.cpp | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 100c6364859..49bea610246 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -4290,7 +4290,7 @@ inline void gcode_M109() {
   #ifdef TEMP_RESIDENCY_TIME
     long residency_start_ms = -1;
     // Loop until the temperature has stabilized
-    #define TEMP_CONDITIONS (residency_start_ms < 0 || now < residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)
+    #define TEMP_CONDITIONS (residency_start_ms == -1 || now < residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)
   #else
     // Loop until the temperature is very close target
     #define TEMP_CONDITIONS (isHeatingHotend(target_extruder))
@@ -4307,7 +4307,7 @@ inline void gcode_M109() {
       #endif
       #ifdef TEMP_RESIDENCY_TIME
         SERIAL_PROTOCOLPGM(" W:");
-        if (residency_start_ms >= 0) {
+        if (residency_start_ms != -1) {
           long rem = (((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL;
           SERIAL_PROTOCOLLN(rem);
         }
@@ -4323,11 +4323,18 @@ inline void gcode_M109() {
     refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
 
     #ifdef TEMP_RESIDENCY_TIME
-      // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
-      // Restart the timer whenever the temperature falls outside the hysteresis.
-      if ((residency_start_ms <= 0 && labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) < TEMP_WINDOW) ||
-          (labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) > ((residency_start_ms < 0) ? TEMP_WINDOW : TEMP_HYSTERESIS)))
+
+      float temp_diff = labs(degHotend(target_extruder) - degTargetHotend(target_extruder));
+
+      if (residency_start_ms == -1) {
+        // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
+        if (temp_diff < TEMP_WINDOW) residency_start_ms = millis();
+      }
+      else if (temp_diff > TEMP_HYSTERESIS) {
+        // Restart the timer whenever the temperature falls outside the hysteresis.
         residency_start_ms = millis();
+      }
+
     #endif //TEMP_RESIDENCY_TIME
 
   } // while(!cancel_heatup && TEMP_CONDITIONS)