123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- // Test Teensy SDIO with write busy in a data logger demo.
- //
- // The driver writes to the uSDHC controller's FIFO then returns
- // while the controller writes the data to the SD. The first sector
- // puts the controller in write mode and takes about 11 usec on a
- // Teensy 4.1. About 5 usec is required to write a sector when the
- // controller is in write mode.
- #include "RingBuf.h"
- #include "SdFat.h"
- // Use Teensy SDIO
- #define SD_CONFIG SdioConfig(FIFO_SDIO)
- // Interval between points for 25 ksps.
- #define LOG_INTERVAL_USEC 40
- // Size to log 10 byte lines at 25 kHz for more than ten minutes.
- #define LOG_FILE_SIZE 10 * 25000 * 600 // 150,000,000 bytes.
- // Space to hold more than 800 ms of data for 10 byte lines at 25 ksps.
- #define RING_BUF_CAPACITY 400 * 512
- #define LOG_FILENAME "SdioLogger.csv"
- SdFs sd;
- FsFile file;
- // RingBuf for File type FsFile.
- RingBuf<FsFile, RING_BUF_CAPACITY> rb;
- void logData() {
- // Initialize the SD.
- if (!sd.begin(SD_CONFIG)) {
- sd.initErrorHalt(&Serial);
- }
- // Open or create file - truncate existing file.
- if (!file.open(LOG_FILENAME, O_RDWR | O_CREAT | O_TRUNC)) {
- Serial.println("open failed\n");
- return;
- }
- // File must be pre-allocated to avoid huge
- // delays searching for free clusters.
- if (!file.preAllocate(LOG_FILE_SIZE)) {
- Serial.println("preAllocate failed\n");
- file.close();
- return;
- }
- // initialize the RingBuf.
- rb.begin(&file);
- Serial.println("Type any character to stop");
- // Max RingBuf used bytes. Useful to understand RingBuf overrun.
- size_t maxUsed = 0;
- // Min spare micros in loop.
- int32_t minSpareMicros = INT32_MAX;
- // Start time.
- uint32_t logTime = micros();
- // Log data until Serial input or file full.
- while (!Serial.available()) {
- // Amount of data in ringBuf.
- size_t n = rb.bytesUsed();
- if ((n + file.curPosition()) > (LOG_FILE_SIZE - 20)) {
- Serial.println("File full - quitting.");
- break;
- }
- if (n > maxUsed) {
- maxUsed = n;
- }
- if (n >= 512 && !file.isBusy()) {
- // Not busy only allows one sector before possible busy wait.
- // Write one sector from RingBuf to file.
- if (512 != rb.writeOut(512)) {
- Serial.println("writeOut failed");
- break;
- }
- }
- // Time for next point.
- logTime += LOG_INTERVAL_USEC;
- int32_t spareMicros = logTime - micros();
- if (spareMicros < minSpareMicros) {
- minSpareMicros = spareMicros;
- }
- if (spareMicros <= 0) {
- Serial.print("Rate too fast ");
- Serial.println(spareMicros);
- break;
- }
- // Wait until time to log data.
- while (micros() < logTime) {
- }
- // Read ADC0 - about 17 usec on Teensy 4, Teensy 3.6 is faster.
- uint16_t adc = analogRead(0);
- // Print spareMicros into the RingBuf as test data.
- rb.print(spareMicros);
- rb.write(',');
- // Print adc into RingBuf.
- rb.println(adc);
- if (rb.getWriteError()) {
- // Error caused by too few free bytes in RingBuf.
- Serial.println("WriteError");
- break;
- }
- }
- // Write any RingBuf data to file.
- rb.sync();
- file.truncate();
- file.rewind();
- // Print first twenty lines of file.
- Serial.println("spareMicros,ADC0");
- for (uint8_t n = 0; n < 20 && file.available();) {
- int c = file.read();
- if (c < 0) {
- break;
- }
- Serial.write(c);
- if (c == '\n') n++;
- }
- Serial.print("fileSize: ");
- Serial.println((uint32_t)file.fileSize());
- Serial.print("maxBytesUsed: ");
- Serial.println(maxUsed);
- Serial.print("minSpareMicros: ");
- Serial.println(minSpareMicros);
- file.close();
- }
- void clearSerialInput() {
- for (uint32_t m = micros(); micros() - m < 10000;) {
- if (Serial.read() >= 0) {
- m = micros();
- }
- }
- }
- void setup() {
- Serial.begin(9600);
- while (!Serial) {
- }
- // Go faster or log more channels. ADC quality will suffer.
- // analogReadAveraging(1);
- }
- void loop() {
- clearSerialInput();
- Serial.println("Type any character to start");
- while (!Serial.available()) {
- }
- clearSerialInput();
- logData();
- }
|