@@ -145,6 +145,7 @@ int16_t CardReader::nrItems = -1;
145
145
#endif
146
146
147
147
DiskIODriver* CardReader::driver = nullptr ;
148
+
148
149
MarlinVolume CardReader::volume;
149
150
MediaFile CardReader::myfile;
150
151
@@ -483,11 +484,15 @@ void CardReader::mount() {
483
484
nrItems = -1 ;
484
485
if (root.isOpen ()) root.close ();
485
486
486
- if (!driver->init (SD_SPI_SPEED, SD_SS_PIN)
487
+ const bool driver_init = (
488
+ driver->init (SD_SPI_SPEED, SD_SS_PIN)
487
489
#if PIN_EXISTS(LCD_SDSS) && (LCD_SDSS_PIN != SD_SS_PIN)
488
- && ! driver->init (SD_SPI_SPEED, LCD_SDSS_PIN)
490
+ || driver->init (SD_SPI_SPEED, LCD_SDSS_PIN)
489
491
#endif
490
- ) SERIAL_ECHO_MSG (STR_SD_INIT_FAIL);
492
+ );
493
+
494
+ if (!driver_init)
495
+ SERIAL_ECHO_MSG (STR_SD_INIT_FAIL);
491
496
else if (!volume.init (driver))
492
497
SERIAL_WARN_MSG (STR_SD_VOL_INIT_FAIL);
493
498
else if (!root.openRoot (&volume))
@@ -519,69 +524,146 @@ void CardReader::mount() {
519
524
#include " ../module/stepper.h"
520
525
#endif
521
526
527
+ // Provide a little time for drives to prepare
528
+ void CardReader::init () {
529
+ #if HAS_USB_FLASH_DRIVE
530
+ for (uint8_t i = 10 ; --i;) {
531
+ media_driver_usbFlash.idle ();
532
+ hal.watchdog_refresh ();
533
+ if (media_driver_usbFlash.isInserted ()) break ;
534
+ delay (20 );
535
+ }
536
+ #endif
537
+ }
538
+
522
539
/* *
523
- * Handle SD card events
540
+ * Handle media insertion and removal events
541
+ * based on SD Card detect and/or driver.isInserted()
542
+ *
543
+ * MULTI_VOLUME:
544
+ * - Track insert/remove for both media drives.
545
+ * - If the MOUNTED media is removed call release().
546
+ * - If media is INSERTED when NO MEDIA is mounted, select and mount it.
524
547
*/
525
548
void CardReader::manage_media () {
526
- #if HAS_USB_FLASH_DRIVE // Wrap for optimal non-virtual?
527
- driver->idle (); // Handle device tasks (e.g., USB Drive insert / remove)
549
+ /* *
550
+ * Handle device tasks (e.g., USB Drive insert / remove)
551
+ * - USB Flash Drive needs to run even when not selected.
552
+ * - SD Card currently has no background tasks.
553
+ */
554
+ // driver->idle();
555
+ #if HAS_USB_FLASH_DRIVE
556
+ // if (!isFlashDriveSelected())
557
+ media_driver_usbFlash.idle ();
558
+ #endif
559
+
560
+ // Prevent re-entry during Marlin::idle
561
+ #if HAS_MULTI_VOLUME
562
+ static bool no_reenter = false ;
563
+ if (no_reenter) return ;
528
564
#endif
529
565
530
- static uint8_t prev_stat = 2 ; // At boot we don't know if media is present or not
531
- uint8_t stat = uint8_t (isInserted ());
566
+ static MediaPresence prev_stat = MEDIA_BOOT; // At boot we don't know if media is present or not
567
+
568
+ // Live status is based on available media flags
569
+ MediaPresence stat = MediaPresence (
570
+ #if HAS_MULTI_VOLUME
571
+ (isSDCardInserted () ? INSERT_SD : 0 ) // Without SD Detect it's always "inserted"
572
+ | (isFlashDriveInserted () ? INSERT_USB : 0 )
573
+ #else
574
+ isInserted () ? INSERT_MEDIA : 0 // Without SD Detect it's always "inserted"
575
+ #endif
576
+ );
577
+
532
578
if (stat == prev_stat) return ; // Already checked and still no change?
533
579
534
580
DEBUG_SECTION (cmm, " CardReader::manage_media()" , true );
535
581
DEBUG_ECHOLNPGM (" Media present: " , prev_stat, " -> " , stat);
536
582
537
- if (!ui.detected ()) {
538
- DEBUG_ECHOLNPGM (" SD: No UI Detected." );
539
- return ;
540
- }
583
+ // Without a UI there's no auto-mount or release
584
+ if (!ui.detected ()) { DEBUG_ECHOLNPGM (" SD: No UI Detected." ); return ; }
541
585
542
- flag.workDirIsRoot = true ; // Return to root on mount/release/init
543
-
544
- const uint8_t old_stat = prev_stat;
586
+ const MediaPresence old_stat = prev_stat,
587
+ old_real = old_stat == MEDIA_BOOT ? INSERT_NONE : old_stat;
545
588
prev_stat = stat; // Change now to prevent re-entry in safe_delay
546
589
547
- if (stat) { // Media Inserted
548
- safe_delay (500 ); // Some boards need a delay to get settled
590
+ #if HAS_MULTI_VOLUME
591
+ const int8_t vdiff = (old_real ^ stat), vadd = vdiff & stat;
592
+ #endif
593
+ const bool did_insert = TERN (HAS_MULTI_VOLUME, vadd, stat) != INSERT_NONE;
594
+
595
+ if (did_insert) { // Media Inserted
596
+
597
+ TERN_ (HAS_MULTI_VOLUME, ui.refresh ()); // Refresh for insert events without messages
598
+
599
+ // Some media is already mounted? Nothing to do.
600
+ if (TERN0 (HAS_MULTI_VOLUME, isMounted ())) return ;
549
601
550
- // Try to mount the media (only later with SD_IGNORE_AT_STARTUP)
551
- if (TERN1 (SD_IGNORE_AT_STARTUP, old_stat != 2 )) mount ();
552
- if (!isMounted ()) stat = 0 ; // Not mounted?
602
+ // Prevent re-entry during the following phases
603
+ TERN_ (HAS_MULTI_VOLUME, no_reenter = true );
604
+
605
+ // Try to mount the media (but not at boot if SD_IGNORE_AT_STARTUP)
606
+ if (TERN1 (SD_IGNORE_AT_STARTUP, old_stat > MEDIA_BOOT)) {
607
+ #if HAS_MULTI_VOLUME
608
+ if ((vadd & INSERT_SD) && !isSDCardSelected ())
609
+ selectMediaSDCard ();
610
+ if ((vadd & INSERT_USB) && !isFlashDriveSelected ())
611
+ selectMediaFlashDrive ();
612
+ #endif
613
+ safe_delay (500 ); // Time for inserted media to settle. May re-enter for multiple media?
614
+ mount ();
615
+ }
616
+
617
+ // If the selected media isn't mounted throw an alert in ui.media_changed
618
+ if (!isMounted ()) stat = old_real;
553
619
554
620
TERN_ (RESET_STEPPERS_ON_MEDIA_INSERT, reset_stepper_drivers ()); // Workaround for Cheetah bug
621
+
622
+ // Re-enable media detection logic
623
+ TERN_ (HAS_MULTI_VOLUME, no_reenter = false );
624
+ }
625
+ else if (
626
+ // Media was removed from the device slot
627
+ #if HAS_MULTI_VOLUME
628
+ (isSDCardSelected () && (vdiff & INSERT_SD))
629
+ || (isFlashDriveSelected () && (vdiff & INSERT_USB))
630
+ #else
631
+ stat // == INSERT_MEDIA
632
+ #endif
633
+ ) {
634
+ flag.workDirIsRoot = true ; // Return to root on release
635
+ release ();
636
+ // TERN_(HAS_MULTI_VOLUME, prev_stat = INSERT_NONE); // HACK to try mounting any remaining media
555
637
}
556
638
else {
557
- TERN_ (HAS_SD_DETECT, release ()); // Card is released
639
+ #if HAS_MULTI_VOLUME
640
+ stat = old_real; // Ignore un-mounted media being ejected
641
+ ui.refresh (); // Refresh for menus that show inserted unmounted media
642
+ #endif
558
643
}
559
644
560
- ui.media_changed (old_stat, stat); // Update the UI or flag an error
645
+ ui.media_changed (old_stat, stat); // Update the UI or flag an error
561
646
562
- if (!stat) return ; // Exit if no media is present
563
-
564
- bool do_auto = true ; UNUSED (do_auto);
647
+ if (stat == INSERT_NONE) return ; // Exit if no media is present
565
648
566
649
// First mount on boot? Load emulated EEPROM and look for PLR file.
567
- if (old_stat == 2 ) {
650
+ if (old_stat <= MEDIA_BOOT ) {
568
651
DEBUG_ECHOLNPGM (" First mount." );
569
652
570
653
// Load settings the first time media is inserted (not just during init)
571
654
TERN_ (SDCARD_EEPROM_EMULATION, settings.first_load ());
572
655
573
- // Check for PLR file. Skip One-Click and auto#.g if found
574
- TERN_ ( POWER_LOSS_RECOVERY, if ( recovery.check ()) do_auto = false ) ;
656
+ // Check for PLR file. If found skip other procedures!
657
+ if ( TERN0 ( POWER_LOSS_RECOVERY, recovery.check ())) return ;
575
658
}
576
659
577
- // Find the newest file and prompt to print it.
578
- TERN_ ( ONE_CLICK_PRINT, if (do_auto && one_click_check ()) do_auto = false ) ;
660
+ // Find the newest file and prompt to print it. Skip other procedures!
661
+ if ( TERN0 ( ONE_CLICK_PRINT, one_click_check ())) return ;
579
662
580
- // Also for the first mount run auto#.g for machine init.
581
- // (Skip if PLR or One-Click Print was invoked.)
582
- if (old_stat == 2 ) {
663
+ // On first mount at boot run auto#.g for machine init.
664
+ if (old_stat <= MEDIA_BOOT) {
583
665
// Look for auto0.g on the next idle()
584
- IF_DISABLED (NO_SD_AUTOSTART, if (do_auto) autofile_begin ());
666
+ IF_DISABLED (NO_SD_AUTOSTART, autofile_begin ());
585
667
}
586
668
}
587
669
@@ -590,6 +672,8 @@ void CardReader::manage_media() {
590
672
* Used by M22, "Release Media", manage_media.
591
673
*/
592
674
void CardReader::release () {
675
+ if (!flag.mounted ) return ;
676
+
593
677
// Card removed while printing? Abort!
594
678
if (isStillPrinting ())
595
679
abortFilePrintSoon ();
0 commit comments