Skip to content

Commit 9e3ce62

Browse files
Antonin ENFRUNAnton-2
Antonin ENFRUN
authored andcommitted
SDCard speedup : don't re-calculate CRC table on each cmd, and allow faster SPI data rate
1 parent c7aa2f2 commit 9e3ce62

File tree

1 file changed

+21
-13
lines changed

1 file changed

+21
-13
lines changed

adafruit_sdcard.py

Lines changed: 21 additions & 13 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 baudrate: The SPI data rate to use after card setup
8485
8586
Example usage:
8687
@@ -99,8 +100,9 @@ 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, baudrate=1320000):
104+
# This is the init baudrate.
105+
# We create a second device with the target baudrate after card initialization.
104106
self._spi = spi_device.SPIDevice(spi, cs, baudrate=250000, extra_clocks=8)
105107

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

112-
# initialise the card
113-
self._init_card()
114+
# initialise the card and switch to high speed
115+
self._init_card(baudrate)
114116

115117
def _clock_card(self, cycles=8):
116118
"""
@@ -128,7 +130,7 @@ def _clock_card(self, cycles=8):
128130
self._spi.spi.write(self._single_byte)
129131
self._spi.spi.unlock()
130132

131-
def _init_card(self):
133+
def _init_card(self, baudrate):
132134
"""Initialize the card in SPI mode."""
133135
# clock card at least cycles with cs high
134136
self._clock_card(80)
@@ -174,7 +176,7 @@ def _init_card(self):
174176

175177
# set to high data rate now that it's initialised
176178
self._spi = spi_device.SPIDevice(self._spi.spi, self._spi.chip_select,
177-
baudrate=1320000, extra_clocks=8)
179+
baudrate=baudrate, extra_clocks=8)
178180

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

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

468468
crc_table = bytearray(256)
469-
470469
crc_poly = const(0x89) # the value of our CRC-7 polynomial
471470

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

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

488496
return ((crc << 1) | 1)

0 commit comments

Comments
 (0)