Skip to content

SDCard speedup : don't re-calculate CRC table, allow faster SPI data rate #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions adafruit_sdcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class SDCard:

:param ~busio.SPI spi: The SPI bus
:param ~digitalio.DigitalInOut cs: The chip select connected to the card
:param int baudrate: The SPI data rate to use after card setup

Example usage:

Expand All @@ -99,8 +100,9 @@ class SDCard:
os.listdir('/')

"""
def __init__(self, spi, cs):
# This is the init baudrate. We create a second device for high speed.
def __init__(self, spi, cs, baudrate=1320000):
# This is the init baudrate.
# We create a second device with the target baudrate after card initialization.
self._spi = spi_device.SPIDevice(spi, cs, baudrate=250000, extra_clocks=8)

self._cmdbuf = bytearray(6)
Expand All @@ -109,8 +111,8 @@ def __init__(self, spi, cs):
# Card is byte addressing, set to 1 if addresses are per block
self._cdv = 512

# initialise the card
self._init_card()
# initialise the card and switch to high speed
self._init_card(baudrate)

def _clock_card(self, cycles=8):
"""
Expand All @@ -128,7 +130,7 @@ def _clock_card(self, cycles=8):
self._spi.spi.write(self._single_byte)
self._spi.spi.unlock()

def _init_card(self):
def _init_card(self, baudrate):
"""Initialize the card in SPI mode."""
# clock card at least cycles with cs high
self._clock_card(80)
Expand Down Expand Up @@ -174,7 +176,7 @@ def _init_card(self):

# set to high data rate now that it's initialised
self._spi = spi_device.SPIDevice(self._spi.spi, self._spi.chip_select,
baudrate=1320000, extra_clocks=8)
baudrate=baudrate, extra_clocks=8)

def _init_card_v1(self):
"""Initialize v1 SDCards which use byte addressing."""
Expand Down Expand Up @@ -253,6 +255,7 @@ def _cmd(self, cmd, arg=0, crc=0, response_buf=None, data_block=True, wait=True)
if response_buf:
if data_block:
# Wait for the start block byte
buf[1] = 0xff
while buf[1] != 0xfe:
spi.readinto(buf, start=1, end=2, write_value=0xff)
spi.readinto(response_buf, write_value=0xff)
Expand Down Expand Up @@ -456,17 +459,13 @@ def writeblocks(self, start_block, buf):
self._cmd_nodata(_TOKEN_STOP_TRAN, 0x0)
return 0

def calculate_crc(message):
"""
Calculate the CRC of a message.
:param bytearray message: Where each index is a byte
"""
def _calculate_crc_table():
"""Precompute the table used in calculate_crc."""
# Code converted from https://github.com/hazelnusse/crc7/blob/master/crc7.cc by devoh747
# With permission from Dale Lukas Peterson <[email protected]>
# 8/6/2019

crc_table = bytearray(256)

crc_poly = const(0x89) # the value of our CRC-7 polynomial

# generate a table value for all 256 possible byte values
Expand All @@ -479,10 +478,19 @@ def calculate_crc(message):
crc_table[i] = crc_table[i] << 1
if (crc_table[i] & 0x80):
crc_table[i] = crc_table[i] ^ crc_poly
return crc_table

CRC_TABLE = _calculate_crc_table()

def calculate_crc(message):
"""
Calculate the CRC of message[0:5], using a precomputed table in CRC_TABLE.
:param bytearray message: Where each index is a byte
"""

crc = 0
# All messages in _cmd are 5 bytes including the cmd.. The 6th byte is the crc value.
for i in range(0, 5):
crc = crc_table[(crc << 1) ^ message[i]]
crc = CRC_TABLE[(crc << 1) ^ message[i]]

return ((crc << 1) | 1)