diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 9a6661e97e..e51e6b4d9b 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -2061,6 +2061,10 @@ #define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE // :[ 'SD_ONBOARD', 'USB_FLASH_DRIVE' ] #endif + // Maximum number of consecutive SD card read errors before aborting the print + // Prevents infinite loops when reading from SD card with hardware/communication faults + #define SD_MAX_READ_ERRORS 5 + #endif // HAS_MEDIA /** diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 00181b602f..98545f4982 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -186,6 +186,8 @@ #define STR_SD_NOT_PRINTING "Not SD printing" #define STR_SD_ERR_WRITE_TO_FILE "error writing to file" #define STR_SD_ERR_READ "SD read error" +#define STR_SD_ERR_TOO_MANY_READ_ERRORS "Too many SD read errors, print aborted" +#define STR_SD_ERR_CARD_REMOVED "SD card removed, print aborted" #define STR_SD_CANT_ENTER_SUBDIR "Cannot enter subdir: " #define STR_ENDSTOPS_HIT "endstops hit: " diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp index 68e5e868b4..2f78fa64b4 100644 --- a/Marlin/src/gcode/queue.cpp +++ b/Marlin/src/gcode/queue.cpp @@ -570,11 +570,30 @@ void GCodeQueue::get_serial_commands() { // Get commands if there are more in the file if (!card.isStillFetching()) return; + #if HAS_SD_DETECT + // Abort print if SD card was removed mid-print + if (!card.isInserted()) { + SERIAL_ERROR_MSG(STR_SD_ERR_CARD_REMOVED); + card.abortFilePrintNow(); + return; + } + #endif + int sd_count = 0; + uint16_t sd_read_errors = 0; while (!ring_buffer.full() && !card.eof()) { const int16_t n = card.get(); const bool card_eof = card.eof(); - if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(STR_SD_ERR_READ); continue; } + if (n < 0 && !card_eof) { + SERIAL_ERROR_MSG(STR_SD_ERR_READ); + if (++sd_read_errors >= SD_MAX_READ_ERRORS) { + SERIAL_ERROR_MSG(STR_SD_ERR_TOO_MANY_READ_ERRORS); + card.abortFilePrintNow(); + break; + } + continue; + } + sd_read_errors = 0; // Reset on successful read CommandLine &command = ring_buffer.commands[ring_buffer.index_w]; const char sd_char = (char)n;