| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 | 
							- /*
 
-  * This program will format an SD or SDHC card.
 
-  * Warning all data will be deleted!
 
-  *
 
-  * For SD/SDHC cards larger than 64 MB this
 
-  * program attempts to match the format
 
-  * generated by SDFormatter available here:
 
-  *
 
-  * http://www.sdcard.org/consumers/formatter/
 
-  *
 
-  * For smaller cards this program uses FAT16
 
-  * and SDFormatter uses FAT12.
 
-  */
 
- #error  use new Version 2 SdFormatter
 
- // Set USE_SDIO to zero for SPI card access.
 
- #define USE_SDIO 0
 
- //
 
- // Change the value of chipSelect if your hardware does
 
- // not use the default value, SS.  Common values are:
 
- // Arduino Ethernet shield: pin 4
 
- // Sparkfun SD shield: pin 8
 
- // Adafruit SD shields and modules: pin 10
 
- const uint8_t chipSelect = SS;
 
- // Initialize at highest supported speed not over 50 MHz.
 
- // Reduce max speed if errors occur.
 
- #define SPI_SPEED SD_SCK_MHZ(50)
 
- // Print extra info for debug if DEBUG_PRINT is nonzero
 
- #define DEBUG_PRINT 0
 
- #include <SPI.h>
 
- #include "SdFat.h"
 
- #include "sdios.h"
 
- #if DEBUG_PRINT
 
- #include "FreeStack.h"
 
- #endif  // DEBUG_PRINT
 
- // Serial output stream
 
- ArduinoOutStream cout(Serial);
 
- #if USE_SDIO
 
- // Use faster SdioCardEX
 
- SdioCardEX card;
 
- // SdioCard card;
 
- #else  // USE_SDIO
 
- Sd2Card card;
 
- #endif  // USE_SDIO
 
- uint32_t cardSizeBlocks;
 
- uint32_t cardCapacityMB;
 
- // cache for SD block
 
- cache_t cache;
 
- // MBR information
 
- uint8_t partType;
 
- uint32_t relSector;
 
- uint32_t partSize;
 
- // Fake disk geometry
 
- uint8_t numberOfHeads;
 
- uint8_t sectorsPerTrack;
 
- // FAT parameters
 
- uint16_t reservedSectors;
 
- uint8_t sectorsPerCluster;
 
- uint32_t fatStart;
 
- uint32_t fatSize;
 
- uint32_t dataStart;
 
- // constants for file system structure
 
- uint16_t const BU16 = 128;
 
- uint16_t const BU32 = 8192;
 
- //  strings needed in file system structures
 
- char noName[] = "NO NAME    ";
 
- char fat16str[] = "FAT16   ";
 
- char fat32str[] = "FAT32   ";
 
- //------------------------------------------------------------------------------
 
- #define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();}
 
- //------------------------------------------------------------------------------
 
- void sdErrorHalt() {
 
-   if (card.errorCode()) {
 
-     cout << F("SD error: ") << hex << int(card.errorCode());
 
-     cout << ',' << int(card.errorData()) << dec << endl;
 
-   }
 
-   while (true) {}
 
- }
 
- //------------------------------------------------------------------------------
 
- #if DEBUG_PRINT
 
- void debugPrint() {
 
-   cout << F("FreeStack: ") << FreeStack() << endl;
 
-   cout << F("partStart: ") << relSector << endl;
 
-   cout << F("partSize: ") << partSize << endl;
 
-   cout << F("reserved: ") << reservedSectors << endl;
 
-   cout << F("fatStart: ") << fatStart << endl;
 
-   cout << F("fatSize: ") << fatSize << endl;
 
-   cout << F("dataStart: ") << dataStart << endl;
 
-   cout << F("clusterCount: ");
 
-   cout << ((relSector + partSize - dataStart)/sectorsPerCluster) << endl;
 
-   cout << endl;
 
-   cout << F("Heads: ") << int(numberOfHeads) << endl;
 
-   cout << F("Sectors: ") << int(sectorsPerTrack) << endl;
 
-   cout << F("Cylinders: ");
 
-   cout << cardSizeBlocks/(numberOfHeads*sectorsPerTrack) << endl;
 
- }
 
- #endif  // DEBUG_PRINT
 
- //------------------------------------------------------------------------------
 
- // write cached block to the card
 
- uint8_t writeCache(uint32_t lbn) {
 
-   return card.writeBlock(lbn, cache.data);
 
- }
 
- //------------------------------------------------------------------------------
 
- // initialize appropriate sizes for SD capacity
 
- void initSizes() {
 
-   if (cardCapacityMB <= 6) {
 
-     sdError("Card is too small.");
 
-   } else if (cardCapacityMB <= 16) {
 
-     sectorsPerCluster = 2;
 
-   } else if (cardCapacityMB <= 32) {
 
-     sectorsPerCluster = 4;
 
-   } else if (cardCapacityMB <= 64) {
 
-     sectorsPerCluster = 8;
 
-   } else if (cardCapacityMB <= 128) {
 
-     sectorsPerCluster = 16;
 
-   } else if (cardCapacityMB <= 1024) {
 
-     sectorsPerCluster = 32;
 
-   } else if (cardCapacityMB <= 32768) {
 
-     sectorsPerCluster = 64;
 
-   } else {
 
-     // SDXC cards
 
-     sectorsPerCluster = 128;
 
-   }
 
-   cout << F("Blocks/Cluster: ") << int(sectorsPerCluster) << endl;
 
-   // set fake disk geometry
 
-   sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
 
-   if (cardCapacityMB <= 16) {
 
-     numberOfHeads = 2;
 
-   } else if (cardCapacityMB <= 32) {
 
-     numberOfHeads = 4;
 
-   } else if (cardCapacityMB <= 128) {
 
-     numberOfHeads = 8;
 
-   } else if (cardCapacityMB <= 504) {
 
-     numberOfHeads = 16;
 
-   } else if (cardCapacityMB <= 1008) {
 
-     numberOfHeads = 32;
 
-   } else if (cardCapacityMB <= 2016) {
 
-     numberOfHeads = 64;
 
-   } else if (cardCapacityMB <= 4032) {
 
-     numberOfHeads = 128;
 
-   } else {
 
-     numberOfHeads = 255;
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- // zero cache and optionally set the sector signature
 
- void clearCache(uint8_t addSig) {
 
-   memset(&cache, 0, sizeof(cache));
 
-   if (addSig) {
 
-     cache.mbr.mbrSig0 = BOOTSIG0;
 
-     cache.mbr.mbrSig1 = BOOTSIG1;
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- // zero FAT and root dir area on SD
 
- void clearFatDir(uint32_t bgn, uint32_t count) {
 
-   clearCache(false);
 
- #if USE_SDIO
 
-   for (uint32_t i = 0; i < count; i++) {
 
-     if (!card.writeBlock(bgn + i, cache.data)) {
 
-        sdError("Clear FAT/DIR writeBlock failed");
 
-     }
 
-     if ((i & 0XFF) == 0) {
 
-       cout << '.';
 
-     }
 
-   }
 
- #else  // USE_SDIO
 
-   if (!card.writeStart(bgn, count)) {
 
-     sdError("Clear FAT/DIR writeStart failed");
 
-   }
 
-   for (uint32_t i = 0; i < count; i++) {
 
-     if ((i & 0XFF) == 0) {
 
-       cout << '.';
 
-     }
 
-     if (!card.writeData(cache.data)) {
 
-       sdError("Clear FAT/DIR writeData failed");
 
-     }
 
-   }
 
-   if (!card.writeStop()) {
 
-     sdError("Clear FAT/DIR writeStop failed");
 
-   }
 
- #endif  // USE_SDIO
 
-   cout << endl;
 
- }
 
- //------------------------------------------------------------------------------
 
- // return cylinder number for a logical block number
 
- uint16_t lbnToCylinder(uint32_t lbn) {
 
-   return lbn / (numberOfHeads * sectorsPerTrack);
 
- }
 
- //------------------------------------------------------------------------------
 
- // return head number for a logical block number
 
- uint8_t lbnToHead(uint32_t lbn) {
 
-   return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
 
- }
 
- //------------------------------------------------------------------------------
 
- // return sector number for a logical block number
 
- uint8_t lbnToSector(uint32_t lbn) {
 
-   return (lbn % sectorsPerTrack) + 1;
 
- }
 
- //------------------------------------------------------------------------------
 
- // format and write the Master Boot Record
 
- void writeMbr() {
 
-   clearCache(true);
 
-   part_t* p = cache.mbr.part;
 
-   p->boot = 0;
 
-   uint16_t c = lbnToCylinder(relSector);
 
-   if (c > 1023) {
 
-     sdError("MBR CHS");
 
-   }
 
-   p->beginCylinderHigh = c >> 8;
 
-   p->beginCylinderLow = c & 0XFF;
 
-   p->beginHead = lbnToHead(relSector);
 
-   p->beginSector = lbnToSector(relSector);
 
-   p->type = partType;
 
-   uint32_t endLbn = relSector + partSize - 1;
 
-   c = lbnToCylinder(endLbn);
 
-   if (c <= 1023) {
 
-     p->endCylinderHigh = c >> 8;
 
-     p->endCylinderLow = c & 0XFF;
 
-     p->endHead = lbnToHead(endLbn);
 
-     p->endSector = lbnToSector(endLbn);
 
-   } else {
 
-     // Too big flag, c = 1023, h = 254, s = 63
 
-     p->endCylinderHigh = 3;
 
-     p->endCylinderLow = 255;
 
-     p->endHead = 254;
 
-     p->endSector = 63;
 
-   }
 
-   p->firstSector = relSector;
 
-   p->totalSectors = partSize;
 
-   if (!writeCache(0)) {
 
-     sdError("write MBR");
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- // generate serial number from card size and micros since boot
 
- uint32_t volSerialNumber() {
 
-   return (cardSizeBlocks << 8) + micros();
 
- }
 
- //------------------------------------------------------------------------------
 
- // format the SD as FAT16
 
- void makeFat16() {
 
-   uint32_t nc;
 
-   for (dataStart = 2 * BU16;; dataStart += BU16) {
 
-     nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
 
-     fatSize = (nc + 2 + 255)/256;
 
-     uint32_t r = BU16 + 1 + 2 * fatSize + 32;
 
-     if (dataStart < r) {
 
-       continue;
 
-     }
 
-     relSector = dataStart - r + BU16;
 
-     break;
 
-   }
 
-   // check valid cluster count for FAT16 volume
 
-   if (nc < 4085 || nc >= 65525) {
 
-     sdError("Bad cluster count");
 
-   }
 
-   reservedSectors = 1;
 
-   fatStart = relSector + reservedSectors;
 
-   partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
 
-   if (partSize < 32680) {
 
-     partType = 0X01;
 
-   } else if (partSize < 65536) {
 
-     partType = 0X04;
 
-   } else {
 
-     partType = 0X06;
 
-   }
 
-   // write MBR
 
-   writeMbr();
 
-   clearCache(true);
 
-   fat_boot_t* pb = &cache.fbs;
 
-   pb->jump[0] = 0XEB;
 
-   pb->jump[1] = 0X00;
 
-   pb->jump[2] = 0X90;
 
-   for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
 
-     pb->oemId[i] = ' ';
 
-   }
 
-   pb->bytesPerSector = 512;
 
-   pb->sectorsPerCluster = sectorsPerCluster;
 
-   pb->reservedSectorCount = reservedSectors;
 
-   pb->fatCount = 2;
 
-   pb->rootDirEntryCount = 512;
 
-   pb->mediaType = 0XF8;
 
-   pb->sectorsPerFat16 = fatSize;
 
-   pb->sectorsPerTrack = sectorsPerTrack;
 
-   pb->headCount = numberOfHeads;
 
-   pb->hidddenSectors = relSector;
 
-   pb->totalSectors32 = partSize;
 
-   pb->driveNumber = 0X80;
 
-   pb->bootSignature = EXTENDED_BOOT_SIG;
 
-   pb->volumeSerialNumber = volSerialNumber();
 
-   memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
 
-   memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
 
-   // write partition boot sector
 
-   if (!writeCache(relSector)) {
 
-     sdError("FAT16 write PBS failed");
 
-   }
 
-   // clear FAT and root directory
 
-   clearFatDir(fatStart, dataStart - fatStart);
 
-   clearCache(false);
 
-   cache.fat16[0] = 0XFFF8;
 
-   cache.fat16[1] = 0XFFFF;
 
-   // write first block of FAT and backup for reserved clusters
 
-   if (!writeCache(fatStart)
 
-       || !writeCache(fatStart + fatSize)) {
 
-     sdError("FAT16 reserve failed");
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- // format the SD as FAT32
 
- void makeFat32() {
 
-   uint32_t nc;
 
-   relSector = BU32;
 
-   for (dataStart = 2 * BU32;; dataStart += BU32) {
 
-     nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
 
-     fatSize = (nc + 2 + 127)/128;
 
-     uint32_t r = relSector + 9 + 2 * fatSize;
 
-     if (dataStart >= r) {
 
-       break;
 
-     }
 
-   }
 
-   // error if too few clusters in FAT32 volume
 
-   if (nc < 65525) {
 
-     sdError("Bad cluster count");
 
-   }
 
-   reservedSectors = dataStart - relSector - 2 * fatSize;
 
-   fatStart = relSector + reservedSectors;
 
-   partSize = nc * sectorsPerCluster + dataStart - relSector;
 
-   // type depends on address of end sector
 
-   // max CHS has lbn = 16450560 = 1024*255*63
 
-   if ((relSector + partSize) <= 16450560) {
 
-     // FAT32
 
-     partType = 0X0B;
 
-   } else {
 
-     // FAT32 with INT 13
 
-     partType = 0X0C;
 
-   }
 
-   writeMbr();
 
-   clearCache(true);
 
-   fat32_boot_t* pb = &cache.fbs32;
 
-   pb->jump[0] = 0XEB;
 
-   pb->jump[1] = 0X00;
 
-   pb->jump[2] = 0X90;
 
-   for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
 
-     pb->oemId[i] = ' ';
 
-   }
 
-   pb->bytesPerSector = 512;
 
-   pb->sectorsPerCluster = sectorsPerCluster;
 
-   pb->reservedSectorCount = reservedSectors;
 
-   pb->fatCount = 2;
 
-   pb->mediaType = 0XF8;
 
-   pb->sectorsPerTrack = sectorsPerTrack;
 
-   pb->headCount = numberOfHeads;
 
-   pb->hidddenSectors = relSector;
 
-   pb->totalSectors32 = partSize;
 
-   pb->sectorsPerFat32 = fatSize;
 
-   pb->fat32RootCluster = 2;
 
-   pb->fat32FSInfo = 1;
 
-   pb->fat32BackBootBlock = 6;
 
-   pb->driveNumber = 0X80;
 
-   pb->bootSignature = EXTENDED_BOOT_SIG;
 
-   pb->volumeSerialNumber = volSerialNumber();
 
-   memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
 
-   memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
 
-   // write partition boot sector and backup
 
-   if (!writeCache(relSector)
 
-       || !writeCache(relSector + 6)) {
 
-     sdError("FAT32 write PBS failed");
 
-   }
 
-   clearCache(true);
 
-   // write extra boot area and backup
 
-   if (!writeCache(relSector + 2)
 
-       || !writeCache(relSector + 8)) {
 
-     sdError("FAT32 PBS ext failed");
 
-   }
 
-   fat32_fsinfo_t* pf = &cache.fsinfo;
 
-   pf->leadSignature = FSINFO_LEAD_SIG;
 
-   pf->structSignature = FSINFO_STRUCT_SIG;
 
-   pf->freeCount = 0XFFFFFFFF;
 
-   pf->nextFree = 0XFFFFFFFF;
 
-   // write FSINFO sector and backup
 
-   if (!writeCache(relSector + 1)
 
-       || !writeCache(relSector + 7)) {
 
-     sdError("FAT32 FSINFO failed");
 
-   }
 
-   clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
 
-   clearCache(false);
 
-   cache.fat32[0] = 0x0FFFFFF8;
 
-   cache.fat32[1] = 0x0FFFFFFF;
 
-   cache.fat32[2] = 0x0FFFFFFF;
 
-   // write first block of FAT and backup for reserved clusters
 
-   if (!writeCache(fatStart)
 
-       || !writeCache(fatStart + fatSize)) {
 
-     sdError("FAT32 reserve failed");
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- // flash erase all data
 
- uint32_t const ERASE_SIZE = 262144L;
 
- void eraseCard() {
 
-   cout << endl << F("Erasing\n");
 
-   uint32_t firstBlock = 0;
 
-   uint32_t lastBlock;
 
-   uint16_t n = 0;
 
-   do {
 
-     lastBlock = firstBlock + ERASE_SIZE - 1;
 
-     if (lastBlock >= cardSizeBlocks) {
 
-       lastBlock = cardSizeBlocks - 1;
 
-     }
 
-     if (!card.erase(firstBlock, lastBlock)) {
 
-       sdError("erase failed");
 
-     }
 
-     cout << '.';
 
-     if ((n++)%32 == 31) {
 
-       cout << endl;
 
-     }
 
-     firstBlock += ERASE_SIZE;
 
-   } while (firstBlock < cardSizeBlocks);
 
-   cout << endl;
 
-   if (!card.readBlock(0, cache.data)) {
 
-     sdError("readBlock");
 
-   }
 
-   cout << hex << showbase << setfill('0') << internal;
 
-   cout << F("All data set to ") << setw(4) << int(cache.data[0]) << endl;
 
-   cout << dec << noshowbase << setfill(' ') << right;
 
-   cout << F("Erase done\n");
 
- }
 
- //------------------------------------------------------------------------------
 
- void formatCard() {
 
-   cout << endl;
 
-   cout << F("Formatting\n");
 
-   initSizes();
 
-   if (card.type() != SD_CARD_TYPE_SDHC) {
 
-     cout << F("FAT16\n");
 
-     makeFat16();
 
-   } else {
 
-     cout << F("FAT32\n");
 
-     makeFat32();
 
-   }
 
- #if DEBUG_PRINT
 
-   debugPrint();
 
- #endif  // DEBUG_PRINT
 
-   cout << F("Format done\n");
 
- }
 
- //------------------------------------------------------------------------------
 
- void setup() {
 
-   char c;
 
-   Serial.begin(9600);
 
-   // Wait for USB Serial
 
-   while (!Serial) {
 
-     yield();
 
-   }
 
-   cout << F("Type any character to start\n");
 
-   while (!Serial.available()) {
 
-     yield();
 
-   }
 
-   // Discard any extra characters.
 
-   do {
 
-     delay(10);
 
-   } while (Serial.available() && Serial.read() >= 0);
 
-   cout << F(
 
-          "\n"
 
-          "This program can erase and/or format SD/SDHC cards.\n"
 
-          "\n"
 
-          "Erase uses the card's fast flash erase command.\n"
 
-          "Flash erase sets all data to 0X00 for most cards\n"
 
-          "and 0XFF for a few vendor's cards.\n"
 
-          "\n"
 
-          "Cards larger than 2 GB will be formatted FAT32 and\n"
 
-          "smaller cards will be formatted FAT16.\n"
 
-          "\n"
 
-          "Warning, all data on the card will be erased.\n"
 
-          "Enter 'Y' to continue: ");
 
-   while (!Serial.available()) {
 
-     yield();
 
-   }
 
-   c = Serial.read();
 
-   cout << c << endl;
 
-   if (c != 'Y') {
 
-     cout << F("Quiting, you did not enter 'Y'.\n");
 
-     return;
 
-   }
 
-   // Read any existing Serial data.
 
-   do {
 
-     delay(10);
 
-   } while (Serial.available() && Serial.read() >= 0);
 
-   cout << F(
 
-          "\n"
 
-          "Options are:\n"
 
-          "E - erase the card and skip formatting.\n"
 
-          "F - erase and then format the card. (recommended)\n"
 
-          "Q - quick format the card without erase.\n"
 
-          "\n"
 
-          "Enter option: ");
 
-   while (!Serial.available()) {
 
-     yield();
 
-   }
 
-   c = Serial.read();
 
-   cout << c << endl;
 
-   if (!strchr("EFQ", c)) {
 
-     cout << F("Quiting, invalid option entered.") << endl;
 
-     return;
 
-   }
 
- #if USE_SDIO
 
-   if (!card.begin()) {
 
-     sdError("card.begin failed");
 
-   }
 
- #else  // USE_SDIO
 
-   if (!card.begin(chipSelect, SPI_SPEED)) {
 
-     cout << F(
 
-            "\nSD initialization failure!\n"
 
-            "Is the SD card inserted correctly?\n"
 
-            "Is chip select correct at the top of this program?\n");
 
-     sdError("card.begin failed");
 
-   }
 
- #endif
 
-   cardSizeBlocks = card.cardSize();
 
-   if (cardSizeBlocks == 0) {
 
-     sdError("cardSize");
 
-   }
 
-   cardCapacityMB = (cardSizeBlocks + 2047)/2048;
 
-   cout << F("Card Size: ") << setprecision(0) << 1.048576*cardCapacityMB;
 
-   cout << F(" MB, (MB = 1,000,000 bytes)") << endl;
 
-   if (c == 'E' || c == 'F') {
 
-     eraseCard();
 
-   }
 
-   if (c == 'F' || c == 'Q') {
 
-     formatCard();
 
-   }
 
- }
 
- //------------------------------------------------------------------------------
 
- void loop() {}
 
 
  |