TeensySdioDemo.ino 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Simple performance test for Teensy 3.5/3.6 4.0 SDHC.
  2. // Demonstrates yield() efficiency for SDIO modes.
  3. #include "SdFat.h"
  4. // Use built-in SD for SPI modes on Teensy 3.5/3.6.
  5. // Teensy 4.0 use first SPI port.
  6. // SDCARD_SS_PIN is defined for the built-in SD on some boards.
  7. #ifndef SDCARD_SS_PIN
  8. const uint8_t SD_CS_PIN = SS;
  9. #else // SDCARD_SS_PIN
  10. // Assume built-in SD is used.
  11. const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
  12. #endif // SDCARD_SS_PIN
  13. // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
  14. // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
  15. #define SD_FAT_TYPE 3
  16. // 32 KiB buffer.
  17. const size_t BUF_DIM = 32768;
  18. // 8 MiB file.
  19. const uint32_t FILE_SIZE = 256UL*BUF_DIM;
  20. #if SD_FAT_TYPE == 0
  21. SdFat sd;
  22. File file;
  23. #elif SD_FAT_TYPE == 1
  24. SdFat32 sd;
  25. File32 file;
  26. #elif SD_FAT_TYPE == 2
  27. SdExFat sd;
  28. ExFile file;
  29. #elif SD_FAT_TYPE == 3
  30. SdFs sd;
  31. FsFile file;
  32. #else // SD_FAT_TYPE
  33. #error Invalid SD_FAT_TYPE
  34. #endif // SD_FAT_TYPE
  35. uint8_t buf[BUF_DIM];
  36. // buffer as uint32_t
  37. uint32_t* buf32 = (uint32_t*)buf;
  38. // Total usec in read/write calls.
  39. uint32_t totalMicros = 0;
  40. // Time in yield() function.
  41. uint32_t yieldMicros = 0;
  42. // Number of yield calls.
  43. uint32_t yieldCalls = 0;
  44. // Max busy time for single yield call.
  45. uint32_t yieldMaxUsec = 0;
  46. //------------------------------------------------------------------------------
  47. void clearSerialInput() {
  48. uint32_t m = micros();
  49. do {
  50. if (Serial.read() >= 0) {
  51. m = micros();
  52. }
  53. } while (micros() - m < 10000);
  54. }
  55. //------------------------------------------------------------------------------
  56. void errorHalt(const char* msg) {
  57. Serial.print("Error: ");
  58. Serial.println(msg);
  59. if (sd.sdErrorCode()) {
  60. if (sd.sdErrorCode() == SD_CARD_ERROR_ACMD41) {
  61. Serial.println("Try power cycling the SD card.");
  62. }
  63. printSdErrorSymbol(&Serial, sd.sdErrorCode());
  64. Serial.print(", ErrorData: 0X");
  65. Serial.println(sd.sdErrorData(), HEX);
  66. }
  67. while (true) {}
  68. }
  69. bool ready = false;
  70. //------------------------------------------------------------------------------
  71. bool sdBusy() {
  72. return ready ? sd.card()->isBusy() : false;
  73. }
  74. //------------------------------------------------------------------------------
  75. // Replace "weak" system yield() function.
  76. void yield() {
  77. // Only count cardBusy time.
  78. if (!sdBusy()) {
  79. return;
  80. }
  81. uint32_t m = micros();
  82. yieldCalls++;
  83. while (sdBusy()) {
  84. // Do something here.
  85. }
  86. m = micros() - m;
  87. if (m > yieldMaxUsec) {
  88. yieldMaxUsec = m;
  89. }
  90. yieldMicros += m;
  91. }
  92. //------------------------------------------------------------------------------
  93. void runTest() {
  94. // Zero Stats
  95. totalMicros = 0;
  96. yieldMicros = 0;
  97. yieldCalls = 0;
  98. yieldMaxUsec = 0;
  99. if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) {
  100. errorHalt("open failed");
  101. }
  102. Serial.println("\nsize,write,read");
  103. Serial.println("bytes,KB/sec,KB/sec");
  104. for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) {
  105. uint32_t nRdWr = FILE_SIZE/nb;
  106. if (!file.truncate(0)) {
  107. errorHalt("truncate failed");
  108. }
  109. Serial.print(nb);
  110. Serial.print(',');
  111. uint32_t t = micros();
  112. for (uint32_t n = 0; n < nRdWr; n++) {
  113. // Set start and end of buffer.
  114. buf32[0] = n;
  115. buf32[nb/4 - 1] = n;
  116. if (nb != file.write(buf, nb)) {
  117. errorHalt("write failed");
  118. }
  119. }
  120. t = micros() - t;
  121. totalMicros += t;
  122. Serial.print(1000.0*FILE_SIZE/t);
  123. Serial.print(',');
  124. file.rewind();
  125. t = micros();
  126. for (uint32_t n = 0; n < nRdWr; n++) {
  127. if ((int)nb != file.read(buf, nb)) {
  128. errorHalt("read failed");
  129. }
  130. // crude check of data.
  131. if (buf32[0] != n || buf32[nb/4 - 1] != n) {
  132. errorHalt("data check");
  133. }
  134. }
  135. t = micros() - t;
  136. totalMicros += t;
  137. Serial.println(1000.0*FILE_SIZE/t);
  138. }
  139. file.close();
  140. Serial.print("\ntotalMicros ");
  141. Serial.println(totalMicros);
  142. Serial.print("yieldMicros ");
  143. Serial.println(yieldMicros);
  144. Serial.print("yieldCalls ");
  145. Serial.println(yieldCalls);
  146. Serial.print("yieldMaxUsec ");
  147. Serial.println(yieldMaxUsec);
  148. // Serial.print("kHzSdClk ");
  149. // Serial.println(kHzSdClk());
  150. Serial.println("Done");
  151. }
  152. //------------------------------------------------------------------------------
  153. void setup() {
  154. Serial.begin(9600);
  155. while (!Serial) {
  156. }
  157. }
  158. //------------------------------------------------------------------------------
  159. void loop() {
  160. static bool warn = true;
  161. if (warn) {
  162. warn = false;
  163. Serial.println(
  164. "SD cards must be power cycled to leave\n"
  165. "SPI mode so do SDIO tests first.\n"
  166. "\nCycle power on the card if an error occurs.");
  167. }
  168. clearSerialInput();
  169. Serial.println(
  170. "\nType '1' for FIFO SDIO"
  171. "\n '2' for DMA SDIO"
  172. "\n '3' for Dedicated SPI"
  173. "\n '4' for Shared SPI");
  174. while (!Serial.available()) {
  175. }
  176. char c = Serial.read();
  177. if (c =='1') {
  178. if (!sd.begin(SdioConfig(FIFO_SDIO))) {
  179. errorHalt("begin failed");
  180. }
  181. Serial.println("\nFIFO SDIO mode.");
  182. } else if (c == '2') {
  183. if (!sd.begin(SdioConfig(DMA_SDIO))) {
  184. errorHalt("begin failed");
  185. }
  186. Serial.println("\nDMA SDIO mode - slow for small transfers.");
  187. } else if (c == '3') {
  188. if (!sd.begin(SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50)))) {
  189. errorHalt("begin failed");
  190. }
  191. Serial.println("\nDedicated SPI mode.");
  192. } else if (c == '4') {
  193. if (!sd.begin(SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))) {
  194. errorHalt("begin failed");
  195. }
  196. Serial.println("\nShared SPI mode - slow for small transfers.");
  197. } else {
  198. Serial.println("Invalid input");
  199. return;
  200. }
  201. ready = true;
  202. runTest();
  203. ready = false;
  204. }