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

RawWrite.ino 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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 "FreeStack.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. // Wait for USB Serial
  48. while (!Serial) {
  49. SysCall::yield();
  50. }
  51. }
  52. //------------------------------------------------------------------------------
  53. void loop(void) {
  54. do {
  55. delay(10);
  56. } while (Serial.read() >= 0);
  57. // F stores strings in flash to save RAM
  58. cout << F("Type any character to start\n");
  59. while (Serial.read() <= 0) {
  60. SysCall::yield();
  61. }
  62. cout << F("FreeStack: ") << FreeStack() << endl;
  63. // initialize the SD card at SPI_FULL_SPEED for best performance.
  64. // try SPI_HALF_SPEED if bus errors occur.
  65. if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
  66. sd.initErrorHalt();
  67. }
  68. // delete possible existing file
  69. sd.remove("RawWrite.txt");
  70. // create a contiguous file
  71. if (!file.createContiguous(sd.vwd(), "RawWrite.txt", 512UL*BLOCK_COUNT)) {
  72. error("createContiguous failed");
  73. }
  74. // get the location of the file's blocks
  75. if (!file.contiguousRange(&bgnBlock, &endBlock)) {
  76. error("contiguousRange failed");
  77. }
  78. //*********************NOTE**************************************
  79. // NO SdFile calls are allowed while cache is used for raw writes
  80. //***************************************************************
  81. // clear the cache and use it as a 512 byte buffer
  82. uint8_t* pCache = (uint8_t*)sd.vol()->cacheClear();
  83. // fill cache with eight lines of 64 bytes each
  84. memset(pCache, ' ', 512);
  85. for (uint16_t i = 0; i < 512; i += 64) {
  86. // put line number at end of line then CR/LF
  87. pCache[i + 61] = '0' + (i/64);
  88. pCache[i + 62] = '\r';
  89. pCache[i + 63] = '\n';
  90. }
  91. cout << F("Start raw write of ") << file.fileSize() << F(" bytes at\n");
  92. cout << 512000000UL/MICROS_PER_BLOCK << F(" bytes per second\n");
  93. cout << F("Please wait ") << (BLOCK_COUNT*MICROS_PER_BLOCK)/1000000UL;
  94. cout << F(" seconds\n");
  95. // tell card to setup for multiple block write with pre-erase
  96. if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
  97. error("writeStart failed");
  98. }
  99. // init stats
  100. uint16_t overruns = 0;
  101. uint32_t maxWriteTime = 0;
  102. uint32_t t = micros();
  103. uint32_t tNext = t;
  104. // write data
  105. for (uint32_t b = 0; b < BLOCK_COUNT; b++) {
  106. // write must be done by this time
  107. tNext += MICROS_PER_BLOCK;
  108. // put block number at start of first line in block
  109. uint32_t n = b;
  110. for (int8_t d = 5; d >= 0; d--) {
  111. pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
  112. n /= 10;
  113. }
  114. // write a 512 byte block
  115. uint32_t tw = micros();
  116. if (!sd.card()->writeData(pCache)) {
  117. error("writeData failed");
  118. }
  119. tw = micros() - tw;
  120. // check for max write time
  121. if (tw > maxWriteTime) {
  122. maxWriteTime = tw;
  123. }
  124. // check for overrun
  125. if (micros() > tNext) {
  126. if (overruns < OVER_DIM) {
  127. over[overruns].block = b;
  128. over[overruns].micros = tw;
  129. }
  130. overruns++;
  131. // advance time to reflect overrun
  132. tNext = micros();
  133. } else {
  134. // wait for time to write next block
  135. while(micros() < tNext);
  136. }
  137. }
  138. // total write time
  139. t = micros() - t;
  140. // end multiple block write mode
  141. if (!sd.card()->writeStop()) {
  142. error("writeStop failed");
  143. }
  144. cout << F("Done\n");
  145. cout << F("Elapsed time: ") << setprecision(3)<< 1.e-6*t;
  146. cout << F(" seconds\n");
  147. cout << F("Max write time: ") << maxWriteTime << F(" micros\n");
  148. cout << F("Overruns: ") << overruns << endl;
  149. if (overruns) {
  150. uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns;
  151. cout << F("fileBlock,micros") << endl;
  152. for (uint8_t i = 0; i < n; i++) {
  153. cout << over[i].block << ',' << over[i].micros << endl;
  154. }
  155. }
  156. // close file for next pass of loop
  157. file.close();
  158. Serial.println();
  159. }