Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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