• AVR Freaks

SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01)

Page: 12 > Showing page 1 of 2
Author
felix007
New Member
  • Total Posts : 29
  • Reward points : 0
  • Joined: 2009/09/15 10:17:16
  • Location: 0
  • Status: offline
2009/10/16 09:10:31 (permalink)
0

SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01)

Hi,

I have a PIC18F26J50 (Vdd @ 3.3V) and I want to interface a 128Mb SD Card with SPI as a big cheap eeprom to log data...

Here is my SPI routine (C18):

char SPI(char d)        // send character over SPI
{
    SSP2BUF = d;            // send character
    while (!SSP2STATbits.BF);        // wait until sent
    //while( !PIR3bits.SSP2IF );
    return SSP2BUF;        // and return the received character
}



The SPI initialisation part is working, everything is OK on the scope. I have a 24Mhz xtal, with SPI freq set to Fosc/64 (ok for the SPI req).
I have 10kohm pullup to Vdd (3.3V) on SDO, SDI, CLK and CS, and all the signals are fine on the scope. The timing are fine too on the scope.

First, I send 80 pulses:
 
    // start MMC in SPI mode
    for(i=0; i < 10; i++)
    {   
        SPI(0xFF);        // send 10*8=80 clock pulses
    }


Then, I send the CMD0 to reset the card:
 
    char i;

    PORTAbits.RA6 = 0;    // CS low (MMC-Enabled)

    SPI(0x40);    // cmd0
    SPI(0x00);   
    SPI(0x00);
    SPI(0x00);
    SPI(0x00);
    SPI(0x95);    // precalculated checksum as we are still in MMC mode

    SPI(0xFF);
    i = SPI(0xFF);

    if ( i == 1 )
    {
        // MMC found, continue
    }   
    else
    {
        // no response from MMC, abort
        return;
    }


The card response is 0x01, it mean that it is in Idle State, wich is OK.

Then, in a while (1) loop, I keep sending CMD1 command:

 
    while (1)
    {
        SPI(0x41);    // CMD1
        SPI(0x00);   
        SPI(0x00);
        SPI(0x00);
        SPI(0x00);
        SPI(0xFF);    // checksum is no longer required but we always send 0xFF

        SPI(0xFF);
        i = SPI(0xFF);
    }


But the card always respond 0x01, which mean that the card is still in Idle State (it never goes to 0x00). Since I have a SD card, i've tried the ACMD41 to wake up the card:

 
    while (1)
    {
        SPI(0xFF);
        SPI(0x77);    // CMD55
        SPI(0x00);   
        SPI(0x00);
        SPI(0x00);
        SPI(0x00);
        SPI(0xFF);    // checksum is no longer required but we always send 0xFF

        SPI(0xFF);
        i1 = SPI(0xFF);


        SPI(0xFF);
        SPI(0x69);    // CMD41
        SPI(0x00);   
        SPI(0x00);
        SPI(0x00);
        SPI(0x00);
        SPI(0xFF);    // checksum is no longer required but we always send 0xFF

        SPI(0xFF);
        i2 = SPI(0xFF);

    }


The card always respond 0x01 to CMD55 and CMD41... Wich mean the card is still idle, even after several seconds...

I've tried a CMD58 (before the ACMD41 and CMD1 while loop) to get the OCR register:

 
        SPI(0xFF);
        SPI(0x7A);    // CMD58
        SPI(0x00);   
        SPI(0x00);
        SPI(0x00);
        SPI(0x00);
        SPI(0xFF);    // checksum is no longer required but we always send 0xFF

        SPI(0xFF);
        a1 = SPI(0xFF);
        a2 = SPI(0xFF);
        a3 = SPI(0xFF);
        a4 = SPI(0xFF);
        a5 = SPI(0xFF);


Here is the result:
a1 = 0x01 (R1 = 1: Idle state)
a2 = 0x00 OCR MSB
a3 = 0xFF
a4 = 0x80
a5 = 0x00 OCR LSB

From Simplified_Physical_Layer_Spec.pdf (the SD datasheet), the bit 31 [Card power up status bit (busy)] is low, wich mean that the card has not finished the power up routine. (It stay low, even after a long delay).


Why the card never respond 0x00 to my CMD1 and ACMD41 command? The card works fine with a PC... I have no other SD card to test, maibe my card is broken? Is my code OK? Is my hardware OK?

Thanks


#1

22 Replies Related Threads

    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/16 09:35:06 (permalink)
    0
    I forgot to mention that CS is high when I send the first 80 pulses...
    #2
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/16 10:30:23 (permalink)
    0
    Take a look at this thread:
    http://www.microchip.com/forums/tm.aspx?m=434180&mpage=1&key=&#434180
     
    I think you need to de-assert CS# after the initialisation. For each CMD41 you'll need to assert CS#, send the command and check for response, then de-assert CS#. Loop until successful.
     
    Here's a timing diagram you may find useful:
    http://mfb.nopdesign.sk/datasheet/cat_d/MMC/spitiming.pdf
     
    When you send CMD1 it seems you send a single dummy byte (i.e. 8 clocks), then look for idle state. However, the timing diagram above suggests you could need to continually poll for some multiple of 8 clocks before you eventually get the 0x00 you're looking for. Also since you're not de-asserting CS# and re-asserting between CMD1 tries it doesn't recognize the start of the command.
     
    Mark.
    #3
    herambmp
    Senior Member
    • Total Posts : 147
    • Reward points : 0
    • Joined: 2006/10/30 21:05:36
    • Location: India(Bharat/Hindustan)
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/18 08:12:21 (permalink)
    0
    The above mentioned is absolutely true. I have initialised my uSD card, with the same procedure. Once CRC is sent, start polling for Idle state. After some dummy bytes(0xFF), you will get expected response as 0x00.
     
    For more details of the code, goto www.silabs.com. I hope Microchip won't mind this. :-) :-)
     
     



    Regards,
    Heramb Phadke
    #4
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/19 12:27:16 (permalink)
    0
    Hi guys!

    Thanks you for the reply, sorry for the delay, I wasn't at the office this week-end. The spi diagram is very useful, thank you very much markp!

    I've rewritten my CMD1 routine as follow:

        for (i = 0; i < 100; i++)
        {
            PORTAbits.RA6 = 0;    // Assert CS#

            SPI(0x41);    // CMD1
            SPI(0x00);   
            SPI(0x00);
            SPI(0x00);
            SPI(0x00);
            SPI(0xFF);

            // trying the next 128 bytes to catch the answer
            for (j = 0; j < 128; j++)
            {
                // waiting for 00h from mmc
                a1 = SPI(0xFF);
                if (a1 == 0x00)
                {
                    // card init OK, finaly!
                    PORTAbits.RA6 = 1;    // Deassert CS#
                    SPI(0xFF);                
                    PutS_USART("SD card ready!....\n");
                    break;
                }
                else if (a1 == 0x01)
                {
                    // the SD card answered 0x01, still IDLE.... try again!
                    j = 255;
                }
                else
                {
                    // no answer yet....
                }
            }

            PORTAbits.RA6 = 1;    // Deassert CS#
            SPI(0xFF);

            // send a message over RS232 (it add a delay before sending another CDM1)...
            PutS_USART("trying CMD1....\n");

        }

    And I deassert CS# after CMD0, before sending CMD1.

    On the scope, the SD card always respond 0x01 at the second byte after the CRC.....

    I've not tried ACMD41 yet, I'll let you know when I will have more result...


    On the scope, the bit from the byte 0x01 from the SD card are aligned like this:




    I really don't know whats is wrong with my design, I'll buy another SD card and test if my card is broken (it is still working with USB card reader...)

    Is there any special things to know when using SDHC (I'm using a 128Mb SD right now)? Is any possibilities that CMD1 don't work with EVERY SD card?

    Thank you so much!
    #5
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/19 13:10:44 (permalink)
    0
    Well by setting j=255 in the test for a1==0x01 you're breaking out of the for loop immediately. If the card actually takes a few more 8-clock cycles before it comes out of idle you'll miss it. Try removing the j=255 statement completely.
     
    Mark.
    #6
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/19 13:37:29 (permalink)
    0
    Hi markp,

    Thank you for the fast reply!

    you are right, but i've already tried without the block


            else if (a1 == 0x01)
               {
                   // the SD card answered 0x01, still IDLE.... try again!
                   j = 255;
               }


    Same result....

    By the way, i've tried the ACMD1 combo, and I have the same answer from the card... 0x01!

    Assert CS#:

          PORTAbits.RA6 = 0;

    I'm sending CMD55 :

          SPI(0x77);    // CMD55
          SPI(0x00);   
          SPI(0x00);
          SPI(0x00);
          SPI(0x00);
          SPI(0xFF);

    I wait for the answer:

          SPI(0xFF);   // first dummy byte
          SPI(0xFF);   // on the scope, I see that the card answer 0x01 here
          SPI(0xFF);   // on more dummy byte before sending the CMD41

    Then I send CMD41:

          SPI(0x69);    // CMD41
          SPI(0x00);
          SPI(0x00);
          SPI(0x00);
          SPI(0x00);
          SPI(0xFF);

    And I wait for the 0x00:

         // trying the next 128 bytes to catch the answer
           for (j = 0; j < 128; j++)
           {
               // waiting for 00h from mmc
               a1 = SPI(0xFF);
               if (a1 == 0x00)
               {
                   // card init OK, finaly!
                   PORTAbits.RA6 = 1;    // Deassert CS#
                   SPI(0xFF);                
                    PutS_USART("SD card ready!....\n");
                   break;
               }
               else
               {
                   // no answer yet....
               }
           }

    Deassert CS#:

          PORTAbits.RA6 = 1;

    And then loop again up to 100 times




    The card respond 0x01 the second dummy byte... and then 0xFF 128 times

    Should I wait longer? 16bits timer to wait more than 255 8clocks cycle?

    I really don't know what is going on.....


    !!!
    post edited by felix007 - 2009/10/19 13:39:37
    #7
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/19 13:57:42 (permalink)
    0
    OK, it's looking like the commands are failing. Note that the card will enter idle mode from power up as well as from CMD0, so maybe the SPI mode is wrong? What are the CKE, SPE and CKP bits set too? If the wrong edge is being used to capture data the result might be flaky, sometimes it works sometimes it doesn't.
     
    Mark.
    #8
    herambmp
    Senior Member
    • Total Posts : 147
    • Reward points : 0
    • Joined: 2006/10/30 21:05:36
    • Location: India(Bharat/Hindustan)
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/20 04:54:24 (permalink)
    0
    For any type of response, you need not have to check only for 0x00 and 0x01. After CRC byte is sent, start getting the response. When bit 7 of the response becomes 0, you have to stop there. This response gives many error flags. All should be zero.
    For CMD1, get the response as indicated above. If still in idle state(and other flags are zero), resend the same command. Do this till you get 0x00 as a response.
    P.S = Before sending a command, make CS = 1, and send atleast 80 clocks. After this make CS = 0, and send the command.



    Regards,
    Heramb Phadke
    #9
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/20 06:13:20 (permalink)
    0
    Hi markp,

    I've already investigated this, and I think my SPI hardware is well initialized. Here is my SPI init code. I'm using the SPI2 in the PIC18F26J50 (I can't use SPI1 because the pins are hardmapped with USART1.....). The only thing I do before this is to initialize USART1 (without interrupt). I know that I should embed ASM code to initialize the PPS (as stated in the datasheet), but C code with interrupt disabled seems to work....

    void init_MMC(void)
    {

        TRISAbits.TRISA6 = 0;        // CS output
        PORTAbits.RA6 = 1;            // Deassert CS#
        PutS_USART("MMC Init\n");

        ANCON1bits.PCFG11 = 1;     // AN11 configured as a digital port

        TRISCbits.TRISC0 = 0;    // SDO output
        TRISCbits.TRISC1 = 1;    // SDI input
        TRISCbits.TRISC2 = 0;    // SCK output

        // Peripheral Pin Select (PPS) configuration for SPI2
        INTCONbits.GIE = 0;
        EECON2 = 0x55;
        EECON2 = 0xAA;
        PPSCON = 0;

        RPOR11 = 9;            // RP11 = SDO2
        RPOR13 = 10;        // RP13 = SCK2
        RPINR21 = 12;        // RP12 = SDI2
        RPINR22 = 13;        // CLKOUT also an input (see datasheet note)

        INTCONbits.GIE = 1;
        EECON2 = 0x55;
        EECON2 = 0xAA;
        PPSCON = 1;

        SSP2STATbits.SMP = 0;        // input is valid in the middle of clock
        SSP2STATbits.CKE = 0;        // rising edge is data capture
        SSP2CON1bits.CKP = 1;        // high value is passive state
        SSP2CON1bits.SSPM3 = 0;        // speed f/64(312kHz), Master
        SSP2CON1bits.SSPM2 = 0;
        SSP2CON1bits.SSPM1 = 1;
        SSP2CON1bits.SSPM0 = 0;
        SSP2CON1bits.SSPEN = 1;        // enable SPI
       
        // start MMC in SPI mode
        for(i=0; i < 10; i++)
        {   
            SPI(0xFF);        // send 10*8=80 clock pulses
        }


         (....)
    }


    And then I reassert CS, send CMD0, ....


    So the SD card will enter idle mode right from power up? The card will respond 0x01 after CMD1 even if I don't send CMD0 before? Even if I don't send 80 pulses?


    My hardware is pretty simple: I've soldered a jumper on my SD card, so I can plug it in my breadboard. Here is pinout of my SD card with the PIC:

    1) CS# (10k pull-up to Vdd) -> pin10 (RA6)
    2) DI (10k pull-up to Vdd) -> pin11 (SDO)
    3) Vss Ground
    4) Vdd (supply voltage, 3.3V, same LDO as the PIC, well decoupled)
    5) CLK (10k pull-up to Vdd) -> pin13 (SCK)
    6) Vss2
    7) DO (10k pull-up to Vdd) -> pin12 (SDI)




    Why the commands are failing?

    Very strange....

    herambmp: What do you mean by the bit 7 of the response? The card always respond 7 low bits and 1 high bit... By the way, I've tried what you told me to send 80 pulses with CS# deasserted (high level) between each command (CMD0 - 80pulses - CMD1 - 80pulses - CMD1 - 80 pulses - CMD1 - .....) and its not working (0x01 reponse...)......

    I'Ve not tried another card yet, i'll do it today!

    Thanks

    #10
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/20 06:14:20 (permalink)
    0
    By the way, my PIC is running at 24MHz (internal osc)
    #11
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/20 14:12:59 (permalink)
    0
    OK, i've tried with a 4gb SDHC sd card from Lexar, and the card respond to my CMD8:

          SPI(0x48);    // CMD8
          SPI(0x00);    //
          SPI(0x00);
          SPI(0x01);    // HVS
          SPI(0xAA);    // test pattern
          SPI(0x87);    // right checksum for CMD8

    The give me a R1 response : 0x01
    followed by the 4 argument bytes (echoed back) : 0x00 0x00 0x01 0xAA
    This is OK according to the Secure Digital datasheet.

    When I try with my other card (the first one, 128Mb SD card, not SDHC), I have a R1 response of 0x05 (0b00000101), meaning that its an illegal command. This is normal since it is not a SDHC card, and does not recognize the CMD8 cmd.

    With my Lexar 4Gb SDHC card, when I send CMD8 with the wrong CRC (for example, 0x88), the card respond with a R1 response of 0x09 (0b00001001), meaning that there is a communication CRC error. This is normal...

    This show me that the card is OK, and the commands seem to be interpreted by the card...

    The ACMD1 command is still responding 0x01 !!!!!!

    Vdd of 3.3V is fine for a SD card?

    Thanks guys!
    post edited by felix007 - 2009/10/20 15:44:48
    #12
    herambmp
    Senior Member
    • Total Posts : 147
    • Reward points : 0
    • Joined: 2006/10/30 21:05:36
    • Location: India(Bharat/Hindustan)
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/20 21:56:19 (permalink)
    0
    Do one thing. Read OCR of the card. With this, you can get the working voltage level of the card(current voltage level seems to be ok, but check it again). When I interfaced uSD card, I configured my SPI module in mode-0(idle level of the clock in logic 0, data is sapled at the rising edge).
    Every command has a response of atleast 1 byte. For CMD1, there is R1 response of 1 byte(D7-D0). When you start getting for the response, you will have to check bit D7 of the response. For a proper response(doesn't mean successful completion of the command), bit D7 has to be logic 0. On this response, you have to decide what is to be doen next.
     
    While debugging, constantly monitor your voltage level. Because, during command decoding, card might draw significant amount of current, thus reducing the voltage level from 3.3V.
     
    My experience is, even if the voltage level less than 3.3V, card can respond to CMD0, but further commands are not executed. More or less, this is the same condition with you.



    Regards,
    Heramb Phadke
    #13
    felix007
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2009/09/15 10:17:16
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/21 07:18:00 (permalink)
    +2 (1)
    Hey guys.... IT WORKED!

    You have to READ the whole SD Datasheet in order to be able to init a SDHC card....


    For your information, the problem was my ACMD41 argument, I have to set the HCS bit in order to tell the card that the host support High Capacity cards...

    In my ACMD41 loop:

       for (test = 0; test < 100; test++)
       {
           PORTAbits.RA6 = 0;    // Assert CS#

           SPI(0xFF);
           SPI(0x77);    // CMD55
           SPI(0x00);   
           SPI(0x00);
           SPI(0x00);
           SPI(0x00);
           SPI(0xFF);

           a1 = SPI(0xFF);
           a2 = SPI(0xFF);

           PORTAbits.RA6 = 1;    // DeAssert CS#
           SPI(0xFF);
           PORTAbits.RA6 = 0;    // Assert CS#

           SPI(0xFF);
           SPI(0x69);    // CMD41
           SPI(0x40);    // HCS=1
           SPI(0x00);
           SPI(0x00);
           SPI(0x00);
           SPI(0xFF);

           for (j = 0; j < 150; j++)
           {
               // waiting for 00h from card
               a1 = SPI(0xFF);
               if (a1 == 0x00)
               {
                   // card init OK
                   PORTAbits.RA6 = 1;    // DeAssert CS#
                   SPI(0xFF);
                   PutC_USART("card init OK");
                   return;
               }
               else
               {
                   //wait
               }
           }

           PORTAbits.RA6 = 1;    // DeAssert CS#
       }


    And by the way, it is MANDATORY to issue CMD8 before ACMD1 in order to init the card.

    Thanks you guys, your help was very appreciated!

    Regards,

    Felix Gourdeau
    post edited by felix007 - 2009/10/21 07:25:29
    #14
    markp
    Super Member
    • Total Posts : 397
    • Reward points : 0
    • Joined: 2006/01/26 13:54:56
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/21 14:37:32 (permalink)
    0
    Excellent, glad you got it going. Very useful info too.
     
    Mark.
    #15
    herambmp
    Senior Member
    • Total Posts : 147
    • Reward points : 0
    • Joined: 2006/10/30 21:05:36
    • Location: India(Bharat/Hindustan)
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/21 21:44:58 (permalink)
    0
    Congrats !!! Keep going....



    Regards,
    Heramb Phadke
    #16
    XsavioR
    Super Member
    • Total Posts : 338
    • Reward points : 0
    • Joined: 2008/07/21 16:56:38
    • Location: Chicago
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/30 11:14:44 (permalink)
    0
    Any chance you can post a schematic of the spi - SD interface.  Im also working on getting an sd card working. The only schematics Ive found online are for other manufacturers or in the case of the 18f starter have multiple devices on the bus complicating the schematic. This is my first effort with spi.

    My project:
    USB msd sd card reader - 18f26j50

    Its enumerating but it is obvious to me my hardware is not right looking at yours.
    #17
    asmallri
    Super Member
    • Total Posts : 1864
    • Reward points : 0
    • Joined: 2004/05/26 09:00:05
    • Location: Perth, Australia
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/30 18:33:29 (permalink)
    0
    check out the projects page on my web site for some sample (working) schematics for integrating SD/MMC cards with 5 volt and 3.3 volt PICs

    Regards, Andrew

    http://www.brushelectronics.com/index.php?page=software
    Home of Ethernet, SD Card, and Encrypted Serial and USB Bootloaders for PICs!!
    #18
    XsavioR
    Super Member
    • Total Posts : 338
    • Reward points : 0
    • Joined: 2008/07/21 16:56:38
    • Location: Chicago
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/10/30 19:14:36 (permalink)
    0
    ty , will do . 
    #19
    jezell
    Starting Member
    • Total Posts : 32
    • Reward points : 0
    • Joined: 2008/08/15 11:49:20
    • Location: 0
    • Status: offline
    RE: SD Card SPI Init Problem (ACMD41 & CMD1 always return 0x01) 2009/11/05 15:55:46 (permalink)
    0
    Felix,

    Did you ever eperience the problem of the SD card pulling down your CLK, SDO and SDI lines?  I just started this same type of project and whenever I connect the SD card in the circuit it pulls all my lines down to to around .2-.5V  I have 10K pull up resistors on SDI and SDO and everything is connected correctly.  Any suggestions?
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5