For a SD card driver I tried to calculate CRC7 for the commands. Now, if I "enable CRC7 check" with CMD59, I get errors with some SD cards. But if I "disable CRC7" check with CMD59, I can read and write files on all kinds of SD cards, who support SPI.
Well, my initial assumption was that it was due to the CRC7 calculation. With SD cards that give me errors, I can still initialize them without any problems with "enabled CRC7 check" and also read and write a few files. But usually only about 10-15 files at most before an error occurs.
The error manifests itself as follows:
After CMD17, I get R1 = 0x00. But then I only read 0xFF. The data token never comes. Also no Data Error Token. Only 0xFF. I read 100 times (100 bytes), but at least for 200 ms (the SD card standard specifies that a timeout can be assumed after 100 ms, so I should be on the safe side to not miss the token). But I only get 0xFF. When I read the status again with CMD13, I get R1 = 0x00 and R2 = 0x00. So no error. From this point on, neither writing nor reading works. I can execute all commands without errors in R1 or R2 (also CMD17,18,24,25), but I only get 0xFF when reading afterwards; the tokens never come. But always with no indication of errors.
If someone is interested, the SD card initialization process is done like this:
- baudrate <400'000 Hz
- CMD0 -> CMD59 -> CMD8
- IF SDSC: CMD58 -> loop(CMD55 -> ACMD41)
- IF SDHC/SDXC:CMD58 (get OCR register values) -> loop(CMD55 -> ACMD41) -> CDMD50 (get OCR register values and check CCS)
- CMD9 -> Check CSD-Version and get values
- CMD10 (get CID register values)
- CMD55 -> ACMD13 (get SD register values)
- CMD55 -> ACDM51 (get SCR register values)
- check, if CMD42 is supported
- if yes and password should be set or is set:
- CMD16 (set block length for CMD42)
- CMD42
- CMD16 (set block length 51 bytes, for all card)
- Mount filesystem
- Switch to baudrate 12 MHz
- Read with CMD17, CMD18 (CMD12 for STOP_TRAN)
- Write with CMD24, CMD25
- if error, check with CDM13
I would now like to rule out that it is due to the CRC7 calculation, which may only return an error with certain inputs. Here is the code (Python/Micropython), and I would be grateful if someone familiar with CRC could check it for correctness. As I said, without CRC7 check, I never get an error, but with CRC7 check, until a error arrives, all CRC7 are calculated correct (double checked with CRC-Calculator)
def crc7(self, cmd, arg1, arg2, arg3, arg4):
crc = 0x00
poly = 0x89
cmd_token = bytes([cmd, arg1, arg2, arg3, arg4])
# Example: CMD0 -> 0x40, 0x00, 0x00, 0x00, 0x00
for byte in cmd_token:
for bit in range(8):
bit = ((byte >> (7 - bit)) & 1)
crc_bit = ((crc >> 6) & 1)
crc = ((crc << 1) & 0x7F)
if bit ^ crc_bit:
crc ^= poly
crc = crc & 0x7F
crc = (crc << 1) | 0x01 # CRC7 and end bit = 1 for CMD
return crc