Closed stewmystre closed 6 years ago
If you delete the adafruit_sdcard.SDCARD()
object associated with the filesystem prior to calling storage.umount('\sd')
the unmount is successful, allowing for a 'new' adafruit_sdcard.SDCARD()
call and subsequent storage.mount()
call to occur ...
Do you mean that you do del the_sdcard_object
? Could you post code examples for both failure and success?
Code snippets for failure 1:
# Function that manages mounting and unmounting the SD card
def mount_sd_card():
global sd_card
global vfs
# Check to make sure an SD card is present
if sd_cd.value:
if sd_card:
del sd_card
sd_card = adafruit_sdcard.SDCard(spi, sd_cs)
vfs = storage.VfsFat(sd_card)
storage.mount(vfs, SD_MOUNT_PATH) # Mount SD card
print("SD Card Mounted")
return True
else:
print("No SD Card present")
return False
def log_data():
if sd_cd.value and sd_mounted:
with open(LOG_FILE, LOG_MODE) as outfile:
while True:
sentence = read_data()
if sentence:
outfile.write(sentence)
outfile.flush()
green_led.value = not green_led.value
else:
green_led.value = False
if not sd_cd.value: # SD Card has been removed
green_led.value = False
# Debug
print("4 SD Detected: {}".format(sd_cd.value))
print("4 SD Mounted: {}".format(sd_mounted))
for item in os.listdir('/'):
print(item)
storage.umount('/sd') #Failure point
return False
elif sd_cd.value and not sd_mounted: # SD Card inserted
print('SD Card Inserted')
time.sleep(2)
print('Mounting...')
return mount_sd_card()
Code snippets for failure 2:
def log_data():
if sd_cd.value and sd_mounted:
with open(LOG_FILE, LOG_MODE) as outfile:
while True:
sentence = read_data()
if sentence:
outfile.write(sentence)
outfile.flush()
green_led.value = not green_led.value
else:
green_led.value = False
if not sd_cd.value: # SD Card has been removed
green_led.value = False
# Debug
print("4 SD Detected: {}".format(sd_cd.value))
print("4 SD Mounted: {}".format(sd_mounted))
for item in os.listdir('/'):
print(item)
return False
elif sd_cd.value and not sd_mounted: # SD Card inserted
print('SD Card Inserted')
time.sleep(2)
print('Mounting...')
# Debug
print("3 SD Detected: {}".format(sd_cd.value))
print("3 SD Mounted: {}".format(sd_mounted))
storage.remount('/sd', False) #Failure point
return True
Other combinations also resulted in failure Calling the unmount function after deleting of the sdcard works
# Function that manages mounting and unmounting the SD card
def mount_sd_card():
global sd_card
global vfs
# Check to make sure an SD card is present
if sd_cd.value:
if sd_card:
del sd_card
storage.umount(SD_MOUNT_PATH)
sd_card = adafruit_sdcard.SDCard(spi, sd_cs)
vfs = storage.VfsFat(sd_card)
storage.mount(vfs, SD_MOUNT_PATH) # Mount SD card
print("SD Card Mounted")
return True
else:
print("No SD Card present")
return False
# Initialize the SD card:
SD_CD_PIN = board.SD_CD
sd_cd = digitalio.DigitalInOut(SD_CD_PIN)
sd_cd.switch_to_input(pull=digitalio.Pull.UP)
SD_CS_PIN = board.SD_CS
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
sd_cs = digitalio.DigitalInOut(SD_CS_PIN)
sd_card = None
vfs = None
sd_mounted = mount_sd_card()
# Function that reads the line of text from the uart connection and
# then prints it to serial output and returns it for further processing
def read_data():
sentence = uart.readline()
if sentence:
print(str(sentence, 'ascii').strip())
else:
print("No Input - UART timed out after 2 seconds")
print(" - Is the uart input device connected?")
print("Board has been running for: {} seconds\n".format(time.monotonic()))
return sentence
# Function that logs data to the SD card if mounted or mounts the SD card if inserted
# Allows removal and insertion of SD Card with power applied
# DO NOT remove the SD card while green LED is flashing - remove/disconnect input (UART)
# first so that green LED stops flashing THEN remove and insert another or same SD Card
# Reads data then writes it back out to the output file. Also flashes the green LED every
# second loop to show that data is being logged to the SD card.
def log_data():
if sd_cd.value and sd_mounted:
with open(LOG_FILE, LOG_MODE) as outfile:
while True:
sentence = read_data()
if sentence:
outfile.write(sentence)
outfile.flush()
green_led.value = not green_led.value
else:
green_led.value = False
if not sd_cd.value: # SD Card has been removed
green_led.value = False
return False
elif sd_cd.value and not sd_mounted: # SD Card inserted
print('SD Card Inserted')
time.sleep(2)
print('Mounting...')
return mount_sd_card()
# Main loop has two states:
# - SD card inserted = logs data
# - SD card not inserted = prompt to insert SD card
while True:
if sd_cd.value:
print("Logging ...")
sd_mounted = log_data()
else:
print("Please insert an SD card to start logging")
time.sleep(2) # give a little time for the SD card to be fully inserted
Finally getting around to this -- sorry for the delay!
I did some testing: the code below now works without an error on CircuitPython 3.0. Something has been fixed since this issue was filed.
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, '/sd')
input("remove card and press enter:") # card is removed
storage.umount(vfs) # no longer does OSError 22
So if you are still seeing a problem, let us know. I'll close this for now. Also, here are a few notes:
adafruit_sdcard
nor 'storage` know when the SD card has been removed. They are passive and do not monitor any available CD pin.The M0 Adalogger has a CD pin, but the Adalogger Featherwing does not.remount()
is not meant to be used to remount an unmounted filesystem, but to change the protection on an already mounted filesystem from readonly to read/write or vice versa.umount()
and then remove the card, rather than the other way around, in case some data was not yet written back to the card. So if you could have some way of signalling that you want to unmount the card (like flipping a switch), that would be good. However, it may be true that closing the file and then waiting a bit is good enough.There are some other problems with the sdcard library: see #301. The library doesn't do a good job failing when trying to read or write when the card is missing.
When the SD card has been mounted and is then removed with power still applied, it remains listed when calling
os.listdir('/')
(as byte string refer #249)a subsequent call to
storage.umount()
parsing either the file system object [vfs where vfs = storage.VfsFat(sd_card)] or the path [str where str = '/sd'] fails with OSError: 22waiting until the card has been reinserted and a subsequent call to
storage.remount()
parsing the path [str where str = '/sd'] and False fails with OSError: 22At the moment there doesn't seem to be a way to recover and remount to the same mount path after an SD card has been removed and then reinserted.