SD card and SPI

Started by "ara...@yahoo.com [AT91SAM]" August 15, 2014
Hi everyone,
I found SD.c that works with SD card thorough SPI for LPC series. But I work with AT91SAM7x256 and I want to change the code to work with this series. I am working on USB and new to memories. This very important to me. I am so grateful for your help.

can anyone help me?


#include"lpc214x.h"
#include "PCF8833.h"

#define SD_Disable() IO0SET |= 1 << 20 //SD Chip Select Pin is P0.7
#define SD_Enable() IO0CLR |= 1 << 20
typedef unsigned char INT8U;
typedef unsigned short INT16U;
typedef unsigned int INT32U;

char CMD[]={0x40, 0x00, 0x00, 0x00, 0x00, 0x95};

INT8U SPI_RW(INT8U data)
{
SSPDR = data;
while((SSPSR & 0x01) == 0);
return(SSPDR);
}

void spi_init (void)
{

INT32U i;

/* SSEL is GPIO, output set to high. */
IODIR0 |= 1<<20;
IOSET0 = 1<<20;
/* SCK1, MISO1, MOSI1 are SSP pins. */
PINSEL1 = (PINSEL1 & ~0x000003FC) | 0x000000A8;

/* Enable SPI in Master Mode, CPOL=1, CPHA=1 (Clock low-active). */
SSPCR0 = 0x00C7;
SSPCR1 = 0x0002;
SSPCPSR = 0xFE;

/* Send SPI Command with card not selected at 400 KBit. */
for (i = 0; i < 16; i++) {
SPI_RW (0xFF);
}

/* Enable SSP auto select. */
}

INT8U Write_Command_SD(INT8U *CMD)
{
INT8U i = 0, response = 1, retry = 0;

SD_Disable();
SPI_RW(0xff);
SD_Enable();
for(i = 0; i < 0x06; i++)
{
SPI_RW(*CMD++);
}

SPI_RW(0xff);

do
{
response = SPI_RW(0xff);
retry++;
}
while((response== 0xff) && (retry < 100));
return(response);
}

INT8U SD_write_sector(INT32U Number_Sector, INT8U* Buffer)
{
INT8U response,response_1,retry;
INT16U i;
//Command 24 is a writing blocks command for SD/SD-Card.
INT8U CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
INT8U CMD_SET_BLOCKLEN[]={0x50,0x00,0x00,0x02,0x00,0xFF}; //ة趨¶ءب،؟é´َذ،
retry = 0;
do
{ //Retry 100 times to send command.
response = Write_Command_SD(CMD_SET_BLOCKLEN);
if(++retry >= 100)
return(1); //block read Error!
}
while(response != 0);

SPI_RW(0XFF);

Number_Sector <<= 9; //addr = addr * 512

CMD[1] = ((Number_Sector & 0xFF000000) >> 24 );
CMD[2] = ((Number_Sector & 0x00FF0000) >> 16 );
CMD[3] = ((Number_Sector & 0x0000FF00) >> 8 );
CMD[4] = ((Number_Sector & 0x000000FF) >> 0) ;
//Send Command CMD24 to SD/SD-Card (Write 1 Block/512 Bytes)
retry = 0;
do
{ //Retry 100 times to send command.
response = Write_Command_SD(CMD);
if(++retry >= 100)
{
return(1); //send commamd Error!
}
}
while(response != 0);

// for(i = 0; i < 20; i++)
SPI_RW(0xff);

//Send Start Byte to SD/SD-Card
SPI_RW(0xfe);

//Now send real data Bolck (512Bytes) to SD/SD-Card
for(i = 0; i < 512; i++)
SPI_RW(* Buffer++); //send 512 bytes to Card

//CRC-Byte
SPI_RW(0xFF); //Dummy CRC
SPI_RW(0xFF); //CRC Code
// retry=0;

do
{
response=SPI_RW(0xFF);//Read Response
}
while(response==0xff);

do
{
response_1=SPI_RW(0xFF);
}
while(response_1!=0xFF);
SD_Disable();
SPI_RW(0xff);
if ((response&0x1f)!=0x05) return(1);

return(0);

}

INT8U SD_Read_Block(INT8U *CMD, INT8U *Buffer, INT16U Bytes)
{
INT16U i;
INT8U retry,response;
INT16U Block_Len=0;
INT8U CMD_SET_BLOCKLEN[]={0x50,0x00,0x00,0x00,0x00,0xFF};

if(Bytes != Block_Len)
{
CMD_SET_BLOCKLEN[3] = (INT8U)((Bytes & 0x0000FF00) >> 8 );
CMD_SET_BLOCKLEN[4] = (INT8U)((Bytes & 0x000000FF) >> 0 );

retry = 0;
do
{ //Retry 100 times to send command.
response = Write_Command_SD(CMD_SET_BLOCKLEN);
if(++retry >= 100)
return(1); //block read Error!
}
while(response != 0);
Block_Len = Bytes;
}
//Send reads a block Command CMD to SD/SD-Card
retry = 0;
do
{
response = Write_Command_SD(CMD);
if(++retry >= 100)
return(1); //block read Error!
}
while(response != 0);

//Read Start Byte form SD/SD-Card (FEh/Start Byte)
// while(SPI_RW(0xff) != 0xfe) ;
retry=0;
for(i=0;i<1000;i++)
{
response=SPI_RW(0xff);
retry++;
if(response==0xfe)
i00;
if(retry=00)
return(1);
}

//Write blocks(normal 512Bytes) to SD/SD-Card
for(i = 0; i < Bytes; i++)
*Buffer++ = SPI_RW(0xff);

//CRC-Byte
SPI_RW(0xff);//CRC - Byte
SPI_RW(0xff);//CRC - Byte

SD_Disable();
return(0);
}

SD_INIT()
{
INT8U retry, response;
INT16U i;
for(i=0;i<250;i++)
__asm
{
NOP
}
for(i = 0; i < 0x0f; i++)
{
SPI_RW(0xff);
}
//Send Command CMD0 to SD/SD Card
retry = 0;
do
{ //retry 200 times to send CMD0 command

response = Write_Command_SD(CMD); //CMD0 دىس¦خھ01
retry++;
}
while((response != 1) && (retry < 200));

retry=0;
do
{
CMD[0]=0x77;
CMD[5]=0x55;
Write_Command_SD(CMD); //CMD55 دىس¦خھ01
CMD[0]=0X69;
response=Write_Command_SD(CMD); //ACMD41 دىس¦خھ00
retry++;
}
while((response!=0)&&(retry<200)) ;
// return(response);
}

void SD_WRITE(INT8U* Buffer,INT32U Number_Sector)
{
INT8U retry, response;
retry=0;
do
{
response=SD_write_sector(Number_Sector,Buffer);
retry++;
}
while((response!=0x00)&&(retry<20)) ;
}

void SD_READ(INT8U *Buffer, INT16U Bytes,INT32U Number_Sector)
{
INT8U response,retry;
INT8U CMD[]={0X51,0X00,0X00,0X00,0X00,0XFF};
Number_Sector=Number_Sector<<9;
CMD[1] = ((Number_Sector & 0xFF000000) >> 24 );
CMD[2] = ((Number_Sector & 0x00FF0000) >> 16 );
CMD[3] = ((Number_Sector & 0x0000FF00) >> 8 );
CMD[4] = ((Number_Sector & 0x000000FF) >> 0) ;
retry=0;
do
{
response=SD_Read_Block(CMD,Buffer,Bytes);
retry++;
}
while((response!=0)&&(retry<100));
}

At the very least you would need to change the driver to work with the
AT91SAM's SPI hardware, which is different from the LPC hardware. I
would start on the Atmel website and look for free sample code such as
an SD or MMC driver. Then, find a free implementation such as FreeRTOS
or efsl that implements a FAT filesystem for SD/MMC cards. Official
SD/MMC documentation requires registration and maybe a license, but bits
are posted on the internet. Check websites of companies that make SD
cards, like Sandisk or Toshiba. The information is out there.

And good luck. This is not a small project...

Chris

On 8/15/2014 6:52 AM, a...@yahoo.com [AT91SAM] wrote:
> Hi everyone,
> I found SD.c that works with SD card thorough SPI for LPC
> series. But I work with AT91SAM7x256 and I want to change the code to
> work with this series. I am working on USB and new to memories. This
> very important to me. I am so grateful for your help.
> can anyone help me?
>