SD Card Interface class. Log raw data bytes to memory addresses of your choice, or format the card and use the FAT file system to write files.
Diff: SDCard.cpp
- Revision:
- 1:94c648931f84
- Parent:
- 0:f3870f76a890
- Child:
- 3:210eb67b260c
--- a/SDCard.cpp Sun Jul 18 21:26:24 2010 +0000 +++ b/SDCard.cpp Sat Aug 07 18:32:30 2010 +0000 @@ -1,7 +1,7 @@ #include "SDCard.h" -SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs) - : DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1) +SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs, const char* DiskName) : + FATFileSystem(DiskName), DataLines(mosi, miso, sck), ChipSelect(cs), CRCMode(1), Timeout(8192) { DataLines.frequency(100000); //set universal speed @@ -14,240 +14,523 @@ //generate the command crc lookup table //(generator polynomial x^16 + x^12 + x^5 + 1 converts to decimal 69665) Initialize(); - //send card initialization sequence +} + +unsigned char SDCard::disk_initialize() +{ return 0x00; } +unsigned char SDCard::disk_status() +{ return 0x00; } +unsigned char SDCard::disk_read(unsigned char* buff, unsigned long sector, unsigned char count) +{ return Read((unsigned int)sector, count, buff); } +unsigned char SDCard::disk_write(const unsigned char* buff, unsigned long sector, unsigned char count) +{ return Write((unsigned int)sector, count, (unsigned char*)buff); } +unsigned char SDCard::disk_sync() +{ return 0x00; } +unsigned long SDCard::disk_sector_count() +{ + switch (CSD[0] & 0xC0) + { + case 0x00: + return ((((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1) + * (1 << ((((CSD[9] & 0x03) << 1) | ((CSD[10] & 0x80) >> 7)) + 2)); + case 0x40: + return ((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1) * 1024; + default: + return 0; + } +} +unsigned short SDCard::disk_sector_size() +{ return 512; } +unsigned long SDCard::disk_block_size() +{ + switch (CSD[0] & 0xC0) + { + case 0x00: + return (CSD[10] << 1) | (CSD[11] >> 7) + 1; + case 0x40: + return 1; + default: + return 0; + } } -bool SDCard::Write(unsigned int Address, unsigned char* Data) +unsigned char SDCard::Log(unsigned char Control, unsigned char Data) { - if (Capacity) + static unsigned char Mode = 0x00; + static unsigned short Index = 0; + + if (CRCMode) { - for (unsigned int j = 0; j < 8192; j++) - { - Command(24, Address, Workspace); - if (Workspace[0] == 0x00) - { break; } - if (j == 8191) - { return 0; } - } - } - else - { - for (unsigned int j = 0; j < 8192; j++) - { - Command(24, Address * 512, Workspace);///////////implement block length - if (Workspace[0] == 0x00) - { break; } - if (j == 8191) - { return 0; } - } + SelectCRCMode(0); } - ChipSelect.write(0); - DataLines.write(0xFE); - //start data block token - for (unsigned short j = 0; j < 512; j++) - { - DataLines.write(Data[j]); - //write the data - } - DataCRC(512, Data, Workspace); - DataLines.write(Workspace[1]); - DataLines.write(Workspace[2]); - for (unsigned int j = 0; j < 8192; j++) + + switch (Control) { - Workspace[0] = DataLines.write(0xFF); - if ((Workspace[0] & 0x1F) == 0x05) - { break; } - } - while (!DataLines.write(0xFF)); - ChipSelect.write(1); - DataLines.write(0xFF); - if ((Workspace[0] & 0x1F) == 0x05) - { return 1; } - else - { - for (unsigned int j = 0; j < 8192; j++) - { - Command(13, 0, Workspace); - if (Workspace[0] == 0x00) - { break; } - } - return 0; + case 0x00: + if (Mode) + { + ChipSelect.write(0); + for (; Index < 512; Index++) + { + DataLines.write(0xFF); + } + DataLines.write(0xFF); + DataLines.write(0xFF); + ChipSelect.write(1); + if (Mode == 0x01) + { + ChipSelect.write(0); + t = 0; + do + { + t++; + } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout)); + while (!DataLines.write(0xFF)); + DataLines.write(0xFD); + DataLines.write(0xFF); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + } + else + { + Command(12, 0, Workspace); + ChipSelect.write(0); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + } + Index = 0; + Mode = 0x00; + } + return 0xFF; + + case 0x01: + if (Mode != 0x01) + { + Log(0, 0); + Command(25, 0, Workspace); + Mode = 0x01; + } + if (Index == 0) + { + ChipSelect.write(0); + DataLines.write(0xFC); + DataLines.write(Data); + ChipSelect.write(1); + Index++; + } + else if (Index < 511) + { + ChipSelect.write(0); + DataLines.write(Data); + ChipSelect.write(1); + Index++; + } + else + { + ChipSelect.write(0); + DataLines.write(Data); + DataLines.write(0xFF); + DataLines.write(0xFF); + t = 0; + do + { + t++; + } while (((DataLines.write(0xFF) & 0x11) != 0x01) && (t < Timeout)); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + Index = 0; + } + return 0xFF; + + case 0x02: + if (Mode != 0x02) + { + Log(0, 0); + Command(18, 0, Workspace); + Mode = 0x02; + } + if (Index == 0) + { + ChipSelect.write(0); + t = 0; + do + { + t++; + } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); + Workspace[0] = DataLines.write(0xFF); + ChipSelect.write(1); + Index++; + return Workspace[0]; + } + else if (Index < 511) + { + ChipSelect.write(0); + Workspace[0] = DataLines.write(0xFF); + ChipSelect.write(1); + Index++; + return Workspace[0]; + } + else + { + ChipSelect.write(0); + Workspace[0] = DataLines.write(0xFF); + DataLines.write(0xFF); + DataLines.write(0xFF); + ChipSelect.write(1); + Index = 0; + return Workspace[0]; + } + + default: + return 0xFF; } } -bool SDCard::Read(unsigned int Address, unsigned char* Data) +unsigned char SDCard::Write(unsigned int Address, unsigned char* Data) { - if (Capacity) + if (!Capacity) { - for (unsigned int j = 0; j < 8192; j++) - { - Command(17, Address, Workspace); - if (Workspace[0] == 0x00) - { break; } - if (j == 8191) - { return 0; } - } + Command(24, Address * 512, Workspace); + if (Workspace[0]) + { return 0x04; } } else { - for (unsigned int j = 0; j < 8192; j++) + Command(24, Address, Workspace); + if (Workspace[0]) + { return 0x04; } + } + DataCRC(512, Data, Workspace); + ChipSelect.write(0); + DataLines.write(0xFE); + for (unsigned short i = 0; i < 512; i++) + { + DataLines.write(Data[i]); + } + DataLines.write(Workspace[0]); + DataLines.write(Workspace[1]); + t = 0; + do + { + Workspace[0] = DataLines.write(0xFF); + t++; + } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout)); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + if (((Workspace[0] & 0x1F) != 0x05) || (t == Timeout)) + { return 0x01; } + else + { return 0x00; } +} +unsigned char SDCard::Write(unsigned int Address, unsigned char SectorCount, unsigned char* Data) +{ + static unsigned char CurrentSectorCount = 1; + if (SectorCount != CurrentSectorCount) + { + Command(55, 0, Workspace); + Command(23, SectorCount, Workspace); + if (Workspace[0]) + { return 0x04; } + CurrentSectorCount = SectorCount; + } + if (!Capacity) + { + Command(25, Address * 512, Workspace); + if (Workspace[0]) + { return 0x04; } + } + else + { + Command(25, Address, Workspace); + if (Workspace[0]) + { return 0x04; } + } + Workspace[4] = 0x00; + for (unsigned char i = 0; i < SectorCount; i++) + { + DataCRC(512, &Data[i * 512], Workspace); + ChipSelect.write(0); + DataLines.write(0xFC); + for (unsigned int j = i * 512; j < (i + 1) * 512; j++) { - Command(17, Address * 512, Workspace);///////////implement block length - if (Workspace[0] == 0x00) - { break; } - if (j == 8191) - { return 0; } + DataLines.write(Data[j]); + } + DataLines.write(Workspace[0]); + DataLines.write(Workspace[1]); + t = 0; + do + { + Workspace[0] = DataLines.write(0xFF); + t++; + } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout)); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + Workspace[4] |= Workspace[0]; + if (t == Timeout) + { + ChipSelect.write(0); + DataLines.write(0xFD); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + return 0x01; } } ChipSelect.write(0); - for (unsigned int j = 0; j < 8192; j++) + DataLines.write(0xFD); + DataLines.write(0xFF); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + if ((Workspace[4] & 0x1F) != 0x05) + { return 0x01; } + else + { return 0x00; } +} + +unsigned char SDCard::Read(unsigned int Address, unsigned char* Data) +{ + if (!Capacity) { - if (DataLines.write(0xFF) == 0xFE) - { break; } + Command(17, Address * 512, Workspace); + if (Workspace[0]) + { return 0x04; } } - for (unsigned short j = 0; j < 512; j++) + else + { + Command(17, Address, Workspace); + if (Workspace[0]) + { return 0x04; } + } + ChipSelect.write(0); + t = 0; + do { - Data[j] = DataLines.write(0xFF); + t++; + } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); + if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; } + for (unsigned short i = 0; i < 512; i++) + { + Data[i] = DataLines.write(0xFF); } + Workspace[2] = DataLines.write(0xFF); Workspace[3] = DataLines.write(0xFF); - Workspace[4] = DataLines.write(0xFF); ChipSelect.write(1); DataLines.write(0xFF); DataCRC(512, Data, Workspace); - if ((Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4])) - { return 1; } + if (CRCMode && ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]))) + { return 0x01; } + else + { return 0x00; } +} +unsigned char SDCard::Read(unsigned int Address, unsigned char SectorCount, unsigned char* Data) +{ + if (!Capacity) + { + Command(18, Address * 512, Workspace); + if (Workspace[0]) + { return 0; } + } else - { return 0; } + { + Command(18, Address, Workspace); + if (Workspace[0]) + { return 0; } + } + Workspace[4] = 0x00; + for (unsigned char i = 0; i < SectorCount; i++) + { + ChipSelect.write(0); + t = 0; + do + { + t++; + } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); + if (t == Timeout) + { + ChipSelect.write(1); + Command(12, 0, Workspace); + ChipSelect.write(0); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + DataLines.write(0xFF); + return 0x01; + } + for (unsigned int j = i * 512; j < (i + 1) * 512; j++) + { + Data[j] = DataLines.write(0xFF); + } + Workspace[2] = DataLines.write(0xFF); + Workspace[3] = DataLines.write(0xFF); + ChipSelect.write(1); + DataCRC(512, &Data[i * 512], Workspace); + Workspace[4] |= ((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])); + } + Command(12, 0, Workspace); + ChipSelect.write(0); + while (!DataLines.write(0xFF)); + ChipSelect.write(1); + if (Workspace[4]) + { return 0x01; } + else + { return 0x00; } } -bool SDCard::Initialize() +unsigned char SDCard::SelectCRCMode(bool Mode) { - for (unsigned char j = 0; j < 16; j++) + t = 0; + do + { + Command(59, Mode, Workspace); + t++; + } while (Workspace[0] && (t < Timeout)); + CRCMode = Mode; + if (t == Timeout) + { return 0x01; } + else + { return 0x00; } +} + +unsigned char SDCard::Initialize() +{ + for (unsigned char i = 0; i < 16; i++) { DataLines.write(0xFF); + //clock card at least 74 times to power up } - //perform specified power up sequence - - for (unsigned int j = 0; j < 8192; j++) + + t = 0; + do { Command(0, 0, Workspace); //send command 0 to put the card into SPI mode - if (Workspace[0] == 0x01) - //check for idle mode - { break; } - if (j == 8191) - { return 0; } - } - - for (unsigned int j = 0; j < 8192; j++) + t++; + } while ((Workspace[0] != 0x01) && (t < Timeout)); + if (t == Timeout) { return 0x01; } + + t = 0; + do { Command(59, 1, Workspace); - //send command 59 to turn on CRCs - if (Workspace[0] == 0x01) - { break; } - if (j == 8191) - { return 0; } - } - - for (unsigned int j = 0; j < 8192; j++) + //turn on CRCs + t++; + } while ((Workspace[0] != 0x01) && (Workspace[0] != 0x05) && (t < Timeout)); + //command 59 is not valid for all cards in idle state + if (t == Timeout) { return 0x01; } + + t = 0; + do { Command(8, 426, Workspace); //voltage bits are 0x01 for 2.7V - 3.6V, //check pattern 0xAA, [00,00,01,AA] = 426 - if ((Workspace[0] == 0x05) || ((Workspace[0] == 0x01) && - ((Workspace[3] & 0x0F) == 0x01) && (Workspace[4] == 0xAA))) - //check version, voltage acceptance, and check pattern - { break; } - if (j == 8191) - { return 0; } - } - Version = Workspace[0] == 0x01; + t++; + } while (((Workspace[0] != 0x01) || ((Workspace[3] & 0x0F) != 0x01) || + (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05) && (t < Timeout)); + //check version, voltage acceptance, and check pattern + if (t == Timeout) { return 0x01; } + Version = Workspace[0] != 0x05; //store card version - - for (unsigned int j = 0; j < 8192; j++) + + t = 0; + do { Command(58, 0, Workspace); //check the OCR - if ((Workspace[0] == 0x01) && ((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) - //check for correct operating voltage 3.3V - { break; } - if (j == 8191) - { return 0; } - } - - for (unsigned int j = 0; j < 8192; j++) + t++; + } while (((Workspace[0] != 0x01) || + !((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) && (t < Timeout)); + //check for correct operating voltage 3.3V + if (t == Timeout) { return 0x01; } + + t = 0; + do { Command(55, 0, Workspace); - //specify application-specific command Command(41, 1073741824, Workspace); - //specify host supports high capacity cards - //[40,00,00,00] = 1073741824 - if (Workspace[0] == 0x00) - //check if card is ready - { break; } - if (j == 8191) - { return 0; } - } - - for (unsigned int j = 0; j < 8192; j++) + //specify host supports high capacity + //cards, [40,00,00,00] = 1073741824 + t++; + } while (Workspace[0] && (t < Timeout)); + //check if card is ready + if (t == Timeout) { return 0x01; } + + if (SelectCRCMode(1)) + { return 0x01; } + //turn on CRCs for all cards + + t = 0; + do { Command(58, 0, Workspace); //check the OCR again - if ((Workspace[0] == 0x00) && (Workspace[1] & 0x80)) - { break; } - if (j == 8191) - { return 0; } + t++; + } while ((Workspace[0] || !(Workspace[1] & 0x80)) && (t < Timeout)); + //check power up status + if (t == Timeout) { return 0x01; } + for (unsigned char i = 0; i < 4; i++) + { + OCR[i] = Workspace[i + 1]; + //record OCR } - for (unsigned char j = 0; j < 4; j++) - { - OCR[j] = Workspace[j + 1]; - } - //record OCR Capacity = (OCR[0] & 0x40) == 0x40; //record capacity - - for (unsigned int j = 0; j < 8192; j++) + + t = 0; + do { - Command(9, 0, Workspace); - //read the card-specific data register - ChipSelect.write(0); - for (unsigned int k = 0; k < 8192; k++) + do { - if (DataLines.write(0xFF) == 0xFE) - { break; } - } + Command(9, 0, Workspace); + //read the card-specific-data register + t++; + } while (Workspace[0] && (t < Timeout)); + if (t == Timeout) { return 0x01; } + ChipSelect.write(0); + do + { + t++; + } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); //get to the start-data-block token - for (unsigned char k = 0; k < 16; k++) + if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; } + for (unsigned char i = 0; i < 16; i++) { - CSD[k] = DataLines.write(0xFF); + CSD[i] = DataLines.write(0xFF); + //gather CSD } + Workspace[2] = DataLines.write(0xFF); Workspace[3] = DataLines.write(0xFF); - Workspace[4] = DataLines.write(0xFF); + //save CSD CRC ChipSelect.write(1); DataLines.write(0xFF); DataCRC(16, CSD, Workspace); //calculate the CSD data CRC - Workspace[0] = 0; - for (unsigned char k = 0; k < 15; k++) + Workspace[4] = 0; + for (unsigned char i = 0; i < 15; i++) { - Workspace[0] = CommandCRCTable[Workspace[0]] ^ CSD[k]; + Workspace[4] = CommandCRCTable[Workspace[4]] ^ CSD[i]; } - Workspace[0] = CommandCRCTable[Workspace[0]] | 0x01; - if ((Workspace[0] == CSD[15]) && (Workspace[1] == Workspace[3]) && (Workspace[2] == Workspace[4])) - { break; } - if (j == 8191) - { return 0; } - } - - if (((CSD[3] & 0x07) > 2) || ((CSD[3] & 0x7F) > 0x32)) + Workspace[4] = CommandCRCTable[Workspace[4]] | 0x01; + //calculate the CSD table CRC + t++; + } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]) || + (Workspace[4] != CSD[15])) && (t < Timeout)); + //check all CSD CRCs + if (t == Timeout) { return 0x01; } + + if (((CSD[3] & 0x07) > 0x02) || + (((CSD[3] & 0x78) > 0x30) && ((CSD[3] & 0x07) > 0x01))) { DataLines.frequency(25000000); - //maximum speed is given at 25MHz + //maximum speed is 25MHz } else { Workspace[0] = 1; - for (unsigned char j = 0; j < (CSD[3] & 0x07); j++) + for (unsigned char i = 0; i < (CSD[3] & 0x07); i++) { Workspace[0] *= 10; //the first three bits are a power of ten multiplier for speed @@ -273,25 +556,78 @@ //read the CSD card speed bits and speed up card operations } } - + + if (CSD[4] & 0x40) + //check for switch command class support + { + t = 0; + do + { + Command(6, 2147483649, Workspace); + //switch to high-speed mode (SDR25, 50MHz) + t++; + } while (Workspace[0] && (Workspace[0] != 0x04) && (t < Timeout)); + //some cards that support switch class commands respond with illegal command + if (t == Timeout) { return 0x01; } + if (!Workspace[0]) + { + do + { + ChipSelect.write(0); + do + { + t++; + } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); + //get to the start-data-block token + if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); return 0x01; } + for (unsigned char i = 0; i < 64; i++) + { + FSR[i] = DataLines.write(0xFF); + //gather function-status register + } + Workspace[2] = DataLines.write(0xFF); + Workspace[3] = DataLines.write(0xFF); + //record data CRC + ChipSelect.write(1); + DataLines.write(0xFF); + DataCRC(64, FSR, Workspace); + //calculate CRC + t++; + } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3])) && + (t < Timeout)); + //complete CRC + if (t == Timeout) { return 0x01; } + if ((FSR[13] & 0x02) && ((FSR[16] & 0x0F) == 0x01)) + { + DataLines.frequency(50000000); + //increase speed if function switch was successful + } + } + } + if (!Version) { - for (unsigned int j = 0; j < 8192; j++) + t = 0; + do { Command(16, 512, Workspace); //set data-block length to 512 bytes - if (Workspace[0] == 0x00) - { break; } - if (j == 8191) - { return 0; } - } + t++; + } while (Workspace[0] && (t < Timeout)); + if (t == Timeout) { return 0x01; } } - ////////////////////////////////////////////implement data block sizing later - return 1; + + if (SelectCRCMode(0)) + { return 0x01; } + //turn off CRCs + + return 0x00; } void SDCard::Command(unsigned char Index, unsigned int Argument, unsigned char* Response) { + CommandCRC(&Index, &Argument, Workspace); + //calculate command CRC ChipSelect.write(0); //assert chip select low to synchronize command DataLines.write(0x40 | Index); @@ -301,25 +637,22 @@ DataLines.write(((char*)&Argument)[1]); DataLines.write(((char*)&Argument)[0]); //send the argument bytes in order from MSB to LSB (mbed is little endian) - if (CRCMode) - { DataLines.write(CommandCRC(&Index, &Argument)); } - else - { DataLines.write(0x00); } + DataLines.write(Workspace[0]); //send the command CRC - for (unsigned int j = 0; j < 8192; j++) + t = 0; + do { Response[0] = DataLines.write(0xFF); //clock the card high to let it run operations, the first byte will be //busy (all high), the response will be sent some time later - if (!(Response[0] & 0x80)) - //check for a response by testing if the first bit is low - { break; } - } + t++; + } while ((Response[0] & 0x80) && (t < Timeout)); + //check for a response by testing if the first bit is low if ((Index == 8) || (Index == 13) || (Index == 58)) { - for (unsigned char j = 1; j < 5; j++) + for (unsigned char i = 1; i < 5; i++) { - Response[j] = DataLines.write(0xFF); + Response[i] = DataLines.write(0xFF); } //get the rest of the response } @@ -329,66 +662,83 @@ //clock the deselected card high to complete processing for some cards } -char SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr) +void SDCard::CommandCRC(unsigned char* IndexPtr, unsigned int* ArgumentPtr, unsigned char* Result) { - return - CommandCRCTable[ + if (CRCMode) + { + Result[0] = CommandCRCTable[ CommandCRCTable[ CommandCRCTable[ CommandCRCTable[ - *IndexPtr | 0x40 - ] ^ ((char*)ArgumentPtr)[3] - ] ^ ((char*)ArgumentPtr)[2] - ] ^ ((char*)ArgumentPtr)[1] - ] ^ ((char*)ArgumentPtr)[0] - ] | 0x01; - //using a CRC table, the CRC result of a byte is equal to the byte in the table at the - //address equal to the input byte, a message CRC is obtained by successively XORing these - //with the message bytes + CommandCRCTable[ + *IndexPtr | 0x40 + ] ^ ((char*)ArgumentPtr)[3] + ] ^ ((char*)ArgumentPtr)[2] + ] ^ ((char*)ArgumentPtr)[1] + ] ^ ((char*)ArgumentPtr)[0] + ] | 0x01; + } + else + { + Result[0] = 0xFF; + } + //using a CRC table, the CRC result of a byte is equal to the byte + //in the table at the address equal to the input byte, a message CRC + //is obtained by successively XORing these with the message bytes } void SDCard::DataCRC(unsigned short Length, unsigned char* Data, unsigned char* Result) { - Result[1] = 0x00; - Result[2] = 0x00; - //initialize result carrier - for (int i = 0; i < Length; i++) - //step through each byte of the data to be checked + if (CRCMode) { - Result[0] = Result[1]; - //record current crc lookup for both bytes - Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2]; - //new fist byte result is XORed with old second byte result - Result[2] = DataCRCTable[(2 * Result[0]) + 1] ^ Data[i]; - //new second byte result is XORed with new data byte + unsigned char Reference; + //store the current CRC lookup value + Result[0] = 0x00; + Result[1] = 0x00; + //initialize result carrier + for (unsigned short i = 0; i < Length; i++) + //step through each byte of the data to be checked + { + Reference = Result[0]; + //record current crc lookup for both bytes + Result[0] = DataCRCTable[2 * Reference] ^ Result[1]; + //new fist byte result is XORed with old second byte result + Result[1] = DataCRCTable[(2 * Reference) + 1] ^ Data[i]; + //new second byte result is XORed with new data byte + } + for (unsigned char i = 0; i < 2; i++) + //the final result must be XORed with two 0x00 bytes. + { + Reference = Result[0]; + Result[0] = DataCRCTable[2 * Reference] ^ Result[1]; + Result[1] = DataCRCTable[(2 * Reference) + 1]; + } } - for (int i = 0; i < 2; i++) - //the final result must be XORed with two 0x00 bytes. + else { - Result[0] = Result[1]; - Result[1] = DataCRCTable[2 * Result[0]] ^ Result[2]; - Result[2] = DataCRCTable[(2 * Result[0]) + 1]; + Result[0] = 0xFF; + Result[1] = 0xFF; } } void SDCard::GenerateCRCTable(unsigned char Size, unsigned long long Generator, unsigned char* Table) { unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - //this will hold information from the generator; the position indicates the - //order of the encountered 1, the value indicates its position in the - //generator, the 9th entry indicates the number of 1's encountered - for (int i = 0; i < 64; i++) + //this will hold information from the generator; the position indicates + //the order of the encountered 1, the value indicates its position in + //the generator, the 9th entry indicates the number of 1's encountered + for (unsigned char i = 0; i < 64; i++) { if (((char*)&Generator)[7] & 0x80) { break; } Generator = Generator << 1; //shift generator so that the first bit is high } - for (unsigned char k = 0; k < Size; k++) + for (unsigned char i = 0; i < Size; i++) { - Table[k] = 0x00; - //initialize the first CRC bytes + Table[i] = 0x00; + //initialize table } for (unsigned char i = 0; i < 8; i++) //increment through each generator bit @@ -407,8 +757,8 @@ //we need to perform operations for each byte in the CRC result { Table[(Size * ((0x01 << i) + j)) + k] = Table[(Size * j) + k]; - //each new power is equal to all previous entries with an added xor - //on the leftmost bit and each succeeding 1 on the generator + //each new power is equal to all previous entries with an added + //xor on the leftmost bit and each succeeding 1 on the generator for (unsigned char l = 0; l < Index[8]; l++) //increment through the encountered generator 1s {