You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Improve SD Card support
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user