I’ve found it difficult to find a 100% complete picture of the SD Card SPI protocool. However, this is what I’ve pieced together and has managed to allow me to communicate with a Sandisk card I had sitting around. Overall progress has been slow as I’ve been occupied with other important things. I have however managed to squash the bug that turned my data line into an oscillator and have successfully read the contents of the OCR register. So, although it’s been slow there has been progress and I expect to be able to pick up the pace again now that things have settled and I’m transitioning back into school.
Each command is at minimum a packet of six bytes and has the structure shown in the picture above. The first byte is the command byte of the packet. This byte is followed by the Argument, a 4 byte word that allows you to provide various information to the SD Card such as an address for a read or write command. Finally a CRC byte is attached to the end of the packet. This allows the SD Card to verify there was no data loss during transmission and is typically ignored during SPI communication (Although it is still required to enter SPI Mode). This structure is required to communicate with the SD Card whether it is via the native protocool or SPI. Don’t send out an 8 bit command without the rest of the packet and expect to receive a valid response.
When you find a list of SD Card commands it will typically be a table containing a list of commands (ie: CMD0, CMD1, CMD17, CMD58). The command names are actually fairly descriptive; The number is the decimal representation of the command byte that needs to be sent. Converting these to hexadecimal will make them much easier to work with. This is especially true here since talking to an SD (vs MMC) requires you to or 0×40 with each command. I’ve yet to find this explicitly stated somewhere but anecdotal evidence points to it being the case.
For example, CMD58 is the command to read the OCR register. Converting this to hexadecimal results in a value of 0x3A. Or this command with 0×40 to obtain a command byte of 0x7A. This command requires an argument of zero so the next four bytes are all zero. At this point SPI mode is already active and the CRC byte is ignored. For consistancy I kept it the same as the initialization CRC of 0×95. Altogether this creates the command packet 0x7A 0×00 0×00 0×00 0×00 0×95. As shown below, my SD Card returns with a response: 0x0080FF8000 indicating it is a standard capacity card that supports the entire SD voltage range.