選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

RawWrite.ino 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 one block every MICROS_PER_BLOCK.
  7. *
  8. * If a high quality SanDisk card is used with this program
  9. * no overruns occur and the maximum block write time is
  10. * under 2000 micros.
  11. *
  12. * Note: Apps should create a very large file then truncates it
  13. * to the length that is used for a logging. It only takes
  14. * a few seconds to erase a 500 MB file since the card only
  15. * marks the blocks as erased; no data transfer is required.
  16. */
  17. #include <SPI.h>
  18. #include <SdFat.h>
  19. #include <SdFatUtil.h>
  20. // SD chip select pin
  21. const uint8_t chipSelect = SS;
  22. // number of blocks in the contiguous file
  23. const uint32_t BLOCK_COUNT = 10000UL;
  24. // time to produce a block of data
  25. const uint32_t MICROS_PER_BLOCK = 10000;
  26. // file system
  27. SdFat sd;
  28. // test file
  29. SdFile file;
  30. // file extent
  31. uint32_t bgnBlock, endBlock;
  32. // Serial output stream
  33. ArduinoOutStream cout(Serial);
  34. //------------------------------------------------------------------------------
  35. // store error strings in flash to save RAM
  36. #define error(s) sd.errorHalt(F(s))
  37. //------------------------------------------------------------------------------
  38. // log of first overruns
  39. #define OVER_DIM 20
  40. struct {
  41. uint32_t block;
  42. uint32_t micros;
  43. } over[OVER_DIM];
  44. //------------------------------------------------------------------------------
  45. void setup(void) {
  46. Serial.begin(9600);
  47. while (!Serial) {} // wait for Leonardo
  48. }
  49. //------------------------------------------------------------------------------
  50. void loop(void) {
  51. while (Serial.read() >= 0) {}
  52. // pstr stores strings in flash to save RAM
  53. cout << F("Type any character to start\n");
  54. while (Serial.read() <= 0) {}
  55. delay(400); // catch Due reset problem
  56. cout << F("Free RAM: ") << FreeRam() << endl;
  57. // initialize the SD card at SPI_FULL_SPEED for best performance.
  58. // try SPI_HALF_SPEED if bus errors occur.
  59. if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
  60. sd.initErrorHalt();
  61. }
  62. // delete possible existing file
  63. sd.remove("RawWrite.txt");
  64. // create a contiguous file
  65. if (!file.createContiguous(sd.vwd(), "RawWrite.txt", 512UL*BLOCK_COUNT)) {
  66. error("createContiguous failed");
  67. }
  68. // get the location of the file's blocks
  69. if (!file.contiguousRange(&bgnBlock, &endBlock)) {
  70. error("contiguousRange failed");
  71. }
  72. //*********************NOTE**************************************
  73. // NO SdFile calls are allowed while cache is used for raw writes
  74. //***************************************************************
  75. // clear the cache and use it as a 512 byte buffer
  76. uint8_t* pCache = (uint8_t*)sd.vol()->cacheClear();
  77. // fill cache with eight lines of 64 bytes each
  78. memset(pCache, ' ', 512);
  79. for (uint16_t i = 0; i < 512; i += 64) {
  80. // put line number at end of line then CR/LF
  81. pCache[i + 61] = '0' + (i/64);
  82. pCache[i + 62] = '\r';
  83. pCache[i + 63] = '\n';
  84. }
  85. cout << F("Start raw write of ") << file.fileSize() << F(" bytes at\n");
  86. cout << 512000000UL/MICROS_PER_BLOCK << F(" bytes per second\n");
  87. cout << F("Please wait ") << (BLOCK_COUNT*MICROS_PER_BLOCK)/1000000UL;
  88. cout << F(" seconds\n");
  89. // tell card to setup for multiple block write with pre-erase
  90. if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
  91. error("writeStart failed");
  92. }
  93. // init stats
  94. uint16_t overruns = 0;
  95. uint32_t maxWriteTime = 0;
  96. uint32_t t = micros();
  97. uint32_t tNext = t;
  98. // write data
  99. for (uint32_t b = 0; b < BLOCK_COUNT; b++) {
  100. // write must be done by this time
  101. tNext += MICROS_PER_BLOCK;
  102. // put block number at start of first line in block
  103. uint32_t n = b;
  104. for (int8_t d = 5; d >= 0; d--) {
  105. pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
  106. n /= 10;
  107. }
  108. // write a 512 byte block
  109. uint32_t tw = micros();
  110. if (!sd.card()->writeData(pCache)) {
  111. error("writeData failed");
  112. }
  113. tw = micros() - tw;
  114. // check for max write time
  115. if (tw > maxWriteTime) {
  116. maxWriteTime = tw;
  117. }
  118. // check for overrun
  119. if (micros() > tNext) {
  120. if (overruns < OVER_DIM) {
  121. over[overruns].block = b;
  122. over[overruns].micros = tw;
  123. }
  124. overruns++;
  125. // advance time to reflect overrun
  126. tNext = micros();
  127. } else {
  128. // wait for time to write next block
  129. while(micros() < tNext);
  130. }
  131. }
  132. // total write time
  133. t = micros() - t;
  134. // end multiple block write mode
  135. if (!sd.card()->writeStop()) {
  136. error("writeStop failed");
  137. }
  138. cout << F("Done\n");
  139. cout << F("Elapsed time: ") << setprecision(3)<< 1.e-6*t;
  140. cout << F(" seconds\n");
  141. cout << F("Max write time: ") << maxWriteTime << F(" micros\n");
  142. cout << F("Overruns: ") << overruns << endl;
  143. if (overruns) {
  144. uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns;
  145. cout << F("fileBlock,micros") << endl;
  146. for (uint8_t i = 0; i < n; i++) {
  147. cout << over[i].block << ',' << over[i].micros << endl;
  148. }
  149. }
  150. // close file for next pass of loop
  151. file.close();
  152. Serial.println();
  153. }