You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
5.4KB

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