Skip to content

Commit 2849602

Browse files
author
Antonin ENFRUN
committed
SDCard speedup : don't re-calculate CRC table on each cmd, and allow faster SPI data rate
1 parent c7aa2f2 commit 2849602

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

adafruit_sdcard.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class SDCard:
8181
8282
:param ~busio.SPI spi: The SPI bus
8383
:param ~digitalio.DigitalInOut cs: The chip select connected to the card
84+
:param int freq: The SPI data rate to use after card setup
8485
8586
Example usage:
8687
@@ -99,8 +100,8 @@ class SDCard:
99100
os.listdir('/')
100101
101102
"""
102-
def __init__(self, spi, cs):
103-
# This is the init baudrate. We create a second device for high speed.
103+
def __init__(self, spi, cs, freq=1320000):
104+
# This is the init baudrate. We create a second device with baudrate=freq for high speed.
104105
self._spi = spi_device.SPIDevice(spi, cs, baudrate=250000, extra_clocks=8)
105106

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

112-
# initialise the card
113-
self._init_card()
113+
# initialise the card and switch to high speed
114+
self._init_card(freq)
114115

115116
def _clock_card(self, cycles=8):
116117
"""
@@ -128,7 +129,7 @@ def _clock_card(self, cycles=8):
128129
self._spi.spi.write(self._single_byte)
129130
self._spi.spi.unlock()
130131

131-
def _init_card(self):
132+
def _init_card(self, freq):
132133
"""Initialize the card in SPI mode."""
133134
# clock card at least cycles with cs high
134135
self._clock_card(80)
@@ -174,7 +175,7 @@ def _init_card(self):
174175

175176
# set to high data rate now that it's initialised
176177
self._spi = spi_device.SPIDevice(self._spi.spi, self._spi.chip_select,
177-
baudrate=1320000, extra_clocks=8)
178+
baudrate=freq, extra_clocks=8)
178179

179180
def _init_card_v1(self):
180181
"""Initialize v1 SDCards which use byte addressing."""
@@ -210,7 +211,7 @@ def _wait_for_ready(self, spi, timeout=0.3):
210211
:param float timeout: Maximum time to wait in seconds.
211212
"""
212213
start_time = time.monotonic()
213-
self._single_byte[0] = 0x00
214+
spi.readinto(self._single_byte, write_value=0xff)
214215
while time.monotonic() - start_time < timeout and self._single_byte[0] != 0xff:
215216
spi.readinto(self._single_byte, write_value=0xff)
216217

@@ -253,6 +254,7 @@ def _cmd(self, cmd, arg=0, crc=0, response_buf=None, data_block=True, wait=True)
253254
if response_buf:
254255
if data_block:
255256
# Wait for the start block byte
257+
spi.readinto(buf, start=1, end=2, write_value=0xff)
256258
while buf[1] != 0xfe:
257259
spi.readinto(buf, start=1, end=2, write_value=0xff)
258260
spi.readinto(response_buf, write_value=0xff)
@@ -341,7 +343,7 @@ def _readinto(self, buf, start=0, end=None):
341343
end = len(buf)
342344
with self._spi as spi:
343345
# read until start byte (0xfe)
344-
buf[start] = 0xff #busy
346+
spi.readinto(buf, start=start, end=start+1, write_value=0xff)
345347
while buf[start] != 0xfe:
346348
spi.readinto(buf, start=start, end=start+1, write_value=0xff)
347349

@@ -456,17 +458,13 @@ def writeblocks(self, start_block, buf):
456458
self._cmd_nodata(_TOKEN_STOP_TRAN, 0x0)
457459
return 0
458460

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

468467
crc_table = bytearray(256)
469-
470468
crc_poly = const(0x89) # the value of our CRC-7 polynomial
471469

472470
# generate a table value for all 256 possible byte values
@@ -479,10 +477,19 @@ def calculate_crc(message):
479477
crc_table[i] = crc_table[i] << 1
480478
if (crc_table[i] & 0x80):
481479
crc_table[i] = crc_table[i] ^ crc_poly
480+
return crc_table
481+
482+
CRC_TABLE = _calculate_crc_table()
483+
484+
def calculate_crc(message):
485+
"""
486+
Calculate the CRC of message[0:5], using a precomputed table in CRC_TABLE.
487+
:param bytearray message: Where each index is a byte
488+
"""
482489

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

488495
return ((crc << 1) | 1)

0 commit comments

Comments
 (0)