From e0e614e192962b646b549265eb816962a2ee5972 Mon Sep 17 00:00:00 2001 From: devoh747 Date: Mon, 5 Aug 2019 14:44:21 -0400 Subject: [PATCH 1/2] Fixed Issue 13, Samsung EVO 32GB cards not working The issue is that Samsung EVO 32GB cards require all command codes to have a valid CRC. I used https://github.com/hazelnusse/crc7/blob/master/crc7.cc to calculate all CRC codes and it is now working. I also changed one command from a _block_cmd to a _cmd. It would hang otherwise. --- adafruit_sdcard.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/adafruit_sdcard.py b/adafruit_sdcard.py index 2906460..d647960 100644 --- a/adafruit_sdcard.py +++ b/adafruit_sdcard.py @@ -153,7 +153,7 @@ def _init_card(self): # get the number of sectors # CMD9: response R2 (R1 byte + 16-byte block read) csd = bytearray(16) - if self._cmd(9, response_buf=csd) != 0: + if self._cmd(9, 0, 0xaf, response_buf=csd) != 0: raise OSError("no response from SD card") #self.readinto(csd) csd_version = (csd[0] & 0xc0) >> 6 @@ -169,7 +169,7 @@ def _init_card(self): self._sectors = block_length // 512 * mult * (c_size + 1) # CMD16: set block length to 512 bytes - if self._cmd(16, 512, 0) != 0: + if self._cmd(16, 512, 0x81) != 0: raise OSError("can't set 512 block size") # set to high data rate now that it's initialised @@ -190,10 +190,10 @@ def _init_card_v2(self): ocr = bytearray(4) for _ in range(_CMD_TIMEOUT): time.sleep(.050) - self._cmd(58, response_buf=ocr, data_block=False) - self._cmd(55) - if self._block_cmd(41, 0x200000, 0) == 0: - self._cmd(58, response_buf=ocr, data_block=False) + self._cmd(58, 0, 0xfd, response_buf=ocr, data_block=False) + self._cmd(55, 0, 0x65) + if self._cmd(41, 0x40000000, 0x77) == 0: + self._cmd(58, 0, 0xfd, response_buf=ocr, data_block=False) # Check for block addressing if (ocr[0] & 0x40) != 0: @@ -405,18 +405,18 @@ def readblocks(self, start_block, buf): # CMD17: set read address for single block # We use _block_cmd to read our data so that the chip select line # isn't toggled between the command, response and data. - if self._block_cmd(17, start_block, 0, response_buf=buf) != 0: + if self._block_cmd(17, start_block, 0x3b, response_buf=buf) != 0: return 1 else: # CMD18: set read address for multiple blocks - if self._block_cmd(18, start_block, 0) != 0: + if self._block_cmd(18, start_block, 0x57) != 0: return 1 offset = 0 while nblocks: self._readinto(buf, start=offset, end=(offset + 512)) offset += 512 nblocks -= 1 - return self._cmd(12, wait=False) + return self._cmd(12, 0, 0x09, wait=False) return 0 def writeblocks(self, start_block, buf): @@ -430,14 +430,14 @@ def writeblocks(self, start_block, buf): assert nblocks and not err, 'Buffer length is invalid' if nblocks == 1: # CMD24: set write address for single block - if self._block_cmd(24, start_block, 0) != 0: + if self._block_cmd(24, start_block, 0x6f) != 0: return 1 # send the data self._write(_TOKEN_DATA, buf) else: # CMD25: set write address for first block - if self._block_cmd(25, start_block, 0) != 0: + if self._block_cmd(25, start_block, 0x03) != 0: return 1 # send the data offset = 0 From bb5342b8154d86554c611ee6b123c8976614daef Mon Sep 17 00:00:00 2001 From: devoh747 Date: Wed, 7 Aug 2019 16:41:14 -0400 Subject: [PATCH 2/2] adding dynamic CRC --- adafruit_sdcard.py | 47 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/adafruit_sdcard.py b/adafruit_sdcard.py index d647960..2eb94d6 100644 --- a/adafruit_sdcard.py +++ b/adafruit_sdcard.py @@ -169,7 +169,7 @@ def _init_card(self): self._sectors = block_length // 512 * mult * (c_size + 1) # CMD16: set block length to 512 bytes - if self._cmd(16, 512, 0x81) != 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 @@ -234,6 +234,10 @@ def _cmd(self, cmd, arg=0, crc=0, response_buf=None, data_block=True, wait=True) buf[2] = (arg >> 16) & 0xff buf[3] = (arg >> 8) & 0xff buf[4] = arg & 0xff + if (!crc): + buf[5] = calculate_crc(buf[:-1]) + else: + buf[5] = crc buf[5] = crc with self._spi as spi: @@ -281,7 +285,10 @@ def _block_cmd(self, cmd, block, crc, response_buf=None): buf[2] = (block >> 7) & 0xff buf[3] = (block << 1) & 0xff buf[4] = 0 - buf[5] = crc + if (!crc): + buf[5] = calculate_crc(buf[:-1]) + else: + buf[5] = crc result = -1 with self._spi as spi: @@ -405,18 +412,18 @@ def readblocks(self, start_block, buf): # CMD17: set read address for single block # We use _block_cmd to read our data so that the chip select line # isn't toggled between the command, response and data. - if self._block_cmd(17, start_block, 0x3b, response_buf=buf) != 0: + if self._block_cmd(17, start_block, 0, response_buf=buf) != 0: return 1 else: # CMD18: set read address for multiple blocks - if self._block_cmd(18, start_block, 0x57) != 0: + if self._block_cmd(18, start_block, 0) != 0: return 1 offset = 0 while nblocks: self._readinto(buf, start=offset, end=(offset + 512)) offset += 512 nblocks -= 1 - return self._cmd(12, 0, 0x09, wait=False) + return self._cmd(12, 0, 0x61, wait=False) return 0 def writeblocks(self, start_block, buf): @@ -430,14 +437,14 @@ def writeblocks(self, start_block, buf): assert nblocks and not err, 'Buffer length is invalid' if nblocks == 1: # CMD24: set write address for single block - if self._block_cmd(24, start_block, 0x6f) != 0: + if self._block_cmd(24, start_block, 0) != 0: return 1 # send the data self._write(_TOKEN_DATA, buf) else: # CMD25: set write address for first block - if self._block_cmd(25, start_block, 0x03) != 0: + if self._block_cmd(25, start_block, 0) != 0: return 1 # send the data offset = 0 @@ -447,3 +454,29 @@ def writeblocks(self, start_block, buf): nblocks -= 1 self._cmd_nodata(_TOKEN_STOP_TRAN, 0x0) return 0 + + def calculate_crc(message): + # Code converted from https://github.com/hazelnusse/crc7/blob/master/crc7.cc by devoh747 + # With permission from Dale Lukas Peterson + # 8/6/2019 + + CRCTable = bytearray(256) + + CRCPoly = const(0x89) # the value of our CRC-7 polynomial + + # generate a table value for all 256 possible byte values + for i in range(256): + if (i & 0x80): + CRCTable[i] = i ^ CRCPoly + else: + CRCTable[i] = i + for _ in range(1,8): + CRCTable[i] = CRCTable[i] << 1 + if (CRCTable[i] & 0x80): + CRCTable[i] = CRCTable[i] ^ CRCPoly + + CRC = 0 + for i in range(len(message)): + CRC = CRCTable[(CRC << 1) ^ message[i]] + + return ((CRC << 1) | 1) \ No newline at end of file