Hi Neil
I did a bit of research. The CSD is defined in the "SD Specifications Part 1 Physical Layer Simplified Specification Version 3.01 May 18, 2010" and is 128 bits long. It is however preceeded by a preamble which is also read. Therefore I also checked this and saw the following differences (your card is the third and I have shown it shifted, compensating for the missing start byte):
CSD: 0xff 0xfe 0x40 0x0e 0x00 0x32 0x5b 0x59 0x00 0x00 0x3b 0x37 0x7f 0x80 0x0a 0x40 0x40 0xaf - 8G version 2
CSD: 0xff 0xfe 0x40 0x0e 0x00 0x32 0x5b 0x59 0x00 0x00 0x1d 0x8a 0x7f 0x80 0x0a 0x40 0x40 0xb9 - 4G version 2
CSD: 0xfe 0x00 0x7f 0x00 0x32 0x5b 0x5a 0x83 0xbd 0x6d 0xb7 0xff 0x80 0x0a 0x80 0x00 0x8d (0xe5) - 2G version 1
CSD: 0xff 0xfe 0x00 0x4f 0x00 0x32 0x5f 0x59 0xa3 0xcb 0xff 0xff 0xff 0x8f 0x8a 0x40 0x00 0x29 - 1G version 1
---(start)[ CSD 128 bits (16 bytes) ]
version
access times
speed
CRC-7
Although the first byte is missing it is in fact quite easy to identify that the pre-amble byte is at the wrong location. Also the content can be checked using the CRC-7 at the end to be absolutely sure.
Just after reading the CSD into the buffer called ucData[] (fnSendSD_command(ucSEND_CSD_CMD9, &ucResult, ucData))) I have added this code:
#if !defined SD_CONTROLLER_AVAILABLE
if (fnCheckCSD(ucData) != 0) {
uTaskerStateChange(OWN_TASK, UTASKER_ACTIVATE); // schedule the task to retry
_return; // not recognised or there was a CRC error
}
#endif
The routine fnCheckCSD() checks for a shifted start and corrects it in the buffer if found. It also checked the CRC-7 of the content. In case the CRC-7 were bad it would repeat the read until it is correct.
This routine is below and can be located anywhere before the task in the file mass_storage().
I could then read all of these cards, including yours, and get the correct CSD content. Then I could also re-format your card successfully.
SD-card MARK (2008023040 bytes) FAT32
Bytes per sector: 512
Cluster size: 4096
Directory base: 0x00000002
FAT start: 0x0000005f
FAT size: 0x00000ef3
Number of FATs: 2
LBA: 0x00001e45
Total clusters: 0x00077737
Info sect: 0x00000040
Free clusters: 0x00077735
Next free: 0x00000004
CSD: 0x00 0x7f 0x00 0x32 0x5b 0x5a 0x83 0xbd 0x6d 0xb7 0xff 0x80 0x0a 0x80 0x00 0x8d
This uses the function uReverseMemcpy(), which you may not have in your Coldfire version so I have also added the SW implementation below (Kinetis uses DMA).
Good luck!
Regards
Mark
#if defined SDCARD_SUPPORT && !defined SD_CONTROLLER_AVAILABLE
static int fnCheckCSD(unsigned char ucData[18])
{
unsigned char ucCRC = 0;
int iOffset;
int i, j;
unsigned char ucByte;
if (ucData[0] == 0xfe) { // if a synchronisation is found at the start of the buffer we assume that the SD card returned the CSD content one byte earlier than normal
iOffset = 1;
}
else {
iOffset = 2; // normal location for the content start
}
for (i = 0; i < 15; i++) { // check the CRC-7 of the content
ucByte = ucData[iOffset++];
for (j = 0; j < 8; j++) { // for each bit of the byte
ucCRC <<= 1;
if ((ucByte & 0x80) ^ (ucCRC & 0x80)) {
ucCRC ^=0x09;
}
ucByte <<= 1;
}
}
if ((ucCRC & 0x7f) == (ucData[iOffset] >> 1)) { // check that the received CRC-7 matches with the value calculated for the content
if (iOffset == 16) {
uReverseMemcpy(&ucData[2], &ucData[1], 16); // shift the content to the expected location in case it was originally shifted
}
return 0; // CRC-7 is correct and the data is in the correct location
}
else {
return -1; // invalid CRC-7
}
}
#endif
// uMemcpy() executed in a reverse order to allow shifting buffers to the right
//
extern void *uReverseMemcpy(void *ptrTo, const void *ptrFrom, size_t Size)
{
void *buffer = ptrTo;
unsigned char *ptr1 = (unsigned char *)ptrTo;
unsigned char *ptr2 = (unsigned char *)ptrFrom;
ptr1 += Size; // move to the end of the buffers
ptr2 += Size;
while (Size--) {
*(--ptr1) = *(--ptr2); // copy backwards
}
return buffer;
}