Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How should I Write data in a SD memory and read it through SPI ?

Status
Not open for further replies.

mf1364

Full Member level 3
Joined
Dec 4, 2007
Messages
185
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,298
Activity points
2,700
Hi every body
Does any body have any information about writing and reading from a SD memory (8Giga byte with 8 pin ) through SPI protocol ? any PDF and information is so appreciated
thx
 

I found this datasheetwww.sandisk.com/Assets/File/OEM/Manuals/SD_SDIO_specsv1.pdf in the net there are a list of commands (cmd0 ... cmdn)for for communicating with the memory but lam a lil confusing and I didn't get that should I send these CMDs commands to the memory through SPI ? and my second question is that are same the commands for both SD and MMC cards ?
 

any body don't help me ? I need a example for writing a number in SD memory and reading it and please answer my above questions
 

You'll find a huge amount of ready to use examples and libraries for SD/MMC handling on the internet, dedicated to various processors and compiler tools.

I need a example for writing a number in SD memory and reading it and please answer my above questions.
...
I didn't get that should I send these CMDs commands to the memory through SPI.
In other words you dont understand how the protocol basically works...

I see two options:
- start with a known working SD code
- study the protocol specification thoroughly and start to implement the code from the scratch. I can assure you, that the posted specification contains all necessary information.
 
  • Like
Reactions: mf1364

    mf1364

    Points: 2
    Helpful Answer Positive Rating
You'll find a huge amount of ready to use examples and libraries for SD/MMC handling on the internet, dedicated to various processors and compiler tools.


In other words you dont understand how the protocol basically works...

I see two options:
- start with a known working SD code
- study the protocol specification thoroughly and start to implement the code from the scratch. I can assure you, that the posted specification contains all necessary information.
thx FvM
at first I should say I don't want to use functions in the compilers for using SD , and I want to read and write in the SD directly according the SD datasheets I should send a 48 bits command to the SD memory includes : start bit, host, command, argument, CRC, end bit. for running this project at first I want to write a number(ex:110) in the SD and read from it again. so, for this action I should use CMD24 command but in the above 48 bits I don't know how should I work with CRC bits, I mean I don't know for part CRC what should I send ? in other words, other parts of this 48 bits commands are clear except the CRC part !!! could you please explain completely, or write for me two commands one of them for writing 110 in the SD memory and the other one for reading it just as example ? I am so confused please help me if you can
 

CRC field in command uses a CRC7, the algorithm is documented in the specification. Please notice the comment on SPI mode.

The default command structure/protocol for SPI mode is that CRC checking is disabled. Since the card powers up in SD Bus mode, CMD0 must be followed by a valid CRC byte (even though the command is sent using the SPI structure). Once in SPI mode, CRCs are disabled by default.

CMD0 is a static command and always generates the same 7-bit CRC of 4Ah. Adding the “1,” end bit (bit 0) to the CRC creates a CRC byte of 95h. The following hexadecimal sequence can be used to send CMD0 in all situations for SPI mode, since the CRC byte (although required) is ignored once in SPI mode. The entire CMD0 sequence appears as 40 00 00 00 00 95 (hexadecimal).

Unless you want to use the SD card as raw storage medium, you need to decode the boot sector and file system information and read and write data in files.

A minimal test program must at least perform the above said CMD0 before other operations. As far as I know, a CMD8 is used next in newer SD card drivers to detect SDHC cards. CMD8 uses a (precomputed) CRC as well.

I don't have a simple example for this. I can only repeat my suggestion to refer to an existing SD card driver for your processor/compiler.
 
  • Like
Reactions: mf1364

    mf1364

    Points: 2
    Helpful Answer Positive Rating
CRC field in command uses a CRC7, the algorithm is documented in the specification. Please notice the comment on SPI mode.



Unless you want to use the SD card as raw storage medium, you need to decode the boot sector and file system information and read and write data in files.

A minimal test program must at least perform the above said CMD0 before other operations. As far as I know, a CMD8 is used next in newer SD card drivers to detect SDHC cards. CMD8 uses a (precomputed) CRC as well.

I don't have a simple example for this. I can only repeat my suggestion to refer to an existing SD card driver for your processor/compiler.

I set the CMD0 according your suggestion, that was good I didn't notice to CMD0 before, and now my new problem is that the minimum size of each block is 512 byte according the datasheet, so for writing "110" in the SD I should send "110" to the SD 512 times ? or it's possible to decreasing the amount of each block to 1 byte? because for writing "110" just one byte is enough . thx for your suggestion about using the existing SD card driver but as I said before, I should run the SD card directly . meanwhile about cmd8 that you said , I checked the datasheet but , the CMD8 is reserved in SPI mode!!!!
 

I am so confusing, after 3 days no luck! one of my friend suggested me to provide code vision AVR book , because he said there is an example in chapter 19 part 7 of this book, related to SD/MMC without using the functions of compiler , so I want to ask if some body has this book could you please put this codes here ? because that is my last solution. please hurry up . thx
 

Let me refer to your previous post before. It clarifies, that you have little knowledge of SD card operation yet. Access to the memory array is in fact in blocks or "sectors" of 512 bytes, you need to write a full block for a successful operation.

Regarding the AVR book, it's one of many available resources. You still didn't mention your processor and involved compiler tool, so nobody feels invited to suggest a specific source of information.
 

Let me refer to your previous post before. It clarifies, that you have little knowledge of SD card operation yet. Access to the memory array is in fact in blocks or "sectors" of 512 bytes, you need to write a full block for a successful operation.

Regarding the AVR book, it's one of many available resources. You still didn't mention your processor and involved compiler tool, so nobody feels invited to suggest a specific source of information.
I am using PIC16F877 and my compiler is MikroC for PIC and according your guidance I should fill all of the 512 bytes with "110" till have a successful operation ? meanwhile recently I found new problem, and it is related to CRC , the 7 last bites of command , you know, there is a formula in the datasheet for calculating the CRC :
View attachment CRC.bmp
but I didn't get how should I calculate the G(x) . !!!?!!! do you have any Idea. by the way could you please give one of that many available resources?
 

maybe this link can help you.
I wrote this codes according a read program and expected to see on the LCD the written numbers on the SD but I just have 64 !!!! do you have any idea ?
Code:
     // */ in This program PIC18f452 has comunicated with  memory IC  25LC640
//  */ and MCU  save  a 32 numbers (a page) in the 25LC640 through SPI
// */
char* text = "mikroElektronika";
unsigned  x=0;
unsigned short take, buffer;
 char txt[6];


char write_buf[512];
char read_buf[512];

unsigned int i;
unsigned long sector;


//////////////////////////////////////////6
char mmccommand(char cmd,unsigned long argument){
char r1;
char retry=0;
//send command
spi_write(cmd | 64);
spi_write(argument>>24);
spi_write(argument>>16);
spi_write(argument>>8);
spi_write(argument);
spi_write(149);                            //crc valid only for mmc_go_idle_state
//wait for response
//if more than 8 retries, card has timeout
//return the received 0xff
while(r1==255)
if(retry++>8) break;
return r1;

}

/////////////////////////////////////////////5
char mmcwrite(unsigned long sector, char* buffer ){
char r1;
unsigned i;
portd.f1=0;
//issue command
r1=mmccommand(24,sector<<9);
if(r1 != 0)
return r1;

spi_write(255);                         // send dummy

spi_write(254);                        //send data start token
for (i=0; i<512; i++) spi_write(*buffer++);
spi_write(255);                         // write 16-bit crc (dummy values)
spi_write(255);
r1 = Spi_Read(buffer);                   // read data response token
if((r1&35) != 5)
return r1;
while(!r1)

portd.f1=1;                              //CS
return 0;                                // return succes
}

/////////////////////////////////////////4
char mmcread(unsigned long sector, char* buffer ){
char r1;
unsigned i;
portd.f1=0;
r1= mmccommand(17,sector<<9);
if (r1!=0)   return r1;
while(spi_read(buffer)!= 254)
for (i=0;i<512;i++) *buffer++ = spi_read(buffer);

spi_read(buffer);                           // read 16-bit CRC
spi_read(buffer);
portd.f1=1;
return 0;
}

/////////////////////////////////////////3
char mmcsendcommand(char cmd, unsigned long argument){
char r1;
portd.f1=0;                               //assert chip select
r1=mmccommand(cmd,argument);              //issue the command
portd.f1=1;
return r1;

}

///////////////////////////////////////////// 2
char mmcreset(){
char i;
char retry;
char r1;
retry=0;

do{
for(i=0;i<10;i++)   spi_write(255);        // send dummy byte with CS high before accessing
r1= mmcsendcommand(0,0);                   //resetting card go to spi mode
retry++;
if(retry>10)  return-1;
}while(r1 != 0x01);
retry=0;
do
{
r1= mmcsendcommand(1,0);                // initializing card for operation
retry++;
if(retry>100)return-1;
}while(r1);
r1= mmcsendcommand(59,0);              //turn off CRC checking to simplify communication

r1=mmcsendcommand(16,512);
return 0;

}


/////////////////////////////////////////////0
void main() {
  trisd.f1=0;
  portd.f1=1;
  TRISB = 0;                // PORTB is output


  Lcd_Init(&PORTB);         // Initialize LCD connected to PORTB
  Lcd_Cmd(Lcd_CLEAR);       // Clear display
  Lcd_Cmd(Lcd_CURSOR_OFF);  // Turn cursor off
  Lcd_Out(1, 1, text);      // Print text to LCD, 2nd row, 1st column


  Spi_Init_Advanced(MASTER_OSC_DIV4,DATA_SAMPLE_End,CLK_IDLE_HIGH , HIGH_2_LOW) ;

  mmcreset();
for (i=0;i<512;i++)  write_buf[i]=i;
sector=5;

mmcwrite(sector,write_buf);      // write to sector 5
delay_ms(1);
mmcread(sector,read_buf);        // read of sector 5
while(1)
{



     x=0;
     while(x<512){

    WordToStr(read_buf[x], txt);
    Lcd_Out(2, 1, txt);

    delay_ms(200);
    Lcd_Cmd(Lcd_CLEAR);
    Lcd_Out(1, 1, text);
         portd.f1=1;

}

}



}//~!
 

in the above codes in the "mmcreset()" function, I don't know what does mean "return -1"; in this line"if(retry>10) return-1;" if some body knows please help me .
 

The whole thing is you gonna write a driver for your "machine" who wants to read SD via SPI protocol.
 

I don't know what does mean "return -1
According to the code, it's a timeout. One of the reset steps doesn't work as intended. This may be a hardware or software problem. Did you notice the requirement to start the initial SD card actions with a lower SPI frequency.

Are you using mikro C? I see that mikro C has a ready-to-use SD/MMC library.

Your SPI parameters, particularly SPI_IDLE_HIGH are incorrect for SD card interface.
 

According to the code, it's a timeout. One of the reset steps doesn't work as intended. This may be a hardware or software problem. Did you notice the requirement to start the initial SD card actions with a lower SPI frequency.

Are you using mikro C? I see that mikro C has a ready-to-use SD/MMC library.

Your SPI parameters, particularly SPI_IDLE_HIGH are incorrect for SD card interface.
thanks your point for SPI was right and I changed it but still nothing meanwhile could you please have a quick look in the codes maybe find the errors. by the way , in the "mmcread ()" function what does mean ''*" in this line "char mmcread(unsigned long sector, char *buffer )" could you please explain clearly, and why it's using sector<<9 in this line r1= mmccommand(17,sector<<9); and one thing more what is the beneficial of this two line "spi_write(255); " in the "mmcwrite" function ? I mean why i should write 16-bit CRC (dummy values) ?
Code:
char* text = "mikroElektronika";
unsigned  x=0;
unsigned short take, buffer;
 char txt[6];


char  write_buf[512];
char  read_buf[512];

unsigned int i;
unsigned long sector;


//////////////////////////////////////////6
char mmccommand(char cmd,unsigned long argument){
char r1;
char retry=0;
//send command
spi_write(cmd | 64);
spi_write(argument>>24);
spi_write(argument>>16);
spi_write(argument>>8);
spi_write(argument);
spi_write(149);                            //crc valid only for mmc_go_idle_state
//wait for response
//if more than 8 retries, card has timeout
//return the received 0xff

//while(r1==255)
//if(retry++>8) break;
//return r1;

while (retry<8) {
r1=spi_read(buffer);
if (r1==255){
retry++;
if ( retry>8) break;
}
if (r1 !=255){
 retry=9;
return r1;
}

}

}

/////////////////////////////////////////////5
char mmcwrite(unsigned long sector, char *buffer ){
char r1;
unsigned i;
portd.f1=0;
//issue command
r1=mmccommand(24,sector<<9);
if(r1 != 0)
return r1;

spi_write(255);                         // send dummy

spi_write(254);                        //send data start token
for (i=0; i<512; i++)
{ spi_write(*buffer++);
}
spi_write(255);                         // write 16-bit crc (dummy values)
spi_write(255);
r1 = Spi_Read(buffer);                   // read data response token
if((r1&31) != 5)
return r1;
while(!r1) portd.f1=1;                              //CS
return 0;                                // return succes
}

/////////////////////////////////////////4
char mmcread(unsigned long sector, char *buffer ){
char r1;
unsigned i;
portd.f1=0;
r1= mmccommand(17,sector<<9);
if (r1!=0)   return r1;
while(spi_read(buffer)!= 254)
for (i=0;i<512;i++) *buffer++ = spi_read(buffer);

spi_read(buffer);                           // read 16-bit CRC
spi_read(buffer);
portd.f1=1;
return 0;
}

/////////////////////////////////////////3
char mmcsendcommand(char cmd, unsigned long argument){
char r1;
portd.f1=0;                               //assert chip select
r1=mmccommand(cmd,argument);              //issue the command
portd.f1=1;
return r1;

}

///////////////////////////////////////////// 2
char mmcreset(){
char i;
char retry;
char r1;
retry=0;

do{
for(i=0;i<10;i++)   spi_write(255);        // send dummy byte with CS high before accessing
r1= mmcsendcommand(0,0);                   //resetting card go to spi mode
retry++;
if(retry>10)  return-1;
}while(r1 != 1);
retry=0;
do
{
r1= mmcsendcommand(1,0);                // initializing card for operation
retry++;
if(retry>100)  return-1;
}while(r1);

r1= mmcsendcommand(59,0);              //turn off CRC checking to simplify communication

r1=mmcsendcommand(16,512);
return 0;

}


/////////////////////////////////////////////0
void main() {
  trisd.f1=0;
  portd.f1=1;
  TRISB = 0;                // PORTB is output


  Lcd_Init(&PORTB);         // Initialize LCD connected to PORTB
  Lcd_Cmd(Lcd_CLEAR);       // Clear display
  Lcd_Cmd(Lcd_CURSOR_OFF);  // Turn cursor off
  Lcd_Out(1, 1, text);      // Print text to LCD, 2nd row, 1st column



  Spi_Init_Advanced(MASTER_OSC_DIV16, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
  mmcreset();
for (i=0;i<512;i++) {
write_buf[i]=i;
sector=5;

mmcwrite(sector,write_buf[i]);      // write to sector 5
}
delay_ms(1);
mmcread(sector,read_buf[i]);        // read of sector 5
while(1)
{



     x=0;
     while(x<512){

    WordToStr(read_buf[x], txt);
    Lcd_Out(2, 1, txt);

    delay_ms(200);
    Lcd_Cmd(Lcd_CLEAR);
    Lcd_Out(1, 1, text);
         portd.f1=1;

}

}



}//~!
 

several days is passing and no success ! you I got decision , to simplify this project to just one command CMD0 . and if I could get right response I will expand the project step by step to the hole of the project (read and write from SD) so I wrote this codes and I want to show the "R1" response of cmd0 on the LCD but most of the time I just receive zero , do you think why ? please have a look in the following codes , by the way I am using "mikroc" as compiler
Code:
// */
char* text = "mikroElektronika";
unsigned  x=110;
unsigned short take, buffer;
 char txt[6];
char r2=1;

void Pins()
{
   trisc.f2 =1;
   portc.f2 = 0;

   trisd.f1 =0;
   portd.f1 =1;

   trisd.f0 =0;
   portd.f0 =0;
   TRISB  = 0;
}




//////////////////////////////////////////LCD
void lcd(){
     Lcd_Cmd(Lcd_CLEAR);       // Clear display
     Lcd_Cmd(Lcd_CURSOR_OFF);  // Turn cursor off
     Lcd_Out(1, 1, text);      // Print text to LCD, 2nd row, 1st column
     WordToStr( x, txt);
     Lcd_Out(2, 1, txt);
    delay_ms(300);
    Lcd_Cmd(Lcd_CLEAR);
    Lcd_Out(1, 1, text);
    }
//////////////////////////////////////////6
 mmccommand(){
char r1=0;

char retry=0;
r2=1;

 portd.f1=0;
spi_write(64);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(149);                            //crc valid only for mmc_go_idle_state

 portd.f1=1;
 delay_ms(3);
  portd.f1=0;

r1=spi_read(buffer);

x=r1;

r1=0;

portd.f1=1;
lcd();


}












/////////////////////////////////////////////0
void main() {
                  // PORTB is output

  Lcd_Init(&PORTB);         // Initialize LCD connected to PORTB
  Spi_Init_Advanced(MASTER_OSC_DIV16, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
   lcd();

 pins();

 mmccommand();

while(1){


}





}



//
dear FVM , please have look maybe you can find the problem, by the way I config SPI according the mikroc help
 

by the way I am using "mikroc" as compiler
Yes, I was able to guess this myself. But you don't have the mikro C SD/MMC library?

I got decision , to simplify this project to just one command CMD0 . and if I could get right response I will expand the project step by step to the hole of the project.
That's a good way to start a project from the scratch. I would do it the same. The point is to check the results of each step exactly. I still think, that you can probably inherit existing code from the internet. But it's also very good to understand, how the stuff is working.
 

Yes, I was able to guess this myself. But you don't have the mikro C SD/MMC library?
of curse it has but as I said I am trying to do it myself.

I still think, that you can probably inherit existing code from the internet
I tried this solution too, as you saw in my previous topic, but it didn't work !!! didn't see, any mistake in my last codes ? I think the problem refers to SPI but I don't know how should I solved it. by the way I set the SPI protocol as mikroc defaults but still nothings!!! I received these numbers as R1: 255,127,240,7 but I expected to receive 5 or at least 1
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top