felix007
New Member
- Total Posts : 29
- Reward points : 0
- Joined: 2009/09/15 10:17:16
- Location: 0
- Status: offline
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
|
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)
I forgot to mention that CS is high when I send the first 80 pulses...
|
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)
Take a look at this thread: http://www.microchip.com/forums/tm.aspx?m=434180&mpage=1&key=񪀄 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.
|
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)
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. :-) :-)
|
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)
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!
|
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)
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.
|
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)
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
|
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)
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.
|
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)
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.
|
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)
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
|
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)
By the way, my PIC is running at 24MHz (internal osc)
|
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)
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
|
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)
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.
|
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)
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
|
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)
Excellent, glad you got it going. Very useful info too. Mark.
|
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)
Congrats !!! Keep going....
|
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)
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.
|
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)
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
|
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)
|
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)
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?
|