Bill Greiman
Well-known member
I have been working on new features for SdFat. Two are useful for Teensy 3.6 and Teensy 4.1.
The first is a ring buffer that is tightly integrated with SdFat and can be called from an ISR. As a test, I did a DMA ADC logger and stress tested it with the max ADC over-clocking on Teensy 3.6. Here is a chart of a 50 kHz square wave at 3 million samples per second.
I have attached the the .ino file for the logger and RingBuf.h, the template for the ring buffer. You can run them with SdFat 2.0.4.
The second feature is a rework of the Teensy SDIO driver. I have been able to get sd busy to work. I also overlap sending data to the sd with execution of the program. I do this by writing a sector to the SDHC FIFO then returning while the data is sent over the SDIO bus. On Teensy 4.1, writing the first sector takes 10-11 usec which includes time to put the controller in write mode. Subsequent sectors take 5 usec.
the isBusy feature plus the short write time allows a simple non DMA program to log data at over 25 kHz.
Here is the loop that logged the data for the above chart. It logged by printing text to a RingBuf object.
I will release a beta of the new driver soon. The isBusy feature is of limited use for Teensy 3.6 since it can't do infinite writes before a reset, only 0xffff sectors.
The first is a ring buffer that is tightly integrated with SdFat and can be called from an ISR. As a test, I did a DMA ADC logger and stress tested it with the max ADC over-clocking on Teensy 3.6. Here is a chart of a 50 kHz square wave at 3 million samples per second.
I have attached the the .ino file for the logger and RingBuf.h, the template for the ring buffer. You can run them with SdFat 2.0.4.
The second feature is a rework of the Teensy SDIO driver. I have been able to get sd busy to work. I also overlap sending data to the sd with execution of the program. I do this by writing a sector to the SDHC FIFO then returning while the data is sent over the SDIO bus. On Teensy 4.1, writing the first sector takes 10-11 usec which includes time to put the controller in write mode. Subsequent sectors take 5 usec.
the isBusy feature plus the short write time allows a simple non DMA program to log data at over 25 kHz.
Here is the loop that logged the data for the above chart. It logged by printing text to a RingBuf object.
Code:
// 400 sector ring buffer for FsFile type.
RingBuf<FsFile, 400*512> rb;
// Initialize the RingBuf - use a large pre-allocated exFAT file.
rb.begin(&file);
// Used for controlling the log interval.
uint32_t logTime = micros();
while (!Serial.available()) {
// Write data to SD if a sector is in the RingBuf.
if (rb.bytesUsed() >= 512 && !file.isBusy()) {
// Writing full sectors assures no copy to SdFat internal cache buffer.
// Write of first sector takes about 11 usec, 5 usec each for remainder.
if (512 != rb.writeOut(512)) {
// Handle SD write error here.
}
}
// Time for next point - log at 25 kHz.
logTime += 40;
// Spare time before next point - negative if time overrun.
int32_t spareMicros = logTime - micros();
// Wait until time to log data.
while (micros() < logTime) {}
// Read ADC0 this takes about 17 usec on Teensy 4.
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()) {
// Handle error caused by too few free bytes in RingBuf.
}
}