Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

179 lines
5.2KB

  1. /*
  2. * This program illustrates raw write functions in SdFat that
  3. * can be used for high speed data logging.
  4. *
  5. * This program simulates logging from a source that produces
  6. * data at a constant rate of RATE_KB_PER_SEC.
  7. *
  8. * Note: Apps should create a very large file then truncates it
  9. * to the length that is used for a logging. It only takes
  10. * a few seconds to erase a 500 MB file since the card only
  11. * marks the blocks as erased; no data transfer is required.
  12. */
  13. #include <SPI.h>
  14. #include "SdFat.h"
  15. #include "FreeStack.h"
  16. // SD chip select pin
  17. const uint8_t chipSelect = SS;
  18. const uint32_t RATE_KB_PER_SEC = 100;
  19. const uint32_t TEST_TIME_SEC = 100;
  20. // Time between printing progress dots
  21. const uint32_t DOT_TIME_MS = 5000UL;
  22. // number of blocks in the contiguous file
  23. const uint32_t BLOCK_COUNT = (1000*RATE_KB_PER_SEC*TEST_TIME_SEC + 511)/512;
  24. // file system
  25. SdFat sd;
  26. // test file
  27. SdFile file;
  28. // file extent
  29. uint32_t bgnBlock, endBlock;
  30. // Serial output stream
  31. ArduinoOutStream cout(Serial);
  32. //------------------------------------------------------------------------------
  33. // store error strings in flash to save RAM
  34. #define error(s) sd.errorHalt(F(s))
  35. //------------------------------------------------------------------------------
  36. void setup(void) {
  37. Serial.begin(9600);
  38. // Wait for USB Serial
  39. while (!Serial) {
  40. SysCall::yield();
  41. }
  42. }
  43. //------------------------------------------------------------------------------
  44. void loop(void) {
  45. // Read any extra Serial data.
  46. do {
  47. delay(10);
  48. } while (Serial.available() && Serial.read() >= 0);
  49. // F stores strings in flash to save RAM
  50. cout << F("Type any character to start\n");
  51. while (!Serial.available()) {
  52. SysCall::yield();
  53. }
  54. cout << F("FreeStack: ") << FreeStack() << endl;
  55. // Initialize at the highest speed supported by the board that is
  56. // not over 50 MHz. Try a lower speed if SPI errors occur.
  57. if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
  58. sd.initErrorHalt();
  59. }
  60. // delete possible existing file
  61. sd.remove("RawWrite.txt");
  62. // create a contiguous file
  63. if (!file.createContiguous("RawWrite.txt", 512UL*BLOCK_COUNT)) {
  64. error("createContiguous failed");
  65. }
  66. // get the location of the file's blocks
  67. if (!file.contiguousRange(&bgnBlock, &endBlock)) {
  68. error("contiguousRange failed");
  69. }
  70. //*********************NOTE**************************************
  71. // NO SdFile calls are allowed while cache is used for raw writes
  72. //***************************************************************
  73. // clear the cache and use it as a 512 byte buffer
  74. uint8_t* pCache = (uint8_t*)sd.vol()->cacheClear();
  75. // fill cache with eight lines of 64 bytes each
  76. memset(pCache, ' ', 512);
  77. for (uint16_t i = 0; i < 512; i += 64) {
  78. // put line number at end of line then CR/LF
  79. pCache[i + 61] = '0' + (i/64);
  80. pCache[i + 62] = '\r';
  81. pCache[i + 63] = '\n';
  82. }
  83. cout << F("Start raw write of ") << file.fileSize()/1000UL << F(" KB\n");
  84. cout << F("Target rate: ") << RATE_KB_PER_SEC << F(" KB/sec\n");
  85. cout << F("Target time: ") << TEST_TIME_SEC << F(" seconds\n");
  86. // tell card to setup for multiple block write with pre-erase
  87. if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
  88. error("writeStart failed");
  89. }
  90. // init stats
  91. delay(1000);
  92. uint32_t dotCount = 0;
  93. uint32_t maxQueuePrint = 0;
  94. uint32_t maxWriteTime = 0;
  95. uint32_t minWriteTime = 9999999;
  96. uint32_t totalWriteTime = 0;
  97. uint32_t maxQueueSize = 0;
  98. uint32_t nWrite = 0;
  99. uint32_t b = 0;
  100. // write data
  101. uint32_t startTime = millis();
  102. while (nWrite < BLOCK_COUNT) {
  103. uint32_t nProduced = RATE_KB_PER_SEC*(millis() - startTime)/512UL;
  104. uint32_t queueSize = nProduced - nWrite;
  105. if (queueSize == 0) continue;
  106. if (queueSize > maxQueueSize) {
  107. maxQueueSize = queueSize;
  108. }
  109. if ((millis() - startTime - dotCount*DOT_TIME_MS) > DOT_TIME_MS) {
  110. if (maxQueueSize != maxQueuePrint) {
  111. cout << F("\nQ: ") << maxQueueSize << endl;
  112. maxQueuePrint = maxQueueSize;
  113. } else {
  114. cout << ".";
  115. if (++dotCount%10 == 0) {
  116. cout << endl;
  117. }
  118. }
  119. }
  120. // put block number at start of first line in block
  121. uint32_t n = b++;
  122. for (int8_t d = 5; d >= 0; d--) {
  123. pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
  124. n /= 10;
  125. }
  126. // write a 512 byte block
  127. uint32_t tw = micros();
  128. if (!sd.card()->writeData(pCache)) {
  129. error("writeData failed");
  130. }
  131. tw = micros() - tw;
  132. totalWriteTime += tw;
  133. // check for max write time
  134. if (tw > maxWriteTime) {
  135. maxWriteTime = tw;
  136. }
  137. if (tw < minWriteTime) {
  138. minWriteTime = tw;
  139. }
  140. nWrite++;
  141. }
  142. uint32_t endTime = millis();
  143. uint32_t avgWriteTime = totalWriteTime/BLOCK_COUNT;
  144. // end multiple block write mode
  145. if (!sd.card()->writeStop()) {
  146. error("writeStop failed");
  147. }
  148. cout << F("\nDone\n");
  149. cout << F("maxQueueSize: ") << maxQueueSize << endl;
  150. cout << F("Elapsed time: ") << setprecision(3)<< 1.e-3*(endTime - startTime);
  151. cout << F(" seconds\n");
  152. cout << F("Min block write time: ") << minWriteTime << F(" micros\n");
  153. cout << F("Max block write time: ") << maxWriteTime << F(" micros\n");
  154. cout << F("Avg block write time: ") << avgWriteTime << F(" micros\n");
  155. // close file for next pass of loop
  156. file.close();
  157. Serial.println();
  158. }