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.

SdFormatter.ino 16KB

pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 10 gadiem
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. // 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() {}