Actually, most of the info/code you may find on SD initialization is either dated or innacurate, since it predates SDHC & SDXC by years. The procedure is more complicated nowadays, as it forces you to deal with old hardware in a backwards-compatible way.
Firstly, as mentioned by others, select a low initial clock rate (generally in the 100 kHz - 400 kHz range; use 400 kHz if possible); you'll be able to switch to higher clock later on, if the device allows for it. While new cards can safely withstand MHz-ish clocking, older will complain (i.e. not communicate or return garbage).
Next thing is that you shouldn't use CMD1
to initialize SD/SDHC/SDXC cards unless your card doesn't recognize CMD55
/ACMD41
; as said in the SD Card specification:
In any of the cases CMD1 is not recommended because it may be difficult for the host to distinguish between MultiMediaCard and SD Memory Card.
Some controllers (newer and higher capacity cards mostly) will simply stay in IDLE if you issue CMD1
to them.
You should first issue CMD8 0x1AA
after the reset (CMD0
), and then try to use CMD55 + ACMD41
. If and only if that fails, use CMD1
.
tl;dr to initialize the card in SPI mode you should:
CMD0
arg: 0x0
, CRC: 0x95
(response: 0x01
) - note that in case of 0xFF
or garbled response you should simply repeat this step; see below for more info.
CMD8
arg: 0x000001AA
, CRC: 0x87
(response: 0x01
, followed by echo of arg, in this case 0x000001AA
) - while it may seem that this command is optional, it's completely mandatory for newer cards. While 0x1AA
is a common arg value here, you may actually pass other values as well; see "Table 7-5: Card Operation for CMD8 in SPI Mode", p. 108 in spec for details.
3a. CMD55
arg: 0x0
, CRC: any, 0x65
actually (response: 0x01
; CMD55
being the prefix to every ACMD
; if the response is 0x05
, you've got an old card - repeat CMD1
with arg 0x0
[CRC 0xF9
] instead of CMD55
/ACMD41
)
3b. ACMD41
, arg: 0x40000000
, CRC: any, 0x77
actually (note that this argument assumes the card is a HCS one, which is usually the case; use 0x0
arg [CRC 0xE5
] for older cards). If response is 0x0
, you're OK; if it's 0x01
, goto 3a; if it's 0x05
, see note on it above (in 3a.); if it's neither, something's wrong with it (also see below).
Most cards require steps 3a/3b (or CMD1
for old cards) to be repeated, usually at least once, even if you wait some time between them; i.e. the actual sequence is CMD0
/CMD8
/CMD55
/ACMD41
/CMD55
/ACMD41
(or CMD0
/CMD8
/CMD1
/CMD1
) - to be sure, try the CMD55
/ACMD41
(or CMD1
if you got 0x05
from them) \$n\$ times (select \$n\$ within your reason; it's actually quite common to have to wait a couple hundred ms if the device is just after the power on, so aim for that), with small delays between the tries if you wish, and assume fail if response 0
doesn't appear (i.e. if the device stays in IDLE mode for some reason). Also, receiving 0xFF
from CMD0
is common if a device was in some "strange" state previously (e.g. hung up, got S̲S̲ deasserted [high], had over-/undervoltage on some pins etc.) - just give it some time, rinse and repeat \$n\$ times. A garbled response to CMD0
is quite OK sometimes - if you sent it a couple of times and the response is still neither 0xFF
nor 0x01
, try to go forward with CMD8
. If it works - you're good to go; if it doesn't - it's probably broken.
Note that responses that have the MSB set but ain't 0xFF
usually suggest that your SPI got a shift in clocking (as a result of e.g. Vcc drop, which happens routinely when you're doing SD hotplugs). To fix it, you can try to completely reset the device (power on/off, deassert/assert S̲S̲ etc.); it usually works.
Also, the spec says
After the last SD Memory Card bus transaction, the host is required, to provide 8 (eight) clock cycles for the card to complete the operation before shutting down the clock.
It could work without it, but since 8 cycles = 1 SPI output byte, it won't hurt much and it's just good to have it.
Note that you should assert S̲S̲ (aka CS) low at least before and after each CMD
- it's completely mandatory in case of CMD0
(the device won't turn on without it) and, in reality, required for all other CMD
s if you have a standards-compliant SD card. Connecting the card's S̲S̲ to GND permanently may seem to be a good idea if the card is the only SPI client your host will ever connect to, as it would save you both the uC output pin & the need to manage it by code at all, and because the card should assume it's selected all of the time. In reality, some cards (if not most of them) actually expect a high-to-low slope to turn on instead of simply detecting low, and thus get angry if you don't toggle the S̲S̲ bit at all, and then either lag clocks or spit garbage; some (usually newer) cards should work, some (older) may not, YMMV (yet again). Still, for any more robust SPI configuration (>1 slave device) remember to assert the pin low before any actual transaction with the given SD card.
Besides, while the spec says that only CMD0
and CMD8
should have CRC in SPI mode, some SD cards (like Transcend ones) seem to require proper CRC for CMD55
/ACMD41
- if you want to be on the safe side, simply use a precalculated value for them.
Also, while SPI doesn't require pullups/downs by itself, throwing a 47k pullup on MISO may be a good idea; some devices leave their DO pin high-Z under specific circumstances (not initialized e.g.), and floating pins can always be a source of strange problems. If your uC has 3.3 Vcc, you may use internal pullups; if it's 5V, don't do that unless your MISO line has a proper 5->3.3V logic translation already.
Further reading:
How To Use MMC/SDC
SD Specifications
Part 1 Simplified
Physical Layer
Simplified Specification - most importantly sections 6.4.1 Power up and 7.2.1 Mode Selection and Initialization with Figure 7-1: SD Memory Card State Diagram (SPI mode)
There are many ways to implement a communication protocol. For example you may choose to use:
- human readable format or binary
- error checking such as a checksum or CRC
- start and/or end message characters
- message length, number etc payload information
- acknowledge / negative acknowledge / retry mechanisms
Your example command is human readable and should use '\n' (enter) as the end of message character. Start / end of message characters make it easier to parse the input stream.
A typical program flow would be to wait for the start character to be received, then store subsequent bytes into a message buffer until the end character is received. Once that happens pass the buffer to another function to parse the message. If no start character, just start storing bytes immediately until the end character is received.
Most* embedded systems run in an infinite loop. Handling of serial transmit and receive is done via interrupts on the Arduino (see HardwareSerial.cpp). Received characters are placed into a buffer. On every iteration of the loop you check to see if there are any characters in the buffer (Serial.available()) and process them. By receiving characters using interrupts no characters should be missed. You don't do all the processing in these interrupt routines though, else they become too long and therefore miss subsequent interrupts.
If you don't want your device to sit idle looping, put it into a sleep state to 'pause' the loop until an interrupt or other event.
I really like this library for human readable messaging: http://playground.arduino.cc/Code/Messenger
* I can't think of a system which doesn't but perhaps there is one out there.
Best Answer
The SPI bidirectional protocol requires that any time the master might try to exchange a byte of data, the slave always be ready to take in a byte of data and spit one out. The master will feed the slave a byte on MOSI without regard for whether or not the slave is ready to do anything useful with it, and whatever the slave does on the MISO pin will be interpreted as a byte of data by the master whether or not the slave had anything useful it wanted to say.
To deal with this, many SPI chips define their behavior such that the first byte following a chip select will indicate whether the device is ready to do anything with a command request other than drop it on the floor. Effectively, the first thing the master does is ask "are you ready?" If the slave answers "no", the master may ask repeatedly as often as it wants until the slave says "yes". Such a design is fairly simple to implement on the slave side, and is fairly easy to use from the master side. Further, it's generally not to hard to subdivide the different kinds of operations a device can perform into steps which are small enough that once the slave is ready to begin performing a step, it will be able to exchange all the data with that step as fast as the master cares to clock it, without further delay.
One slight wrinkle in all of this is that some slaves may need pulses on the clock wire in order to perform certain operations. As a common example, many designs expect to latch all 8 bits of the next byte they're going to send before they receive the first clock pulse. If a device which is primed to send a byte that says "not ready" becomes ready, it would have no way of knowing whether a clock pulse might arrive just as it was getting ready to change the next byte it transmitted, causing that byte to contain a mix of old and new data. One way of avoiding such a danger is to have a device decide on the sixth clock cycle of each byte whether it's going to report itself as ready on the following byte. Even if the device becomes ready just as it receives the sixth cycle of a byte, by the time the eight cycle was received the device would have had a chance to make up its mind as to whether it thought it became ready before the sixth cycle (in which case the next byte should report "ready") or failed to do so (in which case it should report another "not ready" byte).