adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
MIT License
3.97k stars 1.16k forks source link

mimxrt10xx: Implement sdioio, define pins for Teensy 4.1 #4020

Open nezra opened 3 years ago

nezra commented 3 years ago

On the Teensy 4.1 Version 6 circuitpython, the wrong SD card interface is built in:

https://circuitpython.org/board/teensy41/

The builtin interface is for SDcardio. However, the SDcard is actually handled by SDIOIO interface, not SPI for the onboard SDcard slot. i'd suspect given the teensy 4.0's pinout it'd work the same if the pins referenced there are tied to the same ones on the chip.

defined in the port pin map of github/circuitpython for verification of sdioio:

https://github.com/adafruit/circuitpython/blob/main/ports/mimxrt10xx/boards/teensy41/pins.c

defined on the pjrc pinout, matches the pins.c of the port/board:

https://www.pjrc.com/store/teensy41.html#pins

Following the directions here, SDIOIO when iimported states no module. I used the unaltered sample code from the directions here:

https://learn.adafruit.com/adafruit-microsd-spi-sdio/using-sdioio

I attempted to locate the library in the circuitpython 6 library file, but it's not included here:

https://circuitpython.org/libraries

Is there a way to get this fixed, or download the SDIOIO library?

As another side note, the Teensy 4.1 uses all 4 data pins for the SDcard. The "read the docs" references 4 can be used, but its not very clear as to how:

https://circuitpython.readthedocs.io/en/6.0.x/shared-bindings/sdioio/index.html?highlight=sdioio

I can't find anything on "Sequence" in the docs to explain how to properly use this. i'm assuming it's actually a tuple based on the example referenced above, so it'd need to be entered as (....,Data=[board.DAT1,board.DAT2.(etc)...)

jepler commented 3 years ago

We don't yet support sdioio on the mimxrt10xx series. We'd be happy to see someone contribute an implementation to the core.

nezra commented 3 years ago

@jepler The pins are already defined. You'll find that in the board link I posted above for the pin definitions, already in the port for it. You have the framework already done.

Sadly, the build instructions for python and adding a new board don't tell me how to include the sdioio library in the build process to have it compile with it, and since the library is in the shared-bindings list and only in cpython, there's no instructions for just building that library to test. If you'd be so kind as to provide details on the correct process to do this part I'd appreciate it.

The response also doesn't address my other questions regarding the documentation and implementation of multiple data pins, or the library itself. Please review my above requests and let me know.

jepler commented 3 years ago

An implementation of the feature is needed down in ports/mimxrt10xx/common-hal/sdioio. It would be similar in scope to this PR which added support for stm32f405: https://github.com/adafruit/circuitpython/pull/3191 with the bulk of the code being https://github.com/adafruit/circuitpython/blob/main/ports/stm/common-hal/sdioio/SDCard.c

The underlying APIs and/or hardware registers for mimxrt10xx are different than those for stm32, so while that code is a good reference for what functions need to be implemented it's not a great guide to how to implement it for this other MCU family.

When I say the pins should be defined, I mean that the board's pin file needs additions similar to these two bits of code in ports/stm/boards/feather_stm32f405_express/pins.c:

STATIC const mp_rom_obj_tuple_t sdio_data_tuple = {
    {&mp_type_tuple},
    4,
    { 
        MP_ROM_PTR(&pin_PC08),
        MP_ROM_PTR(&pin_PC09),
        MP_ROM_PTR(&pin_PC10),
        MP_ROM_PTR(&pin_PC11),
    } 
};  
...
    { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PC12) },
    { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PD02) },
    { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) },
RyannDaGreat commented 3 years ago

Please - somebody implement sdioio lol - I really need it for my project

ladyada commented 3 years ago

a patch for folks who don't want to wait, latest builds fix bitbangio and you can read/write the SD card with SPI!

import os
import busio
import digitalio
import board
import storage
import adafruit_sdcard
import bitbangio

# Connect to the card and mount the filesystem.
spi = bitbangio.SPI(board.CLK, board.CMD, board.DAT0)
cs = digitalio.DigitalInOut(board.DAT3)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

# Use the filesystem as normal! Our files are under /sd

# This helper function will print the contents of the SD
def print_directory(path, tabs=0):
    for file in os.listdir(path):
        stats = os.stat(path + "/" + file)
        filesize = stats[6]
        isdir = stats[0] & 0x4000

        if filesize < 1000:
            sizestr = str(filesize) + " bytes"
        elif filesize < 1000000:
            sizestr = "%0.1f KB" % (filesize / 1000)
        else:
            sizestr = "%0.1f MB" % (filesize / 1000000)

        prettyprintname = ""
        for _ in range(tabs):
            prettyprintname += "   "
        prettyprintname += file
        if isdir:
            prettyprintname += "/"
        print("{0:<40} Size: {1:>10}".format(prettyprintname, sizestr))

        # recursively print directory contents
        if isdir:
            print_directory(path + "/" + file, tabs + 1)

print("Files on filesystem:")
print("====================")
print_directory("/sd")
cpasto commented 3 years ago

a patch for folks who don't want to wait, latest builds fix bitbangio and you can read/write the SD card with SPI!

import os
import busio
import digitalio
import board
import storage
import adafruit_sdcard
import bitbangio

# Connect to the card and mount the filesystem.
spi = bitbangio.SPI(board.CLK, board.CMD, board.DAT0)
cs = digitalio.DigitalInOut(board.DAT3)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

# Use the filesystem as normal! Our files are under /sd

# This helper function will print the contents of the SD
def print_directory(path, tabs=0):
    for file in os.listdir(path):
        stats = os.stat(path + "/" + file)
        filesize = stats[6]
        isdir = stats[0] & 0x4000

        if filesize < 1000:
            sizestr = str(filesize) + " bytes"
        elif filesize < 1000000:
            sizestr = "%0.1f KB" % (filesize / 1000)
        else:
            sizestr = "%0.1f MB" % (filesize / 1000000)

        prettyprintname = ""
        for _ in range(tabs):
            prettyprintname += "   "
        prettyprintname += file
        if isdir:
            prettyprintname += "/"
        print("{0:<40} Size: {1:>10}".format(prettyprintname, sizestr))

        # recursively print directory contents
        if isdir:
            print_directory(path + "/" + file, tabs + 1)

print("Files on filesystem:")
print("====================")
print_directory("/sd")

Hi ladyada, I've also experienced not working sd card with teensy 4.1. I tried with the code you posted that worked fine only in "r" mode unfortunately. I simply added this below your code:

with open("/sd/test.txt", "w") as f:
    f.write("new line!\r\n")

and it gives me: [Errno 5] Input/output error. I used 16gb class 10 and 4gb class 4 sd cards.

What am I missing?

electric1236 commented 2 years ago

a patch for folks who don't want to wait, latest builds fix bitbangio and you can read/write the SD card with SPI!

import os
import busio
import digitalio
import board
import storage
import adafruit_sdcard
import bitbangio

# Connect to the card and mount the filesystem.
spi = bitbangio.SPI(board.CLK, board.CMD, board.DAT0)
cs = digitalio.DigitalInOut(board.DAT3)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

# Use the filesystem as normal! Our files are under /sd

# This helper function will print the contents of the SD
def print_directory(path, tabs=0):
    for file in os.listdir(path):
        stats = os.stat(path + "/" + file)
        filesize = stats[6]
        isdir = stats[0] & 0x4000

        if filesize < 1000:
            sizestr = str(filesize) + " bytes"
        elif filesize < 1000000:
            sizestr = "%0.1f KB" % (filesize / 1000)
        else:
            sizestr = "%0.1f MB" % (filesize / 1000000)

        prettyprintname = ""
        for _ in range(tabs):
            prettyprintname += "   "
        prettyprintname += file
        if isdir:
            prettyprintname += "/"
        print("{0:<40} Size: {1:>10}".format(prettyprintname, sizestr))

        # recursively print directory contents
        if isdir:
            print_directory(path + "/" + file, tabs + 1)

print("Files on filesystem:")
print("====================")
print_directory("/sd")

Hi ladyada, I've also experienced not working sd card with teensy 4.1. I tried with the code you posted that worked fine only in "r" mode unfortunately. I simply added this below your code:

with open("/sd/test.txt", "w") as f:
    f.write("new line!\r\n")

and it gives me: [Errno 5] Input/output error. I used 16gb class 10 and 4gb class 4 sd cards.

What am I missing?

I also have the exact same problem, I can't get the code to write or append, it gives me the same problem

Ask314 commented 2 years ago

I was excited to find Lady Ada's 'fix' back in May, and I'm trying to implement this too! I still can't use the SD card on my Teensy 4.1. I used Lady Ada's code, copied some files to the SD card on my PC, and it works, it does print the directory of the SD card.
BUT - I get the same: OSError: [Errno 5] Input/output error

when it gets to this code:

with open("/sd/test.txt", "w") as f: f.write("Hello World : \n") f.close()

Please help!

RetiredWizard commented 2 years ago

@Ask314 @electric1236 @cpasto I'm not sure if some work has been done on the libraries or core that might have impacted this in the last year, but I built the latest 8.0.0 CP bits for the Teensy 4.1 and was able to use Lady Ada's code to write to the SD card using:

 >>> with open("/sd/test.txt", "w") as f:
 ...     f.write("new line!\r\n")
 ...
 11

With no issues.