Electronic – Problems reading the Delkin Micro SD 16 GB using SPI

embeddedmicrocontrollersdspi

I have been working with SD Cards and micro SD Cards for a while.

I am using Part1_Physical_Layer_Simplified_Specification_Ver6.00 for reference.

I am able to do successful card initialization, read and write for other micro SDs like ATP 8GB SLC, Panasonic 8GB SLC etc. However when I am using Delkin 16 GB SLC (and also Swissbit 8GB SLC), although I am successful in card initialization and write, when I am trying to read then I am not getting start block token 0xFE and there are around 512 Bytes of junk data before it becomes normal again.

The pattern is as follows (using the Beagle SPI analyzer):

After writing the following (only the first 24 bytes are shown, but the pattern is the same):

enter image description here

If I am writing 0xA0. Please refer to the following image:

enter image description here

If I change the bytes written, then bytes read are also changed and there is one to one correspondence as well between the bytes written and bytes read. But the bytes are not the same.

I am verifying the data is written successfully using the SD Card reader with HxD hex viewer.

For the first case:

enter image description here

For the second case:

enter image description here

It doesn't seem like the voltage to SD card is varying, as I checked it on the oscilloscope and it remains 3.3 volts during the read.

I am using F28377s Launchpad from TI as the microcontroller.

I would like to get the inputs from you. What exactly can I try to fix this problem?

Edit1: Exactly same behavior is observed for Swissbit 8GB SLC. The same images above can be applied to Swissbit. The data read for Swissbit is same as Delkin.
SPI clock before initialization is 200 kHz and after initialization is changed to 1 MHz.

Edit2: Please look at the oscilloscope images below (i have changed the clock frequency to 225 KHz):

enter image description here
enter image description here

Edit3: The second oscilloscope image, immediately follows the first oscilloscope image. The first image is the read command and response whereas the Second image is sending 0xFF and waiting for start data block token, which is 0xA8 in the second image as 0xFE is bit shifted by 2 bits. You can look at the decoded hex data of the oscilloscope in the bottom of the oscilloscope images. They are same as my Beagle SPI Analyzer Debug Data for example 2 (where I am writing 0xA0 and reading back 0x28).

Edit4: As per Anonymous' suggestion, I have updated my code such that before every command and after CS LOW, I send 8 clocks before any actual intended SPI transmission. After the command response completion, I send 8 clock cycles just before CS HIGH and 8 clock cycles just after CS HIGH. Command response completion in SD Read case means when we have received the last CRC byte. Command response completion in SD Write means when the card stops sending the busy signal after writing. Similarly, I have applied to other commands as well.
Also, I don't do CS HIGH until the command and its response are completed. For e.g. in SD Read Case, I do CS LOW and I send the command, get the command response, get the start block token (0xFE), get the CRC and then I do the CS HIGH.

Thanks.

Best Answer

I think you should have noticed the pattern:

fe 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00 01 02 03 ...

shifting this sequence two bits right you get

ff 80 00 40 80 c1 01 41 81 ...

So exactly the sequence you have. You have added two spare bits into the stream, and bytes got misaligned. Why? Without exact diagrams showing the clock it is not possible to say. Most probably you have issues with clock or data synchronization to it.

This misalignment may happen in either write or read - so it may appear that you write wrong sequence because your write command has bytes misaligned, and then read that wrong sequence back (of course), or it could be purely read command issue. The conclusion that you must check what SD-card has actually written to it - using another functioning device (e.g. PC dumping you card to the file and checking the image) - before going into debugging read or write command execution.

Edit: looking to the scope diagrams I see/recommend the following:

  1. change clock polarity when idle to low. Currently it is high. Check here. In other words - use SPI mode 0;
  2. before command starts (before you put first 0 onto MOSI line) perform 8 spare clock cycles with CS low. Ideally you do the same at the end of the command - put 8 spare clocks with CS low when command completes, and another 8 spare clocks with CS high;
  3. not sure I understand second pic - you send FFs as command to the card? And seems card continuously reports 0x05 (invalid command).

Edit 2:

The second oscilloscope image, immediately follows the first oscilloscope image.

Be very cautious when deselecting the card - your images show that you issue command to the card, deselect it raising CS high, and then reselect it continuosuly sending 0xFFs to the card. Seems card does not understand that, and sends 0x28s back, which are actually 0x05 - "invalid command" R1 response shifted. There're only specific circumstances when you may deselect the card, it is explained in simplified SD specification, and follows very specific protocol:

When the card is signaling busy, the host may deselect it (by raising the CS) at any time. The card will release the DataOut line one clock after the CS going high. To check if the card is still busy it needs to be reselected by asserting (set to low) the CS signal. The card will resume busy signal (pulling DataOut low) one clock after the falling edge of CS.

Regarding my second comment

Also, your comment 2, is it required for all the commands? Currently, I have only applied your suggestion to Read Command.

Spare cycles, while will take some time, will ensure card has properly completed/cancelled the previous operation, and gets ready for next one. So I recommend you to implement it for all commands if possible.