Pages: [1]   Go Down
Author Topic: SD & SDHC Card Initilazation problem  (Read 830 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have written a code for the init. of SD & SDHC card. The code is pretty much copied from the SD Library of Arduino. I am checking the code on Arduino but my target board is different. So, Can't use SD Library itself.

I have almost everything same but it didn't work with standard SD (256 MB). However it works with SDHC (8GB), it shows the following output:
Output of SDHC ( 8 GB):

Setup Done!
Card Init Called
SD Card in Idle State
IDLE State Achieved! Moving On
CMD8 Successful _ Moving On    SD Card Type 2
Arg = 40000000
ACMD41 Successful _ Moving On
Card Init. successful so far
Card Type = 2     SDHC

Output of SD Standard (256 MB):

Setup Done!
Card Init Called
SD Card in Idle State
IDLE State Achieved! Moving On
CMD8 Successful _ Moving On    SD Card Type 1
Arg = 0
SD Card Time Out: ACMD41 CMD
Response = 5
Card Init. Failed



And here is the code:
Code:
// Processor Clock = 16 MHz
#define NOP __asm__ __volatile__ ("nop\n\t")

#include <SPI.h>

// Comment out following 4 lines for Real SPI or vice versa
/*
const int CS = 3;
const int MSI = 4;
const int MSO = 5;
const int SLK = 6;
*/
unsigned int SDTimeOut = 100;
volatile boolean SDCardType1 = false;
volatile boolean SDCardType2 = false;
volatile boolean SDCardSDHC = false;

// Comment the following two lines for Fake SPI or vice versa
volatile int CS  = SS;
volatile int MSI = MOSI;
 
void setup (void)
{
  // Uncomment following 4 lines for Fake SPI
  /*pinMode(CS,OUTPUT);
  pinMode(MSI,OUTPUT);     // MOSI
  pinMode(MSO,INPUT);      // MISO
  pinMode(SLK, OUTPUT);    */
  pinMode(13,OUTPUT);      // LED
 
  Serial.begin(9600);
  pinMode(CS, OUTPUT);

  SPI.begin (); // Default: Master, MSB Ist, Low to High Transition
  Serial.println("Setup Done! Bit Bang SPI");
  // Default SPI Clock: 4 MHz
  // SPI.setClockDivider(SPI_CLOCK_DIV8);
}

void loop (void)
{
  boolean Status;
  Status = CardInit();
  if (Status)
       {
       Serial.println("Card Init. successful so far");
       if (SDCardType1) Serial.print("Card Type = 1");
       if (SDCardType2) Serial.print("Card Type = 2");
       if (SDCardSDHC) Serial.println("     SDHC");
       }
  else
       Serial.println("Card Init. Failed");
       
 
  while(1);      // Stay Here
}
// Real SPI Send
void SP_Send(byte data)
{
  SPI.transfer(data);
}

// Fake SPI Send
/*
void SP_Send(byte data)
{
   byte mask = 0x80;
   
   digitalWrite(13,!digitalRead(13));
   for (int i=0; i < 8; i++)
     {
       digitalWrite(SLK,LOW);
       NOP;
       //delay(10);
       
       if (data & mask)
           digitalWrite(MSI,HIGH);
       else
           digitalWrite(MSI,LOW);
     
       NOP;NOP;NOP;NOP;
     
       digitalWrite(SLK,HIGH);
       
       NOP;
       //delay(10);
       
       mask = mask >> 1;
     }
}*/

// Real SPI Read
byte SP_Read(void)
{
  SPI.transfer(0xff);
  return SPDR;
}

// Fake SPI Read
/*
byte SP_Read(void)
{
  byte response = 0;
 
  for (int i=0;i<8;i++)
    {
     response <<= 1; 
     digitalWrite(SLK,LOW);    // set Clock bit
     delay(10);  // SPI Delay/2
   
     if (digitalRead(MSO))  // Scan the input pin
        response |= 1;
   
     delay(10);  // SPI Delay/2
     digitalWrite(SLK,HIGH);// clear the Clock bit
    }
  return response;
}
*/
byte CardCommand(byte cmd, unsigned long arg)
  {
    byte response, retry =0;
   
    digitalWrite(CS,LOW);                  // Card Select Low
   
    SP_Send(cmd | 0x40);              // Send command 1 byte _ first two bits must be (01)
   
    for (int i=24; i>=0; i-=8)  SP_Send(arg >> i);    // Send Command Argument; 4 btyes
   
    // Send CRC _ 1 Byte _ CRC is ignored in all other commands except CMD0 & CMD 8
    // Last bit of CRC is always 1 _ the Stop Bit
    byte crc = 0xFF;
    if (cmd == 0x00) crc = 0x95;    // crc for (CMD0 = 0x00)
    if (cmd == 0x08) crc = 0x87;    // crc for (CMD8 = 0x80)
    SP_Send(crc);
   // digitalWrite(SS,HIGH);
   
    // Wait a little for the SD Card Response
    while ((response = SP_Read()) == 0xff)
        {
          if (retry ++ > 0xfe) break;
        }
   
  //  digitalWrite (CS,HIGH);
    return response;
  }
   
boolean CardInit()
{
  byte InitStatus, retry = 0;
  unsigned long arg;
 
  Serial.println("Card Init Called");
  // Must supply atleast 74 pulses, with CS pin High
  digitalWrite(CS,HIGH);
  digitalWrite(MSI,HIGH);
  for (int i=0;i<10;i++)  SP_Send(0xFF);
 
  // Pull CS pin LOW (Active_Low) to enter the SPI_Mode
  digitalWrite(CS,LOW);
 
  // SD Card must reboot for SPI to start working
  // Send IDLE Command (cmd = 0x00, arg = 0x00 , crc = 0x95) to reset the SD Card.
  do
   {
    InitStatus = CardCommand(0x00,0);
    if (retry++ > SDTimeOut)
       {
        Serial.println("SD Card not Initialized _ Time OUT!");
        break;
       }
   }while(InitStatus != 0x01);      // IDLE State Acknowlegement _ R1 response Token for IDLE state command with LSB bit (Idle State) set.
 
   if (InitStatus == 0x01) 
      {
      Serial.println("SD Card in Idle State");
     // return true;
      }
   else
      {
       Serial.println("SD card idle state Error");
       Serial.print(InitStatus);
       return false;
      }
  Serial. println("IDLE State Achieved! Moving On");
  InitStatus = 0; retry = 0;
 
  // Check SD Card Type

    if(CardCommand(0x08,0x1AA) & 0x04)        // CMD8 = 0x08
    {
      SDCardType1 = true;
   //   return true;
    }
  else 
    {
      for (int i=0;i < 4; i++) InitStatus = SP_Read();      // Only needs last byte of r7 response
       if (InitStatus != 0xAA)
         {
         Serial.println("SD Card Error: CMD8 Failed ");
         Serial.print("Response =  ");
         Serial.println(InitStatus);
         return false;
          }
      SDCardType2 = true;
    }
   
  Serial.print("CMD8 Successful _ Moving On    ");
  if (SDCardType1){Serial.println("SD Card Type 1");}
  if (SDCardType2){Serial.println("SD Card Type 2");}
 
  arg = SDCardType2 ? 0x40000000 : 0;
  Serial.print("Arg = ");
  Serial.println(arg,HEX);
  InitStatus = 1; retry = 0;
  do
    {
      InitStatus = CardCommand(0x37,0);        // CMD55 = 0x37 must be sent before any ACMD command
      //if (InitStatus & 0x04) {Serial.println("Illegal Command CMD55");}
      InitStatus = CardCommand(0x29,arg);      // ACMD41 = 0x29
      if (retry++ > 0xfe)
          {
           Serial.println("SD Card Time Out: ACMD41 CMD ");
           Serial.print("Response = ");
           Serial.println(InitStatus);
           
           return false;
          }
    }while((InitStatus != 0x00) /*|| (InitStatus & 0x04)==1*/);
  if (InitStatus == 0x00) Serial.println("ACMD41 Successful _ Moving On");
  /*
   retry = 0;
   if (InitStatus & 0x04)
     {
       Serial.println("MMC Card detected");
       do
         {
          InitStatus = CardCommand(1,0);
          Serial.println("Sending CMD1");
          if (retry++ > 0xFE)
              {
                Serial.println("SD1 Card TimeOut");
                return false;
              }
         }while(InitStatus != 0x00);
       if (InitStatus == 0x00)
         {
           Serial.println("SD1 Card Initialized!");}
         else Serial.println("SD1 Card Init Failed");
     }
   */
  InitStatus = 0; retry = 0;
   
   if (SDCardType2)
     {
       if (CardCommand(0x3A,0))        // CMD58
         {
           Serial.println("SD Card Error: CMD58");
           return false;
         }
       if ((InitStatus = SP_Read() & 0xC0) == 0xC0) SDCardSDHC = true;
       for (int i = 0;i < 3; i++) SP_Read();
     }
   
  digitalWrite(CS,HIGH);
  return true;   
}
     
Logged

Pages: [1]   Go Up
Jump to: