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.
SDCard.cpp
00001 //mbed Microcontroller Library 00002 //SDCard Interface 00003 //Copyright 2010 00004 //Thomas Hamilton 00005 00006 #include "SDCard.h" 00007 00008 SDCard::SDCard(PinName mosi, PinName miso, PinName sck, PinName cs, 00009 const char* DiskName) : 00010 FATFileSystem(DiskName), DataLines(mosi, miso, sck), ChipSelect(cs), 00011 t(0), Timeout(1024), CRCMode(1), Capacity(0), Version(0), Status(0x00) 00012 //card always starts uninitialized and in CRC mode; version 1 low-capacity 00013 //card protocols are backwards-compatible with all other card protocols 00014 { 00015 DataLines.frequency(100000); 00016 //set universal speed 00017 ChipSelect.write(1); 00018 //deselect the chip 00019 GenerateCRCTable(1, 137, CommandCRCTable); 00020 //generate the CRC7 lookup table; polynomial x^7 + x^3 + 1 converts to 00021 //decimal 137 00022 GenerateCRCTable(2, 69665, DataCRCTable); 00023 //generate the crc16 lookup table; polynomial x^16 + x^12 + x^5 + 1 00024 //converts to decimal 69665 00025 Initialize(); 00026 //run setup operations 00027 } 00028 00029 SDCard::~SDCard() 00030 //delete all tables and card data registers 00031 { 00032 delete[] CommandCRCTable; 00033 delete[] DataCRCTable; 00034 delete[] OCR; 00035 delete[] CSD; 00036 delete[] FSR; 00037 delete this; 00038 } 00039 00040 unsigned char SDCard::disk_initialize() 00041 //give the FAT module access to the card setup routine 00042 { 00043 if (Status == 0x01) 00044 { 00045 return Initialize(); 00046 } 00047 else 00048 { 00049 return Status; 00050 } 00051 } 00052 unsigned char SDCard::disk_status() 00053 //return card initialization and availability status 00054 { return Status; } 00055 unsigned char SDCard::disk_read( 00056 unsigned char* buff, unsigned long sector, unsigned char count) 00057 //give the FAT module access to the multiple-sector reading function 00058 { return Read((unsigned int)sector, count, buff); } 00059 unsigned char SDCard::disk_write( 00060 const unsigned char* buff, unsigned long sector, unsigned char count) 00061 //give the FAT module access to the multiple-sector writing function 00062 { return Write((unsigned int)sector, count, (unsigned char*)buff); } 00063 unsigned char SDCard::disk_sync() 00064 //the disk is always synchronized, so return "disk ready" 00065 { return 0x00; } 00066 unsigned long SDCard::disk_sector_count() 00067 //calculate and return the number of sectors on the card from the CSD 00068 { 00069 switch (CSD[0] & 0xC0) 00070 { 00071 case 0x00: 00072 //calculate sector count as specified for version 1 cards 00073 return ((((CSD[6] & 0x03) << 10) | (CSD[7] << 2) 00074 | ((CSD[8] & 0xC0) >> 6)) + 1) 00075 * (1 << ((((CSD[9] & 0x03) << 1) 00076 | ((CSD[10] & 0x80) >> 7)) + 2)); 00077 case 0x40: 00078 //calculate sector count as specified for version 2 cards 00079 return ((((CSD[7] & 0x3F) << 16) 00080 | (CSD[8] << 8) | CSD[9]) + 1) * 1024; 00081 default: 00082 return 0; 00083 } 00084 } 00085 unsigned short SDCard::disk_sector_size() 00086 //fix the sector size to 512 bytes for all cards versions 00087 { return 512; } 00088 unsigned long SDCard::disk_block_size() 00089 //calculate and return the number of sectors in an erase block from the CSD 00090 { 00091 if (Version) 00092 //the erase sector size is the allocation unit for version 2 cards 00093 { 00094 return 1; 00095 } 00096 else 00097 //calculate the erase sector size for version 1 cards 00098 { 00099 return (CSD[10] << 1) | (CSD[11] >> 7) + 1; 00100 } 00101 } 00102 00103 unsigned char SDCard::Format(unsigned int AllocationUnit) 00104 //call the FAT module formatting function 00105 { 00106 if (format(AllocationUnit)) 00107 { 00108 return 0x01; 00109 } 00110 else 00111 { 00112 return 0x00; 00113 } 00114 } 00115 00116 unsigned char SDCard::Log(unsigned char Control, unsigned char Data) 00117 { 00118 static unsigned char Workspace; 00119 //work area for card commands and data transactions 00120 static unsigned short Index = 0; 00121 //store last written byte number of current memory block 00122 static unsigned char Mode = 0x00; 00123 //store previous operating mode to determine current behavior 00124 00125 SelectCRCMode(0); 00126 //CRC's are not used in raw data mode 00127 00128 switch (Control) 00129 { 00130 case 0x00: 00131 //control code 0x00 synchronizes the card 00132 if (Mode) 00133 //if the card is in read or write mode, synchronize the card 00134 { 00135 ChipSelect.write(0); 00136 for (; Index < 512; Index++) 00137 //get through the left over space, filling with 0xFF 00138 { 00139 DataLines.write(0xFF); 00140 } 00141 DataLines.write(0xFF); 00142 DataLines.write(0xFF); 00143 //get through the CRC 00144 ChipSelect.write(1); 00145 if (Mode == 0x01) 00146 //if the card is in write mode, finish the current sector 00147 //and finalize the writing operation 00148 { 00149 ChipSelect.write(0); 00150 t = 0; 00151 do 00152 { 00153 t++; 00154 } while (((DataLines.write(0xFF) & 0x11) != 0x01) 00155 && (t < Timeout)); 00156 //get through the data response token 00157 while (!DataLines.write(0xFF)); 00158 //get through the busy signal 00159 DataLines.write(0xFD); 00160 DataLines.write(0xFF); 00161 //send the stop transmission token 00162 while (!DataLines.write(0xFF)); 00163 //get through the busy signal 00164 ChipSelect.write(1); 00165 DataLines.write(0xFF); 00166 } 00167 else 00168 //if the card is in read mode, finish the current sector 00169 //and finalize the reading operation 00170 { 00171 Command(12, 0, &Workspace); 00172 //send the stop transmission command 00173 ChipSelect.write(0); 00174 while (!DataLines.write(0xFF)); 00175 //get through the busy signal 00176 ChipSelect.write(1); 00177 DataLines.write(0xFF); 00178 } 00179 Index = 0; 00180 Mode = 0x00; 00181 //reset the index to the start and switch the mode to 00182 //synchronized mode 00183 } 00184 return 0xFF; 00185 00186 case 0x01: 00187 //control code 1 writes a byte 00188 if (Mode != 0x01) 00189 //if the previous call was not a write operation, synchronize 00190 //the card, start a new write block, and set the function to 00191 //write mode 00192 { 00193 Log(0, 0); 00194 Command(25, 0, &Workspace); 00195 Mode = 0x01; 00196 } 00197 if (Index == 0) 00198 //if the index is at the start, send the start block token 00199 //before the byte 00200 { 00201 ChipSelect.write(0); 00202 DataLines.write(0xFC); 00203 DataLines.write(Data); 00204 ChipSelect.write(1); 00205 Index++; 00206 } 00207 else if (Index < 511) 00208 //if the index is between the boundaries, write the byte 00209 { 00210 ChipSelect.write(0); 00211 DataLines.write(Data); 00212 ChipSelect.write(1); 00213 Index++; 00214 } 00215 else 00216 //if the index is at the last address, get through the CRC, 00217 //data response token, and busy signal and reset the index 00218 { 00219 ChipSelect.write(0); 00220 DataLines.write(Data); 00221 DataLines.write(0xFF); 00222 DataLines.write(0xFF); 00223 t = 0; 00224 do 00225 { 00226 t++; 00227 } while (((DataLines.write(0xFF) & 0x11) != 0x01) 00228 && (t < Timeout)); 00229 while (!DataLines.write(0xFF)); 00230 ChipSelect.write(1); 00231 Index = 0; 00232 } 00233 return 0xFF; 00234 00235 case 0x02: 00236 //control code 2 reads a byte 00237 if (Mode != 0x02) 00238 //if the previous call was not a read operation, synchronise 00239 //the card, start a new read block, and set the function to 00240 //read mode 00241 { 00242 Log(0, 0); 00243 Command(18, 0, &Workspace); 00244 Mode = 0x02; 00245 } 00246 if (Index == 0) 00247 //if the index is at the start, get the start block token 00248 //and read the first byte 00249 { 00250 ChipSelect.write(0); 00251 t = 0; 00252 do 00253 { 00254 t++; 00255 } while ((DataLines.write(0xFF) != 0xFE) 00256 && (t < Timeout)); 00257 Workspace = DataLines.write(0xFF); 00258 ChipSelect.write(1); 00259 Index++; 00260 return Workspace; 00261 } 00262 else if (Index < 511) 00263 //if the index is between the boundaries, read the byte 00264 { 00265 ChipSelect.write(0); 00266 Workspace = DataLines.write(0xFF); 00267 ChipSelect.write(1); 00268 Index++; 00269 return Workspace; 00270 } 00271 else 00272 //if the index is at the last address, get through the CRC and 00273 //reset the index 00274 { 00275 ChipSelect.write(0); 00276 Workspace = DataLines.write(0xFF); 00277 DataLines.write(0xFF); 00278 DataLines.write(0xFF); 00279 ChipSelect.write(1); 00280 Index = 0; 00281 return Workspace; 00282 } 00283 00284 default: 00285 //undefined control codes will only return stuff bits 00286 return 0xFF; 00287 } 00288 } 00289 00290 unsigned char SDCard::Write(unsigned int Address, unsigned char* Data) 00291 { 00292 unsigned char Workspace[2]; 00293 //work area for card commands and data transactions 00294 00295 if (Capacity) 00296 //send the single-block write command addressed for high-capacity cards 00297 { 00298 Command(24, Address, Workspace); 00299 } 00300 else 00301 //send the single-block write command addressed for low-capacity cards 00302 { 00303 Command(24, Address * 512, Workspace); 00304 } 00305 if (Workspace[0]) 00306 //if a command error occurs, return "parameter error" 00307 { return 0x04; } 00308 DataCRC(512, Data, Workspace); 00309 //calculate the CRC16 00310 ChipSelect.write(0); 00311 DataLines.write(0xFE); 00312 //write start block token 00313 for (unsigned short i = 0; i < 512; i++) 00314 //write the data to the addressed card sector 00315 { 00316 DataLines.write(Data[i]); 00317 } 00318 DataLines.write(Workspace[0]); 00319 DataLines.write(Workspace[1]); 00320 //write the data CRC16 00321 t = 0; 00322 do 00323 { 00324 Workspace[0] = DataLines.write(0xFF); 00325 t++; 00326 } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout)); 00327 //gather the data block response token 00328 while (!DataLines.write(0xFF)); 00329 //get through the busy signal 00330 ChipSelect.write(1); 00331 DataLines.write(0xFF); 00332 if (((Workspace[0] & 0x1F) != 0x05) || (t == Timeout)) 00333 //if the data response token indicates error, return write error 00334 { return 0x01; } 00335 else 00336 { return 0x00; } 00337 } 00338 unsigned char SDCard::Write( 00339 unsigned int Address, unsigned char SectorCount, unsigned char* Data) 00340 { 00341 unsigned char Workspace[5]; 00342 //work area for card commands and data transactions 00343 static unsigned char CurrentSectorCount = 1; 00344 //store the last write sector count 00345 00346 if (SectorCount != CurrentSectorCount) 00347 //set the expected number of write blocks if its different from 00348 //previous multiple-block write operations 00349 { 00350 Command(55, 0, Workspace); 00351 Command(23, SectorCount, Workspace); 00352 if (Workspace[0]) 00353 { return 0x04; } 00354 CurrentSectorCount = SectorCount; 00355 } 00356 if (Capacity) 00357 //send the multiple-block write command addressed for high-capacity 00358 //cards 00359 { 00360 Command(25, Address, Workspace); 00361 } 00362 else 00363 //send the multiple-block write command addressed for low-capacity 00364 //cards 00365 { 00366 Command(25, Address * 512, Workspace); 00367 } 00368 if (Workspace[0]) 00369 //if a command error occurs, return "parameter error" 00370 { return 0x04; } 00371 Workspace[4] = 0x00; 00372 //initialize the error detection variable 00373 for (unsigned char i = 0; i < SectorCount; i++) 00374 //write each data sector 00375 { 00376 DataCRC(512, &Data[i * 512], Workspace); 00377 //calculate the CRC16 00378 ChipSelect.write(0); 00379 DataLines.write(0xFC); 00380 //send multiple write block start token 00381 for (unsigned int j = i * 512; j < (i + 1) * 512; j++) 00382 //write each data block 00383 { 00384 DataLines.write(Data[j]); 00385 } 00386 DataLines.write(Workspace[0]); 00387 DataLines.write(Workspace[1]); 00388 //write the CRC16 00389 t = 0; 00390 do 00391 { 00392 Workspace[0] = DataLines.write(0xFF); 00393 t++; 00394 } while (((Workspace[0] & 0x11) != 0x01) && (t < Timeout)); 00395 //gather the data block response token 00396 while (!DataLines.write(0xFF)); 00397 //get through the busy signal 00398 ChipSelect.write(1); 00399 Workspace[4] |= Workspace[0]; 00400 //record if any write errors that are detected in the data response 00401 //tokens 00402 if (t == Timeout) 00403 //if a block write operation times out, stop operations 00404 { break; } 00405 } 00406 ChipSelect.write(0); 00407 DataLines.write(0xFD); 00408 DataLines.write(0xFF); 00409 //send the stop transmission token 00410 while (!DataLines.write(0xFF)); 00411 //get through the busy signal 00412 ChipSelect.write(1); 00413 DataLines.write(0xFF); 00414 if (((Workspace[4] & 0x1F) != 0x05) || (t == Timeout)) 00415 //if a data response token indicated an error, return "write error" 00416 { return 0x01; } 00417 else 00418 { return 0x00; } 00419 } 00420 00421 unsigned char SDCard::Read(unsigned int Address, unsigned char* Data) 00422 { 00423 unsigned char Workspace[4]; 00424 //work area for card commands and data transactions 00425 00426 if (Capacity) 00427 //send the single-block read command addressed for high-capacity cards 00428 { 00429 Command(17, Address, Workspace); 00430 } 00431 else 00432 //send the single-block read command addressed for low-capacity cards 00433 { 00434 Command(17, Address * 512, Workspace); 00435 } 00436 if (Workspace[0]) 00437 //if a command error occurs, return "parameter error" 00438 { return 0x04; } 00439 ChipSelect.write(0); 00440 t = 0; 00441 do 00442 { 00443 t++; 00444 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); 00445 //get to the start block token 00446 if (t == Timeout) { 00447 ChipSelect.write(1); DataLines.write(0xFF); return 0x01; } 00448 for (unsigned short i = 0; i < 512; i++) 00449 { 00450 Data[i] = DataLines.write(0xFF); 00451 } 00452 //read the data from the addressed card sector 00453 Workspace[2] = DataLines.write(0xFF); 00454 Workspace[3] = DataLines.write(0xFF); 00455 //read the CRC16 00456 ChipSelect.write(1); 00457 DataLines.write(0xFF); 00458 DataCRC(512, Data, Workspace); 00459 //calculate the CRC16 00460 if (CRCMode && ((Workspace[0] != Workspace[2]) 00461 || (Workspace[1] != Workspace[3]))) 00462 //if the CRC is invalid, return "read error" 00463 { return 0x01; } 00464 else 00465 { return 0x00; } 00466 } 00467 unsigned char SDCard::Read( 00468 unsigned int Address, unsigned char SectorCount, unsigned char* Data) 00469 { 00470 unsigned char Workspace[5]; 00471 //work area for card commands and data transactions 00472 00473 if (Capacity) 00474 //send the multiple-block read command addressed for high-capacity 00475 //cards 00476 { 00477 Command(18, Address, Workspace); 00478 } 00479 else 00480 //send the multiple-block read command addressed for low-capacity 00481 //cards 00482 { 00483 Command(18, Address * 512, Workspace); 00484 } 00485 if (Workspace[0]) 00486 //if a command error occurs, return "parameter error" 00487 { return 0; } 00488 Workspace[4] = 0x00; 00489 //initialize error detection variable 00490 for (unsigned char i = 0; i < SectorCount; i++) 00491 //read each data sector 00492 { 00493 ChipSelect.write(0); 00494 t = 0; 00495 do 00496 { 00497 t++; 00498 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); 00499 //get to the data block start token 00500 if (t == Timeout) 00501 { 00502 break; 00503 } 00504 //if a block read operation times out, stop operations 00505 for (unsigned int j = i * 512; j < (i + 1) * 512; j++) 00506 { 00507 Data[j] = DataLines.write(0xFF); 00508 } 00509 //read the data block 00510 Workspace[2] = DataLines.write(0xFF); 00511 Workspace[3] = DataLines.write(0xFF); 00512 //read the data CRC from the card 00513 ChipSelect.write(1); 00514 DataCRC(512, &Data[i * 512], Workspace); 00515 //calculate the CRC16 for each read data block 00516 Workspace[4] |= (CRCMode && ((Workspace[0] != Workspace[2]) 00517 || (Workspace[1] != Workspace[3]))); 00518 //record if any invalid CRCs are detected during the 00519 //transaction 00520 } 00521 Command(12, 0, Workspace); 00522 //send the stop transmission command 00523 ChipSelect.write(0); 00524 while (!DataLines.write(0xFF)); 00525 //get through the busy signal 00526 ChipSelect.write(1); 00527 DataLines.write(0xFF); 00528 if ((Workspace[4]) || (t == Timeout)) 00529 //if an invalid CRC was detected, return "read error" 00530 { return 0x01; } 00531 else 00532 { return 0x00; } 00533 } 00534 00535 unsigned char SDCard::SelectCRCMode(bool Mode) 00536 { 00537 unsigned char Response; 00538 00539 if (CRCMode != Mode) 00540 //only send command if CRCMode has been changed 00541 { 00542 t = 0; 00543 do 00544 { 00545 Command(59, Mode, &Response); 00546 //send the set CRC mode command 00547 t++; 00548 } while (Response && (t < Timeout)); 00549 CRCMode = Mode; 00550 } 00551 if (t == Timeout) 00552 //if the command times out, return "error" 00553 { return 0x01; } 00554 else 00555 { return 0x00; } 00556 } 00557 00558 void SDCard::SetTimeout(unsigned int Retries) 00559 { 00560 Timeout = Retries; 00561 //Set the global number of times for operations to be retried 00562 } 00563 00564 unsigned char SDCard::Initialize() 00565 { 00566 unsigned char Workspace[5]; 00567 //work area for card commands and data transactions 00568 00569 for (unsigned char i = 0; i < 16; i++) 00570 //clock card at least 74 times to power up 00571 { 00572 DataLines.write(0xFF); 00573 } 00574 00575 t = 0; 00576 do 00577 { 00578 Command(0, 0, Workspace); 00579 //send the reset command to put the card into SPI mode 00580 t++; 00581 } while ((Workspace[0] != 0x01) && (t < Timeout)); 00582 //check for command acceptance 00583 if (t == Timeout) { Status = 0x01; return Status; } 00584 00585 t = 0; 00586 do 00587 { 00588 Command(59, 1, Workspace); 00589 //turn on CRCs 00590 t++; 00591 } while ((Workspace[0] != 0x01) && (Workspace[0] != 0x05) 00592 && (t < Timeout)); 00593 //the set CRC mode command is not valid for all cards in idle state 00594 if (t == Timeout) { Status = 0x01; return Status; } 00595 00596 t = 0; 00597 do 00598 { 00599 Command(8, 426, Workspace); 00600 //the voltage bits are 0x01 for 2.7V - 3.6V, the check pattern is 00601 //0xAA, 0x000001AA converts to decimal 426 00602 t++; 00603 } while (((Workspace[0] != 0x01) || ((Workspace[3] & 0x0F) != 0x01) || 00604 (Workspace[4] != 0xAA)) && (Workspace[0] != 0x05) && (t < Timeout)); 00605 //check the version, voltage acceptance, and check pattern 00606 if (t == Timeout) { Status = 0x01; return Status; } 00607 Version = Workspace[0] != 0x05; 00608 //store the card version 00609 00610 if (!Version) 00611 { 00612 t = 0; 00613 do 00614 { 00615 Command(16, 512, Workspace); 00616 //set the data-block length to 512 bytes 00617 t++; 00618 } while (Workspace[0] && (t < Timeout)); 00619 if (t == Timeout) { Status = 0x01; return Status; } 00620 } 00621 00622 t = 0; 00623 do 00624 { 00625 Command(58, 0, Workspace); 00626 //check the OCR 00627 t++; 00628 } while (((Workspace[0] != 0x01) || 00629 !((Workspace[2] & 0x20) || (Workspace[2] & 0x10))) && (t < Timeout)); 00630 //check for the correct operating voltage, 3.3V 00631 if (t == Timeout) { Status = 0x01; return Status; } 00632 00633 t = 0; 00634 do 00635 { 00636 Command(55, 0, Workspace); 00637 //initialize card command is application-specific 00638 Command(41, 1073741824, Workspace); 00639 //specify host supports high capacity cards, 0x40000000 converts to 00640 //decimal 1073741824d 00641 t++; 00642 } while (Workspace[0] && (t < Timeout)); 00643 //check if the card is ready 00644 if (t == Timeout) { Status = 0x01; return Status; } 00645 00646 if (SelectCRCMode(1)) 00647 //turn on CRCs for all cards 00648 { Status = 0x01; return Status; } 00649 00650 t = 0; 00651 do 00652 { 00653 Command(58, 0, Workspace); 00654 //check the OCR again 00655 t++; 00656 } while ((Workspace[0] || !(Workspace[1] & 0x80)) && (t < Timeout)); 00657 //check the power up status 00658 if (t == Timeout) { Status = 0x01; return Status; } 00659 for (unsigned char i = 0; i < 4; i++) 00660 //record the OCR 00661 { 00662 OCR[i] = Workspace[i + 1]; 00663 } 00664 Capacity = (OCR[0] & 0x40) == 0x40; 00665 //record the capacity 00666 00667 t = 0; 00668 do 00669 { 00670 do 00671 { 00672 Command(9, 0, Workspace); 00673 //read the CSD 00674 t++; 00675 } while (Workspace[0] && (t < Timeout)); 00676 if (t == Timeout) { Status = 0x01; return Status; } 00677 ChipSelect.write(0); 00678 do 00679 { 00680 t++; 00681 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); 00682 //get to the start data block token 00683 if (t == Timeout) { ChipSelect.write(1); DataLines.write(0xFF); 00684 Status = 0x01; return Status; } 00685 for (unsigned char i = 0; i < 16; i++) 00686 //record the CSD 00687 { 00688 CSD[i] = DataLines.write(0xFF); 00689 } 00690 Workspace[2] = DataLines.write(0xFF); 00691 Workspace[3] = DataLines.write(0xFF); 00692 //save the CSD CRC16 00693 ChipSelect.write(1); 00694 DataLines.write(0xFF); 00695 DataCRC(16, CSD, Workspace); 00696 //calculate the CSD CRC16 00697 Workspace[4] = 0; 00698 for (unsigned char i = 0; i < 15; i++) 00699 { 00700 Workspace[4] = CommandCRCTable[Workspace[4]] ^ CSD[i]; 00701 } 00702 Workspace[4] = CommandCRCTable[Workspace[4]] | 0x01; 00703 //calculate the CSD CRC7 00704 t++; 00705 } while (((Workspace[0] != Workspace[2]) || (Workspace[1] != Workspace[3]) 00706 || (Workspace[4] != CSD[15])) && (t < Timeout)); 00707 //perform all CSD CRCs 00708 if (t == Timeout) { Status = 0x01; return Status; } 00709 00710 if (((CSD[3] & 0x07) > 0x02) || 00711 (((CSD[3] & 0x78) > 0x30) && ((CSD[3] & 0x07) > 0x01))) 00712 //read the CSD card speed bits and speed up card operations 00713 { 00714 DataLines.frequency(25000000); 00715 //maximum frequency is 25MHz 00716 } 00717 else 00718 { 00719 Workspace[0] = 1; 00720 for (unsigned char i = 0; i < (CSD[3] & 0x07); i++) 00721 { 00722 Workspace[0] *= 10; 00723 //the first three bits are a power of ten multiplier for speed 00724 } 00725 switch (CSD[3] & 0x78) 00726 { 00727 case 0x08: DataLines.frequency(Workspace[0] * 100000); break; 00728 case 0x10: DataLines.frequency(Workspace[0] * 120000); break; 00729 case 0x18: DataLines.frequency(Workspace[0] * 140000); break; 00730 case 0x20: DataLines.frequency(Workspace[0] * 150000); break; 00731 case 0x28: DataLines.frequency(Workspace[0] * 200000); break; 00732 case 0x30: DataLines.frequency(Workspace[0] * 250000); break; 00733 case 0x38: DataLines.frequency(Workspace[0] * 300000); break; 00734 case 0x40: DataLines.frequency(Workspace[0] * 350000); break; 00735 case 0x48: DataLines.frequency(Workspace[0] * 400000); break; 00736 case 0x50: DataLines.frequency(Workspace[0] * 450000); break; 00737 case 0x58: DataLines.frequency(Workspace[0] * 500000); break; 00738 case 0x60: DataLines.frequency(Workspace[0] * 550000); break; 00739 case 0x68: DataLines.frequency(Workspace[0] * 600000); break; 00740 case 0x70: DataLines.frequency(Workspace[0] * 700000); break; 00741 case 0x78: DataLines.frequency(Workspace[0] * 800000); break; 00742 default: break; 00743 } 00744 } 00745 00746 if (CSD[4] & 0x40) 00747 //check for switch command class support 00748 { 00749 t = 0; 00750 do 00751 { 00752 Command(6, 2147483649, Workspace); 00753 //switch to high-speed mode (SDR25, 50MHz) 00754 t++; 00755 } while (Workspace[0] && (Workspace[0] != 0x04) && (t < Timeout)); 00756 //some cards that support switch class commands respond with 00757 //"illegal command" 00758 if (t == Timeout) { Status = 0x01; return Status; } 00759 if (!Workspace[0]) 00760 { 00761 do 00762 { 00763 ChipSelect.write(0); 00764 do 00765 { 00766 t++; 00767 } while ((DataLines.write(0xFF) != 0xFE) && (t < Timeout)); 00768 //get to the start data block token 00769 if (t == Timeout) { ChipSelect.write(1); 00770 DataLines.write(0xFF); Status = 0x01; return Status; } 00771 for (unsigned char i = 0; i < 64; i++) 00772 //gather the function status register 00773 { 00774 FSR[i] = DataLines.write(0xFF); 00775 } 00776 Workspace[2] = DataLines.write(0xFF); 00777 Workspace[3] = DataLines.write(0xFF); 00778 //record the CRC16 00779 ChipSelect.write(1); 00780 DataLines.write(0xFF); 00781 DataCRC(64, FSR, Workspace); 00782 //calculate the CRC16 00783 t++; 00784 } while (((Workspace[0] != Workspace[2]) 00785 || (Workspace[1] != Workspace[3])) && (t < Timeout)); 00786 //perform the CRC 00787 if (t == Timeout) { Status = 0x01; return Status; } 00788 if ((FSR[13] & 0x02) && ((FSR[16] & 0x0F) == 0x01)) 00789 { 00790 DataLines.frequency(50000000); 00791 //increase the speed if the function switch was successful 00792 } 00793 } 00794 } 00795 00796 if (SelectCRCMode(0)) 00797 { Status = 0x01; return Status; } 00798 //turn off CRCs 00799 00800 Status = 0x00; 00801 return Status; 00802 } 00803 00804 void SDCard::Command( 00805 unsigned char Index, unsigned int Argument, unsigned char* Response) 00806 { 00807 CommandCRC(&Index, &Argument, Response); 00808 //calculate the CRC7 00809 ChipSelect.write(0); 00810 //assert chip select low to synchronize the command 00811 DataLines.write(0x40 | Index); 00812 //the index is assumed valid, commands start with bits 01 00813 DataLines.write(((char*)&Argument)[3]); 00814 DataLines.write(((char*)&Argument)[2]); 00815 DataLines.write(((char*)&Argument)[1]); 00816 DataLines.write(((char*)&Argument)[0]); 00817 //send the argument bytes in order from MSB to LSB 00818 DataLines.write(*Response); 00819 //send the CRC7 00820 t = 0; 00821 do 00822 { 00823 Response[0] = DataLines.write(0xFF); 00824 //clock the card high to let it run operations, the first byte 00825 //will be busy (all high), the response will be sent later 00826 t++; 00827 } while ((Response[0] & 0x80) && (t < Timeout)); 00828 //check for a response by testing if the first bit is low 00829 if ((Index == 8) || (Index == 13) || (Index == 58)) 00830 //if the command returns a larger response, get the rest of it 00831 { 00832 for (unsigned char i = 1; i < 5; i++) 00833 { 00834 Response[i] = DataLines.write(0xFF); 00835 } 00836 } 00837 ChipSelect.write(1); 00838 //assert chip select high to synchronize command 00839 DataLines.write(0xFF); 00840 //clock the deselected card high to complete processing for some cards 00841 } 00842 00843 void SDCard::CommandCRC( 00844 unsigned char* IndexPtr, unsigned int* ArgumentPtr, unsigned char* Result) 00845 { 00846 if (CRCMode) 00847 //only calculate if data-checks are desired 00848 { 00849 Result[0] = 00850 CommandCRCTable[ 00851 CommandCRCTable[ 00852 CommandCRCTable[ 00853 CommandCRCTable[ 00854 CommandCRCTable[ 00855 *IndexPtr | 0x40 00856 ] ^ ((char*)ArgumentPtr)[3] 00857 ] ^ ((char*)ArgumentPtr)[2] 00858 ] ^ ((char*)ArgumentPtr)[1] 00859 ] ^ ((char*)ArgumentPtr)[0] 00860 ] | 0x01; 00861 //calculate the CRC7, SD protocol requires the last bit to be high 00862 } 00863 else 00864 //if no data-checking is desired, the return bits are not used 00865 { 00866 Result[0] = 0xFF; 00867 } 00868 } 00869 00870 void SDCard::DataCRC( 00871 unsigned short Length, unsigned char* Data, unsigned char* Result) 00872 { 00873 if (CRCMode) 00874 //only calculate if data-checks are desired 00875 { 00876 unsigned char Reference; 00877 //store the current CRC16 lookup value 00878 Result[0] = 0x00; 00879 Result[1] = 0x00; 00880 //initialize the result carrier 00881 for (unsigned short i = 0; i < Length; i++) 00882 //step through each byte of the data to be checked 00883 { 00884 Reference = Result[0]; 00885 //record the current CRC16 lookup for both bytes 00886 Result[0] = DataCRCTable[2 * Reference] ^ Result[1]; 00887 //the first byte result is XORed with the old second byte 00888 Result[1] = DataCRCTable[(2 * Reference) + 1] ^ Data[i]; 00889 //the second byte result is XORed with the new data byte 00890 } 00891 for (unsigned char i = 0; i < 2; i++) 00892 //the final result must be XORed with two 0x00 bytes 00893 { 00894 Reference = Result[0]; 00895 Result[0] = DataCRCTable[2 * Reference] ^ Result[1]; 00896 Result[1] = DataCRCTable[(2 * Reference) + 1]; 00897 } 00898 } 00899 else 00900 //if no data-checking is desired, the return bits are not used 00901 { 00902 Result[0] = 0xFF; 00903 Result[1] = 0xFF; 00904 } 00905 } 00906 00907 void SDCard::GenerateCRCTable(unsigned char Size, 00908 unsigned long long Generator, unsigned char* Table) 00909 { 00910 unsigned char Index[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 00911 //this will hold information from the generator; the position indicates 00912 //the order of the encountered 1, the value indicates its position in 00913 //the generator, the 9th entry indicates the number of 1's encountered 00914 00915 for (unsigned char i = 0; i < 64; i++) 00916 //shift generator left until the first bit is high 00917 { 00918 if (((char*)&Generator)[7] & 0x80) 00919 { break; } 00920 Generator = Generator << 1; 00921 } 00922 for (unsigned char i = 0; i < Size; i++) 00923 //initialize table 00924 { 00925 Table[i] = 0x00; 00926 } 00927 for (unsigned char i = 0; i < 8; i++) 00928 //increment through each generator bit 00929 { 00930 if ((0x80 >> i) & ((unsigned char*)&Generator)[7]) 00931 //if a 1 is encountered in the generator, record its order and 00932 //location and increment the counter 00933 { 00934 Index[Index[8]] = i; 00935 Index[8]++; 00936 } 00937 for (unsigned char j = 0; j < (0x01 << i); j++) 00938 //each bit doubles the number of XOR operations 00939 { 00940 for (unsigned char k = 0; k < Size; k++) 00941 //we need to precalculate each byte in the CRC table 00942 { 00943 Table[(Size * ((0x01 << i) + j)) + k] 00944 = Table[(Size * j) + k]; 00945 //each power of two is equal to all previous entries with 00946 //an added XOR with the generator on the leftmost bit and 00947 //on each succeeding 1 in the generator 00948 for (unsigned char l = 0; l < Index[8]; l++) 00949 //increment through the encountered generator 1s 00950 { 00951 Table[(Size * ((0x01 << i) + j)) + k] ^= 00952 (((unsigned char*)&Generator)[7-k] 00953 << (i + 1 - Index[l])); 00954 Table[(Size * ((0x01 << i) + j)) + k] ^= 00955 (((unsigned char*)&Generator)[6-k] 00956 >> (7 - i + Index[l])); 00957 //XOR the new bit and the new generator 1s 00958 } 00959 } 00960 } 00961 } 00962 }
Generated on Wed Jul 13 2022 05:31:45 by 1.7.2