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.

550 satır
16KB

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