You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 5 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /*
  2. * This program will format an SD or SDHC card.
  3. * Warning all data will be deleted!
  4. *
  5. * For SD/SDHC cards larger than 64 MB this
  6. * program attempts to match the format
  7. * generated by SDFormatter available here:
  8. *
  9. * http://www.sdcard.org/consumers/formatter/
  10. *
  11. * For smaller cards this program uses FAT16
  12. * and SDFormatter uses FAT12.
  13. */
  14. #error use new Version 2 SdFormatter
  15. // Set USE_SDIO to zero for SPI card access.
  16. #define USE_SDIO 0
  17. //
  18. // Change the value of chipSelect if your hardware does
  19. // not use the default value, SS. Common values are:
  20. // Arduino Ethernet shield: pin 4
  21. // Sparkfun SD shield: pin 8
  22. // Adafruit SD shields and modules: pin 10
  23. const uint8_t chipSelect = SS;
  24. // Initialize at highest supported speed not over 50 MHz.
  25. // Reduce max speed if errors occur.
  26. #define SPI_SPEED SD_SCK_MHZ(50)
  27. // Print extra info for debug if DEBUG_PRINT is nonzero
  28. #define DEBUG_PRINT 0
  29. #include <SPI.h>
  30. #include "SdFat.h"
  31. #include "sdios.h"
  32. #if DEBUG_PRINT
  33. #include "FreeStack.h"
  34. #endif // DEBUG_PRINT
  35. // Serial output stream
  36. ArduinoOutStream cout(Serial);
  37. #if USE_SDIO
  38. // Use faster SdioCardEX
  39. SdioCardEX card;
  40. // SdioCard card;
  41. #else // USE_SDIO
  42. Sd2Card card;
  43. #endif // USE_SDIO
  44. uint32_t cardSizeBlocks;
  45. uint32_t cardCapacityMB;
  46. // cache for SD block
  47. cache_t cache;
  48. // MBR information
  49. uint8_t partType;
  50. uint32_t relSector;
  51. uint32_t partSize;
  52. // Fake disk geometry
  53. uint8_t numberOfHeads;
  54. uint8_t sectorsPerTrack;
  55. // FAT parameters
  56. uint16_t reservedSectors;
  57. uint8_t sectorsPerCluster;
  58. uint32_t fatStart;
  59. uint32_t fatSize;
  60. uint32_t dataStart;
  61. // constants for file system structure
  62. uint16_t const BU16 = 128;
  63. uint16_t const BU32 = 8192;
  64. // strings needed in file system structures
  65. char noName[] = "NO NAME ";
  66. char fat16str[] = "FAT16 ";
  67. char fat32str[] = "FAT32 ";
  68. //------------------------------------------------------------------------------
  69. #define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();}
  70. //------------------------------------------------------------------------------
  71. void sdErrorHalt() {
  72. if (card.errorCode()) {
  73. cout << F("SD error: ") << hex << int(card.errorCode());
  74. cout << ',' << int(card.errorData()) << dec << endl;
  75. }
  76. SysCall::halt();
  77. }
  78. //------------------------------------------------------------------------------
  79. #if DEBUG_PRINT
  80. void debugPrint() {
  81. cout << F("FreeStack: ") << FreeStack() << endl;
  82. cout << F("partStart: ") << relSector << endl;
  83. cout << F("partSize: ") << partSize << endl;
  84. cout << F("reserved: ") << reservedSectors << endl;
  85. cout << F("fatStart: ") << fatStart << endl;
  86. cout << F("fatSize: ") << fatSize << endl;
  87. cout << F("dataStart: ") << dataStart << endl;
  88. cout << F("clusterCount: ");
  89. cout << ((relSector + partSize - dataStart)/sectorsPerCluster) << endl;
  90. cout << endl;
  91. cout << F("Heads: ") << int(numberOfHeads) << endl;
  92. cout << F("Sectors: ") << int(sectorsPerTrack) << endl;
  93. cout << F("Cylinders: ");
  94. cout << cardSizeBlocks/(numberOfHeads*sectorsPerTrack) << endl;
  95. }
  96. #endif // DEBUG_PRINT
  97. //------------------------------------------------------------------------------
  98. // write cached block to the card
  99. uint8_t writeCache(uint32_t lbn) {
  100. return card.writeBlock(lbn, cache.data);
  101. }
  102. //------------------------------------------------------------------------------
  103. // initialize appropriate sizes for SD capacity
  104. void initSizes() {
  105. if (cardCapacityMB <= 6) {
  106. sdError("Card is too small.");
  107. } else if (cardCapacityMB <= 16) {
  108. sectorsPerCluster = 2;
  109. } else if (cardCapacityMB <= 32) {
  110. sectorsPerCluster = 4;
  111. } else if (cardCapacityMB <= 64) {
  112. sectorsPerCluster = 8;
  113. } else if (cardCapacityMB <= 128) {
  114. sectorsPerCluster = 16;
  115. } else if (cardCapacityMB <= 1024) {
  116. sectorsPerCluster = 32;
  117. } else if (cardCapacityMB <= 32768) {
  118. sectorsPerCluster = 64;
  119. } else {
  120. // SDXC cards
  121. sectorsPerCluster = 128;
  122. }
  123. cout << F("Blocks/Cluster: ") << int(sectorsPerCluster) << endl;
  124. // set fake disk geometry
  125. sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
  126. if (cardCapacityMB <= 16) {
  127. numberOfHeads = 2;
  128. } else if (cardCapacityMB <= 32) {
  129. numberOfHeads = 4;
  130. } else if (cardCapacityMB <= 128) {
  131. numberOfHeads = 8;
  132. } else if (cardCapacityMB <= 504) {
  133. numberOfHeads = 16;
  134. } else if (cardCapacityMB <= 1008) {
  135. numberOfHeads = 32;
  136. } else if (cardCapacityMB <= 2016) {
  137. numberOfHeads = 64;
  138. } else if (cardCapacityMB <= 4032) {
  139. numberOfHeads = 128;
  140. } else {
  141. numberOfHeads = 255;
  142. }
  143. }
  144. //------------------------------------------------------------------------------
  145. // zero cache and optionally set the sector signature
  146. void clearCache(uint8_t addSig) {
  147. memset(&cache, 0, sizeof(cache));
  148. if (addSig) {
  149. cache.mbr.mbrSig0 = BOOTSIG0;
  150. cache.mbr.mbrSig1 = BOOTSIG1;
  151. }
  152. }
  153. //------------------------------------------------------------------------------
  154. // zero FAT and root dir area on SD
  155. void clearFatDir(uint32_t bgn, uint32_t count) {
  156. clearCache(false);
  157. #if USE_SDIO
  158. for (uint32_t i = 0; i < count; i++) {
  159. if (!card.writeBlock(bgn + i, cache.data)) {
  160. sdError("Clear FAT/DIR writeBlock failed");
  161. }
  162. if ((i & 0XFF) == 0) {
  163. cout << '.';
  164. }
  165. }
  166. #else // USE_SDIO
  167. if (!card.writeStart(bgn, count)) {
  168. sdError("Clear FAT/DIR writeStart failed");
  169. }
  170. for (uint32_t i = 0; i < count; i++) {
  171. if ((i & 0XFF) == 0) {
  172. cout << '.';
  173. }
  174. if (!card.writeData(cache.data)) {
  175. sdError("Clear FAT/DIR writeData failed");
  176. }
  177. }
  178. if (!card.writeStop()) {
  179. sdError("Clear FAT/DIR writeStop failed");
  180. }
  181. #endif // USE_SDIO
  182. cout << endl;
  183. }
  184. //------------------------------------------------------------------------------
  185. // return cylinder number for a logical block number
  186. uint16_t lbnToCylinder(uint32_t lbn) {
  187. return lbn / (numberOfHeads * sectorsPerTrack);
  188. }
  189. //------------------------------------------------------------------------------
  190. // return head number for a logical block number
  191. uint8_t lbnToHead(uint32_t lbn) {
  192. return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
  193. }
  194. //------------------------------------------------------------------------------
  195. // return sector number for a logical block number
  196. uint8_t lbnToSector(uint32_t lbn) {
  197. return (lbn % sectorsPerTrack) + 1;
  198. }
  199. //------------------------------------------------------------------------------
  200. // format and write the Master Boot Record
  201. void writeMbr() {
  202. clearCache(true);
  203. part_t* p = cache.mbr.part;
  204. p->boot = 0;
  205. uint16_t c = lbnToCylinder(relSector);
  206. if (c > 1023) {
  207. sdError("MBR CHS");
  208. }
  209. p->beginCylinderHigh = c >> 8;
  210. p->beginCylinderLow = c & 0XFF;
  211. p->beginHead = lbnToHead(relSector);
  212. p->beginSector = lbnToSector(relSector);
  213. p->type = partType;
  214. uint32_t endLbn = relSector + partSize - 1;
  215. c = lbnToCylinder(endLbn);
  216. if (c <= 1023) {
  217. p->endCylinderHigh = c >> 8;
  218. p->endCylinderLow = c & 0XFF;
  219. p->endHead = lbnToHead(endLbn);
  220. p->endSector = lbnToSector(endLbn);
  221. } else {
  222. // Too big flag, c = 1023, h = 254, s = 63
  223. p->endCylinderHigh = 3;
  224. p->endCylinderLow = 255;
  225. p->endHead = 254;
  226. p->endSector = 63;
  227. }
  228. p->firstSector = relSector;
  229. p->totalSectors = partSize;
  230. if (!writeCache(0)) {
  231. sdError("write MBR");
  232. }
  233. }
  234. //------------------------------------------------------------------------------
  235. // generate serial number from card size and micros since boot
  236. uint32_t volSerialNumber() {
  237. return (cardSizeBlocks << 8) + micros();
  238. }
  239. //------------------------------------------------------------------------------
  240. // format the SD as FAT16
  241. void makeFat16() {
  242. uint32_t nc;
  243. for (dataStart = 2 * BU16;; dataStart += BU16) {
  244. nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
  245. fatSize = (nc + 2 + 255)/256;
  246. uint32_t r = BU16 + 1 + 2 * fatSize + 32;
  247. if (dataStart < r) {
  248. continue;
  249. }
  250. relSector = dataStart - r + BU16;
  251. break;
  252. }
  253. // check valid cluster count for FAT16 volume
  254. if (nc < 4085 || nc >= 65525) {
  255. sdError("Bad cluster count");
  256. }
  257. reservedSectors = 1;
  258. fatStart = relSector + reservedSectors;
  259. partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
  260. if (partSize < 32680) {
  261. partType = 0X01;
  262. } else if (partSize < 65536) {
  263. partType = 0X04;
  264. } else {
  265. partType = 0X06;
  266. }
  267. // write MBR
  268. writeMbr();
  269. clearCache(true);
  270. fat_boot_t* pb = &cache.fbs;
  271. pb->jump[0] = 0XEB;
  272. pb->jump[1] = 0X00;
  273. pb->jump[2] = 0X90;
  274. for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
  275. pb->oemId[i] = ' ';
  276. }
  277. pb->bytesPerSector = 512;
  278. pb->sectorsPerCluster = sectorsPerCluster;
  279. pb->reservedSectorCount = reservedSectors;
  280. pb->fatCount = 2;
  281. pb->rootDirEntryCount = 512;
  282. pb->mediaType = 0XF8;
  283. pb->sectorsPerFat16 = fatSize;
  284. pb->sectorsPerTrack = sectorsPerTrack;
  285. pb->headCount = numberOfHeads;
  286. pb->hidddenSectors = relSector;
  287. pb->totalSectors32 = partSize;
  288. pb->driveNumber = 0X80;
  289. pb->bootSignature = EXTENDED_BOOT_SIG;
  290. pb->volumeSerialNumber = volSerialNumber();
  291. memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
  292. memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
  293. // write partition boot sector
  294. if (!writeCache(relSector)) {
  295. sdError("FAT16 write PBS failed");
  296. }
  297. // clear FAT and root directory
  298. clearFatDir(fatStart, dataStart - fatStart);
  299. clearCache(false);
  300. cache.fat16[0] = 0XFFF8;
  301. cache.fat16[1] = 0XFFFF;
  302. // write first block of FAT and backup for reserved clusters
  303. if (!writeCache(fatStart)
  304. || !writeCache(fatStart + fatSize)) {
  305. sdError("FAT16 reserve failed");
  306. }
  307. }
  308. //------------------------------------------------------------------------------
  309. // format the SD as FAT32
  310. void makeFat32() {
  311. uint32_t nc;
  312. relSector = BU32;
  313. for (dataStart = 2 * BU32;; dataStart += BU32) {
  314. nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
  315. fatSize = (nc + 2 + 127)/128;
  316. uint32_t r = relSector + 9 + 2 * fatSize;
  317. if (dataStart >= r) {
  318. break;
  319. }
  320. }
  321. // error if too few clusters in FAT32 volume
  322. if (nc < 65525) {
  323. sdError("Bad cluster count");
  324. }
  325. reservedSectors = dataStart - relSector - 2 * fatSize;
  326. fatStart = relSector + reservedSectors;
  327. partSize = nc * sectorsPerCluster + dataStart - relSector;
  328. // type depends on address of end sector
  329. // max CHS has lbn = 16450560 = 1024*255*63
  330. if ((relSector + partSize) <= 16450560) {
  331. // FAT32
  332. partType = 0X0B;
  333. } else {
  334. // FAT32 with INT 13
  335. partType = 0X0C;
  336. }
  337. writeMbr();
  338. clearCache(true);
  339. fat32_boot_t* pb = &cache.fbs32;
  340. pb->jump[0] = 0XEB;
  341. pb->jump[1] = 0X00;
  342. pb->jump[2] = 0X90;
  343. for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
  344. pb->oemId[i] = ' ';
  345. }
  346. pb->bytesPerSector = 512;
  347. pb->sectorsPerCluster = sectorsPerCluster;
  348. pb->reservedSectorCount = reservedSectors;
  349. pb->fatCount = 2;
  350. pb->mediaType = 0XF8;
  351. pb->sectorsPerTrack = sectorsPerTrack;
  352. pb->headCount = numberOfHeads;
  353. pb->hidddenSectors = relSector;
  354. pb->totalSectors32 = partSize;
  355. pb->sectorsPerFat32 = fatSize;
  356. pb->fat32RootCluster = 2;
  357. pb->fat32FSInfo = 1;
  358. pb->fat32BackBootBlock = 6;
  359. pb->driveNumber = 0X80;
  360. pb->bootSignature = EXTENDED_BOOT_SIG;
  361. pb->volumeSerialNumber = volSerialNumber();
  362. memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
  363. memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
  364. // write partition boot sector and backup
  365. if (!writeCache(relSector)
  366. || !writeCache(relSector + 6)) {
  367. sdError("FAT32 write PBS failed");
  368. }
  369. clearCache(true);
  370. // write extra boot area and backup
  371. if (!writeCache(relSector + 2)
  372. || !writeCache(relSector + 8)) {
  373. sdError("FAT32 PBS ext failed");
  374. }
  375. fat32_fsinfo_t* pf = &cache.fsinfo;
  376. pf->leadSignature = FSINFO_LEAD_SIG;
  377. pf->structSignature = FSINFO_STRUCT_SIG;
  378. pf->freeCount = 0XFFFFFFFF;
  379. pf->nextFree = 0XFFFFFFFF;
  380. // write FSINFO sector and backup
  381. if (!writeCache(relSector + 1)
  382. || !writeCache(relSector + 7)) {
  383. sdError("FAT32 FSINFO failed");
  384. }
  385. clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
  386. clearCache(false);
  387. cache.fat32[0] = 0x0FFFFFF8;
  388. cache.fat32[1] = 0x0FFFFFFF;
  389. cache.fat32[2] = 0x0FFFFFFF;
  390. // write first block of FAT and backup for reserved clusters
  391. if (!writeCache(fatStart)
  392. || !writeCache(fatStart + fatSize)) {
  393. sdError("FAT32 reserve failed");
  394. }
  395. }
  396. //------------------------------------------------------------------------------
  397. // flash erase all data
  398. uint32_t const ERASE_SIZE = 262144L;
  399. void eraseCard() {
  400. cout << endl << F("Erasing\n");
  401. uint32_t firstBlock = 0;
  402. uint32_t lastBlock;
  403. uint16_t n = 0;
  404. do {
  405. lastBlock = firstBlock + ERASE_SIZE - 1;
  406. if (lastBlock >= cardSizeBlocks) {
  407. lastBlock = cardSizeBlocks - 1;
  408. }
  409. if (!card.erase(firstBlock, lastBlock)) {
  410. sdError("erase failed");
  411. }
  412. cout << '.';
  413. if ((n++)%32 == 31) {
  414. cout << endl;
  415. }
  416. firstBlock += ERASE_SIZE;
  417. } while (firstBlock < cardSizeBlocks);
  418. cout << endl;
  419. if (!card.readBlock(0, cache.data)) {
  420. sdError("readBlock");
  421. }
  422. cout << hex << showbase << setfill('0') << internal;
  423. cout << F("All data set to ") << setw(4) << int(cache.data[0]) << endl;
  424. cout << dec << noshowbase << setfill(' ') << right;
  425. cout << F("Erase done\n");
  426. }
  427. //------------------------------------------------------------------------------
  428. void formatCard() {
  429. cout << endl;
  430. cout << F("Formatting\n");
  431. initSizes();
  432. if (card.type() != SD_CARD_TYPE_SDHC) {
  433. cout << F("FAT16\n");
  434. makeFat16();
  435. } else {
  436. cout << F("FAT32\n");
  437. makeFat32();
  438. }
  439. #if DEBUG_PRINT
  440. debugPrint();
  441. #endif // DEBUG_PRINT
  442. cout << F("Format done\n");
  443. }
  444. //------------------------------------------------------------------------------
  445. void setup() {
  446. char c;
  447. Serial.begin(9600);
  448. // Wait for USB Serial
  449. while (!Serial) {
  450. SysCall::yield();
  451. }
  452. cout << F("Type any character to start\n");
  453. while (!Serial.available()) {
  454. SysCall::yield();
  455. }
  456. // Discard any extra characters.
  457. do {
  458. delay(10);
  459. } while (Serial.available() && Serial.read() >= 0);
  460. cout << F(
  461. "\n"
  462. "This program can erase and/or format SD/SDHC cards.\n"
  463. "\n"
  464. "Erase uses the card's fast flash erase command.\n"
  465. "Flash erase sets all data to 0X00 for most cards\n"
  466. "and 0XFF for a few vendor's cards.\n"
  467. "\n"
  468. "Cards larger than 2 GB will be formatted FAT32 and\n"
  469. "smaller cards will be formatted FAT16.\n"
  470. "\n"
  471. "Warning, all data on the card will be erased.\n"
  472. "Enter 'Y' to continue: ");
  473. while (!Serial.available()) {
  474. SysCall::yield();
  475. }
  476. c = Serial.read();
  477. cout << c << endl;
  478. if (c != 'Y') {
  479. cout << F("Quiting, you did not enter 'Y'.\n");
  480. return;
  481. }
  482. // Read any existing Serial data.
  483. do {
  484. delay(10);
  485. } while (Serial.available() && Serial.read() >= 0);
  486. cout << F(
  487. "\n"
  488. "Options are:\n"
  489. "E - erase the card and skip formatting.\n"
  490. "F - erase and then format the card. (recommended)\n"
  491. "Q - quick format the card without erase.\n"
  492. "\n"
  493. "Enter option: ");
  494. while (!Serial.available()) {
  495. SysCall::yield();
  496. }
  497. c = Serial.read();
  498. cout << c << endl;
  499. if (!strchr("EFQ", c)) {
  500. cout << F("Quiting, invalid option entered.") << endl;
  501. return;
  502. }
  503. #if USE_SDIO
  504. if (!card.begin()) {
  505. sdError("card.begin failed");
  506. }
  507. #else // USE_SDIO
  508. if (!card.begin(chipSelect, SPI_SPEED)) {
  509. cout << F(
  510. "\nSD initialization failure!\n"
  511. "Is the SD card inserted correctly?\n"
  512. "Is chip select correct at the top of this program?\n");
  513. sdError("card.begin failed");
  514. }
  515. #endif
  516. cardSizeBlocks = card.cardSize();
  517. if (cardSizeBlocks == 0) {
  518. sdError("cardSize");
  519. }
  520. cardCapacityMB = (cardSizeBlocks + 2047)/2048;
  521. cout << F("Card Size: ") << setprecision(0) << 1.048576*cardCapacityMB;
  522. cout << F(" MB, (MB = 1,000,000 bytes)") << endl;
  523. if (c == 'E' || c == 'F') {
  524. eraseCard();
  525. }
  526. if (c == 'F' || c == 'Q') {
  527. formatCard();
  528. }
  529. }
  530. //------------------------------------------------------------------------------
  531. void loop() {}