I have a basic serial logger application that uses addMemoryForRead() to add a lot of additional buffering to the serial port. The main loop then checks for a fixed size block of data being available, reads a block from the Serial port and writes it to the SD card. The large buffer is because this is part of a larger application, I want to allow for long periods where the background loop could stall.
If I set the additional buffer to be 64k or larger I get 1 or two bytes of incorrect data logged approximately at multiples of the total serial buffer size.
e.g. I set the buffer to 64k which adding the standard 64 byte buffer gives a total buffer size of 0x010040. I then send repeating binary count.
In the resulting log file the data at a location 0x010030 onwards is: 0x30 0x31 0x32 0x00 0x34 0x35....
0x0200A0 onwards I get 0xA0 0xA1 0xA2 0x00 0x34 0xA5 0xA6...
0x030110 onwards I get 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x00 0x1A 0x1B...
No other errors are found, all other logged data matches the input exactly. If I increase the buffer size to 128k the errors become twice as far apart.
Setting the buffer size to 32k or 48k I don't see any errors in the output log.
In all cases the resulting log file is the correct size, no bytes are lost, the issues are always corruption rather than missing data.
Any ideas why this would be happening?
Minimal code to reproduce the issue:
-- edit
It looks to be related to the Serial3.avalible() and/or reading all (or almost all) of the data waiting.
If I change
to
so that it never tries to completely empty the buffer then the correct data is recorded.
If I set the additional buffer to be 64k or larger I get 1 or two bytes of incorrect data logged approximately at multiples of the total serial buffer size.
e.g. I set the buffer to 64k which adding the standard 64 byte buffer gives a total buffer size of 0x010040. I then send repeating binary count.
In the resulting log file the data at a location 0x010030 onwards is: 0x30 0x31 0x32 0x00 0x34 0x35....
0x0200A0 onwards I get 0xA0 0xA1 0xA2 0x00 0x34 0xA5 0xA6...
0x030110 onwards I get 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x00 0x1A 0x1B...
No other errors are found, all other logged data matches the input exactly. If I increase the buffer size to 128k the errors become twice as far apart.
Setting the buffer size to 32k or 48k I don't see any errors in the output log.
In all cases the resulting log file is the correct size, no bytes are lost, the issues are always corruption rather than missing data.
Any ideas why this would be happening?
Minimal code to reproduce the issue:
C++:
#include <SD.h>
#define _BIG_BUFFER_SIZE_ (64*1024)
#define _SD_BLOCK_ 512
uint8_t *serialBuffer;
uint8_t cardWriteBuffer[_SD_BLOCK_];
uint32_t writeTime = 0;
File logfile;
void setup() {
Serial.begin(115200);
Serial.println("Looking for SD card");
while (!(SD.begin(BUILTIN_SDCARD))) {
Serial.println("Still looking for SD card");
delay(500);
}
Serial.println("Card found");
serialBuffer = (uint8_t*)malloc(_BIG_BUFFER_SIZE_);
if (!serialBuffer) {
Serial.println("Failed to allocate buffer");
while (true) {
}
}
Serial3.begin(460800);
Serial3.addMemoryForRead(serialBuffer, _BIG_BUFFER_SIZE_);
logfile = SD.open("log.bin", FILE_WRITE);
if (!logfile) {
Serial.println("Failed to open output file");
while (true) {
}
}
Serial.println("Running");
}
void loop() {
uint32_t serialWaiting = Serial3.available();
if (serialWaiting >= _SD_BLOCK_) { // a full block worth waiting
if (serialWaiting >= (_BIG_BUFFER_SIZE_ - _SD_BLOCK_)) {
Serial.println("Overflow!!");
}
Serial3.readBytes(cardWriteBuffer, _SD_BLOCK_);
if (logfile) {
logfile.write(cardWriteBuffer, _SD_BLOCK_);
logfile.flush();
}
writeTime = millis();
}
if (writeTime && ((millis()-writeTime) > 2000) && logfile) {
logfile.close();
logfile = NULL;
Serial.println("Stopping");
}
}
-- edit
It looks to be related to the Serial3.avalible() and/or reading all (or almost all) of the data waiting.
If I change
Code:
if (serialWaiting >= _SD_BLOCK_) {
Code:
if (serialWaiting >= _SD_BLOCK_ + 64) {
Last edited: