SdInfo.ino 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * This program attempts to initialize an SD card and analyze its structure.
  3. */
  4. #include "SdFat.h"
  5. #include "sdios.h"
  6. /*
  7. Set DISABLE_CS_PIN to disable a second SPI device.
  8. For example, with the Ethernet shield, set DISABLE_CS_PIN
  9. to 10 to disable the Ethernet controller.
  10. */
  11. const int8_t DISABLE_CS_PIN = -1;
  12. /*
  13. Change the value of SD_CS_PIN if you are using SPI
  14. and your hardware does not use the default value, SS.
  15. Common values are:
  16. Arduino Ethernet shield: pin 4
  17. Sparkfun SD shield: pin 8
  18. Adafruit SD shields and modules: pin 10
  19. */
  20. // SDCARD_SS_PIN is defined for the built-in SD on some boards.
  21. #ifndef SDCARD_SS_PIN
  22. const uint8_t SD_CS_PIN = SS;
  23. #else // SDCARD_SS_PIN
  24. const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
  25. #endif // SDCARD_SS_PIN
  26. // Try to select the best SD card configuration.
  27. #if HAS_SDIO_CLASS
  28. #define SD_CONFIG SdioConfig(FIFO_SDIO)
  29. #elif ENABLE_DEDICATED_SPI
  30. #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
  31. #else // HAS_SDIO_CLASS
  32. #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
  33. #endif // HAS_SDIO_CLASS
  34. //------------------------------------------------------------------------------
  35. SdFs sd;
  36. cid_t m_cid;
  37. csd_t m_csd;
  38. uint32_t m_eraseSize;
  39. uint32_t m_ocr;
  40. static ArduinoOutStream cout(Serial);
  41. //------------------------------------------------------------------------------
  42. bool cidDmp() {
  43. cout << F("\nManufacturer ID: ");
  44. cout << uppercase << showbase << hex << int(m_cid.mid) << dec << endl;
  45. cout << F("OEM ID: ") << m_cid.oid[0] << m_cid.oid[1] << endl;
  46. cout << F("Product: ");
  47. for (uint8_t i = 0; i < 5; i++) {
  48. cout << m_cid.pnm[i];
  49. }
  50. cout << F("\nVersion: ");
  51. cout << int(m_cid.prv_n) << '.' << int(m_cid.prv_m) << endl;
  52. cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
  53. cout << F("Manufacturing date: ");
  54. cout << int(m_cid.mdt_month) << '/';
  55. cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
  56. cout << endl;
  57. return true;
  58. }
  59. //------------------------------------------------------------------------------
  60. void clearSerialInput() {
  61. uint32_t m = micros();
  62. do {
  63. if (Serial.read() >= 0) {
  64. m = micros();
  65. }
  66. } while (micros() - m < 10000);
  67. }
  68. //------------------------------------------------------------------------------
  69. bool csdDmp() {
  70. bool eraseSingleBlock;
  71. if (m_csd.v1.csd_ver == 0) {
  72. eraseSingleBlock = m_csd.v1.erase_blk_en;
  73. m_eraseSize = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
  74. } else if (m_csd.v2.csd_ver == 1) {
  75. eraseSingleBlock = m_csd.v2.erase_blk_en;
  76. m_eraseSize = (m_csd.v2.sector_size_high << 1) | m_csd.v2.sector_size_low;
  77. } else {
  78. cout << F("m_csd version error\n");
  79. return false;
  80. }
  81. m_eraseSize++;
  82. cout << F("cardSize: ") << 0.000512 * sdCardCapacity(&m_csd);
  83. cout << F(" MB (MB = 1,000,000 bytes)\n");
  84. cout << F("flashEraseSize: ") << int(m_eraseSize) << F(" blocks\n");
  85. cout << F("eraseSingleBlock: ");
  86. if (eraseSingleBlock) {
  87. cout << F("true\n");
  88. } else {
  89. cout << F("false\n");
  90. }
  91. return true;
  92. }
  93. //------------------------------------------------------------------------------
  94. void errorPrint() {
  95. if (sd.sdErrorCode()) {
  96. cout << F("SD errorCode: ") << hex << showbase;
  97. printSdErrorSymbol(&Serial, sd.sdErrorCode());
  98. cout << F(" = ") << int(sd.sdErrorCode()) << endl;
  99. cout << F("SD errorData = ") << int(sd.sdErrorData()) << endl;
  100. }
  101. }
  102. //------------------------------------------------------------------------------
  103. bool mbrDmp() {
  104. MbrSector_t mbr;
  105. bool valid = true;
  106. if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
  107. cout << F("\nread MBR failed.\n");
  108. errorPrint();
  109. return false;
  110. }
  111. cout << F("\nSD Partition Table\n");
  112. cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
  113. for (uint8_t ip = 1; ip < 5; ip++) {
  114. MbrPart_t *pt = &mbr.part[ip - 1];
  115. if ((pt->boot != 0 && pt->boot != 0X80) ||
  116. getLe32(pt->relativeSectors) > sdCardCapacity(&m_csd)) {
  117. valid = false;
  118. }
  119. cout << int(ip) << ',' << uppercase << showbase << hex;
  120. cout << int(pt->boot) << ',';
  121. for (int i = 0; i < 3; i++ ) {
  122. cout << int(pt->beginCHS[i]) << ',';
  123. }
  124. cout << int(pt->type) << ',';
  125. for (int i = 0; i < 3; i++ ) {
  126. cout << int(pt->endCHS[i]) << ',';
  127. }
  128. cout << dec << getLe32(pt->relativeSectors) << ',';
  129. cout << getLe32(pt->totalSectors) << endl;
  130. }
  131. if (!valid) {
  132. cout << F("\nMBR not valid, assuming Super Floppy format.\n");
  133. }
  134. return true;
  135. }
  136. //------------------------------------------------------------------------------
  137. void dmpVol() {
  138. cout << F("\nScanning FAT, please wait.\n");
  139. uint32_t freeClusterCount = sd.freeClusterCount();
  140. if (sd.fatType() <= 32) {
  141. cout << F("\nVolume is FAT") << int(sd.fatType()) << endl;
  142. } else {
  143. cout << F("\nVolume is exFAT\n");
  144. }
  145. cout << F("sectorsPerCluster: ") << sd.sectorsPerCluster() << endl;
  146. cout << F("clusterCount: ") << sd.clusterCount() << endl;
  147. cout << F("freeClusterCount: ") << freeClusterCount << endl;
  148. cout << F("fatStartSector: ") << sd.fatStartSector() << endl;
  149. cout << F("dataStartSector: ") << sd.dataStartSector() << endl;
  150. if (sd.dataStartSector() % m_eraseSize) {
  151. cout << F("Data area is not aligned on flash erase boundary!\n");
  152. cout << F("Download and use formatter from www.sdcard.org!\n");
  153. }
  154. }
  155. //------------------------------------------------------------------------------
  156. void printCardType() {
  157. cout << F("\nCard type: ");
  158. switch (sd.card()->type()) {
  159. case SD_CARD_TYPE_SD1:
  160. cout << F("SD1\n");
  161. break;
  162. case SD_CARD_TYPE_SD2:
  163. cout << F("SD2\n");
  164. break;
  165. case SD_CARD_TYPE_SDHC:
  166. if (sdCardCapacity(&m_csd) < 70000000) {
  167. cout << F("SDHC\n");
  168. } else {
  169. cout << F("SDXC\n");
  170. }
  171. break;
  172. default:
  173. cout << F("Unknown\n");
  174. }
  175. }
  176. //------------------------------------------------------------------------------
  177. void printConfig(SdSpiConfig config) {
  178. if (DISABLE_CS_PIN < 0) {
  179. cout << F(
  180. "\nAssuming the SD is the only SPI device.\n"
  181. "Edit DISABLE_CS_PIN to disable an SPI device.\n");
  182. } else {
  183. cout << F("\nDisabling SPI device on pin ");
  184. cout << int(DISABLE_CS_PIN) << endl;
  185. pinMode(DISABLE_CS_PIN, OUTPUT);
  186. digitalWrite(DISABLE_CS_PIN, HIGH);
  187. }
  188. cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
  189. cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
  190. }
  191. //------------------------------------------------------------------------------
  192. void printConfig(SdioConfig config) {
  193. (void)config;
  194. cout << F("Assuming an SDIO interface.\n");
  195. }
  196. //-----------------------------------------------------------------------------
  197. void setup() {
  198. Serial.begin(9600);
  199. // Wait for USB Serial
  200. while (!Serial) {
  201. SysCall::yield();
  202. }
  203. cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
  204. printConfig(SD_CONFIG);
  205. }
  206. //------------------------------------------------------------------------------
  207. void loop() {
  208. // Read any existing Serial data.
  209. clearSerialInput();
  210. // F stores strings in flash to save RAM
  211. cout << F("\ntype any character to start\n");
  212. while (!Serial.available()) {
  213. SysCall::yield();
  214. }
  215. uint32_t t = millis();
  216. if (!sd.cardBegin(SD_CONFIG)) {
  217. cout << F(
  218. "\nSD initialization failed.\n"
  219. "Do not reformat the card!\n"
  220. "Is the card correctly inserted?\n"
  221. "Is there a wiring/soldering problem?\n");
  222. if (isSpi(SD_CONFIG)) {
  223. cout << F(
  224. "Is SD_CS_PIN set to the correct value?\n"
  225. "Does another SPI device need to be disabled?\n"
  226. );
  227. }
  228. errorPrint();
  229. return;
  230. }
  231. t = millis() - t;
  232. cout << F("init time: ") << t << " ms" << endl;
  233. if (!sd.card()->readCID(&m_cid) ||
  234. !sd.card()->readCSD(&m_csd) ||
  235. !sd.card()->readOCR(&m_ocr)) {
  236. cout << F("readInfo failed\n");
  237. errorPrint();
  238. return;
  239. }
  240. printCardType();
  241. cidDmp();
  242. csdDmp();
  243. cout << F("\nOCR: ") << uppercase << showbase;
  244. cout << hex << m_ocr << dec << endl;
  245. if (!mbrDmp()) {
  246. return;
  247. }
  248. if (!sd.volumeBegin()) {
  249. cout << F("\nvolumeBegin failed. Is the card formatted?\n");
  250. errorPrint();
  251. return;
  252. }
  253. dmpVol();
  254. }