Ich hatte da noch etwas rumprobiert und entsprechend erweitert, dass darauf gewartet wird, dass der Buffer gefüllt wird. Mit 8K Buffer 2K Blöcken habe ich die besten Ergebnisse bekommen. Die Übertragung ist nicht wesentlich höher, aber stabiler.
Ob das etwas für diesen Fehler bringt weiß ich leider nicht. Ich hatte diesen Fehler bei mir nie - und benutze inzwischen auch nur noch SD_MMC.
@@ -588,7 +588,7 @@ void explorerHandleFileUpload(AsyncWebServerRequest *request, String filename, s
// Create Ringbuffer for upload
if (explorerFileUploadRingBuffer == NULL) {
- explorerFileUploadRingBuffer = xRingbufferCreate(4096, RINGBUF_TYPE_BYTEBUF);
+ explorerFileUploadRingBuffer = xRingbufferCreate(8192, RINGBUF_TYPE_BYTEBUF);
}
// Create Queue for receiving a signal from the store task as synchronisation
@@ -609,7 +609,14 @@ void explorerHandleFileUpload(AsyncWebServerRequest *request, String filename, s
if (len) {
// stream the incoming chunk to the ringbuffer
+ // unsigned long currentMillis=millis();
xRingbufferSend(explorerFileUploadRingBuffer, data, len, portTICK_PERIOD_MS * 1000);
+ // DEBUG
+ // if ( (millis() - currentMillis) > 1 ) {
+ // Serial.print("X");
+ // } else {
+ // Serial.print("|");
+ // }
}
if (final) {
@@ -621,6 +628,7 @@ void explorerHandleFileUpload(AsyncWebServerRequest *request, String filename, s
// delete task
vTaskDelete(fileStorageTaskHandle);
+ vRingbufferDelete(explorerFileUploadRingBuffer);
}
}
@@ -637,17 +645,32 @@ void explorerHandleFileStorageTask(void *parameter) {
BaseType_t uploadFileNotification;
uint32_t uploadFileNotificationValue;
+ UBaseType_t wait;
+
uploadFile = gFSystem.open((char *)parameter, "w");
+ // wait for initial fillup
+ while (true) {
+ size_t wait = xRingbufferGetCurFreeSize(explorerFileUploadRingBuffer);
+ if (wait > 1400 ) {
+ vTaskDelay(portTICK_PERIOD_MS * 1);
+ //#TODO: fix loop for very small files
+ } else {
+ break;
+ }
+ }
+
for (;;) {
//esp_task_wdt_reset();
-
- item = (uint8_t *)xRingbufferReceive(explorerFileUploadRingBuffer, &item_size, portTICK_PERIOD_MS * 100);
+ //item = (uint8_t *)xRingbufferReceive(explorerFileUploadRingBuffer, &item_size, portTICK_PERIOD_MS * 1000);
+ item = (uint8_t *)xRingbufferReceiveUpTo(explorerFileUploadRingBuffer, &item_size, portTICK_PERIOD_MS * 1000,2048); // 1440
+
if (item != NULL) {
- if (!uploadFile.write(item, item_size)) {
- bytesNok += item_size;
+ uploadFile.write(item, item_size);
+ if (item_size < 2048) {
+ //Print Buffer Size if it is smaller than 2048
+ Serial.print(item_size);
} else {
- bytesOk += item_size;
}
vRingbufferReturnItem(explorerFileUploadRingBuffer, (void *)item);
} else {
@@ -657,19 +680,25 @@ void explorerHandleFileStorageTask(void *parameter) {
uploadFile.close();
snprintf(Log_Buffer, Log_BufferLength, "%s: %s => %zu bytes in %lu ms (%lu kB/s)", (char *)FPSTR (fileWritten), (char *)parameter, bytesNok+bytesOk, (millis() - transferStartTimestamp), (bytesNok+bytesOk)/(millis() - transferStartTimestamp));
Log_Println(Log_Buffer, LOGLEVEL_INFO);
- snprintf(Log_Buffer, Log_BufferLength, "Bytes [ok] %zu / [not ok] %zu\n", bytesOk, bytesNok);
- Log_Println(Log_Buffer, LOGLEVEL_DEBUG);
// done exit loop to terminate
break;
}
- vTaskDelay(portTICK_PERIOD_MS * 100);
}
- #ifdef SD_MMC_1BIT_MODE
- vTaskDelay(portTICK_PERIOD_MS * 1);
- #else
- vTaskDelay(portTICK_PERIOD_MS * 6);
- #endif
+ //vTaskDelay(portTICK_PERIOD_MS * 1);
+ unsigned long waitStartMillis=millis();
+ while (true) {
+ vRingbufferGetInfo(explorerFileUploadRingBuffer,NULL,NULL,NULL,&wait);
+ if (wait < 2048 && ( (millis() - waitStartMillis) < 500 ) ) { // wait for buffer to fill up but max 500 ms
+ vTaskDelay(portTICK_PERIOD_MS * 1);
+ } else {
+ break;
+ }
+ }
}
+
+ Serial.print("Stack watermark Upload-Task :");
+ Serial.println(uxTaskGetStackHighWaterMark(NULL));
+
// send signal to upload function to terminate
xQueueSend(explorerFileUploadStatusQueue, &value, 0);
vTaskDelete(NULL);
--
Ich habe in meiner „Dev-Version“ aber auch die Tasks verändert: Kein „CPU-Pinning“, Loop in eigenen Task, Änderung der Prios. Deshalb weiß ich gerade nicht, wie reproduzierbar das wäre.