12

I've had a look at Stack Overflow question Initialization of a microSD card using an SPI interface and didn't see any answers that matched my issue (that is, things I haven't already tried).

I have a similar issue where I'm trying to access a SD card through a microcontroller's SPI interface (specifically an HC908). I've tried following the flow charts in the Physical Layer Simplified Specification v2.00 and it seems to initialize correctly on Transcend 1 GB & 2 GB and an AE&C 1 GB card. But I'm having problems on three other random cards from my stash of old cards that I've used on my camera.

My code is all HC908 assembler. I scoped out the SPI clock line and during initialization it's running about 350 kHz (the only speed multiplier that the HC908 supplies at my low MCU clock speed that falls within the 100 - 400 kHz window).

Here are the results of the three cards that aren't completing my initialization routine (all done consecutively without changing any code or timing parameters):

Canon 16Meg card (labeled as SD):
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (indicates idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
because illegal command branch to error routine
Send CMD13 [0x4D000000000D] (show status buffer) and Loop up to 8 times waiting for high bit on response to go low
R1= 0x05 (idle and illegal command)

Is the illegal command flag stuck? Should I be doing something after CMD8 to clear that flag?

SanDisk UltraII 256Meg
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send 0xFF 4 times to read OCR
OCR = 0xFFFFFFFF
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Repeat the CMD1 50 times (my arbitrary number to wait until idle clears)
Every R1 response is 0x05 (idle and illegal command)

Why is OCR all F? Doesn't seem proper at all. Also, why does ACMD41 and CMD1 respond illegal command? Is CMD1 failing because the card is waiting for a valid ACMD after the CMD55 even with the illegal command response?

SanDisk ExtremeIII 2G:
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x40000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? My loop shows the responses for each iteration and I got 0xFF 0xFF 0xC1 0x7F... is the card getting out of sync?)
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle and back in sync)
Send 0xFF 4 times to read OCR
OCR = 0x00FF80
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x5F (??? loop responses are 0xFF 0xFF 0xF0 0x5F... again out of sync?)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command, but back in sync???)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x00 (out of idle)
Send CMD9 [0x4900000000AF] (get CSD) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x3F (??? loop responses are 0xFF 0xFF 0xC1 0x3F... again out of sync?)
Code craps out because Illegal command bit is high.

What on Earth is wrong with that card?

Sometimes it is in sync, other times not. (The above pattern is repeatable.) I've scoped this one out and I'm not seeing any rogue clock cycles going through between MOSI/MISO transfers.

Community
  • 1
  • 1
Sembazuru
  • 451
  • 1
  • 3
  • 10
  • Forgot to mention. After these failed attempts to initialize the 3 cards, I put them in my laptop's SD card reader and I could still access them as standard SD cards (read and write) w/o issue. – Sembazuru Mar 02 '10 at 19:27
  • Found a bug in your list of commands for "SanDisk ExtremeIII": `Send CMD8 [0x40000001AA87` -it should be 0x48, not 0x40. –  Apr 19 '14 at 15:06

3 Answers3

23

OK... I found my problem. For anyone else who runs into this issue, it is important to remember to send an extra 0xFF after getting responses. This gives the card an extra eight clock cycles to prepare itself for the next command. Some cards don't seem to need it (the Transcends that I'm using for example), but others require it.

I actually put a simple loop at the beginning of my 'write command' routine that sends 0xFF until it gets 0xFF as a response just so I don't have to go to all the different places where I read responses to make sure I put an extra send 0xFF. Because as far as the SD card is (usually) concerned in SPI mode, if there are no clock cycles coming in, time stands still.

One thing that I noted and have yet to find an answer for (but so far it isn't hurting anything), after I read the 16 bytes of the CSR, there seem to be an additional 2 bytes of non-0xFF that comes out... Is that a CRC16? Odd since the CSR has a CRC built in...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sembazuru
  • 451
  • 1
  • 3
  • 10
  • 1
    Thanks, you save me hours!! – Jairo Andres Velasco Romero Feb 19 '13 at 16:30
  • 1
    Ditto, this was very helpful, specifically sending 0xFF until 0xFF is returned. I had a Class 2 Transcend card that worked fine, but when I switched to a Class 4 Transcend card, I could initialize but not read it. Now I can. Thanks. – David Apr 05 '13 at 22:12
  • I had a very similar issue and this answer solved my problem, thank you. I had 3 SDHC cards, my initialisation worked for the Toshiba and the Panasonic but the SanDisk card just would not work. Sending clock cycles solved that – Dean2690 Oct 16 '18 at 10:40
3

If you enabled CRC (with CMD59), then yes, data blocks will have CRC16 appended.

For more info see "Physical Layer Simplified Specification Version 2.00", chapters "Bus Transfer Protection" and "Data Read".

domen
  • 1,819
  • 12
  • 19
  • Sorry for responding so late... (Been busy with other projects...) I guess I didn't conceptually think of the CSR as a "data block". I was just thinking of it as a status register. – Sembazuru Mar 17 '11 at 16:31
2

This is important: I've had very much trouble with SD/MMC card, until I found out that I had to select an operating voltage. You do so, by sending ACMD41 with the bit set for the voltage you're supplying the card with. Note: Only a single bit may be selected. If you don't select a voltage or select more than one, it will KEEP looping in idle-state and never exit on some SD cards.

That is: If your ACMD41 keeps sending response 0x01, you have not selected a voltage. The voltage is in ACMD41's 32-bit parameter bits 23...8. For 3.2V ... 3.3V, this is bit 20, so for instance you could:

acmdSDAppOpCond[2] = (1 << (20 & 7));           /* 3.2V .. 3.3V */

That's hex-value 0x10, so your ACMD41 would look like this... 0x69 0x40 0x10 0x00 0x00 0xCD ...or if it's a SDSC card... 0x69 0x00 0x10 0x00 0x00 0x5F

Here's a short (and incomplete) table of the most common values:

Bit23: 3.5V..3.6V
Bit22: 3.4V..3.5V
Bit21: 3.3V..3.4V
Bit20: 3.2V..3.3V
Bit19: 3.1V..3.2V
Bit18: 3.0V..3.1V
Bit17: 2.9V..3.0V
Bit16: 2.8V..2.9V
Bit15: 2.7V..2.8V

You do NOT have to switch CS high at ANY point in time. You can keep it low ALL the time.

  • 1
    The Sandisk SDCard spec says this: "In SPI mode, as opposed to SD mode, ACMD41 (or CMD1 as well, for 2.1mm-SD Card) has no operands and does not return the contents of the OCR register. Instead, the host may use CMD58 (available in SPI mode only) to read the OCR register. Furthermore, it is in the responsibility of the host to refrain from accessing cards that do not support its voltage range.". The official spec doesn't oppose this and explicitly says that ACMD 41 should have an 0x0 argument for Standard Capacity cards. – thenickdude Oct 21 '15 at 23:15
  • 1
    In SD mode, though, that argument would be required: "[...] the host sends the required VDD voltage window as the operand of the [SD_SEND_OP_COND (ACMD41)] command. SD cards that cannot perform data transfers in the specified range must discard themselves from further bus operations and go into Inactive State2. By omitting the voltage range in the command, the host can query each card and determine if there are any incompatibilities before sending out-of-range cards into an inactive state." – thenickdude Oct 21 '15 at 23:20