Skip to content

micropython/drivers/sdcard.py: Add CRC7 values for SDCard.cmd() function calls #992

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
40 changes: 27 additions & 13 deletions micropython/drivers/storage/sdcard/sdcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
_TOKEN_STOP_TRAN = const(0xFD)
_TOKEN_DATA = const(0xFE)

## This function computes crc7 for SDcard commands
## It is not optimized, so do not call it where performance is critical
## You should usually be precomputing these values and hardcode them
#def crc7( cmd:bytes ):
# crc = 0
# for value in cmd:
# for i in range(8):
# crc <<= 1
# if (value&0x80)^(crc&0x80):
# crc ^= 0x09
# value <<= 1
# return ((crc<<1)|1)&0xFF
#def cmd_args_to_bytes( cmd:int, args:int ):
# return bytes( [cmd|0x40,(args>>24)&0xFF,(args>>16)&0xFF,(args>>8)&0xFF,args&0xFF] )

class SDCard:
def __init__(self, spi, cs, baudrate=1320000):
Expand Down Expand Up @@ -92,7 +106,7 @@ def init_card(self, baudrate):

# get the number of sectors
# CMD9: response R2 (R1 byte + 16-byte block read)
if self.cmd(9, 0, 0, 0, False) != 0:
if self.cmd(9, 0, 0xAF, 0, False) != 0:
raise OSError("no response from SD card")
csd = bytearray(16)
self.readinto(csd)
Expand All @@ -109,7 +123,7 @@ def init_card(self, baudrate):
# print('sectors', self.sectors)

# CMD16: set block length to 512 bytes
if self.cmd(16, 512, 0) != 0:
if self.cmd(16, 512, 0x15) != 0:
raise OSError("can't set 512 block size")

# set to high data rate now that it's initialised
Expand All @@ -118,8 +132,8 @@ def init_card(self, baudrate):
def init_card_v1(self):
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cmd(55, 0, 0x65)
if self.cmd(41, 0, 0xE5) == 0:
# SDSC card, uses byte addressing in read/write/erase commands
self.cdv = 512
# print("[SDCard] v1 card")
Expand All @@ -129,10 +143,10 @@ def init_card_v1(self):
def init_card_v2(self):
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
self.cmd(58, 0, 0xFD, 4)
self.cmd(55, 0, 0x65)
if self.cmd(41, 0x40000000, 0x77) == 0:
self.cmd(58, 0, 0xFD, -4) # 4-byte response, negative means keep the first byte
ocr = self.tokenbuf[0] # get first byte of response, which is OCR
if not ocr & 0x40:
# SDSC card, uses byte addressing in read/write/erase commands
Expand Down Expand Up @@ -250,15 +264,15 @@ def readblocks(self, block_num, buf):
assert nblocks and not len(buf) % 512, "Buffer length is invalid"
if nblocks == 1:
# CMD17: set read address for single block
if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
if self.cmd(17, block_num * self.cdv, 0x7F, release=False) != 0:
# release the card
self.cs(1)
raise OSError(5) # EIO
# receive the data and release card
self.readinto(buf)
else:
# CMD18: set read address for multiple blocks
if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
if self.cmd(18, block_num * self.cdv, 0x7F, release=False) != 0:
# release the card
self.cs(1)
raise OSError(5) # EIO
Expand All @@ -269,7 +283,7 @@ def readblocks(self, block_num, buf):
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
if self.cmd(12, 0, 0xFF, skip1=True):
if self.cmd(12, 0, 0x61, skip1=True):
raise OSError(5) # EIO

def writeblocks(self, block_num, buf):
Expand All @@ -281,14 +295,14 @@ def writeblocks(self, block_num, buf):
assert nblocks and not err, "Buffer length is invalid"
if nblocks == 1:
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
if self.cmd(24, block_num * self.cdv, 0x7F) != 0:
raise OSError(5) # EIO

# send the data
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
if self.cmd(25, block_num * self.cdv, 0x7F) != 0:
raise OSError(5) # EIO
# send the data
offset = 0
Expand Down
Loading