mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-30 05:01:59 +08:00

* Update WebSocket library * Update SSDP library * Update TFT_eSPI library * Update EspLuaEngine library * Update SDFat library * Change to pioarduino * Make ESP3DMessageFIFO and ESP3DMessage more thread safe * Fix sanity checks for BT * Add some C6 support * Refactor ethernet code * Split Ethernet Sta / WiFi sta ESP Commands and settings * Simplify wait and wdtFeed code * Set C3 with 4MB by default in platformio.ini * Apply Disable brown out only on ESP32 to avoid crash e.g:ESP32S3 * Add missing entries in platformio.ini
215 lines
5.7 KiB
C++
215 lines
5.7 KiB
C++
// Test of Teensy exFAT DMA ADC logger.
|
|
// This is mainly to test use of RingBuf in an ISR.
|
|
// This example only supports pins on the first ADC.
|
|
// it has only been tested on Teensy 3.6 and 4.1.
|
|
// You should modify it for serious use as a data logger.
|
|
//
|
|
#include "ADC.h"
|
|
#include "DMAChannel.h"
|
|
#include "FreeStack.h"
|
|
#include "RingBuf.h"
|
|
#include "SdFat.h"
|
|
|
|
// Pin must be on first ADC.
|
|
#define ADC_PIN A0
|
|
|
|
// 400 sector RingBuf - could be larger on Teensy 4.1.
|
|
const size_t RING_BUF_SIZE = 400 * 512;
|
|
|
|
// Preallocate 8GiB file.
|
|
const uint64_t PRE_ALLOCATE_SIZE = 8ULL << 30;
|
|
|
|
// Use FIFO SDIO.
|
|
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
|
|
|
ADC adc;
|
|
|
|
DMAChannel dma(true);
|
|
|
|
SdFs sd;
|
|
|
|
FsFile file;
|
|
|
|
// Ping-pong DMA buffer.
|
|
DMAMEM static uint16_t __attribute__((aligned(32))) dmaBuf[2][256];
|
|
|
|
// Count of DMA interrupts.
|
|
volatile size_t dmaCount;
|
|
|
|
// RingBuf for 512 byte sectors.
|
|
RingBuf<FsFile, RING_BUF_SIZE> rb;
|
|
|
|
// Shared between ISR and background.
|
|
volatile size_t maxBytesUsed;
|
|
|
|
// Overrun error for write to RingBuf.
|
|
volatile bool overrun;
|
|
//------------------------------------------------------------------------------
|
|
// ISR for DMA.
|
|
static void isr() {
|
|
if (!overrun) {
|
|
// Clear cache for buffer filled by DMA to insure read from DMA memory.
|
|
arm_dcache_delete((void*)dmaBuf[dmaCount & 1], 512);
|
|
// Enable RingBuf functions to be called in ISR.
|
|
rb.beginISR();
|
|
if (rb.write(dmaBuf[dmaCount & 1], 512) == 512) {
|
|
dmaCount++;
|
|
if (rb.bytesUsed() > maxBytesUsed) {
|
|
maxBytesUsed = rb.bytesUsed();
|
|
}
|
|
} else {
|
|
overrun = true;
|
|
}
|
|
// End use of RingBuf functions in ISR.
|
|
rb.endISR();
|
|
}
|
|
dma.clearComplete();
|
|
dma.clearInterrupt();
|
|
#if defined(__IMXRT1062__)
|
|
// Handle clear interrupt glitch in Teensy 4.x!
|
|
asm("DSB");
|
|
#endif // defined(__IMXRT1062__)
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
#if defined(__IMXRT1062__) // Teensy 4.x
|
|
#define SOURCE_SADDR ADC1_R0
|
|
#define SOURCE_EVENT DMAMUX_SOURCE_ADC1
|
|
#else
|
|
#define SOURCE_SADDR ADC0_RA
|
|
#define SOURCE_EVENT DMAMUX_SOURCE_ADC0
|
|
#endif
|
|
//------------------------------------------------------------------------------
|
|
static void init(uint8_t pin) {
|
|
dma.begin();
|
|
dma.attachInterrupt(isr);
|
|
dma.source((volatile const signed short&)SOURCE_SADDR);
|
|
dma.destinationBuffer((volatile uint16_t*)dmaBuf, sizeof(dmaBuf));
|
|
dma.interruptAtHalf();
|
|
dma.interruptAtCompletion();
|
|
dma.triggerAtHardwareEvent(SOURCE_EVENT);
|
|
dma.enable();
|
|
adc.adc0->enableDMA();
|
|
adc.adc0->startContinuous(pin);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void stopDma() {
|
|
adc.adc0->disableDMA();
|
|
dma.disable();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void printTest(Print* pr) {
|
|
if (file.fileSize() < 1024 * 2) {
|
|
return;
|
|
}
|
|
file.rewind();
|
|
rb.begin(&file);
|
|
// Could readIn RING_BUF_SIZE bytes and write to a csv file in a loop.
|
|
if (rb.readIn(2048) != 2048) {
|
|
sd.errorHalt("rb.readIn failed");
|
|
}
|
|
uint16_t data;
|
|
for (size_t i = 0; i < 1024; i++) {
|
|
pr->print(i);
|
|
pr->print(',');
|
|
// Test read with: template <typename Type>bool read(Type* data).
|
|
rb.read(&data);
|
|
pr->println(data);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void runTest(uint8_t pin) {
|
|
dmaCount = 0;
|
|
maxBytesUsed = 0;
|
|
overrun = false;
|
|
do {
|
|
delay(10);
|
|
} while (Serial.read() >= 0);
|
|
|
|
if (!file.open("IsrLoggerTest.bin", O_CREAT | O_TRUNC | O_RDWR)) {
|
|
sd.errorHalt("file.open failed");
|
|
}
|
|
if (!file.preAllocate(PRE_ALLOCATE_SIZE)) {
|
|
sd.errorHalt("file.preAllocate failed");
|
|
}
|
|
rb.begin(&file);
|
|
Serial.println("Type any character to stop\n");
|
|
|
|
init(pin);
|
|
uint32_t samplingTime = micros();
|
|
while (!overrun && !Serial.available()) {
|
|
size_t n = rb.bytesUsed();
|
|
if ((n + file.curPosition()) >= (PRE_ALLOCATE_SIZE - 512)) {
|
|
Serial.println("File full - stopping");
|
|
break;
|
|
}
|
|
if (n >= 512) {
|
|
if (rb.writeOut(512) != 512) {
|
|
Serial.println("writeOut() failed");
|
|
file.close();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
stopDma();
|
|
samplingTime = micros() - samplingTime;
|
|
if (!rb.sync()) {
|
|
Serial.println("sync() failed");
|
|
file.close();
|
|
return;
|
|
}
|
|
if (!file.truncate()) {
|
|
sd.errorHalt("truncate failed");
|
|
}
|
|
if (overrun) {
|
|
Serial.println("Overrun ERROR!!");
|
|
}
|
|
Serial.print("dmsCount ");
|
|
Serial.println(dmaCount);
|
|
Serial.print("RingBufSize ");
|
|
Serial.println(RING_BUF_SIZE);
|
|
Serial.print("maxBytesUsed ");
|
|
Serial.println(maxBytesUsed);
|
|
Serial.print("fileSize ");
|
|
file.printFileSize(&Serial);
|
|
Serial.println();
|
|
Serial.print(0.000001 * samplingTime);
|
|
Serial.println(" seconds");
|
|
Serial.print(1.0 * file.fileSize() / samplingTime, 3);
|
|
Serial.println(" MB/sec\n");
|
|
printTest(&Serial);
|
|
file.close();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void waitSerial(const char* msg) {
|
|
do {
|
|
delay(10);
|
|
} while (Serial.read() >= 0);
|
|
Serial.println(msg);
|
|
while (!Serial.available()) {
|
|
}
|
|
Serial.println();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
while (!Serial) {
|
|
yield();
|
|
}
|
|
waitSerial("Type any character to begin");
|
|
Serial.print("FreeStack: ");
|
|
Serial.println(FreeStack());
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
void loop() {
|
|
if (!sd.begin(SD_CONFIG)) {
|
|
sd.initErrorHalt(&Serial);
|
|
}
|
|
// Try for max speed.
|
|
adc.adc0->setAveraging(1);
|
|
adc.adc0->setResolution(10);
|
|
adc.adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
|
|
adc.adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
|
|
runTest(ADC_PIN);
|
|
waitSerial("Type any character to run test again");
|
|
}
|