Improve SD Card support

This commit is contained in:
Thomas Farstrike
2025-10-27 22:17:02 +01:00
parent d17c636785
commit 60fbda4a66
+103 -28
View File
@@ -8,50 +8,110 @@ class SDCardManager:
try:
self._sdcard = machine.SDCard(spi_bus=spi_bus, cs=cs_pin)
self._sdcard.info()
print("SD card initialized")
print("SD card initialized successfully")
except Exception as e:
print(f"ERROR: Failed to initialize SD card: {e}")
print(" - Possible causes: Invalid SPI configuration, SD card not inserted, faulty wiring, or firmware issue")
print(f" - Check: SPI pins for the SPI bus, card insertion, VCC (3.3V/5V), GND")
print(" - Try: Hard reset ESP32, test with known-good SD card")
def mount(self, mount_point):
if not self._sdcard:
return False
def _try_mount(self, mount_point):
try:
os.mount(self._sdcard, mount_point)
print(f"Mounted at {mount_point}")
print(f"SD card mounted successfully at {mount_point}")
return True
except OSError as e:
print(f"Mount failed: {e}")
print(f"WARNING: Failed to mount SD card at {mount_point}: {e}")
print(" - Possible causes: Unformatted SD card (needs FAT32), corrupted filesystem, or card removed")
print(f" - Check: SD card format, ensure card is inserted")
print(" - Try: Format card on PC, or proceed to auto-format if enabled")
return False
def format_and_mount(self, mount_point):
if not self._sdcard:
return False
print("Formatting SD card...")
try:
os.umount(mount_point)
except:
pass
def _format(self, mount_point):
try:
print(f"Attempting to format SD card for {mount_point}...")
try:
os.umount(mount_point)
print(f" - Unmounted {mount_point} (if it was mounted)")
except OSError:
print(f" - No prior mount found for {mount_point}, proceeding with format")
vfs.VfsFat.mkfs(self._sdcard)
print("Formatted")
return self.mount(mount_point)
print("SD card formatted successfully as FAT32")
return True
except OSError as e:
print(f"Format failed: {e}")
print(f"ERROR: Failed to format SD card: {e}")
print(" - Possible causes: SD card not inserted, write-protected, incompatible, or hardware error")
print(f" - Check: Card insertion, write-protect switch, verify wiring of SPI bus.")
print(" - Try: Test with another SD card, reformat on PC, ensure VCC/GND correct")
return False
def mount_with_optional_format(self, mount_point):
if not self._sdcard:
print(f"ERROR: No SD card object initialized for mounting at {mount_point}")
print(" - Possible causes: SD card initialization failed in __init__")
print(" - Check: Review initialization errors above, verify SPI setup and hardware")
print(" - Try: Hard reset, check SPI pins and SD card")
return False
if not self._try_mount(mount_point):
print(f"INFO: Initial mount failed at {mount_point}, attempting to format...")
if self._format(mount_point):
if not self._try_mount(mount_point):
print(f"ERROR: Failed to mount SD card at {mount_point} even after formatting")
print(" - Possible causes: Persistent hardware issue, incompatible SD card, or firmware bug")
print(f" - Check: Wiring of SPI bus and card type.")
print(" - Try: Hard reset, test with different SD card, reflash firmware")
return False
else:
print(f"ERROR: Could not format SD card for {mount_point} - mount aborted")
print(" - See format error details above for troubleshooting")
return False
try:
contents = os.listdir(mount_point)
print(f"SD card contents at {mount_point}: {contents}")
return True
except OSError as e:
print(f"WARNING: Could not list SD card contents at {mount_point}: {e}")
print(" - Possible causes: Filesystem corruption, card removed, or VFS cache issue")
print(f" - Check: Ensure card is inserted, verify mount with is_mounted('{mount_point}')")
print(" - Try: Unmount and remount, or reformat card")
return False
def is_mounted(self, mount_point):
try:
return mount_point in os.listdir('/') and os.path.ismount(mount_point)
except:
mounted = mount_point in os.listdir('/') and not os.mkdir(f'{mount_point}/_tmp_test')
if mounted:
print(f"SD card is mounted at {mount_point}")
try:
os.rmdir(f'{mount_point}/_tmp_test')
except:
pass
else:
print(f"SD card is not mounted at {mount_point}")
print(" - Possible causes: Never mounted, unmounted manually, or card removed")
print(f" - Try: Call mount_with_optional_format('{mount_point}')")
return mounted
except OSError as e:
print(f"WARNING: Failed to check mount status at {mount_point}: {e}")
print(" - Possible causes: Card removed, invalid mount point, or filesystem error")
print(f" - Check: Ensure {mount_point} exists and card is inserted")
print(" - Try: Remount or reinsert card")
return False
def list(self, mount_point):
try:
return os.listdir(mount_point)
except:
contents = os.listdir(mount_point)
print(f"SD card contents at {mount_point}: {contents}")
return contents
except OSError as e:
print(f"WARNING: Failed to list contents at {mount_point}: {e}")
print(" - Possible causes: SD card not mounted, removed, or corrupted filesystem")
print(f" - Check: Run is_mounted('{mount_point}'), ensure card is inserted")
print(" - Try: Remount with mount_with_optional_format('{mount_point}')")
return []
# --- Global instance (singleton) ---
# --- Singleton pattern ---
_manager = None
def init(spi_bus, cs_pin):
@@ -59,19 +119,34 @@ def init(spi_bus, cs_pin):
global _manager
if _manager is None:
_manager = SDCardManager(spi_bus, cs_pin)
else:
print("WARNING: SDCardManager already initialized")
print(" - Use existing instance via get()")
return _manager
def get():
"""Get the global SD card manager instance."""
if _manager is None:
print("ERROR: SDCardManager not initialized")
print(" - Call init(spi_bus, cs_pin) first in boot.py or main.py")
return _manager
# Optional: convenience functions
def mount(mount_point):
mgr = get()
return mgr and mgr.mount(mount_point)
if mgr is None:
print("ERROR: Cannot mount - SDCardManager not initialized")
print(" - Call init(spi_bus, cs_pin) first")
return False
return mgr.mount(mount_point)
def mount_with_format(mount_point):
def mount_with_optional_format(mount_point):
mgr = get()
if mgr and not mgr.mount(mount_point):
return mgr.format_and_mount(mount_point)
return mgr and mgr.is_mounted(mount_point)
if mgr is None:
print("ERROR: Cannot mount with format - SDCardManager not initialized")
print(" - Call init(spi_bus, cs_pin) first")
return False
success = mgr.mount_with_optional_format(mount_point)
if not success:
print(f"ERROR: mount_with_format('{mount_point}') failed")
print(" - See detailed errors above for mount or format issues")
return success