Skip to content

Commit dda1c98

Browse files
committed
drivers/sdcard/sdcard.py: Fixes per PR discussion.
Merged crc7.py into sdcard.py, fixed many little things per suggestions. Removed hardwired crcs from cmd, always recompute. Signed-off-by: Marcus Mendenhall <mendenmh@gmail.com>
1 parent 43386d2 commit dda1c98

File tree

2 files changed

+71
-116
lines changed

2 files changed

+71
-116
lines changed

micropython/drivers/storage/sdcard/crc7.py

Lines changed: 0 additions & 85 deletions
This file was deleted.

micropython/drivers/storage/sdcard/sdcard.py

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,51 @@
3030
import time
3131
import uctypes
3232
from errno import ETIMEDOUT, EIO, ENODEV, EINVAL
33-
from crc7 import crc7
33+
34+
crc7_be_syndrome_table = (
35+
b"\x00\x12$6HZl~\x90\x82\xb4\xa6\xd8\xca\xfc\xee2 \x16\x04zh^L\xa2\xb0\x86\x94\xea\xf8"
36+
b"\xce\xdcdv@R,>\x08\x1a\xf4\xe6\xd0\xc2\xbc\xae\x98\x8aVDr`\x1e\x0c:(\xc6\xd4\xe2\xf0"
37+
b"\x8e\x9c\xaa\xb8\xc8\xda\xec\xfe\x80\x92\xa4\xb6XJ|n\x10\x024&\xfa\xe8\xde\xcc\xb2\xa0"
38+
b'\x96\x84jxN\\"0\x06\x14\xac\xbe\x88\x9a\xe4\xf6\xc0\xd2<.\x18\ntfPB\x9e\x8c\xba\xa8'
39+
b"\xd6\xc4\xf2\xe0\x0e\x1c*8FTbp\x82\x90\xa6\xb4\xca\xd8\xee\xfc\x12\x006$ZH~l\xb0\xa2"
40+
b"\x94\x86\xf8\xea\xdc\xce 2\x04\x16hzL^\xe6\xf4\xc2\xd0\xae\xbc\x8a\x98vdR@>,\x1a\x08"
41+
b"\xd4\xc6\xf0\xe2\x9c\x8e\xb8\xaaDV`r\x0c\x1e(:JXn|\x02\x10&4\xda\xc8\xfe\xec\x92\x80"
42+
b'\xb6\xa4xj\\N0"\x14\x06\xe8\xfa\xcc\xde\xa0\xb2\x84\x96.<\n\x18ftBP\xbe\xac\x9a\x88\xf6'
43+
b"\xe4\xd2\xc0\x1c\x0e8*TFpb\x8c\x9e\xa8\xba\xc4\xd6\xe0\xf2"
44+
)
45+
46+
# ruff: noqa: F821 - @asm_thumb and @viper decorator adds names to function scope
47+
try:
48+
from uctypes import addressof
49+
50+
@micropython.viper
51+
def crc7(buf) -> int:
52+
n = int(len(buf))
53+
table = ptr8(addressof(crc7_be_syndrome_table))
54+
bp = ptr8(addressof(buf))
55+
idx = 0
56+
crc = 0
57+
while idx < n:
58+
crc = table[crc ^ bp[idx]]
59+
idx = idx + 1
60+
return crc
61+
62+
# test to make sure this works!
63+
# print(f"{crc7('abcde'):02x}")
64+
assert crc7(b"abcde") == 0x34
65+
except:
66+
# non-viper version if viper can'r be built
67+
def crc7(buf) -> int:
68+
crc = 0
69+
for b in buf:
70+
crc = crc7_be_syndrome_table[crc ^ b]
71+
return crc
72+
73+
74+
def gb(bigval, b0, bn):
75+
# get numbered bits from a buf_to_int from, for example, the CSD
76+
return (bigval >> b0) & ((1 << (1 + bn - b0)) - 1)
77+
3478

3579
_CMD_TIMEOUT = const(50)
3680

@@ -64,8 +108,9 @@ def __init__(self, spi, cs, baudrate=1320000, crc16_function=None):
64108
def check_crcs(self, crc16_function):
65109
self.crc16 = crc16_function
66110
result = self.cmd(
67-
59, 1 if crc16_function else 0, None, release=True
111+
59, 1 if crc16_function else 0, release=True
68112
) # send CRC enable/disable command
113+
return result
69114

70115
def init_spi(self, baudrate):
71116
try:
@@ -77,12 +122,7 @@ def init_spi(self, baudrate):
77122
# on pyboard
78123
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
79124

80-
@staticmethod
81-
def gb(bigval, b0, bn):
82-
# get numbered bits from a buf_to_int from, for example, the CSD
83-
return (bigval >> b0) & ((1 << (1 + bn - b0)) - 1)
84-
85-
def spiff(self):
125+
def _spiff(self):
86126
self.spi.write(b"\xff")
87127

88128
def init_card(self, baudrate):
@@ -104,40 +144,40 @@ def init_card(self, baudrate):
104144
raise OSError(ENODEV, "no SD card")
105145

106146
# CMD8: determine card version
107-
r = self.cmd(8, 0x01AA, 0x87, 4) # probe version
147+
r = self.cmd(8, 0x01AA, 4) # probe version
108148
v2 = r == _R1_IDLE_STATE
109149
v1 = r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND)
110150

111151
if not (v1 or v2):
112152
raise OSError(EIO, "couldn't determine SD card version")
113153
arg41 = _HCS_BIT if v2 else 0 # we support high capacity, on v2 cards
114154
for i in range(_CMD_TIMEOUT): # loop on acmd41 to get
115-
self.cmd(55, 0, None)
116-
if (r := self.cmd(41, arg41, None)) == 0:
155+
self.cmd(55, 0)
156+
if (r := self.cmd(41, arg41)) == 0:
117157
break
118158
time.sleep_ms(5)
119159
if r != 0:
120160
raise OSError(ETIMEDOUT, "card type", "v2" if v2 else "v1")
121161

122162
# get the number of sectors
123163
# CMD9: response R2 (R1 byte + 16-byte block read)
124-
if self.cmd(9, 0, None, 0, False) != 0:
164+
if self.cmd(9, 0, 0, False) != 0:
125165
raise OSError(EIO, "no CSD response")
126166
csd = bytearray(16)
127167
self.readinto(csd)
128168
self.CSD = csd_int = int.from_bytes(
129169
csd, "big"
130170
) # convert 16-byte CSD to a giant integer for bit extraction
131-
gb = self.gb # just for shorter code
171+
_gb = gb # just for local binding
132172
# use bit numbers from SD card spec v9.0.0, table 5.3.2
133-
vers = gb(csd_int, 126, 127)
173+
vers = _gb(csd_int, 126, 127)
134174
if vers == 1: # CSD version 2.0
135-
self.sectors = (gb(csd_int, 48, 69) + 1) * 1024
175+
self.sectors = (_gb(csd_int, 48, 69) + 1) * 1024
136176
self.cdv = 1
137177
elif vers == 0x00: # CSD version 1.0 (old, <=2GB)
138-
c_size = gb(csd_int, 62, 73)
139-
c_size_mult = gb(csd_int, 47, 49)
140-
read_bl_len = gb(csd_int, 80, 83)
178+
c_size = _gb(csd_int, 62, 73)
179+
c_size_mult = _gb(csd_int, 47, 49)
180+
read_bl_len = _gb(csd_int, 80, 83)
141181
capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
142182
self.sectors = capacity // 512
143183
self.cdv = 512 # converts bytes to sectors
@@ -146,18 +186,18 @@ def init_card(self, baudrate):
146186
# print('sectors', self.sectors)
147187

148188
# CMD16: set block length to 512 bytes
149-
if self.cmd(16, 512, None) != 0:
189+
if self.cmd(16, 512) != 0:
150190
raise OSError(EIO, "can't set 512 block size")
151191

152192
# set to high data rate now that it's initialised
153193
self.init_spi(baudrate)
154194

155-
def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
195+
def cmd(self, cmd, arg, final=0, release=True, skip1=False):
156196
cs = self.cs # prebind
157197
w = self.spi.write
158198
r = self.spi.readinto
159199
tb = self.tokenbuf
160-
spiff = self.spiff
200+
spiff = self._spiff
161201

162202
cs(0) # select chip
163203

@@ -168,7 +208,7 @@ def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
168208
buf[2] = arg >> 16
169209
buf[3] = arg >> 8
170210
buf[4] = arg
171-
buf[5] = (crc if crc is not None else crc7(self.cmdbuf5)) | 1
211+
buf[5] = crc7(self.cmdbuf5) | 1
172212
w(buf)
173213

174214
if skip1:
@@ -207,7 +247,7 @@ def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
207247

208248
def readinto(self, buf):
209249
cs = self.cs
210-
spiff = self.spiff
250+
spiff = self._spiff
211251

212252
cs(0)
213253

@@ -237,7 +277,7 @@ def readinto(self, buf):
237277

238278
def write(self, token, buf):
239279
cs = self.cs
240-
spiff = self.spiff
280+
spiff = self._spiff
241281
r = self.spi.read
242282
w = self.spi.write
243283

@@ -269,13 +309,13 @@ def write(self, token, buf):
269309
def write_token(self, token):
270310
self.cs(0)
271311
self.spi.read(1, token)
272-
self.spiff()
312+
self._spiff()
273313
# wait for write to finish
274314
while self.spi.read(1, 0xFF)[0] == 0x00:
275315
pass
276316

277317
self.cs(1)
278-
self.spiff()
318+
self._spiff()
279319

280320
@staticmethod
281321
def blocks(buf):
@@ -287,29 +327,29 @@ def blocks(buf):
287327
def readblocks(self, block_num, buf):
288328
# workaround for shared bus, required for (at least) some Kingston
289329
# devices, ensure MOSI is high before starting transaction
290-
self.spiff()
330+
self._spiff()
291331
nblocks = self.blocks(buf)
292332

293333
# CMD18: set read address for multiple blocks
294-
if self.cmd(18, block_num * self.cdv, None, release=False) != 0:
334+
if self.cmd(18, block_num * self.cdv, release=False) != 0:
295335
# release the card
296336
self.cs(1)
297337
raise OSError(EIO) # EIO
298338
mv = memoryview(buf)
299339
for offset in range(0, nblocks * 512, 512):
300340
self.readinto(mv[offset : offset + 512])
301341

302-
if self.cmd(12, 0, None, skip1=True):
342+
if self.cmd(12, 0, skip1=True):
303343
raise OSError(EIO) # EIO
304344

305345
def writeblocks(self, block_num, buf):
306346
# workaround for shared bus, required for (at least) some Kingston
307347
# devices, ensure MOSI is high before starting transaction
308-
self.spiff()
348+
self._spiff()
309349
nblocks = self.blocks(buf)
310350

311351
# CMD25: set write address for first block
312-
if (r := self.cmd(25, block_num * self.cdv, None)) != 0:
352+
if self.cmd(25, block_num * self.cdv) != 0:
313353
raise OSError(EIO) # EIO`
314354
# send the data
315355
mv = memoryview(buf)

0 commit comments

Comments
 (0)