TeensySdioDemo.ino 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. }
  70. bool ready = false;
  71. //------------------------------------------------------------------------------
  72. bool sdBusy() { return ready ? sd.card()->isBusy() : false; }
  73. //------------------------------------------------------------------------------
  74. // Replace "weak" system yield() function.
  75. void yield() {
  76. // Only count cardBusy time.
  77. if (!sdBusy()) {
  78. return;
  79. }
  80. uint32_t m = micros();
  81. yieldCalls++;
  82. while (sdBusy()) {
  83. // Do something here.
  84. }
  85. m = micros() - m;
  86. if (m > yieldMaxUsec) {
  87. yieldMaxUsec = m;
  88. }
  89. yieldMicros += m;
  90. }
  91. //------------------------------------------------------------------------------
  92. void runTest() {
  93. // Zero Stats
  94. totalMicros = 0;
  95. yieldMicros = 0;
  96. yieldCalls = 0;
  97. yieldMaxUsec = 0;
  98. if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) {
  99. errorHalt("open failed");
  100. }
  101. Serial.println("\nsize,write,read");
  102. Serial.println("bytes,KB/sec,KB/sec");
  103. for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) {
  104. uint32_t nRdWr = FILE_SIZE / nb;
  105. if (!file.truncate(0)) {
  106. errorHalt("truncate failed");
  107. }
  108. Serial.print(nb);
  109. Serial.print(',');
  110. uint32_t t = micros();
  111. for (uint32_t n = 0; n < nRdWr; n++) {
  112. // Set start and end of buffer.
  113. buf32[0] = n;
  114. buf32[nb / 4 - 1] = n;
  115. if (nb != file.write(buf, nb)) {
  116. errorHalt("write failed");
  117. }
  118. }
  119. t = micros() - t;
  120. totalMicros += t;
  121. Serial.print(1000.0 * FILE_SIZE / t);
  122. Serial.print(',');
  123. file.rewind();
  124. t = micros();
  125. for (uint32_t n = 0; n < nRdWr; n++) {
  126. if ((int)nb != file.read(buf, nb)) {
  127. errorHalt("read failed");
  128. }
  129. // crude check of data.
  130. if (buf32[0] != n || buf32[nb / 4 - 1] != n) {
  131. errorHalt("data check");
  132. }
  133. }
  134. t = micros() - t;
  135. totalMicros += t;
  136. Serial.println(1000.0 * FILE_SIZE / t);
  137. }
  138. file.close();
  139. Serial.print("\ntotalMicros ");
  140. Serial.println(totalMicros);
  141. Serial.print("yieldMicros ");
  142. Serial.println(yieldMicros);
  143. Serial.print("yieldCalls ");
  144. Serial.println(yieldCalls);
  145. Serial.print("yieldMaxUsec ");
  146. Serial.println(yieldMaxUsec);
  147. // Serial.print("kHzSdClk ");
  148. // Serial.println(kHzSdClk());
  149. Serial.println("Done");
  150. }
  151. //------------------------------------------------------------------------------
  152. void setup() {
  153. Serial.begin(9600);
  154. while (!Serial) {
  155. }
  156. }
  157. //------------------------------------------------------------------------------
  158. void loop() {
  159. static bool warn = true;
  160. if (warn) {
  161. warn = false;
  162. Serial.println(
  163. "SD cards must be power cycled to leave\n"
  164. "SPI mode so do SDIO tests first.\n"
  165. "\nCycle power on the card if an error occurs.");
  166. }
  167. clearSerialInput();
  168. Serial.println(
  169. "\nType '1' for FIFO SDIO"
  170. "\n '2' for DMA SDIO"
  171. "\n '3' for Dedicated SPI"
  172. "\n '4' for Shared SPI");
  173. while (!Serial.available()) {
  174. }
  175. char c = Serial.read();
  176. if (c == '1') {
  177. if (!sd.begin(SdioConfig(FIFO_SDIO))) {
  178. errorHalt("begin failed");
  179. }
  180. Serial.println("\nFIFO SDIO mode.");
  181. } else if (c == '2') {
  182. if (!sd.begin(SdioConfig(DMA_SDIO))) {
  183. errorHalt("begin failed");
  184. }
  185. Serial.println("\nDMA SDIO mode - slow for small transfers.");
  186. } else if (c == '3') {
  187. #if ENABLE_DEDICATED_SPI
  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 // ENABLE_DEDICATED_SPI
  193. Serial.println("ENABLE_DEDICATED_SPI must be non-zero.");
  194. return;
  195. #endif // ENABLE_DEDICATED_SPI
  196. } else if (c == '4') {
  197. if (!sd.begin(SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))) {
  198. errorHalt("begin failed");
  199. }
  200. Serial.println("\nShared SPI mode - slow for small transfers.");
  201. } else {
  202. Serial.println("Invalid input");
  203. return;
  204. }
  205. ready = true;
  206. runTest();
  207. ready = false;
  208. }