SdFormatter.ino 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * This program will format SD/SDHC/SDXC cards.
  3. * Warning all data will be deleted!
  4. *
  5. * This program attempts to match the format
  6. * generated by SDFormatter available here:
  7. *
  8. * http://www.sdcard.org/consumers/formatter/
  9. *
  10. * For very small cards this program uses FAT16
  11. * and the above SDFormatter uses FAT12.
  12. */
  13. #include "SdFat.h"
  14. #include "sdios.h"
  15. /*
  16. Set DISABLE_CS_PIN to disable a second SPI device.
  17. For example, with the Ethernet shield, set DISABLE_CS_PIN
  18. to 10 to disable the Ethernet controller.
  19. */
  20. const int8_t DISABLE_CS_PIN = -1;
  21. /*
  22. Change the value of SD_CS_PIN if you are using SPI
  23. and your hardware does not use the default value, SS.
  24. Common values are:
  25. Arduino Ethernet shield: pin 4
  26. Sparkfun SD shield: pin 8
  27. Adafruit SD shields and modules: pin 10
  28. */
  29. // SDCARD_SS_PIN is defined for the built-in SD on some boards.
  30. #ifndef SDCARD_SS_PIN
  31. const uint8_t SD_CS_PIN = SS;
  32. #else // SDCARD_SS_PIN
  33. // Assume built-in SD is used.
  34. const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
  35. #endif // SDCARD_SS_PIN
  36. // Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
  37. #define SPI_CLOCK SD_SCK_MHZ(50)
  38. // Try to select the best SD card configuration.
  39. #if HAS_SDIO_CLASS
  40. #define SD_CONFIG SdioConfig(FIFO_SDIO)
  41. #elif ENABLE_DEDICATED_SPI
  42. #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
  43. #else // HAS_SDIO_CLASS
  44. #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
  45. #endif // HAS_SDIO_CLASS
  46. //==============================================================================
  47. // Serial output stream
  48. ArduinoOutStream cout(Serial);
  49. //------------------------------------------------------------------------------
  50. uint32_t cardSectorCount = 0;
  51. uint8_t sectorBuffer[512];
  52. //------------------------------------------------------------------------------
  53. // SdCardFactory constructs and initializes the appropriate card.
  54. SdCardFactory cardFactory;
  55. // Pointer to generic SD card.
  56. SdCard* m_card = nullptr;
  57. //------------------------------------------------------------------------------
  58. #define sdError(msg) \
  59. { \
  60. cout << F("error: ") << F(msg) << endl; \
  61. sdErrorHalt(); \
  62. }
  63. //------------------------------------------------------------------------------
  64. void sdErrorHalt() {
  65. if (!m_card) {
  66. cout << F("Invalid SD_CONFIG") << endl;
  67. } else if (m_card->errorCode()) {
  68. if (m_card->errorCode() == SD_CARD_ERROR_CMD0) {
  69. cout << F("No card, wrong chip select pin, or wiring error?") << endl;
  70. }
  71. cout << F("SD errorCode: ") << hex << showbase;
  72. printSdErrorSymbol(&Serial, m_card->errorCode());
  73. cout << F(" = ") << int(m_card->errorCode()) << endl;
  74. cout << F("SD errorData = ") << int(m_card->errorData()) << endl;
  75. }
  76. while (true) {
  77. }
  78. }
  79. //------------------------------------------------------------------------------
  80. void clearSerialInput() {
  81. uint32_t m = micros();
  82. do {
  83. if (Serial.read() >= 0) {
  84. m = micros();
  85. }
  86. } while (micros() - m < 10000);
  87. }
  88. //------------------------------------------------------------------------------
  89. // flash erase all data
  90. uint32_t const ERASE_SIZE = 262144L;
  91. void eraseCard() {
  92. cout << endl << F("Erasing\n");
  93. uint32_t firstBlock = 0;
  94. uint32_t lastBlock;
  95. uint16_t n = 0;
  96. do {
  97. lastBlock = firstBlock + ERASE_SIZE - 1;
  98. if (lastBlock >= cardSectorCount) {
  99. lastBlock = cardSectorCount - 1;
  100. }
  101. if (!m_card->erase(firstBlock, lastBlock)) {
  102. sdError("erase failed");
  103. }
  104. cout << '.';
  105. if ((n++) % 64 == 63) {
  106. cout << endl;
  107. }
  108. firstBlock += ERASE_SIZE;
  109. } while (firstBlock < cardSectorCount);
  110. cout << endl;
  111. if (!m_card->readSector(0, sectorBuffer)) {
  112. sdError("readBlock");
  113. }
  114. cout << hex << showbase << setfill('0') << internal;
  115. cout << F("All data set to ") << setw(4) << int(sectorBuffer[0]) << endl;
  116. cout << dec << noshowbase << setfill(' ') << right;
  117. cout << F("Erase done\n");
  118. }
  119. //------------------------------------------------------------------------------
  120. void formatCard() {
  121. ExFatFormatter exFatFormatter;
  122. FatFormatter fatFormatter;
  123. // Format exFAT if larger than 32GB.
  124. bool rtn = cardSectorCount > 67108864
  125. ? exFatFormatter.format(m_card, sectorBuffer, &Serial)
  126. : fatFormatter.format(m_card, sectorBuffer, &Serial);
  127. if (!rtn) {
  128. sdErrorHalt();
  129. }
  130. cout << F("Run the SdInfo example for format details.") << endl;
  131. }
  132. //------------------------------------------------------------------------------
  133. void printConfig(SdSpiConfig config) {
  134. if (DISABLE_CS_PIN < 0) {
  135. cout << F(
  136. "\nAssuming the SD is the only SPI device.\n"
  137. "Edit DISABLE_CS_PIN to disable an SPI device.\n");
  138. } else {
  139. cout << F("\nDisabling SPI device on pin ");
  140. cout << int(DISABLE_CS_PIN) << endl;
  141. pinMode(DISABLE_CS_PIN, OUTPUT);
  142. digitalWrite(DISABLE_CS_PIN, HIGH);
  143. }
  144. cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
  145. cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
  146. }
  147. //------------------------------------------------------------------------------
  148. void printConfig(SdioConfig config) {
  149. (void)config;
  150. cout << F("Assuming an SDIO interface.\n");
  151. }
  152. //------------------------------------------------------------------------------
  153. void setup() {
  154. char c;
  155. Serial.begin(9600);
  156. // Wait for USB Serial
  157. while (!Serial) {
  158. yield();
  159. }
  160. printConfig(SD_CONFIG);
  161. cout << F("\nType any character to start\n");
  162. while (!Serial.available()) {
  163. yield();
  164. }
  165. // Discard any extra characters.
  166. clearSerialInput();
  167. cout << F(
  168. "\n"
  169. "This program can erase and/or format SD/SDHC/SDXC cards.\n"
  170. "\n"
  171. "Erase uses the card's fast flash erase command.\n"
  172. "Flash erase sets all data to 0X00 for most cards\n"
  173. "and 0XFF for a few vendor's cards.\n"
  174. "\n"
  175. "Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n"
  176. "Cards larger than 2 GiB and up to 32 GiB will be formatted\n"
  177. "FAT32. Cards larger than 32 GiB will be formatted exFAT.\n"
  178. "\n"
  179. "Warning, all data on the card will be erased.\n"
  180. "Enter 'Y' to continue: ");
  181. while (!Serial.available()) {
  182. yield();
  183. }
  184. c = Serial.read();
  185. cout << c << endl;
  186. if (c != 'Y') {
  187. cout << F("Quiting, you did not enter 'Y'.\n");
  188. return;
  189. }
  190. // Read any existing Serial data.
  191. clearSerialInput();
  192. // Select and initialize proper card driver.
  193. m_card = cardFactory.newCard(SD_CONFIG);
  194. if (!m_card || m_card->errorCode()) {
  195. sdError("card init failed.");
  196. return;
  197. }
  198. cardSectorCount = m_card->sectorCount();
  199. if (!cardSectorCount) {
  200. sdError("Get sector count failed.");
  201. return;
  202. }
  203. cout << F("\nCard size: ") << cardSectorCount * 5.12e-7;
  204. cout << F(" GB (GB = 1E9 bytes)\n");
  205. cout << F("Card size: ") << cardSectorCount / 2097152.0;
  206. cout << F(" GiB (GiB = 2^30 bytes)\n");
  207. cout << F("Card will be formated ");
  208. if (cardSectorCount > 67108864) {
  209. cout << F("exFAT\n");
  210. } else if (cardSectorCount > 4194304) {
  211. cout << F("FAT32\n");
  212. } else {
  213. cout << F("FAT16\n");
  214. }
  215. cout << F(
  216. "\n"
  217. "Options are:\n"
  218. "E - erase the card and skip formatting.\n"
  219. "F - erase and then format the card. (recommended)\n"
  220. "Q - quick format the card without erase.\n"
  221. "\n"
  222. "Enter option: ");
  223. while (!Serial.available()) {
  224. yield();
  225. }
  226. c = Serial.read();
  227. cout << c << endl;
  228. if (!strchr("EFQ", c)) {
  229. cout << F("Quiting, invalid option entered.") << endl;
  230. return;
  231. }
  232. if (c == 'E' || c == 'F') {
  233. eraseCard();
  234. }
  235. if (c == 'F' || c == 'Q') {
  236. formatCard();
  237. }
  238. }
  239. void loop() {}