Moin zusammen,
mir ist vor einer Weile schon mal etwas aufgefallen, von dem ich inzwischen dachte, dass es gelöst sei. Und zwar fiel auf, dass Dateien unvollständig auf SD geschrieben wurden (sowohl Webtransfer als auch FTP). Hatte dies eher einem Speicherproblem zugeschrieben.
Also scheinbar werden sie kopiert, defacto werden sie jedoch unnvollständig geschrieben. Nun hatte ich am Wochenende größere Mengen (2 GB oder so) via Webtransfer auf den ESPuino meiner Tochter kopiert - da wird ein Lolin32 + PN5180 + SD_MMC verwendet. Da sind mir keine Probleme aufgefallen. Der Durchsatz lag hier bei etwa 350 kB/s - an den kürzlich eingeführten Statistiken kann man das ja gut sehen.
Gestern beim Kopieren auf den ESPuino meines Sohnemanns (Lolin D32 + RC522 + SD-SPI) trat das Problem jedoch wieder auf. Schon beim Transfer (SD-SPI ist ja etwas langsamer als SD_MMC) ist etwas verwunderlich, dass dieser erst etwas langsamer losgeht, um sich dann jedoch irgendwann auf dem Durchsatz von SD_MMC einzupendeln. Das ist dann wohl der Punkt, an dem es Probleme gibt.
Der Webtransfer (@Harry hatte das damals implementiert) funktioniert so, dass der Webserver den Datenstrom entgegennimmt und in IP-Paketgröße ganz oft (bis die ganze Datei abgearbeitet ist) den Datenstrom an eine Methode übergibt. Diese Methode (explorerHandleFileUpload()) erstellt bei ihrem ersten Aufruf einen Ringpuffer, in dem die Daten landen. Zusätzlich einen Task, der die Daten des Ringpuffers entgegen nimmt und in eine Datei schreibt (explorerHandleFileStorageTask()). Ist der Transfer zu Ende, so werden Ringpuffer und Task wieder gelöscht, so dass sie keinen Speicher mehr belegen. Vorteile an dieser Vorgehensweise ist: Das Empfangen und das Schreiben des Datenstroms kann parallel passieren, was die Sache schneller macht. Es frisst aber auch keinen Speicher, wenn nix übertragen wird.
Ein Task ist im Endeffekt eine Funktion, die losgelöst vom Rest läuft und von der der Teil, der zyklisch laufen soll, in einer Endlosschleife läuft. Läuft diese Schleife zu schnell, so kann sie den ESP32 zum Neustart bringen oder andere Funktionen beeinträchtigen, da diese keine CPU-Zeit mehr kriegen. Es kann daher notwendig sein, an dieser Stelle Delays einzubauen. Und genau an dieser Stelle gab es jetzt offenbar ein Problem:
Wir hatten uns einfach darauf verlassen, dass uploadFile.write() schon klappen wird und haben den Rückgabewert nicht ausgewertet. In Verbindung mit nur einer Millisekunde Delay, was ich für SD_MMC optimiert hatte, zeigte sich jedoch, dass diese Methode ganz oft „hat nicht geklappt“ zurückliefert. Ich habe daher jetzt beim Delay eine Unterscheidung vorgenommen, die zwischen SD_MMC und SPI-SD unterscheidet:
Ich habe zusätzlich eine kleine Statistik implementiert, die im Log ausgegeben wird. Dort kann man sehen, ob eine Datei ohne Fehler geschrieben wurde. Das sieht z.B. so aus:
Datei geschrieben: /mp313.mp3 => 240170769 bytes in 646190 ms (371 kB/s)
Bytes [ok] 240170769 / [not ok] 0
Also offenbar ist es so, dass das eigentliche Schreiben auf SD asynchron geschieht und der ESP32 nicht mehr nachkommt, wenn das Delay nicht lange genug ist. Ich meine in Erinnerung zu haben, dass bei SPI-SD noch irgendwelche Checks stattfinden, die das Ganze im Endeffekt auch langsamer machen im Vergleich zu SD_MMC. Vermutung: Diese finden nachgelagert statt und hier gibt es Probleme.
TL;DR:
Meine Bitte an diejenigen, die bereits den aktuellen Master benutzen: Aktualisiert bitte mal auf den aktuellen Softwarestand, ladet ein paar Files via Webtransfer hoch und schaut, ob es hier Probleme gibt. Wenn bei „not ok“ eine 0 steht dann passt alles. Für SD_MMC ist es aus meiner Sicht ok. Bei SPI-SD habe ich jetzt ein wenig mit dem Delay „gespielt“, bis es aus meiner Sicht ok war.
@Harry Du hattest die Ringpuffergröße und auch den Task auf 4k gesetzt. Hat das Vorteile aus deiner Sicht ggü 2k? Weil so wie ich das sehe, kommen die Daten maximal in IP-Paketgröße an (knapp über 1400).
EDIT: Glaube die Frage kann ich mir selbst beantworten: Es erhöht die Sicherheit, falls das Schreiben mal nicht nachkommt. Mit weniger Puffer wäre das Problem vermutlich noch größer bei SPI-SD.