diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index 66d3c78ca464876d26420e933561a5550b453eb1..b1aeaa40e19a003e002a4eaa9000d208f5fd759a 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -1136,7 +1136,7 @@ void setup() {
   #endif
 
   #if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
-    SETUP_RUN(init_closedloop());
+    SETUP_RUN(closedloop.init());
   #endif
 
   #ifdef STARTUP_COMMANDS
diff --git a/Marlin/src/feature/closedloop.cpp b/Marlin/src/feature/closedloop.cpp
index b777243481cae3834b1228b784208b9caa1a4882..5d302683a17b7f8eb738a650342f6cc596dbf496 100644
--- a/Marlin/src/feature/closedloop.cpp
+++ b/Marlin/src/feature/closedloop.cpp
@@ -29,12 +29,14 @@
 
 #include "closedloop.h"
 
-void init_closedloop() {
+ClosedLoop closedloop;
+
+void ClosedLoop::init() {
   OUT_WRITE(CLOSED_LOOP_ENABLE_PIN, LOW);
   SET_INPUT_PULLUP(CLOSED_LOOP_MOVE_COMPLETE_PIN);
 }
 
-void set_closedloop(const byte val) {
+void ClosedLoop::set(const byte val) {
   OUT_WRITE(CLOSED_LOOP_ENABLE_PIN, val);
 }
 
diff --git a/Marlin/src/feature/closedloop.h b/Marlin/src/feature/closedloop.h
index 7e5594447d0e66a6189833351cbcd1a3ee7dea3d..75c7109ce620dde3200b0eda626627f38a63a976 100644
--- a/Marlin/src/feature/closedloop.h
+++ b/Marlin/src/feature/closedloop.h
@@ -21,5 +21,12 @@
  */
 #pragma once
 
-void init_closedloop();
-void set_closedloop(const byte val);
+class ClosedLoop {
+public:
+  static void init();
+  static void set(const byte val);
+};
+
+extern ClosedLoop closedloop;
+
+#define CLOSED_LOOP_WAITING() (READ(CLOSED_LOOP_ENABLE_PIN) && !READ(CLOSED_LOOP_MOVE_COMPLETE_PIN))
diff --git a/Marlin/src/gcode/calibrate/M12.cpp b/Marlin/src/gcode/calibrate/M12.cpp
index 26f15bb892132570798bfe8cbb63d2915329ada6..97d5bbc1ab5b7edd3e27bee08c9d517be891ff11 100644
--- a/Marlin/src/gcode/calibrate/M12.cpp
+++ b/Marlin/src/gcode/calibrate/M12.cpp
@@ -28,9 +28,12 @@
 #include "../../feature/closedloop.h"
 
 void GcodeSuite::M12() {
+
   planner.synchronize();
+
   if (parser.seenval('S'))
-    set_closedloop(parser.value_int()); // Force a CLC set
+    closedloop.set(parser.value_int()); // Force a CLC set
+
 }
 
 #endif
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 5715399e496c970eb18e52f25f9a5756791a300e..1beb63c1a4eec11bd82816b901f3ea57ceb8b656 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -91,6 +91,10 @@
   #include "../feature/power.h"
 #endif
 
+#if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
+  #include "../feature/closedloop.h"
+#endif
+
 #if ENABLED(BACKLASH_COMPENSATION)
   #include "../feature/backlash.h"
 #endif
@@ -1634,11 +1638,8 @@ float Planner::get_axis_position_mm(const AxisEnum axis) {
  * Block until all buffered steps are executed / cleaned
  */
 void Planner::synchronize() {
-  while (
-    has_blocks_queued() || cleaning_buffer_counter
-    #if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
-      || (READ(CLOSED_LOOP_ENABLE_PIN) && !READ(CLOSED_LOOP_MOVE_COMPLETE_PIN))
-    #endif
+  while (has_blocks_queued() || cleaning_buffer_counter
+      || TERN0(EXTERNAL_CLOSED_LOOP_CONTROLLER, CLOSED_LOOP_WAITING())
   ) idle();
 }
 
diff --git a/buildroot/tests/mega1280-tests b/buildroot/tests/mega1280-tests
index 7f2872a0b46d7b63a56395c9ada8c23278766a5e..c9caf7d8525b14962308f78c1efcf4ba4785a233 100644
--- a/buildroot/tests/mega1280-tests
+++ b/buildroot/tests/mega1280-tests
@@ -20,8 +20,11 @@ opt_set LCD_LANGUAGE an
 opt_enable SPINDLE_FEATURE ULTIMAKERCONTROLLER LCD_BED_LEVELING \
            SENSORLESS_BACKOFF_MM HOMING_BACKOFF_POST_MM HOME_Y_BEFORE_X CODEPENDENT_XY_HOMING \
            MESH_BED_LEVELING ENABLE_LEVELING_FADE_HEIGHT MESH_G28_REST_ORIGIN \
-           G26_MESH_VALIDATION MESH_EDIT_MENU GCODE_QUOTED_STRINGS
-exec_test $1 $2 "Spindle, MESH_BED_LEVELING, and LCD"
+           G26_MESH_VALIDATION MESH_EDIT_MENU GCODE_QUOTED_STRINGS \
+           EXTERNAL_CLOSED_LOOP_CONTROLLER
+opt_set CLOSED_LOOP_ENABLE_PIN 44
+opt_set CLOSED_LOOP_MOVE_COMPLETE_PIN 45
+exec_test $1 $2 "Spindle, MESH_BED_LEVELING, closed loop, and LCD"
 
 #
 # Test DUAL_X_CARRIAGE