Week #11 – SD Comms
After adding the software SPI, I started out writing the program. There are four working modes in SPI and the SPI timings for Mode 0 is the proper setting for the SD Cards. After setting the mode I started defined the values for the commands that are to be used. Then I started with the power up sequence. This is necessary to synchronize the card with SPI clock pulses and to let the card know the change in clock pulses. The power up sequence is as follows in figure 1, and after power up the card enters native mode and is ready to accept commands.
Figure 1: Power Up Sequence
SD Card commands are 6 bytes (0 – 47 bits) long and sent Most Significant Byte (MSB) first. Byte 6 has the command index and the bit 47 and bit 46 should be set to 0 and 1 respectively. Bytes 5-2 are the argument bytes and varies depending on the command being sent. The last byte is the Cyclic Redundancy Check (CRC) which is sent with bit 0 set to high. In SPI mode after CMD0 is sent and the card enters its idle state CRC is not considered for the commands that follow after.
Each command has a specific response to it, namely R1, R2, R3 and R7. R1 consists of 1 byte, R2 is 2 bytes, R3 is 5 bytes and R7 is also 5 bytes. In order to debug the program and test if it is working a UART is used to show outputs at relevant points of the code.
I then wrote a function to send commands. This function called “sd_command_tx” has 6 inputs. The command index, argument bytes 1 -4 and the CRC byte. The command index is taken in and then masked to put bit 47 as zero and bit 46 as 1. The CRC is also masked before sending in order to set bit 0 to 1.
This was the point to send commands to the SD Card. To start the change in mode I wrote a function called “mode_select”. This function calls selects the SD card (CS = 0), sends CMD0 (GO_IDLE_STATE), and obtains the response in order to check whether the card is in idle state. The response for CMD0 is R1, which indicates whether the card is in idle state shown by bit 0 of R1. When sending CMD0, a valid CRC has to be input since the card is initially in SD mode.
When the card enters idle state, it is in SPI operation mode and the next command to be sent is CMD8 (SEND_IF_COND). This command checks the operating voltage condition and has the argument 0x000001AA, the argument bytes 4-3 is reserved and set to 0x00, while argument byte 2 has the voltage range and argument byte 1 has the check pattern. The voltage range and check pattern table is found in SD Card documentation under CMD8 in SD mode. The response for CMD8 is R7 and I checked if the voltage condition is right by obtaining byte 2 of the response and masking it to see if voltage range is between 2.6 -3.6. If the voltage range is within the limit the echoed check pattern is obtained and checked if it is same as the one sent. This is the end of the mode_select function. If the response shows that the card is withing working voltage range and echoes back the right check pattern, then card initialization must be started.
Furthermore I realized that when sending commands through sd_command_tx, I had to input a dummy CRC each time. However only the CRC for CMD0 is valid therefore I modified the function to have 5 inputs and to include the CRC of CMD0 inside, so that it removes the necessity of inputing the CRC each time when a command is sent.
I then came up with another function prototype, called “card_init”. The purpose of this function is to initialize the card and check whether it is a Standard Capacity Card (SCSD), High Capacity Card (HCSD) or an Extended Capacity Card (XCSD). Initialization is started by sending ACMD41 (SD_SEND_OP_COND), with the argument 0x00000000, for checking with High Capacity Support (HCS) low. ACMD41 can also be sent with 0x40000000 with HCS set high. ACMD41 is an application specific command and before sending any application specific commands, CMD55 (APP_CMD)has to be sent, since this indicates the card that the next command will be application specific. Both these commands respond with an R1 response.
The function card_init selects the card and sends CMD55, it checks for the response of the card and if R1 returns without illegal command flag, the next command ACMD41 is sent and the response is obtained. This sequence is repeated until the response for R1 is 0x00 indicating that card initialization is completed. CMD58 (READ_OCR) is now sent to the SD card to check for Card Capacity Status (CCS). The argument for CMD58 is 0x00000000 and the response is R3 consisting of 5 bytes. The CCS is bit 30 found in byte 4 of R3, which is stored and masked to see if CCS is high or low. CCS high indicates an HC/XC SD and a low shows a SCSD. HCSD and XCSD have a standard block length of 512 bytes, however the block length of SCSD has to be set by sending CMD16 (SET_BLOCKLEN) with the argument of 0x00000200, and the response R1 = 0x00 indicates that the block has been set and hence this marks the end of the function card_init.