Reading the CSD Register

24 Mar

Reading the CSD Register
When initializing communications, the host must read the card’s CSD register. The CSD union below defines the contents of the CSD register as 4 dwords or 16 bytes. For brevity, I didn’t include a union component with a field for each of the CSD’s 37 items.

typedef union
{
struct
{
DWORD _u320;
DWORD _u321;
DWORD _u322;
DWORD _u323;
};
struct
{
byte _byte[16];
};
} CSD;

The CSDRead function issues the SEND_CSD command and waits for the card to send the register’s 16 bytes. Much of the function is similar to the SendSDCCmd function above. A difference is that the function retrieves data from the card after sending the command.

#define CSD_SIZE 16
#define DATA_START_TOKEN 0xFE // The Start Block token
CSD gblCSDReg;
SDC_Error CSDRead()
{
dword address = 0×00;
byte cmd = SEND_CSD;
CMD_PACKET CmdPacket;
byte data_token;
word index;
SDC_RESPONSE response;
SDC_Error status = sdcValid;
word timeout = 0×2ff;

// Select the card.
SDC_CS = 0;
// Store a command byte, address, and CRC value in the CMD_PACKET structure.
CmdPacket.cmd = sdmmc_cmdtable[cmd].CmdCode;
CmdPacket.address = address;
CmdPacket.crc = sdmmc_cmdtable[cmd].CRC;
// Send the command byte, address bytes, and CRC byte.
// The WriteSPI library function writes a byte on the SPI bus.
WriteSPI(CmdPacket.cmd);
WriteSPI(CmdPacket.addr3);
WriteSPI(CmdPacket.addr2);
WriteSPI(CmdPacket.addr1);
WriteSPI(CmdPacket.addr0);
WriteSPI(CmdPacket.crc);
// Read a byte from the card until the byte doesn’t equal FFh or a timeout occurs.
do
{
response.r1._byte = ReadMedia();
timeout–;
} while ((response.r1._byte == 0xFF) && (timeout != 0));
// A response of 00h means the command was accepted.
if (response.r1._byte != 0×00)
{
status = sdcCardBadCmd;
}

else
{
index = 0×2FF;
//Wait for the data_start token or a timeout.
do
{
data_token = ReadMedia();
index–;
} while ((data_token == SDC_FLOATING_BUS) && (index != 0));
if ((index == 0) || (data_token != DATA_START_TOKEN))
status = sdcCardTimeout;
else
{
// A data start token was received.
// Read the CSD register’s 16 bytes.
for (index = 0; index < CSD_SIZE; index++)
{
gblCSDReg._byte[index] = ReadMedia();
}
}
// Generate 8 clock cycles to complete the command.
mSend8ClkCycles();
}
// Deselect the card.
SDC_CS = 1;
return(status);
}

Reading a Sector
MultiMediaCard firmware reads data from the storage media in sectors, which are typically 512 bytes. The SectorRead function and related code below perform this function. The function accepts a 32-bit LBA that identi-fies the sector to read (sector_addr) and a pointer to a buffer that will store the data read from the card (buffer). The function returns a status code.

// This macro writes FFh twice to clock in two CRC bytes.
#define mReadCRC() WriteSPI(0xFF); WriteSPI(0xFF);
#define SDC_FLOATING_BUS 0xFF
#define SDC_BAD_RESPONSE SDC_FLOATING_BUS
#define SDC_SECTOR_SIZE 512
SDC_Error SectorRead(dword sector_addr, byte* buffer)
{
byte data_token;
word index;
SDC_RESPONSE response;
SDC_Error status = sdcValid;
// Issue a READ_SINGLE_BLOCK command.
// Specify the address of the first byte to read in the media.
// To obtain the address of a sector’s first byte,
// shift the sector address left 9 times to multiply by 512 (sector size).
response = SendSDCCmd(READ_SINGLE_BLOCK, (sector_addr << 9));
// A response of 00h indicates success.
if (response.r1._byte != 0×00)
{
status = sdcCardBadCmd;
}
else
{
// The command was accepted.
index = 0×2FF;

do
{
// Read from the card until receiving a response or a timeout.
data_token = ReadMedia();
index–;
} while ((data_token == SDC_FLOATING_BUS) && (index != 0));
if ((index == 0) || (data_token != DATA_START_TOKEN))
// The card didn’t send a data start token.
status = sdcCardTimeout;
else
{
// The card sent a data start token.
// Read a sector’s worth of data from the card.
for (index = 0; index < SDC_SECTOR_SIZE; index++)
{
buffer[index] = ReadMedia();
}
// Read the CRC bytes.
mReadCRC();
}
// Generate 8 clock cycles to complete the command.
mSend8ClkCycles();
}
// Deselect the card.
SDC_CS = 1;
return(status);
}

Random Posts

No comments yet

Leave a Reply

You must be logged in to post a comment.