Hallo. Ich habe einen ESP32-S3 am laufen und ca. alle 5 Minuten habe ich ein Problem mit vermutlich einem DMA. Zum Projekt: SPI Display, Kamera, SD und I2S sind parallel am laufen. WLAN & BT sind aus, denke ich wenigstens weil ich das alles deaktiviert habe und kein Init davon mache. Aber was der ganze FREERTOS kram da noch verstalltet kann ich nicht erkennen. Der Code ist basiert auf dem ofizellen CAM Treiber und einem WEB Player mit Display. Also eigentlich funktionieren Funktionen. Von der SD Karte werden MP3 Daten abgespielt und auf dem Display der Titel oder Menue angezeigt. Im Hintergrund wird das Kammerabild eingeblendet. Über eine Taste kann man zwischen Kamera, Mix und Menu umschalten. So ca. alle 5 Minuten gibt es ein grossen Knall und das Bild & Ton sind kurz gestört. Ist mir beim Bild zuerst aufgefallen. Was ich bis jetzt sehen kann ist das plötzlich Daten im Kammera DMA Speicher fehlen oder einfach nur komplett anders sind wie normal (Standbild mit XOR vergleich zum vorherigen Bild). Bei dem I2S Daten kann ich das nicht sehen, der Speicher dafür wird aber gefüllt. Ob die SPI zum Display auch probleme hat kann ich leider auch nicht erkennen. Dafür müsste ich auch diesen Bus auswerten und ob man das dann dadrin findet ist offen. Es ist schon recht komisch, das ganze passiert recht genau alle 5min +-20sec. Kennt jemand so ein Problem? Was kann das sein?
Überlauf einer Register? Kommt es denn genau alle 5 Minunten? Oder irgendwie 4,2? Könnte auch ein Watchdog sein der nicht bedient ist. DMA und Cache? Wie ist der Cachecoherenz sichergestellt? Debuggen? Gibt es für den ESP32 richtige debuggers mit breakpoints und so? Wenn ja dann ran an das Gerät und gucken was da so läuft.
Im Debugger sieht man nichts. Alles scheint richtig zu sein, ausser den Daten. Schade da du diese Frage stellst benutzt Du anschined nicht diesen Prozessor. Alles was WD heist ist auf anderen Werten, außerdem würde der sich auch anders melden. Tja ein Überlauf könnte zwar sein aber da müsste man erst mal was finden, in dem von mir zusammen gebauten Code ist jedenfalls nichts dergleichen drin. Und der Systemtimer ist da noch lange nicht übergelaufen. DMA & Interrupts sind im IRAM gelegt damit mir kein Code laden rein funken kann. Kann mir jemand sagen auf welchem Kern diese Funktionen laufen?
portENTER_CRITICAL ist der Feind! Ich habe damit Zugriffe auf Ansammlungen von Globalen Variablen von einem Task durch einen 2. Task verhindert. Nachdem ich das nun einfach mal ausgeklammert habe läuft alles anscheined sauber (45min). Weitere Tests über mehrere Stunden muss ich noch machen. Warum das überhaupt so kritisch ist könnte ich versuchen abzuklären, ist mir aber nicht wichtig genug. Unter einem AVR oder unter einem STM32 hatte ich jedenfalls noch nie so ein Problem gehabt, obwohl ich bei Projekten darauf portENTER_CRITICAL sehr viel öfter benutze.
Gebe dir mal alle 100ms den freien Heap aus. Ich würde auch den Stack kontrollieren. Wegen dem OS gibt es vermutlich für jeden Thread einen eigenen Stack, oder?
Dirk E. schrieb: > portENTER_CRITICAL ist der Feind! Vielleicht nimmst Du eher taskENTER_CRITICAL(). Siehe auch: Beitrag "Re: ESP32 Tasks portENTER_CRITICAL" Laut https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html scheint das auch das bessere Mittel zu sein.
Warum kein Mutex? Der ermöglicht es dem RTOS den wartenden Thread schlafen zu legen wenn gerade ein anderer Thread auf die Daten zugreift. portENTER_CRITICAL ist auf ESP32 anscheinend ein Spinlock. D.h. ein Thread welcher gerade nicht zugreifen kann rotiert "sinnlos" in einer Endlosschleife, bis der andere Thread, welcher den Lock aquiriert hat, diesen wieder freigibt. Bei Dual-Core (ESP32S3) wird so die Leistung eines Cores verschwendet, der auch andere Threads ausführen könnte. Bei Singlecore wird der Timeslice des wartenden Threads verschwendet. Erst wenn der präemptive Scheduler (Round Robin) den wartenden Thread nach Ablaufen der Timeslice unterbricht und zum ersten Thread zurückwechselt kann dieser mit den Daten weiter arbeiten und den Spinlock wieder freigeben. Da ist es natürlich kein Wunder dass es nicht gut läuft. Oder überseh ich was?
So ich habe nun etwas gelesen und mir einige meiner alten Projekte angesehen. Das portENTER_CRITICAL in den alten Projekten ist auch falsch, da fällt es nur nicht auf weil da immer nur die SIO parallel per Interrupt läuft. Jetzt mit der Kammera und den Interrupts dazu ist es halt einfacher zu treffen. vTaskSuspendAll & xTaskResumeAll sind da wohl erstmal die bessere Wahl. Auch wenn xTaskResumeAll die Interrupts kurz abschaltet. Mutex ist auch eine gute Möglichkeit, macht aber hier und da es auch komplizierter wie es sein müsste. Am besten man blockiert nichts! Bis auf eine Stelle konnte ich das auch umbauen und dafür finde ich auch noch eine Lösung.
Dirk E. schrieb: > vTaskSuspendAll & xTaskResumeAll sind da wohl erstmal die bessere Wahl. Espressif sagt dazu: > Given that scheduler suspension on ESP-IDF FreeRTOS will only suspend scheduling on a particular core, scheduler suspension is NOT a valid method ensuring mutual exclusion between tasks when accessing shared data. Users should use proper locking primitives such as mutexes or spinlocks if they require mutual exclusion. Außerdem interferiert es mit Delay-Aufrufen auf der anderen CPU. Dirk E. schrieb: > Mutex ist auch eine gute Möglichkeit, macht aber hier und da es auch > komplizierter wie es sein müsste. Mutexe sind halt das Mittel der Wahl unter einem (RT)OS. Den Scheduler anzuhalten ist die ziemliche Holzhammermethode. Außerdem gibt es natürlich noch Atomics und beim ESP-IDF ist auch ein sehr hilfreicher thread-sicherer Ringbuffer mitgeliefert. Ein korrekt(!) mithilfe von Mutex, Semaphore, Atomics implementierter Code funktioniert automatisch korrekt und effizient(!) auf Single- und Multicore-Prozessoren, weil man mithilfe dieser Primitive dem Scheduler genau mitteilt, welche Code-Abschnitte parallel ablaufen dürfen und welche nicht. Der Scheduler kann somit immer Threads finden, welche parallel laufen dürfen, und diese auf die Cores verteilen. Wenn man einfach den Scheduler abwürgt existiert diese Information nicht, und es skaliert nicht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.