micropython / micropython

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems
https://micropython.org
Other
19.12k stars 7.66k forks source link

Raspberry Pi Pico SD Card Errors #11483

Open Draxiss314 opened 1 year ago

Draxiss314 commented 1 year ago

Originally posted here, posted here as there's no response over on micropython-lib:

I am not able to consistently write to my microSD card using the sdcard.py library. EDIT/UPDATE: I'm running "MicroPython v1.20.0 on 2023-04-26." My errors still look like what I've written below.

I have been following this tutorial to get my Raspberry Pi Pico write to my SD card. As the requisite drivers are no longer available in the normal micropython branch, I assume that they've been moved to micropython-lib (and that the tutorial is slightly out-of-date) and copied over the sdcard.py code from micropython-lib to my Pico.

I'm using a Raspberry Pi Pico with a Maker Pi breakout board. My IDE is Thonmy with the Micropython (Raspberry Pi Pico) interpreter. The SD card I use is a Transcend 2GB MicroSD Card, which I have formatted to be FAT32.

These issues may (?) be replicated by following the steps I followed and using the SDcard.py code.

When I attempt to test my Pico's ability (see below for code) to read and write to the SD card, my results are inconsistent and frequently mangle the SD card's filing system, requiring me to reformat or repair the partition before I can access it from my computer. Here is a sample of my most recent results: After having deleted all data from the SD card and subsequently repairing the card, my output acted as expected: Writing . . . Finished Writing. Reading . . . Hello, SD World! This is a test

That is the expected output.

Checking the SD card on my computer showed the expected result: a file called test01.txt containing Hello, SD World! This is a test and nothing else.

Returning the SD card to my Pico, I ran the test again with this result: Traceback (most recent call last): File "<stdin>", line 27, in <module> File "sdcard.py", line 252, in readblocks File "sdcard.py", line 190, in readinto OSError: timeout waiting for response

Checking the SD card on my computer, I found I could not mount it and had to repair the filesystem. After repairing, the data was garbled so I deleted it. Running the test again yielded this: Writing . . . Traceback (most recent call last): File "<stdin>", line 29, in <module> File "sdcard.py", line 252, in readblocks File "sdcard.py", line 190, in readinto OSError: timeout waiting for response

Again, filesystem must be repaired and data is garbled. After fixing and deleting: Writing . . . Traceback (most recent call last): File "<stdin>", line 34, in <module> File "sdcard.py", line 279, in writeblocks OSError: [Errno 5] EIO I think the data was garbled again (can't remember precisely), but regardless I repaired and deleted everything and tried again with the same error. This time, however, my filesystem wasn't corrupted and I had a blank test01.txt file.

I've been dealing with this for a while now and these events represent the typical pattern of issues I've been having with this code. Any help explaining what's going on would be greatly appreciated.

This is the code that I am using to test being able to read/write to the SD card; it's very similar to the default but I've adjusted it to use the Maker Pi Pico board and added a few lines to tell me whether I'm reading or writing:

import machine
import sdcard
import uos
import utime

# Assign chip select (CS) pin (and start it high)
cs = machine.Pin(15, machine.Pin.OUT) #It's 15 on the board we're using.
# Intialize SPI peripheral (start with 1 MHz)
spi = machine.SPI(1, 
                  baudrate=1000000,
                  polarity=0,
                  phase=0,
                  bits=8,
                  firstbit=machine.SPI.MSB,
                  sck=machine.Pin(10),
                  mosi=machine.Pin(11),
                  miso=machine.Pin(12))

# Initialize SD card
sd = sdcard.SDCard(spi, cs)

# Mount filesystem
vfs = uos.VfsFat(sd)
uos.mount(vfs, "/sd")

# Create a file and write something to it
with open("/sd/test01.txt", "w") as file:
    print("Writing . . .")
    file.write("Hello, SD World!\r\n")
    #utime.sleep_ms(75)
    file.write("This is a test\r\n")
    #utime.sleep_ms(75)
    file.close()
    print("Finished Writing.")

# Open the file we just created and read from it
with open("/sd/test01.txt", "r") as file:
    print("Reading . . . ")
    data = file.read()
    print(data)
    file.close()
Flipje1955 commented 1 year ago

using your program as_is (albeit with SPI(0) and thus other pins assignments) works the 1st time and thereafter fails with: OSError: [Errno 1] EPERM

I found out some time ago that for reason not clear to me the program needs uos.umount("/sd") before terminating, if I want to run it again. I could not reproduce any corruption of the file or disk itself, as you experience it. So, creating the file, reading it back, opening the file on a pc, deleting the file and rerunning your pgm by Pico all works (with the unmount added).

Btw: I use 16GB sd cards; for some reason 32GB cards give repeatedly errors (card not detected, timeout).

(My setup is a WAVESHARE 2040_zero and for my test above I was running MicroPython v1.20.0-24-g867e4dd3d on 2023-04-27 but the results go back at least 4 months, so various v1.19.1 nightly builds.)

Draxiss314 commented 1 year ago

using your program as_is (albeit with SPI(0) and thus other pins assignments) works the 1st time and thereafter fails with: OSError: [Errno 1] EPERM

I found out some time ago that for reason not clear to me the program needs uos.umount("/sd") before terminating, if I want to run it again. I could not reproduce any corruption of the file or disk itself, as you experience it. So, creating the file, reading it back, opening the file on a pc, deleting the file and rerunning your pgm by Pico all works (with the unmount added).

Btw: I use 16GB sd cards; for some reason 32GB cards give repeatedly errors (card not detected, timeout).

(My setup is a WAVESHARE 2040_zero and for my test above I was running MicroPython v1.20.0-24-g867e4dd3d on 2023-04-27 but the results go back at least 4 months, so various v1.19.1 nightly builds.)

I completely reformatted and erased my MicroSD card, added the line uos.umount("/sd") and got this error:

Writing . . . Traceback (most recent call last): File "<stdin>", line 29, in <module> File "sdcard.py", line 252, in readblocks File "sdcard.py", line 190, in readinto OSError: timeout waiting for response

How do I check the version of MicroPython I'm running?

Draxiss314 commented 1 year ago

I get this line in the shell, but I don't have any of the numbers that follow it: MicroPython v1.19.1 on 2022-06-18; Raspberry Pi Pico with RP2040

Okay, follow-up question: How do I update to a more recent version?

robert-hh commented 1 year ago

Okay, follow-up question: How do I update to a more recent version?

Get the new firmware from the Download page at https://micropython.org/download/rp2-pico/ and follow the short instruction.

Draxiss314 commented 1 year ago

Thank you. Okay, I'm updated to MicroPython v1.20.0 on 2023-04-26; Raspberry Pi Pico with RP2040 and I'm still getting this error:

Writing . . . Traceback (most recent call last): File "<stdin>", line 29, in <module> File "sdcard.py", line 252, in readblocks File "sdcard.py", line 190, in readinto OSError: timeout waiting for response

Draxiss314 commented 1 year ago

I got it running under CircuitPython, so it's probably not an error inherent to the SD card.

Draxiss314 commented 1 year ago

To be clear, getting it working under CircuitPython doesn't mean it works under MicroPython. MicroPython's sdcard.py kind-of looks like a python version of CircuitPython's sdcardio.c, but I don't fully understand what I'm looking at.

Flipje1955 commented 1 year ago

what sdcard driver are you using ? This one I am using.

https://github.com/micropython/micropython-lib/blob/c8603192d1d142fdeb7f9578e000c9834669a082/micropython/drivers/storage/sdcard/sdcard.py

Draxiss314 commented 1 year ago

what sdcard driver are you using ? This one I am using.

https://github.com/micropython/micropython-lib/blob/c8603192d1d142fdeb7f9578e000c9834669a082/micropython/drivers/storage/sdcard/sdcard.py

That's the one.

Flipje1955 commented 1 year ago

I re-tested this with a Rp2040 "maker board" (the only other sdcard reader with an "authentic Raspberry Pi Pico I have available) icm an old version: MicroPython v1.19.1 on 2022-06-18. I used your code as well as the sdcard driver referenced in the link above. It works. That is: writing to the file, reading the file, putting the file in a W10 pc, accessing the file, deleting it and rerunning the program on the Pico.

Do not wish to push back on this problem but could there be any aspect specific to your configuration ? Perhaps Robert with all his experience has the insights to interprete the fact that it does work under CPython but not under MP.

robert-hh commented 1 year ago

Hard to say. For cross-check I have taken

and it works. I can repeat it dozen of times. Another test, which just writes a large file, works as well. It works as well with SCK set to 16MHz. Wiring with patch cables and breadboards is a common problem. SDCard.py is also very picky about SD card models, and it is a simple driver, which does not cover all possible states. Transcend cards usually work well, but I never tried a 2GB card.

NoicTheBrave commented 1 year ago

Interesting thing to add: For me, since this was last written, (And thank you all for bringing up this issue, I just ran into it), I discovered that a 4GB microSD does not work (at least, it did not for me, yes it was FAT32 formatted with 1024-etc etc), but a 32GB right outta the box (was FAT32 formatted I suppose) worked just fine. Just leaving this little nugget of information for someone if they too got stuck by this. (Sorry if this was previously mentioned elsewhere)