10 SD.c
The MMC/SD memory cards have several communication protocols (some of which are optional), particularly the SD (Secure Digital) memories always support the SPI protocol.
To speak with a SD memory, the controller have to send a command, that is always followed by a response from the card.
The SPI mode is activated holding down the CS signal when sending the CMD0 command (that makes the card in Idle Mode). At this point, to finish the initialization, we have to send the ACMD41 command until the memory exits from the Idle state
(card status is read in its response).
The ACMD41 is an Application-Specific command, so it is preceded by CMD55.
char SDInit()
{
char i;
char status;
TRISCbits.TRISC5 = 0;
TRISCbits.TRISC4 = 1;
TRISCbits.TRISC3 = 0;
SSP1STAT = 0x00;
SSP1CON1 = 0x30; // SPI master, Fosc/4
PIR1bits.SSP1IF = 0;
SD_CS_TRIS = 0;
SD_CS = 1;
for(i=0; i < 16; i++)
spi(0xFF); // extra clock for powerup
SD_CS = 0;
SDCmd(CMD0, 0); // Send reset command
if (SDWait()!=0x01)
goto SDError;
i = 20;
do {
SDCmd(CMD55, 0);
SDWait();
SDCmd(ACMD41, 0); // send ACMD41 to finish the initialization
if (i-- < 0)
goto SDError;
} while ((SDWait()&1) != 0x00); // wait until the memory is not in idle state
SD_CS = 1;
return TRUE;
SDError:
SD_CS = 1;
return FALSE;
}With the SDInit method, the SPI module is configured, and then the operations described above are executed.
In the previous code fragment, two methods are used: SDCmd is used to send a command to the memory, and SDWait waits for the response.
char SDCmd(char cmd, unsigned long param)
{
spi(0xFF); // extra clock
spi(cmd); // command
spi(param >> 24);
spi(param >> 16);
spi(param >> 8);
spi(param);
spi(cmd == CMD0 ? 0x95 : 0xFF); // CRC, mandatory only for CMD0
}
char SDWait(void)
{
unsigned short count = 0xFF;
char response;
while((response=spi(0xFF)) == 0xFF && --count > 0); // wait for a response different from 0xFF, with timeout
return response;
}
Finally, the method that we use to read a sector from the card with CMD17 is SDReadSector.
Data can be transferred from the card to the controller (and vice versa) only in blocks of fixed size (512 by default).
char SDReadSector(unsigned long sector)
{
int i;
char* buf_pt = &sd_buffer[0];
char status;
SD_CS = 0;
SDCmd(CMD17, (sector * SECTOR_SIZE)); // read from the address = sector*512
if(SDWait()!=0x00 || SDWait()!=0xFE) // wait for two responses
{
SD_CS = 1;
sdPresent = FALSE; // if the reading fails, we suppose that the card is not present
return FALSE;
}
for (i = 0; i < SECTOR_SIZE; i++)
buf_pt[i] = spi(0xFF); // read block
spi(0xFF);
spi(0xFF); // flush CRC
SD_CS = 1;
return TRUE;
}Read data is stored in a buffer, that has to fit exactly two memory banks (of 256 bytes each), to do that the pragma directive is used;
besides that, the RAM occupied by the buffer must be declared as Protected.


