SD card interface

I am trying to use an SD card for additional memory. I have some code, but of course it doesn't work. Is someone else working on this? I got inspired by several sites:
http://www.zeveland.net/wiki/index.php?title=Computers_for_the_Rest_of_You_-_Personal_Entropy_Monitor
most of the code I got here:

Some background info about mmc:
http://elm-chan.org/docs/mmc/mmc_e.html
But, I have seen to much info at the moment. I will have to pause for a bit. My code:

// modified code for arduino, original code @: http://www.captain.at/electronic-atmega-mmc.php
#define DATAOUT 11    //SD pin 2 
#define DATAIN 12     //SD pin 7
#define SPICLOCK 13   //SD pin 5
#define CHIPSELECT 10 //SD pin 1

char sector[512];
byte clr;

char spi_transfer(volatile char data)
{
  SPDR = data;    //start the transmission
  while (!(SPSR & (1<<SPIF)))     //wait for the end of the transmission
  {
  }
  return SPDR;    //return the received byte
}
char Command(char befF, long AdrH, long AdrL, char befH) 
{
  //sends a command to the SD card
  spi_transfer(0xFF);
  spi_transfer(befF);
  char highHigh = (AdrH >> 8);
  spi_transfer(highHigh);
  spi_transfer(AdrH);
  char highLow = (AdrL >> 8);
  spi_transfer(highLow);
  spi_transfer(AdrL);
  spi_transfer(befH);
  spi_transfer(0xFF);
  return spi_transfer(0xFF);
}
char MMC_init() 
{
  char i,c=0xAA;
  digitalWrite(CHIPSELECT, HIGH);  //disable the SD card
  for (i=0; i<10; i++) //send 10*8=80 clock pulses
  {
    spi_transfer(0xFF);
  }
  digitalWrite(CHIPSELECT, LOW);  //enable the SD card
  //send CMD0 to put card in SPI mode
  Command(0x00, 0 , 0, 0x95);
  delay(2); 
  //c = (Command(0x40, 0,0,0x95));
  while (c != 0x01)
  {
    Serial.print(c, HEX);
    Serial.print(" ");
    c =(Command(0x40, 0,0,0x95));
  }
  return c;
}
void setup() 
{
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(CHIPSELECT, OUTPUT);
  digitalWrite(CHIPSELECT, LOW);  
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  Serial.begin(9600);
  Serial.println("starting up");
}
void fillram()
{
  int i,c;
  char mystring[18] = "bigengineer@work ";
  c = 0;
  for (i=0;i<=512;i++)
  {
    sector[i] = mystring[c];
    c++;
    if (c>17) c = 0;
  }
  //Serial.println(mystring);
}
int writeramtommc(void)
{
  int i;
  char c;
  if (Command(0x58, 0, 512, 0xFF) != 0)
  {
    Serial.println("MMC write error 1");
    return 1;
  }
  spi_transfer(0xFF);
  spi_transfer(0xFF);
  spi_transfer(0xFE);
  for (i=0;i<512;i++) spi_transfer(sector[i]);
  spi_transfer(0xFF); //2 dummy bytes
  spi_transfer(0xFF);
  c = spi_transfer(0xFF);
  c &= 0x1F;
  if (c != 0x05)
  {
    Serial.print("MMC write error c: ");
    Serial.println(c, HEX);
    return 1;
  }
  //wait until MMC is not busy anymore
  while(spi_transfer(0xFF) != (0xFF));
  return 0;
}
char readmmc()
{
  int i;

  if (Command(0x51, 0, 512, 0xFF))
  {
    Serial.println("MMC read error 1");
    return 1;
  }

  //wait for 0xFE
  while(spi_transfer(0xFF) != (0xFE));
  for (i = 0;i<512;i++) Serial.print(spi_transfer(0xFF));
  spi_transfer(0xFF); //2 dummy bytes
  spi_transfer(0xFF);
  Serial.println("end of read");
  return 0;
}

void loop() 
{
  char c;
  fillram();
  c = MMC_init();
  Serial.print("MMC OK c: ");
  Serial.println(c, HEX);

  writeramtommc();
  readmmc();
  delay(2000);
}

If I recall well, you did the SPI modification to your Arduino, right?

Groeten,

JD

Howdy,

A schematic diagram and a specific description of what actually happens (like the R1 response from the CMD0) would help others help you. Still, with out that, here are some things I would run through:

  1. Make sure you power your SD at or around 3.3V. Voltage dividers, voltage reg, or just plain powering the Arduino at 3.somethingV should do.
  2. Connect your clock to the the SPI clock pin on the ICSP pins of the Arduino instead of pin 13.
  3. Change your code to do the initialization (CMD0, CMD1) at 100-400 khz (see SanDisk Document No. 80-13-00169 ). SPR1=1, SPR0=0, SPI2X=0 will put your Arduino at 250 khz.
  4. Your MMC_Init function is going to put the card into SPI mode but leave it idle. You will need to send CMD1 until the idle bit in the R1 response is cleared. The Captain had that in the original code. I assume it is omitted here by mistake.

This document can be somewhat helpful.
http://www.sdcard.org/sd_memorycard/Simplified%20Physical%20Layer%20Specification.PDF

Joseph C Moreland

@ JDS, yes, i have modified this board.

Connecting to the ICSP clock is an interesting idea. I had an SPI acceleration sensor working on this modified NG board. So I assume the SPI interface and pin13 are ok. But I will try the ICSP connection.
Since posting my code I added the CMD1. It didn't help though.
i will have a look at the pdf. I have seen so much documentation that I don't know what to read anymore.

Hello,

Executing the above code i get

starting up                                          
FFFFFFAA 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFFFFFFF 0 0 0 0 0 FFF1
MMC write error c: 1F

(That was without any MMC/SD Card)

now, i plug microSD card to the arduino and ...

starting up                                          
FFFFFFAA 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

This time Arduino sends continously '0' thru serial port