diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 7601dd65a367afc0c313e2e04882e3b81163a2a3..b8cc3d3869322587684dd636afb17789c4b9d3c4 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+ * Select a secondary serial port on the board to use for communication with the host.
+ * This allows the connection of wireless adapters (for instance) to non-default port pins.
+ * Serial port -1 is the USB emulated serial port, if avaialble.
+ *
+ * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+ */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/HAL/HAL_AVR/HAL_AVR.cpp b/Marlin/src/HAL/HAL_AVR/HAL_AVR.cpp
index b4619323d146af48f0f62bb55213ff77fd535c31..9c69b90a864fa00ec52ab0ab3326625197321d2e 100644
--- a/Marlin/src/HAL/HAL_AVR/HAL_AVR.cpp
+++ b/Marlin/src/HAL/HAL_AVR/HAL_AVR.cpp
@@ -33,8 +33,7 @@
 // Includes
 // --------------------------------------------------------------------------
 
-#include "../HAL.h"
-#include "../../core/macros.h"
+#include "../../inc/MarlinConfig.h"
 
 // --------------------------------------------------------------------------
 // Externals
diff --git a/Marlin/src/HAL/HAL_AVR/HAL_AVR.h b/Marlin/src/HAL/HAL_AVR/HAL_AVR.h
index 2d59323051ca6abf4b7d55aa32f90be77146f5e1..8ea43c81548ce8784f930855b315132ac1445a80 100644
--- a/Marlin/src/HAL/HAL_AVR/HAL_AVR.h
+++ b/Marlin/src/HAL/HAL_AVR/HAL_AVR.h
@@ -47,6 +47,12 @@
 #include "watchdog_AVR.h"
 #include "math_AVR.h"
 
+#ifdef USBCON
+  #include "HardwareSerial.h"
+#else
+  #include "MarlinSerial.h"
+#endif
+
 // --------------------------------------------------------------------------
 // Defines
 // --------------------------------------------------------------------------
@@ -79,6 +85,18 @@ typedef int8_t pin_t;
 
 //extern uint8_t MCUSR;
 
+#define NUM_SERIAL 1
+
+#ifdef USBCON
+  #if ENABLED(BLUETOOTH)
+    #define MYSERIAL0 bluetoothSerial
+  #else
+    #define MYSERIAL0 Serial
+  #endif
+#else
+  #define MYSERIAL0 customizedSerial
+#endif
+
 // --------------------------------------------------------------------------
 // Public functions
 // --------------------------------------------------------------------------
diff --git a/Marlin/src/HAL/HAL_AVR/HAL_pinsDebug_AVR.h b/Marlin/src/HAL/HAL_AVR/HAL_pinsDebug_AVR.h
index b9e5abc4b30e79e696a027318bee1056ebf9ee9b..f66c2ef7f41aa0cfff9e5372ab97281a14b6b0ec 100644
--- a/Marlin/src/HAL/HAL_AVR/HAL_pinsDebug_AVR.h
+++ b/Marlin/src/HAL/HAL_AVR/HAL_pinsDebug_AVR.h
@@ -483,9 +483,9 @@ inline void report_pin_state_extended(pin_t pin, bool ignore, bool extended = fa
       for (uint8_t y = 0; y < 28; y++) {                   // always print pin name
         temp_char = pgm_read_byte(name_mem_pointer + y);
         if (temp_char != 0)
-          MYSERIAL.write(temp_char);
+          SERIAL_CHAR(temp_char);
         else {
-          for (uint8_t i = 0; i < 28 - y; i++) MYSERIAL.write(' ');
+          for (uint8_t i = 0; i < 28 - y; i++) SERIAL_CHAR(' ');
           break;
         }
       }
diff --git a/Marlin/src/HAL/HAL_AVR/pinsDebug_AVR_8_bit.h b/Marlin/src/HAL/HAL_AVR/pinsDebug_AVR_8_bit.h
index 5c68f2d99490246317a42698205ebebc7f5c65d6..02f23f05d41a928f4023e945ca061f5ab76c0d4d 100644
--- a/Marlin/src/HAL/HAL_AVR/pinsDebug_AVR_8_bit.h
+++ b/Marlin/src/HAL/HAL_AVR/pinsDebug_AVR_8_bit.h
@@ -66,9 +66,9 @@ void PRINT_ARRAY_NAME(uint8_t x) {
   for (uint8_t y = 0; y < MAX_NAME_LENGTH; y++) {
     char temp_char = pgm_read_byte(name_mem_pointer + y);
     if (temp_char != 0)
-      MYSERIAL.write(temp_char);
+      SERIAL_CHAR(temp_char);
     else {
-      for (uint8_t i = 0; i < MAX_NAME_LENGTH - y; i++) MYSERIAL.write(' ');
+      for (uint8_t i = 0; i < MAX_NAME_LENGTH - y; i++) SERIAL_CHAR(' ');
       break;
     }
   }
diff --git a/Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp b/Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp
index a7afb6e6a0a6eb920309d3c0175cd9bd973dbdf2..466556554416993fade0fbd4857f29d171aa5373 100644
--- a/Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp
@@ -121,7 +121,7 @@ static uint8_t curGroup = 0xFF;     // Current FLASH group
     char buffer[80];
 
     sprintf(buffer, "Page: %d (0x%04x)\n", page, page);
-    MYSERIAL.print(buffer);
+    SERIAL_PROTOCOL(buffer);
 
     char* p = &buffer[0];
     for (int i = 0; i< PageSize; ++i) {
@@ -133,7 +133,7 @@ static uint8_t curGroup = 0xFF;     // Current FLASH group
       if ((i & 15) == 15) {
         *p++ = '\n';
         *p = 0;
-        MYSERIAL.print(buffer);
+        SERIAL_PROTOCOL(buffer);
         p = &buffer[0];
       }
     }
@@ -182,7 +182,7 @@ static bool ee_PageWrite(uint16_t page,const void* data) {
     SERIAL_ECHOLNPAIR("EEPROM PageWrite   ",page);
     SERIAL_ECHOLNPAIR(" in FLASH address ",(uint32_t)addrflash);
     SERIAL_ECHOLNPAIR(" base address     ",(uint32_t)getFlashStorage(0));
-    MYSERIAL.flush();
+    SERIAL_FLUSH();
   #endif
 
   // Get the page relative to the start of the EFC controller, and the EFC controller to use
@@ -313,7 +313,7 @@ static bool ee_PageErase(uint16_t page) {
     SERIAL_ECHOLNPAIR("EEPROM PageErase  ",page);
     SERIAL_ECHOLNPAIR(" in FLASH address ",(uint32_t)addrflash);
     SERIAL_ECHOLNPAIR(" base address     ",(uint32_t)getFlashStorage(0));
-    MYSERIAL.flush();
+    SERIAL_FLUSH();
   #endif
 
   // Get the page relative to the start of the EFC controller, and the EFC controller to use
@@ -943,7 +943,7 @@ static void ee_Init() {
   #ifdef EE_EMU_DEBUG
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPAIR("EEPROM Current Group: ",curGroup);
-    MYSERIAL.flush();
+    SERIAL_FLUSH();
   #endif
 
   // Now, validate that all the other group pages are empty
@@ -957,7 +957,7 @@ static void ee_Init() {
           SERIAL_ECHO_START();
           SERIAL_ECHOPAIR("EEPROM Page ",page);
           SERIAL_ECHOLNPAIR(" not clean on group ",grp);
-          MYSERIAL.flush();
+          SERIAL_FLUSH();
         #endif
         ee_PageErase(grp * PagesPerGroup + page);
       }
@@ -978,7 +978,7 @@ static void ee_Init() {
   #ifdef EE_EMU_DEBUG
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPAIR("EEPROM Active page: ",curPage);
-    MYSERIAL.flush();
+    SERIAL_FLUSH();
   #endif
 
   // Make sure the pages following the first clean one are also clean
@@ -988,7 +988,7 @@ static void ee_Init() {
         SERIAL_ECHO_START();
         SERIAL_ECHOPAIR("EEPROM Page ",page);
         SERIAL_ECHOLNPAIR(" not clean on active group ",curGroup);
-        MYSERIAL.flush();
+        SERIAL_FLUSH();
         ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
       #endif
       ee_PageErase(curGroup * PagesPerGroup + page);
diff --git a/Marlin/src/HAL/HAL_DUE/HAL_Due.h b/Marlin/src/HAL/HAL_DUE/HAL_Due.h
index 9519a2ba74ae3a7f28e207ab44f2e3cca2dbc209..8c31ece35485dcb67de9f7be4c66a0d5297bc431 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/HAL_Due.h
@@ -40,8 +40,15 @@
 //
 // Defines
 //
-#if SERIAL_PORT >= -1 && SERIAL_PORT <= 4
-  #define MYSERIAL customizedSerial
+#define NUM_SERIAL 1
+
+//#undef SERIAL_PORT
+//#define SERIAL_PORT -1
+
+#if SERIAL_PORT == -1
+  #define MYSERIAL0 SerialUSB
+#else
+  #define MYSERIAL0 customizedSerial
 #endif
 
 // We need the previous define before the include, or compilation bombs...
@@ -147,6 +154,10 @@ uint16_t HAL_getAdcFreerun(uint8_t chan, bool wait_for_conversion = false);
 void HAL_enable_AdcFreerun(void);
 //void HAL_disable_AdcFreerun(uint8_t chan);
 
+/**
+ * Pin Map
+ */
+
 #define GET_PIN_MAP_PIN(index) index
 #define GET_PIN_MAP_INDEX(pin) pin
 #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL.cpp b/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
index 5579810346d51d0acbfb453b3d0915ee4d21769f..71315fdfde85d2812da3c02ef72ab67c91b858a6 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL.cpp
@@ -29,7 +29,7 @@ extern "C" {
 
 HalSerial usb_serial;
 
-//u8glib required fucntions
+// U8glib required functions
 extern "C" void u8g_xMicroDelay(uint16_t val) {
   delayMicroseconds(val);
 }
@@ -85,7 +85,7 @@ void HAL_adc_enable_channel(int ch) {
   pin_t pin = analogInputToDigitalPin(ch);
 
   if (pin == -1) {
-    MYSERIAL.printf("%sINVALID ANALOG PORT:%d\n", errormagic, ch);
+    SERIAL_PRINTF("%sINVALID ANALOG PORT:%d\n", errormagic, ch);
     kill(MSG_KILLED);
   }
 
@@ -97,15 +97,15 @@ void HAL_adc_enable_channel(int ch) {
                               pin_port == 1                        ? 3 : 10;
 
   switch (pin_sel_register) {
-    case 1 :
+    case 1:
       LPC_PINCON->PINSEL1 &= ~(0x3 << pinsel_start_bit);
       LPC_PINCON->PINSEL1 |=  (0x1 << pinsel_start_bit);
       break;
-    case 3 :
+    case 3:
       LPC_PINCON->PINSEL3 &= ~(0x3 << pinsel_start_bit);
       LPC_PINCON->PINSEL3 |=  (0x3 << pinsel_start_bit);
       break;
-    case 0 :
+    case 0:
       LPC_PINCON->PINSEL0 &= ~(0x3 << pinsel_start_bit);
       LPC_PINCON->PINSEL0 |=  (0x2 << pinsel_start_bit);
       break;
@@ -115,7 +115,7 @@ void HAL_adc_enable_channel(int ch) {
 uint8_t active_adc = 0;
 void HAL_adc_start_conversion(const uint8_t ch) {
   if (analogInputToDigitalPin(ch) == -1) {
-    MYSERIAL.printf("HAL: HAL_adc_start_conversion: invalid channel %d\n", ch);
+    SERIAL_PRINTF("HAL: HAL_adc_start_conversion: invalid channel %d\n", ch);
     return;
   }
 
diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL.h b/Marlin/src/HAL/HAL_LPC1768/HAL.h
index cf54cb1d717f62dd24706544fc515eb6f7c8cab2..162bb1a5976a34f8927ad43961d70170c5173cdf 100644
--- a/Marlin/src/HAL/HAL_LPC1768/HAL.h
+++ b/Marlin/src/HAL/HAL_LPC1768/HAL.h
@@ -69,19 +69,44 @@ extern "C" volatile uint32_t _millis;
 #define ST7920_DELAY_2 DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP
 #define ST7920_DELAY_3 DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP;DELAY_5_NOP
 
-//Serial override
 extern HalSerial usb_serial;
 
+#if !WITHIN(SERIAL_PORT, -1, 3)
+  #error "SERIAL_PORT must be from -1 to 3"
+#endif
+
 #if SERIAL_PORT == -1
-  #define MYSERIAL usb_serial
+  #define MYSERIAL0 usb_serial
 #elif SERIAL_PORT == 0
-  #define MYSERIAL Serial
+  #define MYSERIAL0 Serial
 #elif SERIAL_PORT == 1
-  #define MYSERIAL Serial1
+  #define MYSERIAL0 Serial1
 #elif SERIAL_PORT == 2
-  #define MYSERIAL Serial2
+  #define MYSERIAL0 Serial2
 #elif SERIAL_PORT == 3
-  #define MYSERIAL Serial3
+  #define MYSERIAL0 Serial3
+#endif
+
+#ifdef SERIAL_PORT_2
+  #if !WITHIN(SERIAL_PORT_2, -1, 3)
+    #error "SERIAL_PORT_2 must be from -1 to 3"
+  #elif SERIAL_PORT_2 == SERIAL_PORT
+    #error "SERIAL_PORT_2 must be different than SERIAL_PORT"
+  #endif
+  #define NUM_SERIAL 2
+  #if SERIAL_PORT_2 == -1
+    #define MYSERIAL1 usb_serial
+  #elif SERIAL_PORT_2 == 0
+    #define MYSERIAL1 Serial
+  #elif SERIAL_PORT_2 == 1
+    #define MYSERIAL1 Serial1
+  #elif SERIAL_PORT_2 == 2
+    #define MYSERIAL1 Serial2
+  #elif SERIAL_PORT_2 == 3
+    #define MYSERIAL1 Serial3
+  #endif
+#else
+  #define NUM_SERIAL 1
 #endif
 
 #define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq();
diff --git a/Marlin/src/HAL/HAL_LPC1768/arduino.cpp b/Marlin/src/HAL/HAL_LPC1768/arduino.cpp
index feab1e8b092b86dbef3e1335e70a3cd8e23244b5..94026f27a7e5bc3d707da6ea0738ef1f0301c712 100644
--- a/Marlin/src/HAL/HAL_LPC1768/arduino.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/arduino.cpp
@@ -139,7 +139,7 @@ void analogWrite(pin_t pin, int pwm_value) {  // 1 - 254: pwm_value, 0: LOW, 255
     if (LPC1768_PWM_attach_pin(pin, 1, LPC_PWM1->MR0, 0xFF))
       LPC1768_PWM_write(pin, map(value, 0, 255, 1, LPC_PWM1->MR0));  // map 1-254 onto PWM range
     else {                                                                 // out of PWM channels
-      if (!out_of_PWM_slots) MYSERIAL.printf(".\nWARNING - OUT OF PWM CHANNELS\n.\n");  //only warn once
+      if (!out_of_PWM_slots) SERIAL_ECHOPGM(".\nWARNING - OUT OF PWM CHANNELS\n.\n");  //only warn once
       out_of_PWM_slots = true;
       digitalWrite(pin, value);  // treat as a digital pin if out of channels
     }
diff --git a/Marlin/src/HAL/HAL_LPC1768/main.cpp b/Marlin/src/HAL/HAL_LPC1768/main.cpp
index dd6d24681db458c7c619ccf63d23d5dfd1870a2b..da3e0c648150dd61eabfd62aa26e3c887614f583 100644
--- a/Marlin/src/HAL/HAL_LPC1768/main.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/main.cpp
@@ -88,14 +88,13 @@ int main(void) {
     #endif
   }
 
-  // Only initialize the debug framework if using the USB emulated serial port
-  if ((HalSerial*) &MYSERIAL == &usb_serial)
-    debug_frmwrk_init();
-
-  MYSERIAL.begin(BAUDRATE);
-  MYSERIAL.printf("\n\nLPC1768 (%dMhz) UART0 Initialised\n", SystemCoreClock / 1000000);
-  #if TX_BUFFER_SIZE > 0
-    MYSERIAL.flushTX();
+  #if NUM_SERIAL > 0
+    MYSERIAL0.begin(BAUDRATE);
+    #if NUM_SERIAL > 1
+      MYSERIAL1.begin(BAUDRATE);
+    #endif
+    SERIAL_PRINTF("\n\nLPC1768 (%dMhz) UART0 Initialised\n", SystemCoreClock / 1000000);
+    SERIAL_FLUSHTX();
   #endif
 
   HAL_timer_init();
diff --git a/Marlin/src/HAL/HAL_LPC1768/serial.h b/Marlin/src/HAL/HAL_LPC1768/serial.h
index d3c3be9127af0646aa0b6cebcbe3c1b3146b07d3..8f496d3f7f795b83587c4bdc06c4be7331689e1b 100644
--- a/Marlin/src/HAL/HAL_LPC1768/serial.h
+++ b/Marlin/src/HAL/HAL_LPC1768/serial.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef HAL_SERIAL_H_
-#define HAL_SERIAL_H_
+#ifndef _HAL_SERIAL_H_
+#define _HAL_SERIAL_H_
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -30,7 +30,7 @@ extern "C" {
 #include <debug_frmwrk.h>
 }
 
-/*
+/**
  * Generic RingBuffer
  * T type of the buffer array
  * S size of the buffer (must be power of 2)
@@ -39,46 +39,33 @@ extern "C" {
  */
 template <typename T, uint32_t S> class RingBuffer {
 public:
-  RingBuffer() {
-    index_read = 0;
-    index_write = 0;
-  }
+  RingBuffer() { index_read = index_write = 0; }
+  uint32_t available() volatile { return buffer_mask & (index_write - index_read); }
+  uint32_t free() volatile      { return buffer_size - available(); }
+  bool empty() volatile         { return (buffer_mask & index_read) == (buffer_mask & index_write); }
+  bool full() volatile          { return index_read == buffer_mask & (index_write + 1); }
+  void clear() volatile         { index_read = index_write = 0; }
   bool peek(T *value) volatile {
-    if(value == 0 || available() == 0)
+    if (value == 0 || available() == 0)
       return false;
     *value = buffer[buffer_mask & index_read];
     return true;
   }
-  uint32_t available() volatile {
-    return buffer_mask & (index_write - index_read);
-  }
-  uint32_t free() volatile {
-    return buffer_size - available();
-  }
-  T read() volatile {
-    if((buffer_mask & index_read) == (buffer_mask & index_write)) return T(-1);
+  int read() volatile {
+    if ((buffer_mask & index_read) == (buffer_mask & index_write)) return -1;
     T val = buffer[buffer_mask & index_read];
     ++index_read;
     return val;
   }
-  bool write( T value) volatile {
+  bool write(T value) volatile {
     uint32_t next_head = buffer_mask & (index_write + 1);
-    if(next_head != index_read) {
+    if (next_head != index_read) {
       buffer[buffer_mask & index_write] = value;
       index_write = next_head;
       return true;
     }
     return false;
   }
-  bool empty() volatile {
-    return (buffer_mask & index_read) == (buffer_mask & index_write);
-  }
-  bool full() volatile {
-    return index_read == buffer_mask & (index_write + 1);
-  }
-  void clear() volatile {
-    index_read = index_write = 0;
-  }
 
 private:
   static const uint32_t buffer_size = S;
@@ -90,42 +77,35 @@ private:
 
 class HalSerial {
 public:
-  HalSerial() {
-    host_connected = false;
-  }
+  HalSerial() { host_connected = false; }
 
   void begin(int32_t baud) {
   }
 
-  char read() {
-    return (char)receive_buffer.read();
+  int peek() {
+    uint8_t value;
+    return receive_buffer.peek(&value) ? value : -1;
   }
 
-  void write(char c) {
-    _DBC(c); //Duplicate output over uart0
-    if(host_connected) transmit_buffer.write((uint8_t)c);
-  }
+  int read() { return receive_buffer.read(); }
 
-  operator bool() {
-    return host_connected;
-  }
+  size_t write(char c) { return host_connected ? transmit_buffer.write((uint8_t)c) : 0; }
+
+  operator bool() { return host_connected; }
 
   uint16_t available() {
     return (uint16_t)receive_buffer.available();
   }
 
-  void flush() {
-    receive_buffer.clear();
-  }
+  void flush() { receive_buffer.clear(); }
 
   uint8_t availableForWrite(void){
     return transmit_buffer.free() > 255 ? 255 : (uint8_t)transmit_buffer.free();
   }
 
   void flushTX(void){
-    if(host_connected) {
-      while(transmit_buffer.available());
-    }
+    if (host_connected)
+      while (transmit_buffer.available()) { /* nada */ }
   }
 
   void printf(const char *format, ...) {
@@ -135,7 +115,6 @@ public:
     int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs);
     va_end(vArgs);
     if (length > 0 && length < 256) {
-      _DBG(buffer); //Duplicate output over uart0
       if (host_connected) {
         for (int i = 0; i < length;) {
           if (transmit_buffer.write(buffer[i])) {
@@ -152,108 +131,72 @@ public:
   #define BIN 2
   #define BYTE 0
 
-
   void print_bin(uint32_t value, uint8_t num_digits) {
     uint32_t mask = 1 << (num_digits -1);
     for (uint8_t i = 0; i < num_digits; i++) {
-      if (!(i % 4) && i)    printf(" ");
-      if (!(i % 16)  && i)  printf(" ");
-      if (value & mask)     printf("1");
-      else                  printf("0");
+      if (!(i % 4) && i)    write(' ');
+      if (!(i % 16)  && i)  write(' ');
+      if (value & mask)     write('1');
+      else                  write('0');
       value <<= 1;
     }
   }
 
-  void print(const char value[]) {
-    printf("%s" , value);
-  }
+  void print(const char value[]) { printf("%s" , value); }
   void print(char value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,8);
+    if (nbase == BIN) print_bin(value, 8);
     else if (nbase == OCT) printf("%3o", value);
     else if (nbase == HEX) printf("%2X", value);
     else if (nbase == DEC ) printf("%d", value);
     else printf("%c" , value);
   }
   void print(unsigned char value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,8);
+    if (nbase == BIN) print_bin(value, 8);
     else if (nbase == OCT) printf("%3o", value);
     else if (nbase == HEX) printf("%2X", value);
     else printf("%u" , value);
   }
   void print(int value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,16);
+    if (nbase == BIN) print_bin(value, 16);
     else if (nbase == OCT) printf("%6o", value);
     else if (nbase == HEX) printf("%4X", value);
     else printf("%d", value);
   }
   void print(unsigned int value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,16);
+    if (nbase == BIN) print_bin(value, 16);
     else if (nbase == OCT) printf("%6o", value);
     else if (nbase == HEX) printf("%4X", value);
     else printf("%u" , value);
   }
   void print(long value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,32);
+    if (nbase == BIN) print_bin(value, 32);
     else if (nbase == OCT) printf("%11o", value);
     else if (nbase == HEX) printf("%8X", value);
     else printf("%ld" , value);
   }
   void print(unsigned long value, int nbase = BYTE) {
-    if (nbase == BIN) print_bin(value,32);
+    if (nbase == BIN) print_bin(value, 32);
     else if (nbase == OCT) printf("%11o", value);
     else if (nbase == HEX) printf("%8X", value);
     else printf("%lu" , value);
   }
-  void print(float value, int round = 6) {
-    printf("%f" , value);
-  }
-  void print(double value, int round = 6) {
-    printf("%f" , value );
-  }
+  void print(float value, int round = 6)  { printf("%f" , value); }
+  void print(double value, int round = 6) { printf("%f" , value); }
 
-
-
-  void println(const char value[]) {
-    printf("%s\n" , value);
-  }
-  void println(char value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(unsigned char value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(int value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(unsigned int value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(long value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(unsigned long value, int nbase = BYTE) {
-    print(value, nbase);
-    println();
-  }
-  void println(float value, int round = 6) {
-    printf("%f\n" , value );
-  }
-  void println(double value, int round = 6) {
-    printf("%f\n" , value );
-  }
-  void println(void) {
-    print('\n');
-  }
+  void println(const char value[]) { printf("%s\n" , value); }
+  void println(char value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(unsigned char value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(int value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(unsigned int value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(long value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(unsigned long value, int nbase = BYTE) { print(value, nbase); println(); }
+  void println(float value, int round = 6) { printf("%f\n" , value); }
+  void println(double value, int round = 6) { printf("%f\n" , value); }
+  void println(void) { print('\n'); }
 
   volatile RingBuffer<uint8_t, 128> receive_buffer;
   volatile RingBuffer<uint8_t, 128> transmit_buffer;
   volatile bool host_connected;
 };
 
-
-#endif /* MARLIN_SRC_HAL_HAL_SERIAL_H_ */
+#endif // _HAL_SERIAL_H_
diff --git a/Marlin/src/HAL/HAL_STM32F1/HAL_Stm32f1.h b/Marlin/src/HAL/HAL_STM32F1/HAL_Stm32f1.h
index d9ff5d8cbc244647ac08fa638a8bcc668f2dd289..c5186c9fd823ce18a3315390c9bccc41039ed2e6 100644
--- a/Marlin/src/HAL/HAL_STM32F1/HAL_Stm32f1.h
+++ b/Marlin/src/HAL/HAL_STM32F1/HAL_Stm32f1.h
@@ -65,16 +65,41 @@
 // Defines
 // --------------------------------------------------------------------------
 
+#if !WITHIN(SERIAL_PORT, -1, 3)
+  #error "SERIAL_PORT must be from -1 to 3"
+#endif
 #if SERIAL_PORT == -1
-  #define MYSERIAL SerialUSB
+  #define MYSERIAL0 SerialUSB
 #elif SERIAL_PORT == 0
-  #define MYSERIAL Serial
+  #define MYSERIAL0 Serial
 #elif SERIAL_PORT == 1
-  #define MYSERIAL Serial1
+  #define MYSERIAL0 Serial1
 #elif SERIAL_PORT == 2
-  #define MYSERIAL Serial2
+  #define MYSERIAL0 Serial2
 #elif SERIAL_PORT == 3
-  #define MYSERIAL Serial3
+  #define MYSERIAL0 Serial3
+#endif
+
+#ifdef SERIAL_PORT_2
+  #if !WITHIN(SERIAL_PORT_2, -1, 3)
+    #error "SERIAL_PORT_2 must be from -1 to 3"
+  #elif SERIAL_PORT_2 == SERIAL_PORT
+    #error "SERIAL_PORT_2 must be different than SERIAL_PORT"
+  #endif
+  #define NUM_SERIAL 2
+  #if SERIAL_PORT_2 == -1
+    #define MYSERIAL1 SerialUSB
+  #elif SERIAL_PORT_2 == 0
+    #define MYSERIAL1 Serial
+  #elif SERIAL_PORT_2 == 1
+    #define MYSERIAL1 Serial1
+  #elif SERIAL_PORT_2 == 2
+    #define MYSERIAL1 Serial2
+  #elif SERIAL_PORT_2 == 3
+    #define MYSERIAL1 Serial3
+  #endif
+#else
+  #define NUM_SERIAL 1
 #endif
 
 /**
diff --git a/Marlin/src/HAL/HAL_TEENSY35_36/HAL_Teensy.h b/Marlin/src/HAL/HAL_TEENSY35_36/HAL_Teensy.h
index b5dfb60802e0aff71586fa3cb9ff96e1aebc8fbf..120772ffd739ac2f1f7cca0683d7f880da5c26f1 100644
--- a/Marlin/src/HAL/HAL_TEENSY35_36/HAL_Teensy.h
+++ b/Marlin/src/HAL/HAL_TEENSY35_36/HAL_Teensy.h
@@ -57,16 +57,18 @@
 #define IS_TEENSY35 defined(__MK64FX512__)
 #define IS_TEENSY36 defined(__MK66FX1M0__)
 
+#define NUM_SERIAL 1
+
 #if SERIAL_PORT == -1
-  #define MYSERIAL SerialUSB
+  #define MYSERIAL0 SerialUSB
 #elif SERIAL_PORT == 0
-  #define MYSERIAL Serial
+  #define MYSERIAL0 Serial
 #elif SERIAL_PORT == 1
-  #define MYSERIAL Serial1
+  #define MYSERIAL0 Serial1
 #elif SERIAL_PORT == 2
-  #define MYSERIAL Serial2
+  #define MYSERIAL0 Serial2
 #elif SERIAL_PORT == 3
-  #define MYSERIAL Serial3
+  #define MYSERIAL0 Serial3
 #endif
 
 #define HAL_SERVO_LIB libServo
diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index b801281dd67747e8f627c711c000b3a5510d60e7..012839503ff3cdc730f5924e98b06898c055ebc6 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -669,9 +669,22 @@ void setup() {
     disableStepperDrivers();
   #endif
 
-  MYSERIAL.begin(BAUDRATE);
-  uint32_t serial_connect_timeout = millis() + 1000;
-  while(!MYSERIAL && PENDING(millis(), serial_connect_timeout));
+  #if NUM_SERIAL > 0
+    MYSERIAL0.begin(BAUDRATE);
+    #if NUM_SERIAL > 1
+      MYSERIAL1.begin(BAUDRATE);
+    #endif
+  #endif
+
+  #if NUM_SERIAL > 0
+    uint32_t serial_connect_timeout = millis() + 1000UL;
+    while(!MYSERIAL0 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
+    #if NUM_SERIAL > 1
+      serial_connect_timeout = millis() + 1000UL;
+      while(!MYSERIAL1 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
+    #endif
+  #endif
+
   SERIAL_PROTOCOLLNPGM("start");
   SERIAL_ECHO_START();
 
diff --git a/Marlin/src/config/default/Configuration.h b/Marlin/src/config/default/Configuration.h
index 7601dd65a367afc0c313e2e04882e3b81163a2a3..4e674e97c4c90e559ce213bdf385530b94c8d8f6 100644
--- a/Marlin/src/config/default/Configuration.h
+++ b/Marlin/src/config/default/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration.h b/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration.h
index eebbe77994f5ee3dfdf1a81e3cc587a48cefd3eb..39c3c7686b9cb476e200d5c0fba6ada28d14f5d5 100644
--- a/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration.h
+++ b/Marlin/src/config/examples/AlephObjects/TAZ4/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/AliExpress/CL-260/Configuration.h b/Marlin/src/config/examples/AliExpress/CL-260/Configuration.h
index b64643537ccdf33dbd8181ec3856d48a6227ecb4..80a4b58272446ffdd72ae46bb2f72aa6a0531462 100644
--- a/Marlin/src/config/examples/AliExpress/CL-260/Configuration.h
+++ b/Marlin/src/config/examples/AliExpress/CL-260/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Anet/A6/Configuration.h b/Marlin/src/config/examples/Anet/A6/Configuration.h
index feec3b2c10a04b9101e13fe96188e1649337ebd7..f3f395a8b811927f2ff1f1ff74b1ab16f3c106ea 100644
--- a/Marlin/src/config/examples/Anet/A6/Configuration.h
+++ b/Marlin/src/config/examples/Anet/A6/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Anet/A8/Configuration.h b/Marlin/src/config/examples/Anet/A8/Configuration.h
index d352828a73d7b464b8c05feba6f07b068ea0fa39..28e603495a3994cbd83167089385c6217533088b 100644
--- a/Marlin/src/config/examples/Anet/A8/Configuration.h
+++ b/Marlin/src/config/examples/Anet/A8/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Azteeg/X5GT/Configuration.h b/Marlin/src/config/examples/Azteeg/X5GT/Configuration.h
index bdbd3be4c0afaf1593662f683fca59e69eae87cf..0bba68b40265caf551048ba2932653ffd4c38428 100644
--- a/Marlin/src/config/examples/Azteeg/X5GT/Configuration.h
+++ b/Marlin/src/config/examples/Azteeg/X5GT/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/BQ/Hephestos/Configuration.h b/Marlin/src/config/examples/BQ/Hephestos/Configuration.h
index 4cf6844c0548eeb1e7e193382ee9b627eba099fd..fd01fabbf8327bb545557b602cbe08794e2b2ba3 100644
--- a/Marlin/src/config/examples/BQ/Hephestos/Configuration.h
+++ b/Marlin/src/config/examples/BQ/Hephestos/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/BQ/Hephestos_2/Configuration.h b/Marlin/src/config/examples/BQ/Hephestos_2/Configuration.h
index d0378cdddc867d621ea224591b7dcf73cd6cabff..6e1a085f3dad0716cc9876660b4bdf9ae3a44d26 100644
--- a/Marlin/src/config/examples/BQ/Hephestos_2/Configuration.h
+++ b/Marlin/src/config/examples/BQ/Hephestos_2/Configuration.h
@@ -101,6 +101,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/BQ/WITBOX/Configuration.h b/Marlin/src/config/examples/BQ/WITBOX/Configuration.h
index 1fcc1f8b6a1190a00b21e2b1448978b38a09e057..003182abf86fa8585612637880ecad2e0f935129 100644
--- a/Marlin/src/config/examples/BQ/WITBOX/Configuration.h
+++ b/Marlin/src/config/examples/BQ/WITBOX/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Cartesio/Configuration.h b/Marlin/src/config/examples/Cartesio/Configuration.h
index c7ade6ee6d15b7af390971468f96c619da546138..b731a518df05a88c733545dd9d614717888247d2 100644
--- a/Marlin/src/config/examples/Cartesio/Configuration.h
+++ b/Marlin/src/config/examples/Cartesio/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Creality/CR-10/Configuration.h b/Marlin/src/config/examples/Creality/CR-10/Configuration.h
index 1719f0846abb4724cc8e454514ea33b6c68ada90..6cd5fa26aa8ec8e89140b4eaae67c5cbecc3bea5 100755
--- a/Marlin/src/config/examples/Creality/CR-10/Configuration.h
+++ b/Marlin/src/config/examples/Creality/CR-10/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Felix/Configuration.h b/Marlin/src/config/examples/Felix/Configuration.h
index 052a16779ce9969acb1673ba11b4b88259536ff4..1cee114012f5064acf63699094a76d3e84d11014 100644
--- a/Marlin/src/config/examples/Felix/Configuration.h
+++ b/Marlin/src/config/examples/Felix/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Felix/DUAL/Configuration.h b/Marlin/src/config/examples/Felix/DUAL/Configuration.h
index 83a6ab34feb4d822727d90030fa3180188dcdaf6..4492e0747eeecef0f5f0de54208e86c6ea07858a 100644
--- a/Marlin/src/config/examples/Felix/DUAL/Configuration.h
+++ b/Marlin/src/config/examples/Felix/DUAL/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration.h b/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration.h
index dafd79109f2cbe4aa4d4fe4ee1b035c5992917c0..d5a22705399ae444a4e45731c48d98ea7950ced1 100644
--- a/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration.h
+++ b/Marlin/src/config/examples/FolgerTech/i3-2020/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Geeetech/GT2560/Configuration.h b/Marlin/src/config/examples/Geeetech/GT2560/Configuration.h
index 9f2c25d38585b6ffa0e79b6905f59cf1c41032aa..7d3a4f56e594196bf346207991f78478c202148d 100644
--- a/Marlin/src/config/examples/Geeetech/GT2560/Configuration.h
+++ b/Marlin/src/config/examples/Geeetech/GT2560/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Geeetech/I3_Pro_X-GT2560/Configuration.h b/Marlin/src/config/examples/Geeetech/I3_Pro_X-GT2560/Configuration.h
index 2a7033879d76e5edb400b24f77cd3269779a2b4b..be5270596fe3a79103feef4c13e70c3a026a5ccd 100644
--- a/Marlin/src/config/examples/Geeetech/I3_Pro_X-GT2560/Configuration.h
+++ b/Marlin/src/config/examples/Geeetech/I3_Pro_X-GT2560/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Infitary/i3-M508/Configuration.h b/Marlin/src/config/examples/Infitary/i3-M508/Configuration.h
index ee4c0b0884a4e186de06d51edd7893812f930573..d461f760aacc2c1207ebbee972ba06bd65f29c3f 100644
--- a/Marlin/src/config/examples/Infitary/i3-M508/Configuration.h
+++ b/Marlin/src/config/examples/Infitary/i3-M508/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Malyan/M150/Configuration.h b/Marlin/src/config/examples/Malyan/M150/Configuration.h
index b247802edf94cb7b5147381d65e468e39850bfa1..420b3bdf13db98741414a0ce5b746f77e3e949cd 100644
--- a/Marlin/src/config/examples/Malyan/M150/Configuration.h
+++ b/Marlin/src/config/examples/Malyan/M150/Configuration.h
@@ -107,6 +107,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Micromake/C1/basic/Configuration.h b/Marlin/src/config/examples/Micromake/C1/basic/Configuration.h
index d5bcd1a58202d908fa279181d631ffa859060a33..6d8c0de1a3c65a4530a3db00dce8b4ed1854123d 100644
--- a/Marlin/src/config/examples/Micromake/C1/basic/Configuration.h
+++ b/Marlin/src/config/examples/Micromake/C1/basic/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration.h b/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration.h
index 90018c4f14cd8589c12570b37d5a673071eee8bf..4238c4b3f559973c072c41ce7fcccacc11220d4d 100644
--- a/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration.h
+++ b/Marlin/src/config/examples/Micromake/C1/enhanced/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Mks/Sbase/Configuration.h b/Marlin/src/config/examples/Mks/Sbase/Configuration.h
index c99d9af89302271b3a06017582affdef5fd9dc99..e6e5e6e80a7afe4755da65e9b54eef303bc7b95d 100644
--- a/Marlin/src/config/examples/Mks/Sbase/Configuration.h
+++ b/Marlin/src/config/examples/Mks/Sbase/Configuration.h
@@ -101,7 +101,16 @@
  *
  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
  */
-#define SERIAL_PORT -1
+#define SERIAL_PORT 0
+
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
 
 /**
  * This setting determines the communication speed of the printer.
diff --git a/Marlin/src/config/examples/RepRapWorld/Megatronics/Configuration.h b/Marlin/src/config/examples/RepRapWorld/Megatronics/Configuration.h
index 6e4b8f718f1c9a93fe45a45701d8e714c91a7721..37b41a311b6197d0464d1937f6a0f62654573c7b 100644
--- a/Marlin/src/config/examples/RepRapWorld/Megatronics/Configuration.h
+++ b/Marlin/src/config/examples/RepRapWorld/Megatronics/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/RigidBot/Configuration.h b/Marlin/src/config/examples/RigidBot/Configuration.h
index 4b4219e986ffb6c727892886e7596fb994f30e13..33ef0803af18b07224acd691528aff44319f514d 100644
--- a/Marlin/src/config/examples/RigidBot/Configuration.h
+++ b/Marlin/src/config/examples/RigidBot/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/SCARA/Configuration.h b/Marlin/src/config/examples/SCARA/Configuration.h
index 4b364e67d197a2f65afbaa5d78a3ccb33a30f390..0e1f4d589c1c40646063d37b841e7470f5989e36 100644
--- a/Marlin/src/config/examples/SCARA/Configuration.h
+++ b/Marlin/src/config/examples/SCARA/Configuration.h
@@ -132,6 +132,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/STM32F10/Configuration.h b/Marlin/src/config/examples/STM32F10/Configuration.h
index bebd2ff553976931917e0af15df08f462c1bc34d..659d81d519870efc0024118a9641a8bad3b2240e 100644
--- a/Marlin/src/config/examples/STM32F10/Configuration.h
+++ b/Marlin/src/config/examples/STM32F10/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Sanguinololu/Configuration.h b/Marlin/src/config/examples/Sanguinololu/Configuration.h
index 8f90e4f9a0e353958bb7e3d506e936736ae4261b..59163521a88cc55d70a84000b0b9b101b8b3d53b 100644
--- a/Marlin/src/config/examples/Sanguinololu/Configuration.h
+++ b/Marlin/src/config/examples/Sanguinololu/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/TinyBoy2/Configuration.h b/Marlin/src/config/examples/TinyBoy2/Configuration.h
index 645f94e17f0bbf6cf6382ecc058c4720bf17ea40..0e0176175f4b14415ad941db8e372b7517baf8ee 100644
--- a/Marlin/src/config/examples/TinyBoy2/Configuration.h
+++ b/Marlin/src/config/examples/TinyBoy2/Configuration.h
@@ -118,6 +118,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Velleman/K8200/Configuration.h b/Marlin/src/config/examples/Velleman/K8200/Configuration.h
index 086060e4f052fbf7f8d55ab8c14e913f7e0d57ea..e81a48edbd56c2ed18275967b66eada1b74dcfc5 100644
--- a/Marlin/src/config/examples/Velleman/K8200/Configuration.h
+++ b/Marlin/src/config/examples/Velleman/K8200/Configuration.h
@@ -118,6 +118,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Velleman/K8400/Configuration.h b/Marlin/src/config/examples/Velleman/K8400/Configuration.h
index f6d8efa009454af229045339d1466b4e1d28b4c3..6e8e448fc55a2a634878596cc6e8cef09a2b99d5 100644
--- a/Marlin/src/config/examples/Velleman/K8400/Configuration.h
+++ b/Marlin/src/config/examples/Velleman/K8400/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/Velleman/K8400/Dual-head/Configuration.h b/Marlin/src/config/examples/Velleman/K8400/Dual-head/Configuration.h
index 2d03ef33ca7619afcf0cbcfbeeee4baf9769f2b5..298188ff4f481b1ffac1edc5dc95f638fefa9897 100644
--- a/Marlin/src/config/examples/Velleman/K8400/Dual-head/Configuration.h
+++ b/Marlin/src/config/examples/Velleman/K8400/Dual-head/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/adafruit/ST7565/Configuration.h b/Marlin/src/config/examples/adafruit/ST7565/Configuration.h
index e01bd065cab78a0ff9ccef9b2d2098093139f1b6..2a735c100e48b319b863a71ac970dca790ff03e4 100644
--- a/Marlin/src/config/examples/adafruit/ST7565/Configuration.h
+++ b/Marlin/src/config/examples/adafruit/ST7565/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration.h b/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration.h
index f623b8a14e5b5e4263ed354070f58ecbfdeff5b9..ddbd140b5889c306dce68c9d261b57952a198706 100644
--- a/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration.h
+++ b/Marlin/src/config/examples/delta/FLSUN/auto_calibrate/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration.h b/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration.h
index 316494b72e2516e7a1acb12c886973742b8c0c7b..86bd299a630b8bf55e78c7d72782492aae1d2885 100644
--- a/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration.h
+++ b/Marlin/src/config/examples/delta/FLSUN/kossel_mini/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/generic/Configuration.h b/Marlin/src/config/examples/delta/generic/Configuration.h
index 4c53d2107240808a2d19a7c3cc4e999cc0fd75a4..4d8cbc63dd1253a96f4711d3132128301c4b4859 100644
--- a/Marlin/src/config/examples/delta/generic/Configuration.h
+++ b/Marlin/src/config/examples/delta/generic/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/kossel_mini/Configuration.h b/Marlin/src/config/examples/delta/kossel_mini/Configuration.h
index b48db2a4e1ebfa24b5adbdfd92b70e58c9557e8e..9d4e7ea5874c130d6e9db401bda2efb9bcf04ea6 100644
--- a/Marlin/src/config/examples/delta/kossel_mini/Configuration.h
+++ b/Marlin/src/config/examples/delta/kossel_mini/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/kossel_pro/Configuration.h b/Marlin/src/config/examples/delta/kossel_pro/Configuration.h
index 84695b0a64d22021c93cb5aa773c23883578e660..24190541ea4e43d8389f38754ec6ab621084aed5 100644
--- a/Marlin/src/config/examples/delta/kossel_pro/Configuration.h
+++ b/Marlin/src/config/examples/delta/kossel_pro/Configuration.h
@@ -106,6 +106,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/delta/kossel_xl/Configuration.h b/Marlin/src/config/examples/delta/kossel_xl/Configuration.h
index 4fb53477dcaba9e039b859a9218ceeced43f64db..bf6f22ebe9b933add3b600218a53f308115ec6e7 100644
--- a/Marlin/src/config/examples/delta/kossel_xl/Configuration.h
+++ b/Marlin/src/config/examples/delta/kossel_xl/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration.h b/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration.h
index bca4e3a2a3190015c1f6b2ee8b3ce96b91f0c256..c530d793494c8c5273066e2fdd72ddc1aeedc02c 100644
--- a/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration.h
+++ b/Marlin/src/config/examples/gCreate/gMax1.5+/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/makibox/Configuration.h b/Marlin/src/config/examples/makibox/Configuration.h
index e3dd1c2b71073302f6871d95d802e0995049fdc2..fa47d8a794e22726311ad5f2b2e566d1dd375442 100644
--- a/Marlin/src/config/examples/makibox/Configuration.h
+++ b/Marlin/src/config/examples/makibox/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/tvrrug/Round2/Configuration.h b/Marlin/src/config/examples/tvrrug/Round2/Configuration.h
index 6e3c385424b8df1260f333d0458c78bb870526ef..41c69148612feaa53491fbf5cbf92a05332c01d0 100644
--- a/Marlin/src/config/examples/tvrrug/Round2/Configuration.h
+++ b/Marlin/src/config/examples/tvrrug/Round2/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/config/examples/wt150/Configuration.h b/Marlin/src/config/examples/wt150/Configuration.h
index 69f6815b3d2bdf398c92f1ce4daa429c45c1dad4..f1bef4b46c7651291851af5c55c81663a7b18207 100644
--- a/Marlin/src/config/examples/wt150/Configuration.h
+++ b/Marlin/src/config/examples/wt150/Configuration.h
@@ -102,6 +102,15 @@
  */
 #define SERIAL_PORT 0
 
+/**
+  * Select a secondary serial port on the board to use for communication with the host.
+  * This allows the connection of wireless adapters (for instance) to non-default port pins.
+  * Serial port -1 is the USB emulated serial port, if avaialble.
+  *
+  * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+  */
+#define SERIAL_PORT_2 -1
+
 /**
  * This setting determines the communication speed of the printer.
  *
diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp
index a02d943bd68523d8842434bde207a3dd02ed6397..f7b9dbf61dd2fdf6a5c9cf2d985a4cd710230f27 100644
--- a/Marlin/src/core/serial.cpp
+++ b/Marlin/src/core/serial.cpp
@@ -27,25 +27,37 @@ uint8_t marlin_debug_flags = DEBUG_NONE;
 const char errormagic[] PROGMEM = "Error:";
 const char echomagic[] PROGMEM = "echo:";
 
+#if NUM_SERIAL > 1
+  void serialprintPGM_P(const int8_t p, const char * str) {
+    while (char ch = pgm_read_byte(str++)) SERIAL_CHAR_P(p, ch);
+  }
+
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, const char *v)   { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, char v)          { serialprintPGM_P(p, s_P); SERIAL_CHAR_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, int v)           { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, long v)          { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, float v)         { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, double v)        { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, unsigned int v)  { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, unsigned long v) { serialprintPGM_P(p, s_P); SERIAL_ECHO_P(p, v); }
+
+  void serial_spaces_P(const int8_t p, uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR_P(p, ' '); }
+#endif
 
 void serialprintPGM(const char * str) {
-  #ifdef TARGET_LPC1768
-    MYSERIAL.print(str);
-  #else
-    while (char ch = pgm_read_byte(str++)) MYSERIAL.write(ch);
-  #endif
+  while (char ch = pgm_read_byte(str++)) SERIAL_CHAR(ch);
 }
 
-void serial_echopair_P(const char* s_P, const char *v)   { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, char v)          { serialprintPGM(s_P); SERIAL_CHAR(v); }
-void serial_echopair_P(const char* s_P, int v)           { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, long v)          { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, float v)         { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, double v)        { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, unsigned int v)  { serialprintPGM(s_P); SERIAL_ECHO(v); }
-void serial_echopair_P(const char* s_P, unsigned long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, const char *v)   { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, char v)          { serialprintPGM(s_P); SERIAL_CHAR(v); }
+void serial_echopair_PGM(const char* s_P, int v)           { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, long v)          { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, float v)         { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, double v)        { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, unsigned int v)  { serialprintPGM(s_P); SERIAL_ECHO(v); }
+void serial_echopair_PGM(const char* s_P, unsigned long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
 
-void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) MYSERIAL.write(' '); }
+void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); }
 
 #if ENABLED(DEBUG_LEVELING_FEATURE)
 
diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h
index 04d94829d4856b03ec061503d166592f4ab2affe..4c045338291644aaf284c2eac623105776a310d9 100644
--- a/Marlin/src/core/serial.h
+++ b/Marlin/src/core/serial.h
@@ -75,9 +75,7 @@ enum DebugFlags {
     #include "../HAL/HAL_AVR/MarlinSerial.h"
     #define MYSERIAL customizedSerial
   #endif
-#endif
-
-#ifdef ARDUINO_ARCH_SAM
+#elif defined(ARDUINO_ARCH_SAM)
   // To pull the Serial port definitions and overrides
   #include "../HAL/HAL_DUE/MarlinSerial_Due.h"
 #endif
@@ -88,17 +86,152 @@ extern uint8_t marlin_debug_flags;
 extern const char echomagic[] PROGMEM;
 extern const char errormagic[] PROGMEM;
 
-#define SERIAL_CHAR(x) ((void)MYSERIAL.write(x))
+#if TX_BUFFER_SIZE < 1
+  #define SERIAL_FLUSHTX_P(p)
+  #define SERIAL_FLUSHTX()
+#endif
+
+#if NUM_SERIAL > 1
+  #define SERIAL_CHAR_P(p,x)          (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.write(x) : MYSERIAL1.write(x)) : SERIAL_CHAR(x))
+  #define SERIAL_PROTOCOL_P(p,x)      (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.print(x) : MYSERIAL1.print(x)) : SERIAL_PROTOCOL(x))
+  #define SERIAL_PROTOCOL_F_P(p,x,y)  (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.print(x,y) : MYSERIAL1.print(x,y)) : SERIAL_PROTOCOL_F(x,y))
+  #define SERIAL_PROTOCOLLN_P(p,x)    (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.println(x) : MYSERIAL1.println(x)) : SERIAL_PROTOCOLLN(x))
+  #define SERIAL_PRINT_P(p,x,b)       (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.print(x,b) : MYSERIAL1.print(x,b)) : SERIAL_PRINT(x,b))
+  #define SERIAL_PRINTLN_P(p,x,b)     (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.println(x,b) : MYSERIAL1.println(x,b)) : SERIAL_PRINTLN(x,b))
+  #define SERIAL_PRINTF_P(p,args...)  (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.printf(args) : MYSERIAL1.printf(args)) : SERIAL_PRINTF(args))
+
+  #define SERIAL_CHAR(x)              (MYSERIAL0.write(x), MYSERIAL1.write(x))
+  #define SERIAL_PROTOCOL(x)          (MYSERIAL0.print(x), MYSERIAL1.print(x))
+  #define SERIAL_PROTOCOL_F(x,y)      (MYSERIAL0.print(x,y), MYSERIAL1.print(x,y))
+  #define SERIAL_PROTOCOLLN(x)        (MYSERIAL0.println(x), MYSERIAL1.println(x))
+  #define SERIAL_PRINT(x,b)           (MYSERIAL0.print(x,b), MYSERIAL1.print(x,b))
+  #define SERIAL_PRINTLN(x,b)         (MYSERIAL0.println(x,b), MYSERIAL1.println(x,b))
+  #define SERIAL_PRINTF(args...)      (MYSERIAL0.printf(args), MYSERIAL1.printf(args))
+
+  #define SERIAL_FLUSH_P(p)           (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.flush() : MYSERIAL1.flush()) : SERIAL_FLUSH())
+  #define SERIAL_FLUSH()              (MYSERIAL0.flush(), MYSERIAL1.flush())
+  #if TX_BUFFER_SIZE > 0
+    #define SERIAL_FLUSHTX_P(p)       (WITHIN(p, 0, NUM_SERIAL-1) ? (p == 0 ? MYSERIAL0.flushTX() : MYSERIAL1.flushTX()) : SERIAL_FLUSHTX())
+    #define SERIAL_FLUSHTX()          (MYSERIAL0.flushTX(), MYSERIAL1.flushTX())
+  #endif
+
+  #define SERIAL_EOL_P(p) SERIAL_CHAR_P(p,'\n')
+  
+  #define SERIAL_PROTOCOLCHAR_P(p,x)              SERIAL_CHAR_P(p,x)
+  #define SERIAL_PROTOCOLPGM_P(p,x)               (serialprintPGM_P(p,PSTR(x)))
+  #define SERIAL_PROTOCOLLNPGM_P(p,x)             (serialprintPGM_P(p,PSTR(x "\n")))
+  #define SERIAL_PROTOCOLPAIR_P(p, pre, value)    (serial_echopair_PGM_P(p,PSTR(pre),(value)))
+  #define SERIAL_PROTOCOLLNPAIR_P(p, pre, value)  do { SERIAL_PROTOCOLPAIR_P(p, pre, value); SERIAL_EOL_P(p); } while(0)
+  
+  #define SERIAL_ECHO_START_P(p)             (serialprintPGM_P(p,echomagic))
+  #define SERIAL_ECHO_P(p,x)                 SERIAL_PROTOCOL_P(p,x)
+  #define SERIAL_ECHOPGM_P(p,x)              SERIAL_PROTOCOLPGM_P(p,x)
+  #define SERIAL_ECHOLN_P(p,x)               SERIAL_PROTOCOLLN_P(p,x)
+  #define SERIAL_ECHOLNPGM_P(p,x)            SERIAL_PROTOCOLLNPGM_P(p,x)
+  #define SERIAL_ECHOPAIR_P(p,pre,value)     SERIAL_PROTOCOLPAIR_P(p, pre, value)
+  #define SERIAL_ECHOLNPAIR_P(p,pre, value)  SERIAL_PROTOCOLLNPAIR_P(p, pre, value)
+  #define SERIAL_ECHO_F_P(p,x,y)             SERIAL_PROTOCOL_F_P(p,x,y)
+  
+  #define SERIAL_ERROR_START_P(p)            (serialprintPGM_P(p,errormagic))
+  #define SERIAL_ERROR_P(p,x)                SERIAL_PROTOCOL_P(p,x)
+  #define SERIAL_ERRORPGM_P(p,x)             SERIAL_PROTOCOLPGM_P(p,x)
+  #define SERIAL_ERRORLN_P(p,x)              SERIAL_PROTOCOLLN_P(p,x)
+  #define SERIAL_ERRORLNPGM_P(p,x)           SERIAL_PROTOCOLLNPGM_P(p,x)
+  
+  // These macros compensate for float imprecision
+  #define SERIAL_PROTOCOLPAIR_F_P(p, pre, value)    SERIAL_PROTOCOLPAIR_P(p, pre, FIXFLOAT(value))
+  #define SERIAL_PROTOCOLLNPAIR_F_P(p, pre, value)  SERIAL_PROTOCOLLNPAIR_P(p, pre, FIXFLOAT(value))
+  #define SERIAL_ECHOPAIR_F_P(p,pre,value)          SERIAL_ECHOPAIR_P(p, pre, FIXFLOAT(value))
+  #define SERIAL_ECHOLNPAIR_F_P(p,pre, value)       SERIAL_ECHOLNPAIR_P(p, pre, FIXFLOAT(value))
+
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, const char *v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, char v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, int v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, long v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, float v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, double v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, unsigned int v);
+  void serial_echopair_PGM_P(const int8_t p, const char* s_P, unsigned long v);
+  FORCE_INLINE void serial_echopair_PGM_P(const int8_t p, const char* s_P, uint8_t v) { serial_echopair_PGM_P(p, s_P, (int)v); }
+  FORCE_INLINE void serial_echopair_PGM_P(const int8_t p, const char* s_P, bool v) { serial_echopair_PGM_P(p, s_P, (int)v); }
+  FORCE_INLINE void serial_echopair_PGM_P(const int8_t p, const char* s_P, void *v) { serial_echopair_PGM_P(p, s_P, (unsigned long)v); }
+
+  void serial_spaces_P(const int8_t p, uint8_t count);
+  #define SERIAL_ECHO_SP_P(p,C)     serial_spaces_P(p,C)
+  #define SERIAL_ERROR_SP_P(p,C)    serial_spaces_P(p,C)
+  #define SERIAL_PROTOCOL_SP_P(p,C) serial_spaces_P(p,C)
+
+  void serialprintPGM_P(const int8_t p, const char* str);
+#else
+  #define SERIAL_CHAR_P(p,x)          SERIAL_CHAR(x)
+  #define SERIAL_PROTOCOL_P(p,x)      SERIAL_PROTOCOL(x)
+  #define SERIAL_PROTOCOL_F_P(p,x,y)  SERIAL_PROTOCOL_F(x,y)
+  #define SERIAL_PROTOCOLLN_P(p,x)    SERIAL_PROTOCOLLN(x)
+  #define SERIAL_PRINT_P(p,x,b)       SERIAL_PRINT(x,b)
+  #define SERIAL_PRINTLN_P(p,x,b)     SERIAL_PRINTLN(x,b) 
+  #define SERIAL_PRINTF_P(p,args...)  SERIAL_PRINTF(args)
+
+  #define SERIAL_CHAR(x)              MYSERIAL0.write(x)
+  #define SERIAL_PROTOCOL(x)          MYSERIAL0.print(x)
+  #define SERIAL_PROTOCOL_F(x,y)      MYSERIAL0.print(x,y)
+  #define SERIAL_PROTOCOLLN(x)        MYSERIAL0.println(x)
+  #define SERIAL_PRINT(x,b)           MYSERIAL0.print(x,b)
+  #define SERIAL_PRINTLN(x,b)         MYSERIAL0.println(x,b)
+  #define SERIAL_PRINTF(args...)      MYSERIAL0.printf(args)
+
+  #define SERIAL_FLUSH_P(p)           SERIAL_FLUSH()
+  #define SERIAL_FLUSH()              MYSERIAL0.flush()
+  #if TX_BUFFER_SIZE > 0
+    #define SERIAL_FLUSHTX_P(p)       SERIAL_FLUSHTX()
+    #define SERIAL_FLUSHTX()          MYSERIAL0.flushTX()
+  #endif
+
+  #define SERIAL_EOL_P(p) SERIAL_EOL()
+  
+  #define SERIAL_PROTOCOLCHAR_P(p,x)              SERIAL_PROTOCOLCHAR(x)
+  #define SERIAL_PROTOCOLPGM_P(p,x)               SERIAL_PROTOCOLPGM(x)
+  #define SERIAL_PROTOCOLLNPGM_P(p,x)             SERIAL_PROTOCOLLNPGM(x)
+  #define SERIAL_PROTOCOLPAIR_P(p, pre, value)    SERIAL_PROTOCOLPAIR(pre, value)
+  #define SERIAL_PROTOCOLLNPAIR_P(p, pre, value)  SERIAL_PROTOCOLLNPAIR(pre, value)
+  
+  #define SERIAL_ECHO_START_P(p)             SERIAL_ECHO_START()
+  #define SERIAL_ECHO_P(p,x)                 SERIAL_ECHO(x)
+  #define SERIAL_ECHOPGM_P(p,x)              SERIAL_ECHOPGM(x)
+  #define SERIAL_ECHOLN_P(p,x)               SERIAL_ECHOLN(x)
+  #define SERIAL_ECHOLNPGM_P(p,x)            SERIAL_ECHOLNPGM(x)
+  #define SERIAL_ECHOPAIR_P(p,pre,value)     SERIAL_ECHOPAIR(pre, value)
+  #define SERIAL_ECHOLNPAIR_P(p,pre, value)  SERIAL_ECHOLNPAIR(pre, value)
+  #define SERIAL_ECHO_F_P(p,x,y)             SERIAL_ECHO_F(x,y)
+  
+  #define SERIAL_ERROR_START_P(p)            SERIAL_ERROR_START()
+  #define SERIAL_ERROR_P(p,x)                SERIAL_ERROR(x)
+  #define SERIAL_ERRORPGM_P(p,x)             SERIAL_ERRORPGM(x)
+  #define SERIAL_ERRORLN_P(p,x)              SERIAL_ERRORLN(x)
+  #define SERIAL_ERRORLNPGM_P(p,x)           SERIAL_ERRORLNPGM(x)
+  
+  // These macros compensate for float imprecision
+  #define SERIAL_PROTOCOLPAIR_F_P(p, pre, value)    SERIAL_PROTOCOLPAIR_F(pre, value)
+  #define SERIAL_PROTOCOLLNPAIR_F_P(p, pre, value)  SERIAL_PROTOCOLLNPAIR_F(pre, value)
+  #define SERIAL_ECHOPAIR_F_P(p,pre,value)          SERIAL_ECHOPAIR_F(pre, value)
+  #define SERIAL_ECHOLNPAIR_F_P(p,pre, value)       SERIAL_ECHOLNPAIR_F(pre, value)
+
+  #define serial_echopair_PGM_P(p,s_P,v)            serial_echopair_PGM(s_P, v)
+
+  #define serial_spaces_P(p,c)      serial_spaces(c)
+  #define SERIAL_ECHO_SP_P(p,C)     SERIAL_ECHO_SP(C)
+  #define SERIAL_ERROR_SP_P(p,C)    SERIAL_ERROR_SP(C)
+  #define SERIAL_PROTOCOL_SP_P(p,C) SERIAL_PROTOCOL_SP(C)
+
+  #define serialprintPGM_P(p,s)     serialprintPGM(s)
+#endif
+
 #define SERIAL_EOL() SERIAL_CHAR('\n')
 
 #define SERIAL_PROTOCOLCHAR(x)              SERIAL_CHAR(x)
-#define SERIAL_PROTOCOL(x)                  (MYSERIAL.print(x))
-#define SERIAL_PROTOCOL_F(x,y)              (MYSERIAL.print(x,y))
 #define SERIAL_PROTOCOLPGM(x)               (serialprintPGM(PSTR(x)))
-#define SERIAL_PROTOCOLLN(x)                do{ MYSERIAL.print(x); SERIAL_EOL(); }while(0)
 #define SERIAL_PROTOCOLLNPGM(x)             (serialprintPGM(PSTR(x "\n")))
-#define SERIAL_PROTOCOLPAIR(pre, value)     (serial_echopair_P(PSTR(pre),(value)))
-#define SERIAL_PROTOCOLLNPAIR(pre, value)   do{ SERIAL_PROTOCOLPAIR(pre, value); SERIAL_EOL(); }while(0)
+#define SERIAL_PROTOCOLPAIR(pre, value)     (serial_echopair_PGM(PSTR(pre), value))
+#define SERIAL_PROTOCOLLNPAIR(pre, value)   do { SERIAL_PROTOCOLPAIR(pre, value); SERIAL_EOL(); } while(0)
 
 #define SERIAL_ECHO_START()            (serialprintPGM(echomagic))
 #define SERIAL_ECHO(x)                 SERIAL_PROTOCOL(x)
@@ -107,7 +240,7 @@ extern const char errormagic[] PROGMEM;
 #define SERIAL_ECHOLNPGM(x)            SERIAL_PROTOCOLLNPGM(x)
 #define SERIAL_ECHOPAIR(pre,value)     SERIAL_PROTOCOLPAIR(pre, value)
 #define SERIAL_ECHOLNPAIR(pre, value)  SERIAL_PROTOCOLLNPAIR(pre, value)
-#define SERIAL_ECHO_F(x,y)             SERIAL_PROTOCOL_F(x,y)
+#define SERIAL_ECHO_F(x,y)             SERIAL_PROTOCOL_F(x, y)
 
 #define SERIAL_ERROR_START()           (serialprintPGM(errormagic))
 #define SERIAL_ERROR(x)                SERIAL_PROTOCOL(x)
@@ -121,17 +254,17 @@ extern const char errormagic[] PROGMEM;
 #define SERIAL_ECHOPAIR_F(pre,value)        SERIAL_ECHOPAIR(pre, FIXFLOAT(value))
 #define SERIAL_ECHOLNPAIR_F(pre, value)     SERIAL_ECHOLNPAIR(pre, FIXFLOAT(value))
 
-void serial_echopair_P(const char* s_P, const char *v);
-void serial_echopair_P(const char* s_P, char v);
-void serial_echopair_P(const char* s_P, int v);
-void serial_echopair_P(const char* s_P, long v);
-void serial_echopair_P(const char* s_P, float v);
-void serial_echopair_P(const char* s_P, double v);
-void serial_echopair_P(const char* s_P, unsigned int v);
-void serial_echopair_P(const char* s_P, unsigned long v);
-FORCE_INLINE void serial_echopair_P(const char* s_P, uint8_t v) { serial_echopair_P(s_P, (int)v); }
-FORCE_INLINE void serial_echopair_P(const char* s_P, bool v) { serial_echopair_P(s_P, (int)v); }
-FORCE_INLINE void serial_echopair_P(const char* s_P, void *v) { serial_echopair_P(s_P, (unsigned long)v); }
+void serial_echopair_PGM(const char* s_P, const char *v);
+void serial_echopair_PGM(const char* s_P, char v);
+void serial_echopair_PGM(const char* s_P, int v);
+void serial_echopair_PGM(const char* s_P, long v);
+void serial_echopair_PGM(const char* s_P, float v);
+void serial_echopair_PGM(const char* s_P, double v);
+void serial_echopair_PGM(const char* s_P, unsigned int v);
+void serial_echopair_PGM(const char* s_P, unsigned long v);
+FORCE_INLINE void serial_echopair_PGM(const char* s_P, uint8_t v) { serial_echopair_PGM(s_P, (int)v); }
+FORCE_INLINE void serial_echopair_PGM(const char* s_P, bool v) { serial_echopair_PGM(s_P, (int)v); }
+FORCE_INLINE void serial_echopair_PGM(const char* s_P, void *v) { serial_echopair_PGM(s_P, (unsigned long)v); }
 
 void serial_spaces(uint8_t count);
 #define SERIAL_ECHO_SP(C)     serial_spaces(C)
@@ -149,8 +282,7 @@ void serialprintPGM(const char* str);
   #if HAS_ABL
     void print_xyz(const char* prefix, const char* suffix, const vector_3 &xyz);
   #endif
-  #define DEBUG_POS(SUFFIX,VAR) do { \
-    print_xyz(PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); }while(0)
+  #define DEBUG_POS(SUFFIX,VAR) do { print_xyz(PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); } while(0)
 #endif
 
 #endif // __SERIAL_H__
diff --git a/Marlin/src/feature/bedlevel/abl/abl.cpp b/Marlin/src/feature/bedlevel/abl/abl.cpp
index 672a03c3d8e9df39e640adcff0c7db72b1bebf4a..6362608622f0d01d5f285a0889b4752cc78cfd2d 100644
--- a/Marlin/src/feature/bedlevel/abl/abl.cpp
+++ b/Marlin/src/feature/bedlevel/abl/abl.cpp
@@ -64,9 +64,12 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
         c1 = z_values[x1][y1], c2 = z_values[x2][y2];
 
   // Treat far unprobed points as zero, near as equal to far
-  if (isnan(a2)) a2 = 0.0; if (isnan(a1)) a1 = a2;
-  if (isnan(b2)) b2 = 0.0; if (isnan(b1)) b1 = b2;
-  if (isnan(c2)) c2 = 0.0; if (isnan(c1)) c1 = c2;
+  if (isnan(a2)) a2 = 0.0;
+  if (isnan(a1)) a1 = a2;
+  if (isnan(b2)) b2 = 0.0;
+  if (isnan(b1)) b1 = b2;
+  if (isnan(c2)) c2 = 0.0;
+  if (isnan(c1)) c1 = c2;
 
   const float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2;
 
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
index 89739822f3188c8421687e4db2f1d4a00f234b5c..683848f3644c8931cfb18cc7a54ca591ae1739ae 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
@@ -36,13 +36,27 @@
 
   uint8_t ubl_cnt = 0;
 
-  void unified_bed_leveling::echo_name() { SERIAL_PROTOCOLPGM("Unified Bed Leveling"); }
+  void unified_bed_leveling::echo_name(
+    #if NUM_SERIAL > 1
+      const int8_t port/*= -1*/
+    #endif
+  ) {
+    SERIAL_PROTOCOLPGM_P(port, "Unified Bed Leveling");
+  }
 
-  void unified_bed_leveling::report_state() {
-    echo_name();
-    SERIAL_PROTOCOLPGM(" System v" UBL_VERSION " ");
-    if (!planner.leveling_active) SERIAL_PROTOCOLPGM("in");
-    SERIAL_PROTOCOLLNPGM("active.");
+  void unified_bed_leveling::report_state(
+    #if NUM_SERIAL > 1
+      const int8_t port/*= -1*/
+    #endif
+  ) {
+    echo_name(
+      #if NUM_SERIAL > 1
+        port
+      #endif
+    );
+    SERIAL_PROTOCOLPGM_P(port, " System v" UBL_VERSION " ");
+    if (!planner.leveling_active) SERIAL_PROTOCOLPGM_P(port, "in");
+    SERIAL_PROTOCOLLNPGM_P(port, "active.");
     safe_delay(50);
   }
 
@@ -198,10 +212,7 @@
         }
         idle();
         if (map_type == 1 && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR(',');
-
-        #if TX_BUFFER_SIZE > 0
-          MYSERIAL.flushTX();
-        #endif
+        SERIAL_FLUSHTX();
         safe_delay(15);
         if (map_type == 0) {
           SERIAL_CHAR(is_current ? ']' : ' ');
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h
index 01e93769d3aed4a1eff6833e465350491d14d590..82bdbce870dced6547209a6b37380c233fbe86b7 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.h
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.h
@@ -104,8 +104,16 @@ class unified_bed_leveling {
 
   public:
 
-    static void echo_name();
-    static void report_state();
+    static void echo_name(
+      #if NUM_SERIAL > 1
+        const int8_t port = -1
+      #endif
+    );
+    static void report_state(
+      #if NUM_SERIAL > 1
+        const int8_t port = -1
+      #endif
+    );
     static void save_ubl_active_state_and_disable();
     static void restore_ubl_active_state_and_leave();
     static void display_map(const int);
diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp
index ef80495f6d120db01249341746bcf4b6fa3df24c..b799462d35245295c7782aeeb80767b65ef64d89 100644
--- a/Marlin/src/feature/tmc_util.cpp
+++ b/Marlin/src/feature/tmc_util.cpp
@@ -146,12 +146,12 @@ char extended_axis_codes[11][3] = { "X", "X2", "Y", "Y2", "Z", "Z2", "E0", "E1",
       const uint32_t pwm_scale = get_pwm_scale(st);
       SERIAL_ECHO(axisID);
       SERIAL_ECHOPAIR(":", pwm_scale);
-      SERIAL_ECHO(" |0b"); MYSERIAL.print(get_status_response(st), BIN);
+      SERIAL_ECHO(" |0b"); SERIAL_PRINT(get_status_response(st), BIN);
       SERIAL_ECHO("| ");
       if (data.is_error) SERIAL_ECHO('E');
       else if (data.is_ot) SERIAL_ECHO('O');
       else if (data.is_otpw) SERIAL_ECHO('W');
-      else if (otpw_cnt>0) MYSERIAL.print(otpw_cnt, DEC);
+      else if (otpw_cnt>0) SERIAL_PRINT(otpw_cnt, DEC);
       else if (st.flag_otpw) SERIAL_ECHO('F');
       SERIAL_ECHO("\t");
     }
diff --git a/Marlin/src/gcode/eeprom/M500-M504.cpp b/Marlin/src/gcode/eeprom/M500-M504.cpp
index 74140eee15344685c80b58b38e6af4e491a6c3e9..c67f860a00d512df59e8fd3ae6d77399dd5d8e2f 100644
--- a/Marlin/src/gcode/eeprom/M500-M504.cpp
+++ b/Marlin/src/gcode/eeprom/M500-M504.cpp
@@ -24,25 +24,41 @@
 #include "../../module/configuration_store.h"
 #include "../../inc/MarlinConfig.h"
 
+#if NUM_SERIAL > 1
+  #include "../../gcode/queue.h"
+#endif
+
 /**
  * M500: Store settings in EEPROM
  */
 void GcodeSuite::M500() {
-  (void)settings.save();
+  (void)settings.save(
+    #if ENABLED(EEPROM_CHITCHAT) && NUM_SERIAL > 1
+      command_queue_port[cmd_queue_index_r]
+    #endif
+  );
 }
 
 /**
  * M501: Read settings from EEPROM
  */
 void GcodeSuite::M501() {
-  (void)settings.load();
+  (void)settings.load(
+    #if ENABLED(EEPROM_SETTINGS) && ENABLED(EEPROM_CHITCHAT) && NUM_SERIAL > 1
+      command_queue_port[cmd_queue_index_r]
+    #endif
+  );
 }
 
 /**
  * M502: Revert to default settings
  */
 void GcodeSuite::M502() {
-  (void)settings.reset();
+  (void)settings.reset(
+    #if ENABLED(EEPROM_CHITCHAT) && NUM_SERIAL > 1
+      command_queue_port[cmd_queue_index_r]
+    #endif
+  );
 }
 
 #if DISABLED(DISABLE_M503)
@@ -51,7 +67,11 @@ void GcodeSuite::M502() {
    * M503: print settings currently in memory
    */
   void GcodeSuite::M503() {
-    (void)settings.report(parser.seen('S') && !parser.value_bool());
+    (void)settings.report(parser.seen('S') && !parser.value_bool()
+      #if NUM_SERIAL > 1
+        , command_queue_port[cmd_queue_index_r]
+      #endif
+    );
   }
 
 #endif // !DISABLE_M503
diff --git a/Marlin/src/gcode/feature/trinamic/M122.cpp b/Marlin/src/gcode/feature/trinamic/M122.cpp
index 843e2e7e9a604ad091b17a04a69b495565a93036..dc6d51eed9dfab32ed923aec91580710ac2a92ac 100644
--- a/Marlin/src/gcode/feature/trinamic/M122.cpp
+++ b/Marlin/src/gcode/feature/trinamic/M122.cpp
@@ -79,21 +79,21 @@ static void drv_status_print_hex(const char name[], const uint32_t drv_status) {
   SERIAL_ECHO(name);
   SERIAL_ECHOPGM(" = 0x");
   for(int B=24; B>=8; B-=8){
-    MYSERIAL.print((drv_status>>(B+4))&0xF, HEX);
-    MYSERIAL.print((drv_status>>B)&0xF, HEX);
-    MYSERIAL.print(':');
+    SERIAL_PRINT((drv_status>>(B+4))&0xF, HEX);
+    SERIAL_PRINT((drv_status>>B)&0xF, HEX);
+    SERIAL_CHAR(':');
   }
-  MYSERIAL.print((drv_status>>4)&0xF, HEX);
-  MYSERIAL.print((drv_status)&0xF, HEX);
+  SERIAL_PRINT((drv_status>>4)&0xF, HEX);
+  SERIAL_PRINT((drv_status)&0xF, HEX);
   SERIAL_EOL();
 }
 
 #if ENABLED(HAVE_TMC2130)
   static void tmc_status(TMC2130Stepper &st, const TMC_debug_enum i) {
     switch(i) {
-      case TMC_PWM_SCALE: MYSERIAL.print(st.PWM_SCALE(), DEC); break;
+      case TMC_PWM_SCALE: SERIAL_PRINT(st.PWM_SCALE(), DEC); break;
       case TMC_TSTEP: SERIAL_ECHO(st.TSTEP()); break;
-      case TMC_SGT: MYSERIAL.print(st.sgt(), DEC); break;
+      case TMC_SGT: SERIAL_PRINT(st.sgt(), DEC); break;
       case TMC_STEALTHCHOP: serialprintPGM(st.stealthChop() ? PSTR("true") : PSTR("false")); break;
       default: break;
     }
@@ -101,7 +101,7 @@ static void drv_status_print_hex(const char name[], const uint32_t drv_status) {
   static void tmc_parse_drv_status(TMC2130Stepper &st, const TMC_drv_status_enum i) {
     switch(i) {
       case TMC_STALLGUARD: if (st.stallguard()) SERIAL_ECHOPGM("X"); break;
-      case TMC_SG_RESULT:  MYSERIAL.print(st.sg_result(), DEC);      break;
+      case TMC_SG_RESULT:  SERIAL_PRINT(st.sg_result(), DEC);      break;
       case TMC_FSACTIVE:   if (st.fsactive())   SERIAL_ECHOPGM("X"); break;
       default: break;
     }
@@ -113,10 +113,10 @@ static void drv_status_print_hex(const char name[], const uint32_t drv_status) {
       case TMC_TSTEP: {
           uint32_t data = 0;
           st.TSTEP(&data);
-          MYSERIAL.print(data);
+          SERIAL_PROTOCOL(data);
           break;
         }
-      case TMC_PWM_SCALE: MYSERIAL.print(st.pwm_scale_sum(), DEC); break;
+      case TMC_PWM_SCALE: SERIAL_PRINT(st.pwm_scale_sum(), DEC); break;
       case TMC_STEALTHCHOP: serialprintPGM(st.stealth() ? PSTR("true") : PSTR("false")); break;
       case TMC_S2VSA: if (st.s2vsa()) SERIAL_ECHOPGM("X"); break;
       case TMC_S2VSB: if (st.s2vsb()) SERIAL_ECHOPGM("X"); break;
@@ -140,18 +140,18 @@ static void tmc_status(TMC &st, TMC_AxisEnum axis, const TMC_debug_enum i, const
     case TMC_CODES: SERIAL_ECHO(extended_axis_codes[axis]); break;
     case TMC_ENABLED: serialprintPGM(st.isEnabled() ? PSTR("true") : PSTR("false")); break;
     case TMC_CURRENT: SERIAL_ECHO(st.getCurrent()); break;
-    case TMC_RMS_CURRENT: MYSERIAL.print(st.rms_current()); break;
-    case TMC_MAX_CURRENT: MYSERIAL.print((float)st.rms_current()*1.41, 0); break;
+    case TMC_RMS_CURRENT: SERIAL_PROTOCOL(st.rms_current()); break;
+    case TMC_MAX_CURRENT: SERIAL_PRINT((float)st.rms_current()*1.41, 0); break;
     case TMC_IRUN:
-      MYSERIAL.print(st.irun(), DEC);
+      SERIAL_PRINT(st.irun(), DEC);
       SERIAL_ECHOPGM("/31");
       break;
     case TMC_IHOLD:
-      MYSERIAL.print(st.ihold(), DEC);
+      SERIAL_PRINT(st.ihold(), DEC);
       SERIAL_ECHOPGM("/31");
       break;
     case TMC_CS_ACTUAL:
-      MYSERIAL.print(st.cs_actual(), DEC);
+      SERIAL_PRINT(st.cs_actual(), DEC);
       SERIAL_ECHOPGM("/31");
       break;
 
@@ -170,10 +170,10 @@ static void tmc_status(TMC &st, TMC_AxisEnum axis, const TMC_debug_enum i, const
       break;
     case TMC_OTPW: serialprintPGM(st.otpw() ? PSTR("true") : PSTR("false")); break;
     case TMC_OTPW_TRIGGERED: serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false")); break;
-    case TMC_TOFF: MYSERIAL.print(st.toff(), DEC); break;
-    case TMC_TBL: MYSERIAL.print(st.blank_time(), DEC); break;
-    case TMC_HEND: MYSERIAL.print(st.hysterisis_end(), DEC); break;
-    case TMC_HSTRT: MYSERIAL.print(st.hysterisis_start(), DEC); break;
+    case TMC_TOFF: SERIAL_PRINT(st.toff(), DEC); break;
+    case TMC_TBL: SERIAL_PRINT(st.blank_time(), DEC); break;
+    case TMC_HEND: SERIAL_PRINT(st.hysterisis_end(), DEC); break;
+    case TMC_HSTRT: SERIAL_PRINT(st.hysterisis_start(), DEC); break;
     default: tmc_status(st, i); break;
   }
 }
@@ -189,7 +189,7 @@ static void tmc_parse_drv_status(TMC &st, TMC_AxisEnum axis, const TMC_drv_statu
     case TMC_S2GA:          if (st.s2ga())         SERIAL_ECHOPGM("X"); break;
     case TMC_DRV_OTPW:      if (st.otpw())         SERIAL_ECHOPGM("X"); break;
     case TMC_OT:            if (st.ot())           SERIAL_ECHOPGM("X"); break;
-    case TMC_DRV_CS_ACTUAL: MYSERIAL.print(st.cs_actual(), DEC);        break;
+    case TMC_DRV_CS_ACTUAL: SERIAL_PRINT(st.cs_actual(), DEC);        break;
     case TMC_DRV_STATUS_HEX:drv_status_print_hex(extended_axis_codes[axis], st.DRV_STATUS()); break;
     default: tmc_parse_drv_status(st, i); break;
   }
diff --git a/Marlin/src/gcode/host/M115.cpp b/Marlin/src/gcode/host/M115.cpp
index b5e8bd788b066b9e3a78b1ad9180138a6ee59fb9..b67238f2b2b561456af648eaea5719c891d6675f 100644
--- a/Marlin/src/gcode/host/M115.cpp
+++ b/Marlin/src/gcode/host/M115.cpp
@@ -23,6 +23,10 @@
 #include "../gcode.h"
 #include "../../inc/MarlinConfig.h"
 
+#if NUM_SERIAL > 1
+  #include "../../gcode/queue.h"
+#endif
+
 #if ENABLED(EXTENDED_CAPABILITIES_REPORT)
   static void cap_line(const char * const name, bool ena=false) {
     SERIAL_PROTOCOLPGM("Cap:");
@@ -36,7 +40,14 @@
  * M115: Capabilities string
  */
 void GcodeSuite::M115() {
-  SERIAL_PROTOCOLLNPGM(MSG_M115_REPORT);
+  #if NUM_SERIAL > 1
+    const int8_t port = command_queue_port[cmd_queue_index_r];
+    #define CAPLINE(STR,...) cap_line(PSTR(STR), port, __VA_ARGS__)
+  #else
+    #define CAPLINE(STR,...) cap_line(PSTR(STR), __VA_ARGS__)
+  #endif
+
+  SERIAL_PROTOCOLLNPGM_P(port, MSG_M115_REPORT);
 
   #if ENABLED(EXTENDED_CAPABILITIES_REPORT)
 
diff --git a/Marlin/src/gcode/parser.cpp b/Marlin/src/gcode/parser.cpp
index c02ddff4a89b37315173a1fc972f1d64ccadeae6..807ad3ad2d438986d4a991d93e4ba65371641eab 100644
--- a/Marlin/src/gcode/parser.cpp
+++ b/Marlin/src/gcode/parser.cpp
@@ -32,6 +32,10 @@
   #include "../libs/hex_print_routines.h"
 #endif
 
+#if NUM_SERIAL > 1
+  #include "queue.h"
+#endif
+
 // Must be declared for allocation and to satisfy the linker
 // Zero values need no initialization.
 
@@ -265,10 +269,13 @@ void GCodeParser::parse(char *p) {
 #endif // CNC_COORDINATE_SYSTEMS
 
 void GCodeParser::unknown_command_error() {
-  SERIAL_ECHO_START();
-  SERIAL_ECHOPAIR(MSG_UNKNOWN_COMMAND, command_ptr);
-  SERIAL_CHAR('"');
-  SERIAL_EOL();
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+  #endif
+  SERIAL_ECHO_START_P(port);
+  SERIAL_ECHOPAIR_P(port, MSG_UNKNOWN_COMMAND, command_ptr);
+  SERIAL_CHAR_P(port, '"');
+  SERIAL_EOL_P(port);
 }
 
 #if ENABLED(DEBUG_GCODE_PARSER)
diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp
index 6a7916c538813a5b9fab798c166cc94ffd9bc7a9..11fd46fa755111b52af92f9594aa2a2f60e56e93 100644
--- a/Marlin/src/gcode/queue.cpp
+++ b/Marlin/src/gcode/queue.cpp
@@ -58,12 +58,19 @@ uint8_t commands_in_queue = 0, // Count of commands in the queue
 
 char command_queue[BUFSIZE][MAX_CMD_SIZE];
 
+/*
+ * The port that the command was received on
+ */
+#if NUM_SERIAL > 1
+  int16_t command_queue_port[BUFSIZE];
+#endif
+
 /**
  * Serial command injection
  */
 
 // Number of characters read in the current line of serial input
-static int serial_count = 0;
+static int serial_count[NUM_SERIAL] = { 0 };
 
 bool send_ok[BUFSIZE];
 
@@ -90,8 +97,15 @@ void clear_command_queue() {
 /**
  * Once a new command is in the ring buffer, call this to commit it
  */
-inline void _commit_command(bool say_ok) {
+inline void _commit_command(bool say_ok
+  #if NUM_SERIAL > 1
+    , int16_t port = -1
+  #endif
+) {
   send_ok[cmd_queue_index_w] = say_ok;
+  #if NUM_SERIAL > 1
+    command_queue_port[cmd_queue_index_w] = port;
+  #endif
   if (++cmd_queue_index_w >= BUFSIZE) cmd_queue_index_w = 0;
   commands_in_queue++;
 }
@@ -101,10 +115,18 @@ inline void _commit_command(bool say_ok) {
  * Return true if the command was successfully added.
  * Return false for a full buffer, or if the 'command' is a comment.
  */
-inline bool _enqueuecommand(const char* cmd, bool say_ok/*=false*/) {
+inline bool _enqueuecommand(const char* cmd, bool say_ok
+  #if NUM_SERIAL > 1
+    , int16_t port = -1
+  #endif
+) {
   if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
   strcpy(command_queue[cmd_queue_index_w], cmd);
-  _commit_command(say_ok);
+  _commit_command(say_ok
+    #if NUM_SERIAL > 1
+      , port
+    #endif
+  );
   return true;
 }
 
@@ -178,21 +200,25 @@ void enqueue_and_echo_commands_P(const char * const pgcode) {
  *   B<int>  Block queue space remaining
  */
 void ok_to_send() {
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+    if (port < 0) return;
+  #endif
   gcode.refresh_cmd_timeout();
   if (!send_ok[cmd_queue_index_r]) return;
-  SERIAL_PROTOCOLPGM(MSG_OK);
+  SERIAL_PROTOCOLPGM_P(port, MSG_OK);
   #if ENABLED(ADVANCED_OK)
     char* p = command_queue[cmd_queue_index_r];
     if (*p == 'N') {
-      SERIAL_PROTOCOL(' ');
-      SERIAL_ECHO(*p++);
+      SERIAL_PROTOCOL_P(port, ' ');
+      SERIAL_ECHO_P(port, *p++);
       while (NUMERIC_SIGNED(*p))
-        SERIAL_ECHO(*p++);
+        SERIAL_ECHO_P(port, *p++);
     }
-    SERIAL_PROTOCOLPGM(" P"); SERIAL_PROTOCOL(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
-    SERIAL_PROTOCOLPGM(" B"); SERIAL_PROTOCOL(BUFSIZE - commands_in_queue);
+    SERIAL_PROTOCOLPGM_P(port, " P"); SERIAL_PROTOCOL_P(port, int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
+    SERIAL_PROTOCOLPGM_P(port, " B"); SERIAL_PROTOCOL_P(port, BUFSIZE - commands_in_queue);
   #endif
-  SERIAL_EOL();
+  SERIAL_EOL_P(port);
 }
 
 /**
@@ -200,20 +226,39 @@ void ok_to_send() {
  * indicate that a command needs to be re-sent.
  */
 void flush_and_request_resend() {
-  //char command_queue[cmd_queue_index_r][100]="Resend:";
-  MYSERIAL.flush();
-  SERIAL_PROTOCOLPGM(MSG_RESEND);
-  SERIAL_PROTOCOLLN(gcode_LastN + 1);
-  ok_to_send();
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+    if (port < 0) return;
+  #endif
+  SERIAL_FLUSH_P(port);
+  SERIAL_PROTOCOLPGM_P(port, MSG_RESEND);
+  SERIAL_PROTOCOLLN_P(port, gcode_LastN + 1);
 }
 
-void gcode_line_error(const char* err, bool doFlush = true) {
-  SERIAL_ERROR_START();
-  serialprintPGM(err);
-  SERIAL_ERRORLN(gcode_LastN);
-  //Serial.println(gcode_N);
-  if (doFlush) flush_and_request_resend();
-  serial_count = 0;
+void gcode_line_error(const char* err, uint8_t port) {
+  SERIAL_ERROR_START_P(port);
+  serialprintPGM_P(port, err);
+  SERIAL_ERRORLN_P(port, gcode_LastN);
+  flush_and_request_resend();
+  serial_count[port] = 0;
+}
+
+static bool serial_data_available() {
+  return (MYSERIAL0.available() ? true :
+    #if NUM_SERIAL > 1
+      MYSERIAL1.available() ? true :
+    #endif
+    false);
+}
+
+static int read_serial(const int index) {
+  switch (index) {
+    case 0: return MYSERIAL0.read();
+    #if NUM_SERIAL > 1 
+      case 1: return MYSERIAL1.read();
+    #endif
+    default: return -1;
+  }
 }
 
 /**
@@ -222,15 +267,15 @@ void gcode_line_error(const char* err, bool doFlush = true) {
  * left on the serial port.
  */
 inline void get_serial_commands() {
-  static char serial_line_buffer[MAX_CMD_SIZE];
-  static bool serial_comment_mode = false;
+  static char serial_line_buffer[NUM_SERIAL][MAX_CMD_SIZE];
+  static bool serial_comment_mode[NUM_SERIAL] = { false };
 
   // If the command buffer is empty for too long,
   // send "wait" to indicate Marlin is still waiting.
   #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
     static millis_t last_command_time = 0;
     const millis_t ms = millis();
-    if (commands_in_queue == 0 && !MYSERIAL.available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
+    if (commands_in_queue == 0 && !serial_data_available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
       SERIAL_ECHOLNPGM(MSG_WAIT);
       last_command_time = ms;
     }
@@ -239,110 +284,117 @@ inline void get_serial_commands() {
   /**
    * Loop while serial characters are incoming and the queue is not full
    */
-  int c;
-  while (commands_in_queue < BUFSIZE && (c = MYSERIAL.read()) >= 0) {
-    char serial_char = c;
+  while (commands_in_queue < BUFSIZE && serial_data_available()) {
+    for (uint8_t i = 0; i < NUM_SERIAL; ++i) {
+      int c;
+      if ((c = read_serial(i)) < 0) continue;
 
-    /**
-     * If the character ends the line
-     */
-    if (serial_char == '\n' || serial_char == '\r') {
+      char serial_char = c;
 
-      serial_comment_mode = false;                      // end of line == end of comment
+      /**
+       * If the character ends the line
+       */
+      if (serial_char == '\n' || serial_char == '\r') {
 
-      if (!serial_count) continue;                      // Skip empty lines
+        serial_comment_mode[i] = false;                   // end of line == end of comment
 
-      serial_line_buffer[serial_count] = 0;             // Terminate string
-      serial_count = 0;                                 // Reset buffer
+        if (!serial_count[i]) continue;                   // Skip empty lines
 
-      char* command = serial_line_buffer;
+        serial_line_buffer[i][serial_count[i]] = 0;       // Terminate string
+        serial_count[i] = 0;                              // Reset buffer
 
-      while (*command == ' ') command++;                // Skip leading spaces
-      char *npos = (*command == 'N') ? command : NULL;  // Require the N parameter to start the line
+        char* command = serial_line_buffer[i];
 
-      if (npos) {
+        while (*command == ' ') command++;                // Skip leading spaces
+        char *npos = (*command == 'N') ? command : NULL;  // Require the N parameter to start the line
 
-        bool M110 = strstr_P(command, PSTR("M110")) != NULL;
+        if (npos) {
 
-        if (M110) {
-          char* n2pos = strchr(command + 4, 'N');
-          if (n2pos) npos = n2pos;
-        }
+          bool M110 = strstr_P(command, PSTR("M110")) != NULL;
 
-        gcode_N = strtol(npos + 1, NULL, 10);
+          if (M110) {
+            char* n2pos = strchr(command + 4, 'N');
+            if (n2pos) npos = n2pos;
+          }
 
-        if (gcode_N != gcode_LastN + 1 && !M110) {
-          gcode_line_error(PSTR(MSG_ERR_LINE_NO));
-          return;
-        }
+          gcode_N = strtol(npos + 1, NULL, 10);
 
-        char *apos = strrchr(command, '*');
-        if (apos) {
-          uint8_t checksum = 0, count = uint8_t(apos - command);
-          while (count) checksum ^= command[--count];
-          if (strtol(apos + 1, NULL, 10) != checksum) {
-            gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH));
+          if (gcode_N != gcode_LastN + 1 && !M110) {
+            gcode_line_error(PSTR(MSG_ERR_LINE_NO), i);
             return;
           }
-        }
-        else {
-          gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM));
-          return;
-        }
-
-        gcode_LastN = gcode_N;
-      }
 
-      // Movement commands alert when stopped
-      if (IsStopped()) {
-        char* gpos = strchr(command, 'G');
-        if (gpos) {
-          const int codenum = strtol(gpos + 1, NULL, 10);
-          switch (codenum) {
-            case 0:
-            case 1:
-            case 2:
-            case 3:
-              SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
-              LCD_MESSAGEPGM(MSG_STOPPED);
-              break;
+          char *apos = strrchr(command, '*');
+          if (apos) {
+            uint8_t checksum = 0, count = uint8_t(apos - command);
+            while (count) checksum ^= command[--count];
+            if (strtol(apos + 1, NULL, 10) != checksum) {
+              gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH), i);
+              return;
+            }
+          }
+          else {
+            gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i);
+            return;
           }
-        }
-      }
 
-      #if DISABLED(EMERGENCY_PARSER)
-        // If command was e-stop process now
-        if (strcmp(command, "M108") == 0) {
-          wait_for_heatup = false;
-          #if ENABLED(ULTIPANEL)
-            wait_for_user = false;
-          #endif
+          gcode_LastN = gcode_N;
         }
-        if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
-        if (strcmp(command, "M410") == 0) { quickstop_stepper(); }
-      #endif
-
-      #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
-        last_command_time = ms;
-      #endif
 
-      // Add the command to the queue
-      _enqueuecommand(serial_line_buffer, true);
-    }
-    else if (serial_count >= MAX_CMD_SIZE - 1) {
-      // Keep fetching, but ignore normal characters beyond the max length
-      // The command will be injected when EOL is reached
-    }
-    else if (serial_char == '\\') {  // Handle escapes
-      // if we have one more character, copy it over
-      if ((c = MYSERIAL.read()) >= 0 && !serial_comment_mode)
-        serial_line_buffer[serial_count++] = serial_char;
-    }
-    else { // it's not a newline, carriage return or escape char
-      if (serial_char == ';') serial_comment_mode = true;
-      if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
-    }
+        // Movement commands alert when stopped
+        if (IsStopped()) {
+          char* gpos = strchr(command, 'G');
+          if (gpos) {
+            const int codenum = strtol(gpos + 1, NULL, 10);
+            switch (codenum) {
+              case 0:
+              case 1:
+              case 2:
+              case 3:
+                SERIAL_ERRORLNPGM_P(i, MSG_ERR_STOPPED);
+                LCD_MESSAGEPGM(MSG_STOPPED);
+                break;
+            }
+          }
+        }
 
+        #if DISABLED(EMERGENCY_PARSER)
+          // If command was e-stop process now
+          if (strcmp(command, "M108") == 0) {
+            wait_for_heatup = false;
+            #if ENABLED(ULTIPANEL)
+              wait_for_user = false;
+            #endif
+          }
+          if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
+          if (strcmp(command, "M410") == 0) { quickstop_stepper(); }
+        #endif
+
+        #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
+          last_command_time = ms;
+        #endif
+
+        // Add the command to the queue
+        _enqueuecommand(serial_line_buffer[i], true
+          #if NUM_SERIAL > 1
+            , i
+          #endif
+        );
+      }
+      else if (serial_count[i] >= MAX_CMD_SIZE - 1) {
+        // Keep fetching, but ignore normal characters beyond the max length
+        // The command will be injected when EOL is reached
+      }
+      else if (serial_char == '\\') {  // Handle escapes
+        // if we have one more character, copy it over
+        if ((c = read_serial(i)) >= 0 && !serial_comment_mode[i])
+          serial_line_buffer[i][serial_count[i]++] = serial_char;
+      }
+      else { // it's not a newline, carriage return or escape char
+        if (serial_char == ';') serial_comment_mode[i] = true;
+        if (!serial_comment_mode[i]) serial_line_buffer[i][serial_count[i]++] = serial_char;
+      }
+    } // for NUM_SERIAL
   } // queue has space, serial has data
 }
 
diff --git a/Marlin/src/gcode/queue.h b/Marlin/src/gcode/queue.h
index f2e2ef70745b93ff672d111e8c3ca1428e763bbb..68e9de65aa1d71bc55c5725567bc0656bce06ed4 100644
--- a/Marlin/src/gcode/queue.h
+++ b/Marlin/src/gcode/queue.h
@@ -51,6 +51,13 @@ extern uint8_t commands_in_queue, // Count of commands in the queue
 
 extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
 
+/*
+ * The port that the command was received on
+ */
+#if NUM_SERIAL > 1
+  extern int16_t command_queue_port[BUFSIZE];
+#endif
+
 /**
  * Initialization of queue for setup()
  */
diff --git a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
index 566a8801036f3643d233b7c27abd3d88ee871746..993e328d21787a633b5c9c6813f24f6cc86bce51 100644
--- a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
+++ b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
@@ -34,13 +34,25 @@
   #include "../queue.h"
 #endif
 
+#if NUM_SERIAL > 1
+  #include "../../gcode/queue.h"
+#endif
+
 /**
  * M20: List SD card to serial output
  */
 void GcodeSuite::M20() {
-  SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST);
-  card.ls();
-  SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST);
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+  #endif
+
+  SERIAL_PROTOCOLLNPGM_P(port, MSG_BEGIN_FILE_LIST);
+  card.ls(
+    #if NUM_SERIAL > 1
+      port
+    #endif
+  );
+  SERIAL_PROTOCOLLNPGM_P(port, MSG_END_FILE_LIST);
 }
 
 /**
@@ -97,7 +109,13 @@ void GcodeSuite::M26() {
 /**
  * M27: Get SD Card status
  */
-void GcodeSuite::M27() { card.getStatus(); }
+void GcodeSuite::M27() { 
+  card.getStatus(
+    #if NUM_SERIAL > 1
+      command_queue_port[cmd_queue_index_r]
+    #endif
+  );
+}
 
 /**
  * M28: Start SD Write
@@ -164,7 +182,11 @@ void GcodeSuite::M32() {
    *   /Miscellaneous/Armchair/Armchair.gcode
    */
   void GcodeSuite::M33() {
-    card.printLongPath(parser.string_arg);
+    card.printLongPath(parser.string_arg
+      #if NUM_SERIAL > 1
+        , command_queue_port[cmd_queue_index_r]
+      #endif
+    );
   }
 
 #endif // LONG_FILENAME_HOST_SUPPORT
diff --git a/Marlin/src/gcode/stats/M31.cpp b/Marlin/src/gcode/stats/M31.cpp
index 327ff8c37d552d1b5e754d5221b25cd2c8960565..958556e544e3b8284bb0fa2ea522c729f61a839c 100644
--- a/Marlin/src/gcode/stats/M31.cpp
+++ b/Marlin/src/gcode/stats/M31.cpp
@@ -26,15 +26,22 @@
 #include "../../libs/duration_t.h"
 #include "../../lcd/ultralcd.h"
 
+#if NUM_SERIAL > 1
+  #include "../../gcode/queue.h"
+#endif
+
 /**
  * M31: Get the time since the start of SD Print (or last M109)
  */
 void GcodeSuite::M31() {
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+  #endif
   char buffer[21];
   duration_t elapsed = print_job_timer.duration();
   elapsed.toString(buffer);
   lcd_setstatus(buffer);
 
-  SERIAL_ECHO_START();
-  SERIAL_ECHOLNPAIR("Print time: ", buffer);
+  SERIAL_ECHO_START_P(port);
+  SERIAL_ECHOLNPAIR_P(port, "Print time: ", buffer);
 }
diff --git a/Marlin/src/gcode/temperature/M105.cpp b/Marlin/src/gcode/temperature/M105.cpp
index e4417c6afa5b2604a549fae29f3b8b8c2c72d819..36d4d67ac5e208aa35b300f17769915bfa42c3f9 100644
--- a/Marlin/src/gcode/temperature/M105.cpp
+++ b/Marlin/src/gcode/temperature/M105.cpp
@@ -23,19 +23,31 @@
 #include "../gcode.h"
 #include "../../module/temperature.h"
 
+#if NUM_SERIAL > 1
+  #include "../../gcode/queue.h"
+#endif
+
 /**
  * M105: Read hot end and bed temperature
  */
 void GcodeSuite::M105() {
   if (get_target_extruder_from_command()) return;
 
+  #if NUM_SERIAL > 1
+    const int16_t port = command_queue_port[cmd_queue_index_r];
+  #endif
+
   #if HAS_TEMP_HOTEND || HAS_TEMP_BED
-    SERIAL_PROTOCOLPGM(MSG_OK);
-    thermalManager.print_heaterstates();
+    SERIAL_PROTOCOLPGM_P(port, MSG_OK);
+    thermalManager.print_heaterstates(
+      #if NUM_SERIAL > 1
+        port
+      #endif
+    );
   #else // !HAS_TEMP_HOTEND && !HAS_TEMP_BED
-    SERIAL_ERROR_START();
-    SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
+    SERIAL_ERROR_START_P(port);
+    SERIAL_ERRORLNPGM_P(port, MSG_ERR_NO_THERMISTORS);
   #endif
 
-  SERIAL_EOL();
+  SERIAL_EOL_P(port);
 }
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index ee7e1126f8cc96bcb057c143dc367744a13a4969..fa85e5c1f8f07219597286af45db69858fea9fd4 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -494,10 +494,4 @@
 #define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
 #define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED))
 
-// For Re-ARM boards, always use the USB Emulated Serial Port unless RE_ARM_FORCE_SERIAL_PORT is defined
-#if !defined(RE_ARM_FORCE_SERIAL_PORT) && (MB(RAMPS_14_RE_ARM_EFB) || MB(RAMPS_14_RE_ARM_EEB) || MB(RAMPS_14_RE_ARM_EFF) || MB(RAMPS_14_RE_ARM_EEF) || MB(RAMPS_14_RE_ARM_SF))
-  #undef SERIAL_PORT
-  #define SERIAL_PORT -1
-#endif
-
 #endif // CONDITIONALS_LCD_H
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 1ab2a26cf2a430608ae19d831738949ea754dedf..d2680229a9d885c26d6a3dbeeedcf69b05efa3d4 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -322,7 +322,7 @@ void MarlinSettings::postprocess() {
   #define EEPROM_WRITE(VAR) HAL::PersistentStore::write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
   #define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc, !validating)
   #define EEPROM_READ_ALWAYS(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
-  #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START(); SERIAL_ERRORLNPGM(ERR); eeprom_error = true; }while(0)
+  #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START_P(port); SERIAL_ERRORLNPGM_P(port, ERR); eeprom_error = true; }while(0)
 
   #if ENABLED(DEBUG_EEPROM_READWRITE)
     #define _FIELD_TEST(FIELD) \
@@ -338,10 +338,16 @@ void MarlinSettings::postprocess() {
 
   bool MarlinSettings::eeprom_error, MarlinSettings::validating;
 
-  bool MarlinSettings::size_error(const uint16_t size) {
+  bool MarlinSettings::size_error(const uint16_t size
+    #if ADD_PORT_ARG
+      , const int8_t port/*=-1*/
+    #endif
+  ) {
     if (size != datasize()) {
-      SERIAL_ERROR_START();
-      SERIAL_ERRORLNPGM("EEPROM datasize error.");
+      #if ENABLED(EEPROM_CHITCHAT)
+        SERIAL_ERROR_START_P(port);
+        SERIAL_ERRORLNPGM_P(port, "EEPROM datasize error.");
+      #endif
       return true;
     }
     return false;
@@ -350,7 +356,11 @@ void MarlinSettings::postprocess() {
   /**
    * M500 - Store Configuration
    */
-  bool MarlinSettings::save() {
+  bool MarlinSettings::save(
+    #if ADD_PORT_ARG
+      const int8_t port/*=-1*/
+    #endif
+  ) {
     float dummy = 0.0f;
     char ver[4] = "ERR";
 
@@ -810,10 +820,10 @@ void MarlinSettings::postprocess() {
 
       // Report storage size
       #if ENABLED(EEPROM_CHITCHAT)
-        SERIAL_ECHO_START();
-        SERIAL_ECHOPAIR("Settings Stored (", eeprom_size);
-        SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)final_crc);
-        SERIAL_ECHOLNPGM(")");
+        SERIAL_ECHO_START_P(port);
+        SERIAL_ECHOPAIR_P(port, "Settings Stored (", eeprom_size);
+        SERIAL_ECHOPAIR_P(port, " bytes; crc ", (uint32_t)final_crc);
+        SERIAL_ECHOLNPGM_P(port, ")");
       #endif
 
       eeprom_error |= size_error(eeprom_size);
@@ -834,7 +844,11 @@ void MarlinSettings::postprocess() {
   /**
    * M501 - Retrieve Configuration
    */
-  bool MarlinSettings::_load() {
+  bool MarlinSettings::_load(
+    #if ADD_PORT_ARG
+      const int8_t port/*=-1*/
+    #endif
+  ) {
     uint16_t working_crc = 0;
 
     EEPROM_START();
@@ -852,10 +866,10 @@ void MarlinSettings::postprocess() {
         stored_ver[1] = '\0';
       }
       #if ENABLED(EEPROM_CHITCHAT)
-        SERIAL_ECHO_START();
-        SERIAL_ECHOPGM("EEPROM version mismatch ");
-        SERIAL_ECHOPAIR("(EEPROM=", stored_ver);
-        SERIAL_ECHOLNPGM(" Marlin=" EEPROM_VERSION ")");
+        SERIAL_ECHO_START_P(port);
+        SERIAL_ECHOPGM_P(port, "EEPROM version mismatch ");
+        SERIAL_ECHOPAIR_P(port, "(EEPROM=", stored_ver);
+        SERIAL_ECHOLNPGM_P(port, " Marlin=" EEPROM_VERSION ")");
       #endif
       if (!validating) reset();
       eeprom_error = true;
@@ -1334,28 +1348,28 @@ void MarlinSettings::postprocess() {
 
       eeprom_error = size_error(eeprom_index - (EEPROM_OFFSET));
       if (eeprom_error) {
-        SERIAL_ECHO_START();
-        SERIAL_ECHOPAIR("Index: ", int(eeprom_index - (EEPROM_OFFSET)));
-        SERIAL_ECHOLNPAIR(" Size: ", datasize());
+        SERIAL_ECHO_START_P(port);
+        SERIAL_ECHOPAIR_P(port, "Index: ", int(eeprom_index - (EEPROM_OFFSET)));
+        SERIAL_ECHOLNPAIR_P(port, " Size: ", datasize());
       }
       else if (working_crc != stored_crc) {
         eeprom_error = true;
         #if ENABLED(EEPROM_CHITCHAT)
-          SERIAL_ERROR_START();
-          SERIAL_ERRORPGM("EEPROM CRC mismatch - (stored) ");
-          SERIAL_ERROR(stored_crc);
-          SERIAL_ERRORPGM(" != ");
-          SERIAL_ERROR(working_crc);
-          SERIAL_ERRORLNPGM(" (calculated)!");
+          SERIAL_ERROR_START_P(port);
+          SERIAL_ERRORPGM_P(port, "EEPROM CRC mismatch - (stored) ");
+          SERIAL_ERROR_P(port, stored_crc);
+          SERIAL_ERRORPGM_P(port, " != ");
+          SERIAL_ERROR_P(port, working_crc);
+          SERIAL_ERRORLNPGM_P(port, " (calculated)!");
         #endif
       }
       else if (!validating) {
         #if ENABLED(EEPROM_CHITCHAT)
-          SERIAL_ECHO_START();
-          SERIAL_ECHO(version);
-          SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
-          SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)working_crc);
-          SERIAL_ECHOLNPGM(")");
+          SERIAL_ECHO_START_P(port);
+          SERIAL_ECHO_P(port, version);
+          SERIAL_ECHOPAIR_P(port, " stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
+          SERIAL_ECHOPAIR_P(port, " bytes; crc ", (uint32_t)working_crc);
+          SERIAL_ECHOLNPGM_P(port, ")");
         #endif
       }
 
@@ -1368,18 +1382,18 @@ void MarlinSettings::postprocess() {
 
         if (!validating) {
           if (!ubl.sanity_check()) {
-            SERIAL_EOL();
+            SERIAL_EOL_P(port);
             #if ENABLED(EEPROM_CHITCHAT)
               ubl.echo_name();
-              SERIAL_ECHOLNPGM(" initialized.\n");
+              SERIAL_ECHOLNPGM_P(port, " initialized.\n");
             #endif
           }
           else {
             eeprom_error = true;
             #if ENABLED(EEPROM_CHITCHAT)
-              SERIAL_PROTOCOLPGM("?Can't enable ");
+              SERIAL_PROTOCOLPGM_P(port, "?Can't enable ");
               ubl.echo_name();
-              SERIAL_PROTOCOLLNPGM(".");
+              SERIAL_PROTOCOLLNPGM_P(port, ".");
             #endif
             ubl.reset();
           }
@@ -1387,14 +1401,14 @@ void MarlinSettings::postprocess() {
           if (ubl.storage_slot >= 0) {
             load_mesh(ubl.storage_slot);
             #if ENABLED(EEPROM_CHITCHAT)
-              SERIAL_ECHOPAIR("Mesh ", ubl.storage_slot);
-              SERIAL_ECHOLNPGM(" loaded from storage.");
+              SERIAL_ECHOPAIR_P(port, "Mesh ", ubl.storage_slot);
+              SERIAL_ECHOLNPGM_P(port, " loaded from storage.");
             #endif
           }
           else {
             ubl.reset();
             #if ENABLED(EEPROM_CHITCHAT)
-              SERIAL_ECHOLNPGM("UBL System reset()");
+              SERIAL_ECHOLNPGM_P(port, "UBL System reset()");
             #endif
           }
         }
@@ -1402,22 +1416,42 @@ void MarlinSettings::postprocess() {
     }
 
     #if ENABLED(EEPROM_CHITCHAT) && DISABLED(DISABLE_M503)
-      if (!validating) report();
+      if (!validating) report(
+        #if NUM_SERIAL > 1
+          port
+        #endif
+      );
     #endif
     EEPROM_FINISH();
 
     return !eeprom_error;
   }
 
-  bool MarlinSettings::validate() {
+  bool MarlinSettings::validate(
+    #if NUM_SERIAL > 1
+      const int8_t port/*=-1*/
+    #endif
+  ) {
     validating = true;
-    const bool success = _load();
+    const bool success = _load(
+      #if NUM_SERIAL > 1
+        port
+      #endif
+    );
     validating = false;
     return success;
   }
 
-  bool MarlinSettings::load() {
-    if (validate()) return _load();
+  bool MarlinSettings::load(
+    #if ADD_PORT_ARG
+      const int8_t port/*=-1*/
+    #endif
+  ) {
+    if (validate()) return _load(
+      #if ADD_PORT_ARG
+        port
+      #endif
+    );
     reset();
     return true;
   }
@@ -1524,9 +1558,15 @@ void MarlinSettings::postprocess() {
 
 #else // !EEPROM_SETTINGS
 
-  bool MarlinSettings::save() {
-    SERIAL_ERROR_START();
-    SERIAL_ERRORLNPGM("EEPROM disabled");
+  bool MarlinSettings::save(
+    #if ADD_PORT_ARG
+      const int8_t port/*=-1*/
+    #endif
+  ) {
+    #if ENABLED(EEPROM_CHITCHAT)
+      SERIAL_ERROR_START_P(port);
+      SERIAL_ERRORLNPGM_P(port, "EEPROM disabled");
+    #endif
     return false;
   }
 
@@ -1535,7 +1575,11 @@ void MarlinSettings::postprocess() {
 /**
  * M502 - Reset Configuration
  */
-void MarlinSettings::reset() {
+void MarlinSettings::reset(
+  #if ADD_PORT_ARG
+    const int8_t port/*=-1*/
+  #endif
+) {
   static const float tmp1[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT, tmp2[] PROGMEM = DEFAULT_MAX_FEEDRATE;
   static const uint32_t tmp3[] PROGMEM = DEFAULT_MAX_ACCELERATION;
   LOOP_XYZE_N(i) {
@@ -1775,22 +1819,25 @@ void MarlinSettings::reset() {
   postprocess();
 
   #if ENABLED(EEPROM_CHITCHAT)
-    SERIAL_ECHO_START();
-    SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
+    SERIAL_ECHO_START_P(port);
+    SERIAL_ECHOLNPGM_P(port, "Hardcoded Default Settings Loaded");
   #endif
 }
 
 #if DISABLED(DISABLE_M503)
 
-  #define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START(); }while(0)
+  #define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START_P(port); }while(0)
 
   /**
    * M503 - Report current settings in RAM
    *
    * Unless specifically disabled, M503 is available even without EEPROM
    */
-  void MarlinSettings::report(const bool forReplay) {
-
+  void MarlinSettings::report(const bool forReplay
+    #if NUM_SERIAL > 1
+      , const int8_t port/*=-1*/
+    #endif
+  ) {
     /**
      * Announce current units, in case inches are being displayed
      */
@@ -1798,14 +1845,14 @@ void MarlinSettings::reset() {
     #if ENABLED(INCH_MODE_SUPPORT)
       #define LINEAR_UNIT(N) (float(N) / parser.linear_unit_factor)
       #define VOLUMETRIC_UNIT(N) (float(N) / (parser.volumetric_enabled ? parser.volumetric_unit_factor : parser.linear_unit_factor))
-      SERIAL_ECHOPGM("  G2");
-      SERIAL_CHAR(parser.linear_unit_factor == 1.0 ? '1' : '0');
-      SERIAL_ECHOPGM(" ; Units in ");
+      SERIAL_ECHOPGM_P(port, "  G2");
+      SERIAL_CHAR_P(port, parser.linear_unit_factor == 1.0 ? '1' : '0');
+      SERIAL_ECHOPGM_P(port, " ; Units in ");
       serialprintPGM(parser.linear_unit_factor == 1.0 ? PSTR("mm\n") : PSTR("inches\n"));
     #else
       #define LINEAR_UNIT(N) (N)
       #define VOLUMETRIC_UNIT(N) (N)
-      SERIAL_ECHOLNPGM("  G21    ; Units in mm");
+      SERIAL_ECHOLNPGM_P(port, "  G21    ; Units in mm");
     #endif
 
     #if ENABLED(ULTIPANEL)
@@ -1815,18 +1862,18 @@ void MarlinSettings::reset() {
       CONFIG_ECHO_START;
       #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
         #define TEMP_UNIT(N) parser.to_temp_units(N)
-        SERIAL_ECHOPGM("  M149 ");
-        SERIAL_CHAR(parser.temp_units_code());
-        SERIAL_ECHOPGM(" ; Units in ");
-        serialprintPGM(parser.temp_units_name());
+        SERIAL_ECHOPGM_P(port, "  M149 ");
+        SERIAL_CHAR_P(port, parser.temp_units_code());
+        SERIAL_ECHOPGM_P(port, " ; Units in ");
+        serialprintPGM_P(port, parser.temp_units_name());
       #else
         #define TEMP_UNIT(N) (N)
-        SERIAL_ECHOLNPGM("  M149 C ; Units in Celsius");
+        SERIAL_ECHOLNPGM_P(port, "  M149 C ; Units in Celsius");
       #endif
 
     #endif
 
-    SERIAL_EOL();
+    SERIAL_EOL_P(port);
 
     #if DISABLED(NO_VOLUMETRICS)
 
@@ -1835,32 +1882,32 @@ void MarlinSettings::reset() {
        */
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOPGM("Filament settings:");
+        SERIAL_ECHOPGM_P(port, "Filament settings:");
         if (parser.volumetric_enabled)
-          SERIAL_EOL();
+          SERIAL_EOL_P(port);
         else
-          SERIAL_ECHOLNPGM(" Disabled");
+          SERIAL_ECHOLNPGM_P(port, " Disabled");
       }
 
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M200 D", LINEAR_UNIT(planner.filament_size[0]));
-      SERIAL_EOL();
+      SERIAL_ECHOPAIR_P(port, "  M200 D", LINEAR_UNIT(planner.filament_size[0]));
+      SERIAL_EOL_P(port);
       #if EXTRUDERS > 1
         CONFIG_ECHO_START;
-        SERIAL_ECHOPAIR("  M200 T1 D", LINEAR_UNIT(planner.filament_size[1]));
-        SERIAL_EOL();
+        SERIAL_ECHOPAIR_P(port, "  M200 T1 D", LINEAR_UNIT(planner.filament_size[1]));
+        SERIAL_EOL_P(port);
         #if EXTRUDERS > 2
           CONFIG_ECHO_START;
-          SERIAL_ECHOPAIR("  M200 T2 D", LINEAR_UNIT(planner.filament_size[2]));
-          SERIAL_EOL();
+          SERIAL_ECHOPAIR_P(port, "  M200 T2 D", LINEAR_UNIT(planner.filament_size[2]));
+          SERIAL_EOL_P(port);
           #if EXTRUDERS > 3
             CONFIG_ECHO_START;
-            SERIAL_ECHOPAIR("  M200 T3 D", LINEAR_UNIT(planner.filament_size[3]));
-            SERIAL_EOL();
+            SERIAL_ECHOPAIR_P(port, "  M200 T3 D", LINEAR_UNIT(planner.filament_size[3]));
+            SERIAL_EOL_P(port);
             #if EXTRUDERS > 4
               CONFIG_ECHO_START;
-              SERIAL_ECHOPAIR("  M200 T4 D", LINEAR_UNIT(planner.filament_size[4]));
-              SERIAL_EOL();
+              SERIAL_ECHOPAIR_P(port, "  M200 T4 D", LINEAR_UNIT(planner.filament_size[4]));
+              SERIAL_EOL_P(port);
             #endif // EXTRUDERS > 4
           #endif // EXTRUDERS > 3
         #endif // EXTRUDERS > 2
@@ -1868,118 +1915,118 @@ void MarlinSettings::reset() {
 
       if (!parser.volumetric_enabled) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("  M200 D0");
+        SERIAL_ECHOLNPGM_P(port, "  M200 D0");
       }
 
     #endif // !NO_VOLUMETRICS
 
     if (!forReplay) {
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPGM("Steps per unit:");
+      SERIAL_ECHOLNPGM_P(port, "Steps per unit:");
     }
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M92 X", LINEAR_UNIT(planner.axis_steps_per_mm[X_AXIS]));
-    SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.axis_steps_per_mm[Y_AXIS]));
-    SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.axis_steps_per_mm[Z_AXIS]));
+    SERIAL_ECHOPAIR_P(port, "  M92 X", LINEAR_UNIT(planner.axis_steps_per_mm[X_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.axis_steps_per_mm[Y_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.axis_steps_per_mm[Z_AXIS]));
     #if DISABLED(DISTINCT_E_FACTORS)
-      SERIAL_ECHOPAIR(" E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS]));
     #endif
-    SERIAL_EOL();
+    SERIAL_EOL_P(port);
     #if ENABLED(DISTINCT_E_FACTORS)
       CONFIG_ECHO_START;
       for (uint8_t i = 0; i < E_STEPPERS; i++) {
-        SERIAL_ECHOPAIR("  M92 T", (int)i);
-        SERIAL_ECHOLNPAIR(" E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS + i]));
+        SERIAL_ECHOPAIR_P(port, "  M92 T", (int)i);
+        SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.axis_steps_per_mm[E_AXIS + i]));
       }
     #endif
 
     if (!forReplay) {
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPGM("Maximum feedrates (units/s):");
+      SERIAL_ECHOLNPGM_P(port, "Maximum feedrates (units/s):");
     }
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M203 X", LINEAR_UNIT(planner.max_feedrate_mm_s[X_AXIS]));
-    SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.max_feedrate_mm_s[Y_AXIS]));
-    SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.max_feedrate_mm_s[Z_AXIS]));
+    SERIAL_ECHOPAIR_P(port, "  M203 X", LINEAR_UNIT(planner.max_feedrate_mm_s[X_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_feedrate_mm_s[Y_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_feedrate_mm_s[Z_AXIS]));
     #if DISABLED(DISTINCT_E_FACTORS)
-      SERIAL_ECHOPAIR(" E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS]));
     #endif
-    SERIAL_EOL();
+    SERIAL_EOL_P(port);
     #if ENABLED(DISTINCT_E_FACTORS)
       CONFIG_ECHO_START;
       for (uint8_t i = 0; i < E_STEPPERS; i++) {
-        SERIAL_ECHOPAIR("  M203 T", (int)i);
-        SERIAL_ECHOLNPAIR(" E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS + i]));
+        SERIAL_ECHOPAIR_P(port, "  M203 T", (int)i);
+        SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_feedrate_mm_s[E_AXIS + i]));
       }
     #endif
 
     if (!forReplay) {
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPGM("Maximum Acceleration (units/s2):");
+      SERIAL_ECHOLNPGM_P(port, "Maximum Acceleration (units/s2):");
     }
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M201 X", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[X_AXIS]));
-    SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Y_AXIS]));
-    SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Z_AXIS]));
+    SERIAL_ECHOPAIR_P(port, "  M201 X", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[X_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Y_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_acceleration_mm_per_s2[Z_AXIS]));
     #if DISABLED(DISTINCT_E_FACTORS)
-      SERIAL_ECHOPAIR(" E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS]));
     #endif
-    SERIAL_EOL();
+    SERIAL_EOL_P(port);
     #if ENABLED(DISTINCT_E_FACTORS)
       CONFIG_ECHO_START;
       for (uint8_t i = 0; i < E_STEPPERS; i++) {
-        SERIAL_ECHOPAIR("  M201 T", (int)i);
-        SERIAL_ECHOLNPAIR(" E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS + i]));
+        SERIAL_ECHOPAIR_P(port, "  M201 T", (int)i);
+        SERIAL_ECHOLNPAIR_P(port, " E", VOLUMETRIC_UNIT(planner.max_acceleration_mm_per_s2[E_AXIS + i]));
       }
     #endif
 
     if (!forReplay) {
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPGM("Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>");
+      SERIAL_ECHOLNPGM_P(port, "Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>");
     }
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M204 P", LINEAR_UNIT(planner.acceleration));
-    SERIAL_ECHOPAIR(" R", LINEAR_UNIT(planner.retract_acceleration));
-    SERIAL_ECHOLNPAIR(" T", LINEAR_UNIT(planner.travel_acceleration));
+    SERIAL_ECHOPAIR_P(port, "  M204 P", LINEAR_UNIT(planner.acceleration));
+    SERIAL_ECHOPAIR_P(port, " R", LINEAR_UNIT(planner.retract_acceleration));
+    SERIAL_ECHOLNPAIR_P(port, " T", LINEAR_UNIT(planner.travel_acceleration));
 
     if (!forReplay) {
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPGM("Advanced: S<min_feedrate> T<min_travel_feedrate> B<min_segment_time_us> X<max_xy_jerk> Z<max_z_jerk> E<max_e_jerk>");
+      SERIAL_ECHOLNPGM_P(port, "Advanced: S<min_feedrate> T<min_travel_feedrate> B<min_segment_time_us> X<max_xy_jerk> Z<max_z_jerk> E<max_e_jerk>");
     }
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M205 S", LINEAR_UNIT(planner.min_feedrate_mm_s));
-    SERIAL_ECHOPAIR(" T", LINEAR_UNIT(planner.min_travel_feedrate_mm_s));
-    SERIAL_ECHOPAIR(" B", planner.min_segment_time_us);
-    SERIAL_ECHOPAIR(" X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
-    SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
-    SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
-    SERIAL_ECHOLNPAIR(" E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
+    SERIAL_ECHOPAIR_P(port, "  M205 S", LINEAR_UNIT(planner.min_feedrate_mm_s));
+    SERIAL_ECHOPAIR_P(port, " T", LINEAR_UNIT(planner.min_travel_feedrate_mm_s));
+    SERIAL_ECHOPAIR_P(port, " B", planner.min_segment_time_us);
+    SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
+    SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
+    SERIAL_ECHOLNPAIR_P(port, " E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
 
     #if HAS_M206_COMMAND
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Home offset:");
+        SERIAL_ECHOLNPGM_P(port, "Home offset:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M206 X", LINEAR_UNIT(home_offset[X_AXIS]));
-      SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(home_offset[Y_AXIS]));
-      SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(home_offset[Z_AXIS]));
+      SERIAL_ECHOPAIR_P(port, "  M206 X", LINEAR_UNIT(home_offset[X_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(home_offset[Y_AXIS]));
+      SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(home_offset[Z_AXIS]));
     #endif
 
     #if HOTENDS > 1
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Hotend offsets:");
+        SERIAL_ECHOLNPGM_P(port, "Hotend offsets:");
       }
       CONFIG_ECHO_START;
       for (uint8_t e = 1; e < HOTENDS; e++) {
-        SERIAL_ECHOPAIR("  M218 T", (int)e);
-        SERIAL_ECHOPAIR(" X", LINEAR_UNIT(hotend_offset[X_AXIS][e]));
-        SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(hotend_offset[Y_AXIS][e]));
+        SERIAL_ECHOPAIR_P(port, "  M218 T", (int)e);
+        SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(hotend_offset[X_AXIS][e]));
+        SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(hotend_offset[Y_AXIS][e]));
         #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_NOZZLE) ||ENABLED(PARKING_EXTRUDER)
-          SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(hotend_offset[Z_AXIS][e]));
+          SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(hotend_offset[Z_AXIS][e]));
         #endif
-        SERIAL_EOL();
+        SERIAL_EOL_P(port);
       }
     #endif
 
@@ -1992,7 +2039,7 @@ void MarlinSettings::reset() {
 
         if (!forReplay) {
           CONFIG_ECHO_START;
-          SERIAL_ECHOLNPGM("Mesh Bed Leveling:");
+          SERIAL_ECHOLNPGM_P(port, "Mesh Bed Leveling:");
         }
 
       #elif ENABLED(AUTO_BED_LEVELING_UBL)
@@ -2000,46 +2047,46 @@ void MarlinSettings::reset() {
         if (!forReplay) {
           CONFIG_ECHO_START;
           ubl.echo_name();
-          SERIAL_ECHOLNPGM(":");
+          SERIAL_ECHOLNPGM_P(port, ":");
         }
 
       #elif HAS_ABL
 
         if (!forReplay) {
           CONFIG_ECHO_START;
-          SERIAL_ECHOLNPGM("Auto Bed Leveling:");
+          SERIAL_ECHOLNPGM_P(port, "Auto Bed Leveling:");
         }
 
       #endif
 
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M420 S", planner.leveling_active ? 1 : 0);
+      SERIAL_ECHOPAIR_P(port, "  M420 S", planner.leveling_active ? 1 : 0);
       #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
-        SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(planner.z_fade_height));
+        SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.z_fade_height));
       #endif
-      SERIAL_EOL();
+      SERIAL_EOL_P(port);
 
       #if ENABLED(MESH_BED_LEVELING)
 
         for (uint8_t py = 0; py < GRID_MAX_POINTS_Y; py++) {
           for (uint8_t px = 0; px < GRID_MAX_POINTS_X; px++) {
             CONFIG_ECHO_START;
-            SERIAL_ECHOPAIR("  G29 S3 X", (int)px + 1);
-            SERIAL_ECHOPAIR(" Y", (int)py + 1);
-            SERIAL_ECHOPGM(" Z");
-            SERIAL_PROTOCOL_F(LINEAR_UNIT(mbl.z_values[px][py]), 5);
-            SERIAL_EOL();
+            SERIAL_ECHOPAIR_P(port, "  G29 S3 X", (int)px + 1);
+            SERIAL_ECHOPAIR_P(port, " Y", (int)py + 1);
+            SERIAL_ECHOPGM_P(port, " Z");
+            SERIAL_PROTOCOL_F_P(port, LINEAR_UNIT(mbl.z_values[px][py]), 5);
+            SERIAL_EOL_P(port);
           }
         }
 
       #elif ENABLED(AUTO_BED_LEVELING_UBL)
 
         if (!forReplay) {
-          SERIAL_EOL();
+          SERIAL_EOL_P(port);
           ubl.report_state();
-          SERIAL_ECHOLNPAIR("\nActive Mesh Slot: ", ubl.storage_slot);
-          SERIAL_ECHOPAIR("EEPROM can hold ", calc_num_meshes());
-          SERIAL_ECHOLNPGM(" meshes.\n");
+          SERIAL_ECHOLNPAIR_P(port, "\nActive Mesh Slot: ", ubl.storage_slot);
+          SERIAL_ECHOPAIR_P(port, "EEPROM can hold ", calc_num_meshes());
+          SERIAL_ECHOLNPGM_P(port, " meshes.\n");
         }
 
       #endif
@@ -2047,59 +2094,62 @@ void MarlinSettings::reset() {
     #endif // HAS_LEVELING
 
     #if ENABLED(DELTA)
+
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Endstop adjustment:");
+        SERIAL_ECHOLNPGM_P(port, "Endstop adjustment:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M666 X", LINEAR_UNIT(delta_endstop_adj[X_AXIS]));
-      SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(delta_endstop_adj[Y_AXIS]));
-      SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(delta_endstop_adj[Z_AXIS]));
+      SERIAL_ECHOPAIR_P(port, "  M666 X", LINEAR_UNIT(delta_endstop_adj[X_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(delta_endstop_adj[Y_AXIS]));
+      SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(delta_endstop_adj[Z_AXIS]));
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Delta settings: L<diagonal_rod> R<radius> H<height> S<segments_per_s> B<calibration radius> XYZ<tower angle corrections>");
+        SERIAL_ECHOLNPGM_P(port, "Delta settings: L<diagonal_rod> R<radius> H<height> S<segments_per_s> B<calibration radius> XYZ<tower angle corrections>");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M665 L", LINEAR_UNIT(delta_diagonal_rod));
-      SERIAL_ECHOPAIR(" R", LINEAR_UNIT(delta_radius));
-      SERIAL_ECHOPAIR(" H", LINEAR_UNIT(delta_height));
-      SERIAL_ECHOPAIR(" S", delta_segments_per_second);
-      SERIAL_ECHOPAIR(" B", LINEAR_UNIT(delta_calibration_radius));
-      SERIAL_ECHOPAIR(" X", LINEAR_UNIT(delta_tower_angle_trim[A_AXIS]));
-      SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(delta_tower_angle_trim[B_AXIS]));
-      SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(delta_tower_angle_trim[C_AXIS]));
-      SERIAL_EOL();
+      SERIAL_ECHOPAIR_P(port, "  M665 L", LINEAR_UNIT(delta_diagonal_rod));
+      SERIAL_ECHOPAIR_P(port, " R", LINEAR_UNIT(delta_radius));
+      SERIAL_ECHOPAIR_P(port, " H", LINEAR_UNIT(delta_height));
+      SERIAL_ECHOPAIR_P(port, " S", delta_segments_per_second);
+      SERIAL_ECHOPAIR_P(port, " B", LINEAR_UNIT(delta_calibration_radius));
+      SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(delta_tower_angle_trim[A_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(delta_tower_angle_trim[B_AXIS]));
+      SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(delta_tower_angle_trim[C_AXIS]));
+      SERIAL_EOL_P(port);
 
     #elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
+
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Endstop adjustment:");
+        SERIAL_ECHOLNPGM_P(port, "Endstop adjustment:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPGM("  M666");
+      SERIAL_ECHOPGM_P(port, "  M666");
       #if ENABLED(X_DUAL_ENDSTOPS)
-        SERIAL_ECHOPAIR(" X", LINEAR_UNIT(endstops.x_endstop_adj));
+        SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(endstops.x_endstop_adj));
       #endif
       #if ENABLED(Y_DUAL_ENDSTOPS)
-        SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(endstops.y_endstop_adj));
+        SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(endstops.y_endstop_adj));
       #endif
       #if ENABLED(Z_DUAL_ENDSTOPS)
-        SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(endstops.z_endstop_adj));
+        SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(endstops.z_endstop_adj));
       #endif
-      SERIAL_EOL();
-    #endif // DELTA
+      SERIAL_EOL_P(port);
+
+    #endif // [XYZ]_DUAL_ENDSTOPS
 
     #if ENABLED(ULTIPANEL)
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Material heatup parameters:");
+        SERIAL_ECHOLNPGM_P(port, "Material heatup parameters:");
       }
       for (uint8_t i = 0; i < COUNT(lcd_preheat_hotend_temp); i++) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOPAIR("  M145 S", (int)i);
-        SERIAL_ECHOPAIR(" H", TEMP_UNIT(lcd_preheat_hotend_temp[i]));
-        SERIAL_ECHOPAIR(" B", TEMP_UNIT(lcd_preheat_bed_temp[i]));
-        SERIAL_ECHOLNPAIR(" F", lcd_preheat_fan_speed[i]);
+        SERIAL_ECHOPAIR_P(port, "  M145 S", (int)i);
+        SERIAL_ECHOPAIR_P(port, " H", TEMP_UNIT(lcd_preheat_hotend_temp[i]));
+        SERIAL_ECHOPAIR_P(port, " B", TEMP_UNIT(lcd_preheat_bed_temp[i]));
+        SERIAL_ECHOLNPAIR_P(port, " F", lcd_preheat_fan_speed[i]);
       }
     #endif // ULTIPANEL
 
@@ -2107,22 +2157,22 @@ void MarlinSettings::reset() {
 
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("PID settings:");
+        SERIAL_ECHOLNPGM_P(port, "PID settings:");
       }
       #if ENABLED(PIDTEMP)
         #if HOTENDS > 1
           if (forReplay) {
             HOTEND_LOOP() {
               CONFIG_ECHO_START;
-              SERIAL_ECHOPAIR("  M301 E", e);
-              SERIAL_ECHOPAIR(" P", PID_PARAM(Kp, e));
-              SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, e)));
-              SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, e)));
+              SERIAL_ECHOPAIR_P(port, "  M301 E", e);
+              SERIAL_ECHOPAIR_P(port, " P", PID_PARAM(Kp, e));
+              SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(PID_PARAM(Ki, e)));
+              SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(PID_PARAM(Kd, e)));
               #if ENABLED(PID_EXTRUSION_SCALING)
-                SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, e));
-                if (e == 0) SERIAL_ECHOPAIR(" L", lpq_len);
+                SERIAL_ECHOPAIR_P(port, " C", PID_PARAM(Kc, e));
+                if (e == 0) SERIAL_ECHOPAIR_P(port, " L", lpq_len);
               #endif
-              SERIAL_EOL();
+              SERIAL_EOL_P(port);
             }
           }
           else
@@ -2130,23 +2180,23 @@ void MarlinSettings::reset() {
         // !forReplay || HOTENDS == 1
         {
           CONFIG_ECHO_START;
-          SERIAL_ECHOPAIR("  M301 P", PID_PARAM(Kp, 0)); // for compatibility with hosts, only echo values for E0
-          SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, 0)));
-          SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, 0)));
+          SERIAL_ECHOPAIR_P(port, "  M301 P", PID_PARAM(Kp, 0)); // for compatibility with hosts, only echo values for E0
+          SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(PID_PARAM(Ki, 0)));
+          SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(PID_PARAM(Kd, 0)));
           #if ENABLED(PID_EXTRUSION_SCALING)
-            SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, 0));
-            SERIAL_ECHOPAIR(" L", lpq_len);
+            SERIAL_ECHOPAIR_P(port, " C", PID_PARAM(Kc, 0));
+            SERIAL_ECHOPAIR_P(port, " L", lpq_len);
           #endif
-          SERIAL_EOL();
+          SERIAL_EOL_P(port);
         }
       #endif // PIDTEMP
 
       #if ENABLED(PIDTEMPBED)
         CONFIG_ECHO_START;
-        SERIAL_ECHOPAIR("  M304 P", thermalManager.bedKp);
-        SERIAL_ECHOPAIR(" I", unscalePID_i(thermalManager.bedKi));
-        SERIAL_ECHOPAIR(" D", unscalePID_d(thermalManager.bedKd));
-        SERIAL_EOL();
+        SERIAL_ECHOPAIR_P(port, "  M304 P", thermalManager.bedKp);
+        SERIAL_ECHOPAIR_P(port, " I", unscalePID_i(thermalManager.bedKi));
+        SERIAL_ECHOPAIR_P(port, " D", unscalePID_d(thermalManager.bedKd));
+        SERIAL_EOL_P(port);
       #endif
 
     #endif // PIDTEMP || PIDTEMPBED
@@ -2154,39 +2204,39 @@ void MarlinSettings::reset() {
     #if HAS_LCD_CONTRAST
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("LCD Contrast:");
+        SERIAL_ECHOLNPGM_P(port, "LCD Contrast:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPAIR("  M250 C", lcd_contrast);
+      SERIAL_ECHOLNPAIR_P(port, "  M250 C", lcd_contrast);
     #endif
 
     #if ENABLED(FWRETRACT)
 
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Retract: S<length> F<units/m> Z<lift>");
+        SERIAL_ECHOLNPGM_P(port, "Retract: S<length> F<units/m> Z<lift>");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M207 S", LINEAR_UNIT(fwretract.retract_length));
-      SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_length));
-      SERIAL_ECHOPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_feedrate_mm_s)));
-      SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(fwretract.retract_zlift));
+      SERIAL_ECHOPAIR_P(port, "  M207 S", LINEAR_UNIT(fwretract.retract_length));
+      SERIAL_ECHOPAIR_P(port, " W", LINEAR_UNIT(fwretract.swap_retract_length));
+      SERIAL_ECHOPAIR_P(port, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_feedrate_mm_s)));
+      SERIAL_ECHOLNPAIR_P(port, " Z", LINEAR_UNIT(fwretract.retract_zlift));
 
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Recover: S<length> F<units/m>");
+        SERIAL_ECHOLNPGM_P(port, "Recover: S<length> F<units/m>");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M208 S", LINEAR_UNIT(fwretract.retract_recover_length));
-      SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_recover_length));
-      SERIAL_ECHOLNPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_recover_feedrate_mm_s)));
+      SERIAL_ECHOPAIR_P(port, "  M208 S", LINEAR_UNIT(fwretract.retract_recover_length));
+      SERIAL_ECHOPAIR_P(port, " W", LINEAR_UNIT(fwretract.swap_retract_recover_length));
+      SERIAL_ECHOLNPAIR_P(port, " F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_recover_feedrate_mm_s)));
 
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret E-only moves as retract/recover");
+        SERIAL_ECHOLNPGM_P(port, "Auto-Retract: S=0 to disable, 1 to interpret E-only moves as retract/recover");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPAIR("  M209 S", fwretract.autoretract_enabled ? 1 : 0);
+      SERIAL_ECHOLNPAIR_P(port, "  M209 S", fwretract.autoretract_enabled ? 1 : 0);
 
     #endif // FWRETRACT
 
@@ -2196,10 +2246,10 @@ void MarlinSettings::reset() {
     #if HAS_BED_PROBE
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Z-Probe Offset (mm):");
+        SERIAL_ECHOLNPGM_P(port, "Z-Probe Offset (mm):");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOLNPAIR("  M851 Z", LINEAR_UNIT(zprobe_zoffset));
+      SERIAL_ECHOLNPAIR_P(port, "  M851 Z", LINEAR_UNIT(zprobe_zoffset));
     #endif
 
     /**
@@ -2208,18 +2258,18 @@ void MarlinSettings::reset() {
     #if ENABLED(SKEW_CORRECTION_GCODE)
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Skew Factor: ");
+        SERIAL_ECHOLNPGM_P(port, "Skew Factor: ");
       }
       CONFIG_ECHO_START;
       #if ENABLED(SKEW_CORRECTION_FOR_Z)
-        SERIAL_ECHO("  M852 I");
-        SERIAL_ECHO_F(LINEAR_UNIT(planner.xy_skew_factor), 6);
-        SERIAL_ECHOPAIR(" J", LINEAR_UNIT(planner.xz_skew_factor));
-        SERIAL_ECHOLNPAIR(" K", LINEAR_UNIT(planner.yz_skew_factor));
+        SERIAL_ECHO_P(port, "  M852 I");
+        SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.xy_skew_factor), 6);
+        SERIAL_ECHOPAIR_P(port, " J", LINEAR_UNIT(planner.xz_skew_factor));
+        SERIAL_ECHOLNPAIR_P(port, " K", LINEAR_UNIT(planner.yz_skew_factor));
       #else
-        SERIAL_ECHO("  M852 S");
-        SERIAL_ECHO_F(LINEAR_UNIT(planner.xy_skew_factor), 6);
-        SERIAL_EOL();
+        SERIAL_ECHO_P(port, "  M852 S");
+        SERIAL_ECHO_F_P(port, LINEAR_UNIT(planner.xy_skew_factor), 6);
+        SERIAL_EOL_P(port);
       #endif
     #endif
 
@@ -2229,44 +2279,44 @@ void MarlinSettings::reset() {
     #if HAS_TRINAMIC
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Stepper driver current:");
+        SERIAL_ECHOLNPGM_P(port, "Stepper driver current:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHO("  M906");
+      SERIAL_ECHO_P(port, "  M906");
       #if ENABLED(X_IS_TMC2130) || ENABLED(X_IS_TMC2208)
-        SERIAL_ECHOPAIR(" X ", stepperX.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " X ", stepperX.getCurrent());
       #endif
       #if ENABLED(Y_IS_TMC2130) || ENABLED(Y_IS_TMC2208)
-        SERIAL_ECHOPAIR(" Y ", stepperY.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " Y ", stepperY.getCurrent());
       #endif
       #if ENABLED(Z_IS_TMC2130) || ENABLED(Z_IS_TMC2208)
-        SERIAL_ECHOPAIR(" Z ", stepperZ.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " Z ", stepperZ.getCurrent());
       #endif
       #if ENABLED(X2_IS_TMC2130) || ENABLED(X2_IS_TMC2208)
-        SERIAL_ECHOPAIR(" X2 ", stepperX2.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " X2 ", stepperX2.getCurrent());
       #endif
       #if ENABLED(Y2_IS_TMC2130) || ENABLED(Y2_IS_TMC2208)
-        SERIAL_ECHOPAIR(" Y2 ", stepperY2.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " Y2 ", stepperY2.getCurrent());
       #endif
       #if ENABLED(Z2_IS_TMC2130) || ENABLED(Z2_IS_TMC2208)
-        SERIAL_ECHOPAIR(" Z2 ", stepperZ2.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " Z2 ", stepperZ2.getCurrent());
       #endif
       #if ENABLED(E0_IS_TMC2130) || ENABLED(E0_IS_TMC2208)
-        SERIAL_ECHOPAIR(" E0 ", stepperE0.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " E0 ", stepperE0.getCurrent());
       #endif
       #if ENABLED(E1_IS_TMC2130) || ENABLED(E1_IS_TMC2208)
-        SERIAL_ECHOPAIR(" E1 ", stepperE1.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " E1 ", stepperE1.getCurrent());
       #endif
       #if ENABLED(E2_IS_TMC2130) || ENABLED(E2_IS_TMC2208)
-        SERIAL_ECHOPAIR(" E2 ", stepperE2.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " E2 ", stepperE2.getCurrent());
       #endif
       #if ENABLED(E3_IS_TMC2130) || ENABLED(E3_IS_TMC2208)
-        SERIAL_ECHOPAIR(" E3 ", stepperE3.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " E3 ", stepperE3.getCurrent());
       #endif
       #if ENABLED(E4_IS_TMC2130) || ENABLED(E4_IS_TMC2208)
-        SERIAL_ECHOPAIR(" E4 ", stepperE4.getCurrent());
+        SERIAL_ECHOPAIR_P(port, " E4 ", stepperE4.getCurrent());
       #endif
-      SERIAL_EOL();
+      SERIAL_EOL_P(port);
     #endif
 
     /**
@@ -2275,23 +2325,23 @@ void MarlinSettings::reset() {
     #if ENABLED(SENSORLESS_HOMING)
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Sensorless homing threshold:");
+        SERIAL_ECHOLNPGM_P(port, "Sensorless homing threshold:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHO("  M914");
+      SERIAL_ECHO_P(port, "  M914");
       #if ENABLED(X_IS_TMC2130)
-        SERIAL_ECHOPAIR(" X", stepperX.sgt());
+        SERIAL_ECHOPAIR_P(port, " X", stepperX.sgt());
       #endif
       #if ENABLED(X2_IS_TMC2130)
-        SERIAL_ECHOPAIR(" X2 ", stepperX2.sgt());
+        SERIAL_ECHOPAIR_P(port, " X2 ", stepperX2.sgt());
       #endif
       #if ENABLED(Y_IS_TMC2130)
-        SERIAL_ECHOPAIR(" Y", stepperY.sgt());
+        SERIAL_ECHOPAIR_P(port, " Y", stepperY.sgt());
       #endif
       #if ENABLED(X2_IS_TMC2130)
-        SERIAL_ECHOPAIR(" Y2 ", stepperY2.sgt());
+        SERIAL_ECHOPAIR_P(port, " Y2 ", stepperY2.sgt());
       #endif
-      SERIAL_EOL();
+      SERIAL_EOL_P(port);
     #endif
 
     /**
@@ -2300,23 +2350,23 @@ void MarlinSettings::reset() {
     #if ENABLED(LIN_ADVANCE)
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Linear Advance:");
+        SERIAL_ECHOLNPGM_P(port, "Linear Advance:");
       }
       CONFIG_ECHO_START;
-      SERIAL_ECHOPAIR("  M900 K", planner.extruder_advance_k);
-      SERIAL_ECHOLNPAIR(" R", planner.advance_ed_ratio);
+      SERIAL_ECHOPAIR_P(port, "  M900 K", planner.extruder_advance_k);
+      SERIAL_ECHOLNPAIR_P(port, " R", planner.advance_ed_ratio);
     #endif
 
     #if HAS_MOTOR_CURRENT_PWM
       CONFIG_ECHO_START;
       if (!forReplay) {
-        SERIAL_ECHOLNPGM("Stepper motor currents:");
+        SERIAL_ECHOLNPGM_P(port, "Stepper motor currents:");
         CONFIG_ECHO_START;
       }
-      SERIAL_ECHOPAIR("  M907 X", stepper.motor_current_setting[0]);
-      SERIAL_ECHOPAIR(" Z", stepper.motor_current_setting[1]);
-      SERIAL_ECHOPAIR(" E", stepper.motor_current_setting[2]);
-      SERIAL_EOL();
+      SERIAL_ECHOPAIR_P(port, "  M907 X", stepper.motor_current_setting[0]);
+      SERIAL_ECHOPAIR_P(port, " Z", stepper.motor_current_setting[1]);
+      SERIAL_ECHOPAIR_P(port, " E", stepper.motor_current_setting[2]);
+      SERIAL_EOL_P(port);
     #endif
 
     /**
@@ -2325,30 +2375,30 @@ void MarlinSettings::reset() {
     #if ENABLED(ADVANCED_PAUSE_FEATURE)
       if (!forReplay) {
         CONFIG_ECHO_START;
-        SERIAL_ECHOLNPGM("Filament load/unload lengths:");
+        SERIAL_ECHOLNPGM_P(port, "Filament load/unload lengths:");
       }
       CONFIG_ECHO_START;
       #if EXTRUDERS == 1
-        SERIAL_ECHOPAIR("  M603 L", LINEAR_UNIT(filament_change_load_length[0]));
-        SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[0]));
+        SERIAL_ECHOPAIR_P(port, "  M603 L", LINEAR_UNIT(filament_change_load_length[0]));
+        SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[0]));
       #else
-        SERIAL_ECHOPAIR("  M603 T0 L", LINEAR_UNIT(filament_change_load_length[0]));
-        SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[0]));
+        SERIAL_ECHOPAIR_P(port, "  M603 T0 L", LINEAR_UNIT(filament_change_load_length[0]));
+        SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[0]));
         CONFIG_ECHO_START;
-        SERIAL_ECHOPAIR("  M603 T1 L", LINEAR_UNIT(filament_change_load_length[1]));
-        SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[1]));
+        SERIAL_ECHOPAIR_P(port, "  M603 T1 L", LINEAR_UNIT(filament_change_load_length[1]));
+        SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[1]));
         #if EXTRUDERS > 2
           CONFIG_ECHO_START;
-          SERIAL_ECHOPAIR("  M603 T2 L", LINEAR_UNIT(filament_change_load_length[2]));
-          SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[2]));
+          SERIAL_ECHOPAIR_P(port, "  M603 T2 L", LINEAR_UNIT(filament_change_load_length[2]));
+          SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[2]));
           #if EXTRUDERS > 3
             CONFIG_ECHO_START;
-            SERIAL_ECHOPAIR("  M603 T3 L", LINEAR_UNIT(filament_change_load_length[3]));
-            SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[3]));
+            SERIAL_ECHOPAIR_P(port, "  M603 T3 L", LINEAR_UNIT(filament_change_load_length[3]));
+            SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[3]));
             #if EXTRUDERS > 4
               CONFIG_ECHO_START;
-              SERIAL_ECHOPAIR("  M603 T4 L", LINEAR_UNIT(filament_change_load_length[4]));
-              SERIAL_ECHOLNPAIR(" U", LINEAR_UNIT(filament_change_unload_length[4]));
+              SERIAL_ECHOPAIR_P(port, "  M603 T4 L", LINEAR_UNIT(filament_change_load_length[4]));
+              SERIAL_ECHOLNPAIR_P(port, " U", LINEAR_UNIT(filament_change_unload_length[4]));
             #endif // EXTRUDERS > 4
           #endif // EXTRUDERS > 3
         #endif // EXTRUDERS > 2
diff --git a/Marlin/src/module/configuration_store.h b/Marlin/src/module/configuration_store.h
index 361a51e94a597af4bf40d33150100a7c183400c5..fdbf917493597be3c58b2b0ee4dd376f71f7640b 100644
--- a/Marlin/src/module/configuration_store.h
+++ b/Marlin/src/module/configuration_store.h
@@ -25,14 +25,24 @@
 
 #include "../inc/MarlinConfig.h"
 
+#define ADD_PORT_ARG ENABLED(EEPROM_CHITCHAT) && NUM_SERIAL > 1
+
 class MarlinSettings {
   public:
     MarlinSettings() { }
 
     static uint16_t datasize();
 
-    static void reset();
-    static bool save();   // Return 'true' if data was saved
+    static void reset(
+      #if ADD_PORT_ARG
+        const int8_t port=-1
+      #endif
+    );
+    static bool save(
+      #if ADD_PORT_ARG
+        const int8_t port=-1
+      #endif
+    );   // Return 'true' if data was saved
 
     FORCE_INLINE static bool init_eeprom() {
       bool success = true;
@@ -47,8 +57,16 @@ class MarlinSettings {
     }
 
     #if ENABLED(EEPROM_SETTINGS)
-      static bool load();     // Return 'true' if data was loaded ok
-      static bool validate(); // Return 'true' if EEPROM data is ok
+      static bool load(
+        #if ADD_PORT_ARG
+          const int8_t port=-1
+        #endif
+      );     // Return 'true' if data was loaded ok
+      static bool validate(
+        #if ADD_PORT_ARG
+          const int8_t port=-1
+        #endif
+      ); // Return 'true' if EEPROM data is ok
 
       #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
                                          // That can store is enabled
@@ -67,7 +85,11 @@ class MarlinSettings {
     #endif
 
     #if DISABLED(DISABLE_M503)
-      static void report(const bool forReplay=false);
+      static void report(const bool forReplay=false
+        #if ADD_PORT_ARG
+          , const int8_t port=-1
+        #endif
+      );
     #else
       FORCE_INLINE
       static void report(const bool forReplay=false) { UNUSED(forReplay); }
@@ -87,8 +109,16 @@ class MarlinSettings {
 
       #endif
 
-      static bool _load();
-      static bool size_error(const uint16_t size);
+      static bool _load(
+        #if ADD_PORT_ARG
+          const int8_t port=-1
+        #endif
+      );
+      static bool size_error(const uint16_t size
+        #if ADD_PORT_ARG
+          const int8_t port=-1
+        #endif
+      );
     #endif
 };
 
diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h
index 77e180a2a1d592b08abf8b21b4e6a53561fd359f..73c3dd8b6654620f38c760c07f9337fabd689306 100644
--- a/Marlin/src/module/stepper.h
+++ b/Marlin/src/module/stepper.h
@@ -337,8 +337,8 @@ class Stepper {
         }
         if (timer < 100) { // (20kHz - this should never happen)
           timer = 100;
-          MYSERIAL.print(MSG_STEPPER_TOO_HIGH);
-          MYSERIAL.println(step_rate);
+          SERIAL_ECHOPGM(MSG_STEPPER_TOO_HIGH);
+          SERIAL_ECHOLN(step_rate);
         }
       #endif
 
diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp
index 887b0717ef4ebb811ac8dfd91f557886b0086bb3..c859e414fe8407c2341e300c92bb8737d46d07ec 100644
--- a/Marlin/src/module/temperature.cpp
+++ b/Marlin/src/module/temperature.cpp
@@ -2121,18 +2121,21 @@ void Temperature::isr() {
 
   #include "../gcode/gcode.h"
 
-  void print_heater_state(const float &c, const float &t,
+  static void print_heater_state(const float &c, const float &t
     #if ENABLED(SHOW_TEMP_ADC_VALUES)
-      const float r,
+      , const float r
     #endif
-    const int8_t e=-2
+    #if NUM_SERIAL > 1
+      , const int8_t port=-1
+    #endif
+    , const int8_t e=-2
   ) {
     #if !(HAS_TEMP_BED && HAS_TEMP_HOTEND) && HOTENDS <= 1
       UNUSED(e);
     #endif
 
-    SERIAL_PROTOCOLCHAR(' ');
-    SERIAL_PROTOCOLCHAR(
+    SERIAL_PROTOCOLCHAR_P(port, ' ');
+    SERIAL_PROTOCOLCHAR_P(port,
       #if HAS_TEMP_BED && HAS_TEMP_HOTEND
         e == -1 ? 'B' : 'T'
       #elif HAS_TEMP_HOTEND
@@ -2142,23 +2145,30 @@ void Temperature::isr() {
       #endif
     );
     #if HOTENDS > 1
-      if (e >= 0) SERIAL_PROTOCOLCHAR('0' + e);
+      if (e >= 0) SERIAL_PROTOCOLCHAR_P(port, '0' + e);
     #endif
-    SERIAL_PROTOCOLCHAR(':');
-    SERIAL_PROTOCOL(c);
-    SERIAL_PROTOCOLPAIR(" /" , t);
+    SERIAL_PROTOCOLCHAR_P(port, ':');
+    SERIAL_PROTOCOL_P(port, c);
+    SERIAL_PROTOCOLPAIR_P(port, " /" , t);
     #if ENABLED(SHOW_TEMP_ADC_VALUES)
-      SERIAL_PROTOCOLPAIR(" (", r / OVERSAMPLENR);
-      SERIAL_PROTOCOLCHAR(')');
+      SERIAL_PROTOCOLPAIR_P(port, " (", r / OVERSAMPLENR);
+      SERIAL_PROTOCOLCHAR_P(port, ')');
     #endif
   }
 
-  void Temperature::print_heaterstates() {
+  void Temperature::print_heaterstates(
+    #if NUM_SERIAL > 1
+      const int8_t port
+    #endif
+  ) {
     #if HAS_TEMP_HOTEND
       print_heater_state(degHotend(gcode.target_extruder), degTargetHotend(gcode.target_extruder)
         #if ENABLED(SHOW_TEMP_ADC_VALUES)
           , rawHotendTemp(gcode.target_extruder)
         #endif
+        #if NUM_SERIAL > 1
+          , port
+        #endif
       );
     #endif
     #if HAS_TEMP_BED
@@ -2166,6 +2176,9 @@ void Temperature::isr() {
         #if ENABLED(SHOW_TEMP_ADC_VALUES)
           , rawBedTemp()
         #endif
+        #if NUM_SERIAL > 1
+          , port
+        #endif
         , -1 // BED
       );
     #endif
@@ -2174,20 +2187,23 @@ void Temperature::isr() {
         #if ENABLED(SHOW_TEMP_ADC_VALUES)
           , rawHotendTemp(e)
         #endif
+        #if NUM_SERIAL > 1
+          , port
+        #endif
         , e
       );
     #endif
-    SERIAL_PROTOCOLPGM(" @:");
-    SERIAL_PROTOCOL(getHeaterPower(gcode.target_extruder));
+    SERIAL_PROTOCOLPGM_P(port, " @:");
+    SERIAL_PROTOCOL_P(port, getHeaterPower(gcode.target_extruder));
     #if HAS_TEMP_BED
-      SERIAL_PROTOCOLPGM(" B@:");
-      SERIAL_PROTOCOL(getHeaterPower(-1));
+      SERIAL_PROTOCOLPGM_P(port, " B@:");
+      SERIAL_PROTOCOL_P(port, getHeaterPower(-1));
     #endif
     #if HOTENDS > 1
       HOTEND_LOOP() {
-        SERIAL_PROTOCOLPAIR(" @", e);
-        SERIAL_PROTOCOLCHAR(':');
-        SERIAL_PROTOCOL(getHeaterPower(e));
+        SERIAL_PROTOCOLPAIR_P(port, " @", e);
+        SERIAL_PROTOCOLCHAR_P(port, ':');
+        SERIAL_PROTOCOL_P(port, getHeaterPower(e));
       }
     #endif
   }
diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h
index 107fa67249b7083fb625deb0fafc3a7eccdab62f..147a2df24f31bc4c5c3dcf913e058cb2c4d6aa6c 100644
--- a/Marlin/src/module/temperature.h
+++ b/Marlin/src/module/temperature.h
@@ -547,7 +547,11 @@ class Temperature {
     #endif // HEATER_IDLE_HANDLER
 
     #if HAS_TEMP_HOTEND || HAS_TEMP_BED
-      static void print_heaterstates();
+      static void print_heaterstates(
+        #if NUM_SERIAL > 1
+          const int8_t port = -1
+        #endif
+      );
       #if ENABLED(AUTO_REPORT_TEMPERATURES)
         static uint8_t auto_report_temp_interval;
         static millis_t next_temp_report_ms;
diff --git a/Marlin/src/sd/SdBaseFile.cpp b/Marlin/src/sd/SdBaseFile.cpp
index b25a7f9f5c5f729a63c72ba8e79cab00ba670755..ddde1d0d1fb8e8e0ae51120d788290d51516871d 100644
--- a/Marlin/src/sd/SdBaseFile.cpp
+++ b/Marlin/src/sd/SdBaseFile.cpp
@@ -339,38 +339,38 @@ int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
         && DIR_IS_FILE_OR_SUBDIR(&dir)) break;
   }
   // indent for dir level
-  for (uint8_t i = 0; i < indent; i++) MYSERIAL.write(' ');
+  for (uint8_t i = 0; i < indent; i++) SERIAL_CHAR(' ');
 
   // print name
   for (uint8_t i = 0; i < 11; i++) {
     if (dir.name[i] == ' ')continue;
     if (i == 8) {
-      MYSERIAL.write('.');
+      SERIAL_CHAR('.');
       w++;
     }
-    MYSERIAL.write(dir.name[i]);
+    SERIAL_CHAR(dir.name[i]);
     w++;
   }
   if (DIR_IS_SUBDIR(&dir)) {
-    MYSERIAL.write('/');
+    SERIAL_CHAR('/');
     w++;
   }
   if (flags & (LS_DATE | LS_SIZE)) {
-    while (w++ < 14) MYSERIAL.write(' ');
+    while (w++ < 14) SERIAL_CHAR(' ');
   }
   // print modify date/time if requested
   if (flags & LS_DATE) {
-    MYSERIAL.write(' ');
+    SERIAL_CHAR(' ');
     printFatDate(dir.lastWriteDate);
-    MYSERIAL.write(' ');
+    SERIAL_CHAR(' ');
     printFatTime(dir.lastWriteTime);
   }
   // print size if requested
   if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
-    MYSERIAL.write(' ');
-    MYSERIAL.print(dir.fileSize);
+    SERIAL_CHAR(' ');
+    SERIAL_ECHO(dir.fileSize);
   }
-  MYSERIAL.println();
+  SERIAL_EOL();
   return DIR_IS_FILE(&dir) ? 1 : 2;
 }
 
@@ -902,11 +902,10 @@ int SdBaseFile::peek() {
   return c;
 }
 
-
 // print uint8_t with width 2
-static void print2u(uint8_t v) {
-  if (v < 10) MYSERIAL.write('0');
-  MYSERIAL.print(v, DEC);
+static void print2u(const uint8_t v) {
+  if (v < 10) SERIAL_CHAR('0');
+  SERIAL_ECHO_F(v, DEC);
 }
 
 /**
@@ -927,10 +926,10 @@ static void print2u(uint8_t v) {
  * \param[in] fatDate The date field from a directory entry.
  */
 void SdBaseFile::printFatDate(uint16_t fatDate) {
-  MYSERIAL.print(FAT_YEAR(fatDate));
-  MYSERIAL.write('-');
+  SERIAL_ECHO(FAT_YEAR(fatDate));
+  SERIAL_CHAR('-');
   print2u(FAT_MONTH(fatDate));
-  MYSERIAL.write('-');
+  SERIAL_CHAR('-');
   print2u(FAT_DAY(fatDate));
 }
 
@@ -945,9 +944,9 @@ void SdBaseFile::printFatDate(uint16_t fatDate) {
  */
 void SdBaseFile::printFatTime(uint16_t fatTime) {
   print2u(FAT_HOUR(fatTime));
-  MYSERIAL.write(':');
+  SERIAL_CHAR(':');
   print2u(FAT_MINUTE(fatTime));
-  MYSERIAL.write(':');
+  SERIAL_CHAR(':');
   print2u(FAT_SECOND(fatTime));
 }
 
@@ -959,7 +958,7 @@ void SdBaseFile::printFatTime(uint16_t fatTime) {
 bool SdBaseFile::printName() {
   char name[FILENAME_LENGTH];
   if (!getFilename(name)) return false;
-  MYSERIAL.print(name);
+  SERIAL_ECHO(name);
   return true;
 }
 
diff --git a/Marlin/src/sd/SdFatUtil.cpp b/Marlin/src/sd/SdFatUtil.cpp
index 329a59decc2871e0acb0e32c10a6b809c440d352..1110d1dc9cb531a714b5e5ab8000a5a0d5ce2599 100644
--- a/Marlin/src/sd/SdFatUtil.cpp
+++ b/Marlin/src/sd/SdFatUtil.cpp
@@ -38,54 +38,22 @@
  * \return The number of free bytes.
  */
 #ifdef __arm__
-extern "C" char* sbrk(int incr);
-int SdFatUtil::FreeRam() {
-  char top;
-  return &top - reinterpret_cast<char*>(sbrk(0));
-}
-#else  // __arm__
-extern char* __brkval;
-extern char __bss_end;
-/**
- * Amount of free RAM
- * \return The number of free bytes.
- */
-int SdFatUtil::FreeRam() {
-  char top;
-  return __brkval ? &top - __brkval : &top - &__bss_end;
-}
-#endif  // __arm
 
-/**
- * %Print a string in flash memory.
- *
- * \param[in] pr Print object for output.
- * \param[in] str Pointer to string stored in flash memory.
- */
-void SdFatUtil::print_P(PGM_P str) {
-  for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
-}
+  extern "C" char* sbrk(int incr);
+  int SdFatUtil::FreeRam() {
+    char top;
+    return &top - reinterpret_cast<char*>(sbrk(0));
+  }
 
-/**
- * %Print a string in flash memory followed by a CR/LF.
- *
- * \param[in] pr Print object for output.
- * \param[in] str Pointer to string stored in flash memory.
- */
-void SdFatUtil::println_P(PGM_P str) { print_P(str); MYSERIAL.println(); }
+#else
 
-/**
- * %Print a string in flash memory to Serial.
- *
- * \param[in] str Pointer to string stored in flash memory.
- */
-void SdFatUtil::SerialPrint_P(PGM_P str) { print_P(str); }
+  extern char* __brkval;
+  extern char __bss_end;
+  int SdFatUtil::FreeRam() {
+    char top;
+    return __brkval ? &top - __brkval : &top - &__bss_end;
+  }
 
-/**
- * %Print a string in flash memory to Serial followed by a CR/LF.
- *
- * \param[in] str Pointer to string stored in flash memory.
- */
-void SdFatUtil::SerialPrintln_P(PGM_P str) { println_P(str); }
+#endif
 
 #endif // SDSUPPORT
diff --git a/Marlin/src/sd/SdFatUtil.h b/Marlin/src/sd/SdFatUtil.h
index 825d6d29d6bafbd89afd84b47e0eb60b3900cef8..1deb1eb8f36e624c98d97b4f657fd61a270a1b18 100644
--- a/Marlin/src/sd/SdFatUtil.h
+++ b/Marlin/src/sd/SdFatUtil.h
@@ -35,17 +35,9 @@
  * \file
  * \brief Useful utility functions.
  */
-/** Store and print a string in flash memory.*/
-#define PgmPrint(x) SerialPrint_P(PSTR(x))
-/** Store and print a string in flash memory followed by a CR/LF.*/
-#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
 
 namespace SdFatUtil {
   int FreeRam();
-  void print_P(PGM_P str);
-  void println_P(PGM_P str);
-  void SerialPrint_P(PGM_P str);
-  void SerialPrintln_P(PGM_P str);
 }
 
 using namespace SdFatUtil;  // NOLINT
diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp
index 7d5959d10fbee11ce20b2a22f0827a80679c8031..62e2b1466c904c0a20f1f28dec574b304c19577a 100644
--- a/Marlin/src/sd/cardreader.cpp
+++ b/Marlin/src/sd/cardreader.cpp
@@ -85,7 +85,11 @@ char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
 
 uint16_t nrFile_index;
 
-void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
+void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/
+  #if NUM_SERIAL > 1
+    , const int8_t port/*= -1*/
+  #endif
+) {
   dir_t p;
   uint8_t cnt = 0;
 
@@ -118,12 +122,16 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
       SdFile dir;
       if (!dir.open(parent, lfilename, O_READ)) {
         if (lsAction == LS_SerialPrint) {
-          SERIAL_ECHO_START();
-          SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
-          SERIAL_ECHOLN(lfilename);
+          SERIAL_ECHO_START_P(port);
+          SERIAL_ECHOPGM_P(port, MSG_SD_CANT_OPEN_SUBDIR);
+          SERIAL_ECHOLN_P(port, lfilename);
         }
       }
-      lsDive(path, dir);
+      lsDive(path, dir
+        #if NUM_SERIAL > 1
+          , NULL, port
+        #endif
+      );
       // close() is done automatically by destructor of SdFile
     }
     else {
@@ -145,10 +153,10 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
 
         case LS_SerialPrint:
           createFilename(filename, p);
-          SERIAL_PROTOCOL(prepend);
-          SERIAL_PROTOCOL(filename);
-          SERIAL_PROTOCOLCHAR(' ');
-          SERIAL_PROTOCOLLN(p.fileSize);
+          SERIAL_PROTOCOL_P(port, prepend);
+          SERIAL_PROTOCOL_P(port, filename);
+          SERIAL_PROTOCOLCHAR_P(port, ' ');
+          SERIAL_PROTOCOLLN_P(port, p.fileSize);
           break;
 
         case LS_GetFilename:
@@ -165,10 +173,18 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
   } // while readDir
 }
 
-void CardReader::ls() {
+void CardReader::ls(
+  #if NUM_SERIAL > 1
+    const int8_t port
+  #endif
+) {
   lsAction = LS_SerialPrint;
   root.rewind();
-  lsDive("", root);
+  lsDive("", root  
+    #if NUM_SERIAL > 1
+      , NULL, port
+    #endif
+  );
 }
 
 #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
@@ -176,12 +192,16 @@ void CardReader::ls() {
   /**
    * Get a long pretty path based on a DOS 8.3 path
    */
-  void CardReader::printLongPath(char *path) {
+  void CardReader::printLongPath(char *path
+    #if NUM_SERIAL > 1
+      , const int8_t port/*= -1*/
+    #endif
+  ) {
     lsAction = LS_GetFilename;
 
     int i, pathLen = strlen(path);
 
-    // SERIAL_ECHOPGM("Full Path: "); SERIAL_ECHOLN(path);
+    // SERIAL_ECHOPGM_P(port, "Full Path: "); SERIAL_ECHOLN_P(port, path);
 
     // Zero out slashes to make segments
     for (i = 0; i < pathLen; i++) if (path[i] == '/') path[i] = '\0';
@@ -199,28 +219,32 @@ void CardReader::ls() {
       // Go to the next segment
       while (path[++i]) { }
 
-      // SERIAL_ECHOPGM("Looking for segment: "); SERIAL_ECHOLN(segment);
+      // SERIAL_ECHOPGM_P(port, "Looking for segment: "); SERIAL_ECHOLN_P(port, segment);
 
       // Find the item, setting the long filename
       diveDir.rewind();
-      lsDive("", diveDir, segment);
+      lsDive("", diveDir, segment
+        #if NUM_SERIAL > 1
+          , port
+        #endif
+      );
 
       // Print /LongNamePart to serial output
-      SERIAL_PROTOCOLCHAR('/');
-      SERIAL_PROTOCOL(longFilename[0] ? longFilename : "???");
+      SERIAL_PROTOCOLCHAR_P(port, '/');
+      SERIAL_PROTOCOL_P(port, longFilename[0] ? longFilename : "???");
 
       // If the filename was printed then that's it
       if (!filenameIsDir) break;
 
-      // SERIAL_ECHOPGM("Opening dir: "); SERIAL_ECHOLN(segment);
+      // SERIAL_ECHOPGM_P(port, "Opening dir: "); SERIAL_ECHOLN_P(port, segment);
 
       // Open the sub-item as the new dive parent
       SdFile dir;
       if (!dir.open(diveDir, segment, O_READ)) {
-        SERIAL_EOL();
-        SERIAL_ECHO_START();
-        SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
-        SERIAL_ECHO(segment);
+        SERIAL_EOL_P(port);
+        SERIAL_ECHO_START_P(port);
+        SERIAL_ECHOPGM_P(port, MSG_SD_CANT_OPEN_SUBDIR);
+        SERIAL_ECHO_P(port, segment);
         break;
       }
 
@@ -229,7 +253,7 @@ void CardReader::ls() {
 
     } // while i<pathLen
 
-    SERIAL_EOL();
+    SERIAL_EOL_P(port);
   }
 
 #endif // LONG_FILENAME_HOST_SUPPORT
@@ -500,15 +524,19 @@ void CardReader::removeFile(const char * const name) {
   }
 }
 
-void CardReader::getStatus() {
+void CardReader::getStatus(
+  #if NUM_SERIAL > 1
+    const int8_t port/*= -1*/
+  #endif
+) {
   if (cardOK) {
-    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
-    SERIAL_PROTOCOL(sdpos);
-    SERIAL_PROTOCOLCHAR('/');
-    SERIAL_PROTOCOLLN(filesize);
+    SERIAL_PROTOCOLPGM_P(port, MSG_SD_PRINTING_BYTE);
+    SERIAL_PROTOCOL_P(port, sdpos);
+    SERIAL_PROTOCOLCHAR_P(port, '/');
+    SERIAL_PROTOCOLLN_P(port, filesize);
   }
   else
-    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
+    SERIAL_PROTOCOLLNPGM_P(port, MSG_SD_NOT_PRINTING);
 }
 
 void CardReader::write_command(char *buf) {
diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h
index 4d8b5b4b3631a148443d4a98379bba4c99d6d38f..915a639ed87c9e3c101c40ff553fe8c2a8b18912 100644
--- a/Marlin/src/sd/cardreader.h
+++ b/Marlin/src/sd/cardreader.h
@@ -49,11 +49,19 @@ public:
   void openAndPrintFile(const char *name);
   void startFileprint();
   void stopSDPrint();
-  void getStatus();
+  void getStatus(
+    #if NUM_SERIAL > 1
+      const int8_t port = -1
+    #endif
+  );
   void printingHasFinished();
 
   #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
-    void printLongPath(char *path);
+    void printLongPath(char *path
+      #if NUM_SERIAL > 1
+        , const int8_t port = -1
+      #endif
+    );
   #endif
 
   void getfilename(uint16_t nr, const char* const match=NULL);
@@ -61,7 +69,11 @@ public:
 
   void getAbsFilename(char *t);
 
-  void ls();
+  void ls(
+    #if NUM_SERIAL > 1
+      const int8_t port = -1
+    #endif
+  );
   void chdir(const char *relpath);
   int8_t updir();
   void setroot();
@@ -162,7 +174,11 @@ private:
   LsAction lsAction; //stored for recursion.
   uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
   char* diveDirName;
-  void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
+  void lsDive(const char *prepend, SdFile parent, const char * const match=NULL  
+    #if NUM_SERIAL > 1
+      , const int8_t port = -1
+    #endif
+  );
 
   #if ENABLED(SDCARD_SORT_ALPHA)
     void flush_presort();