Dev-Branch

Ja, das habe ich auch schon gesehen und das Plugin installiert. Aber verstanden habe ich’s noch nicht, wie ich da jetzt zB nen grünen Haken reinkriege.

Ich deaktiviere momentan einfach Bluetooth, weil ich das nicht brauche. Da könnte man auch mal drüber nachdenken ob man das standardmäßig deaktiviert.

Ansonsten habe ich gerade nicht so viel Zeit damit zu experimentieren. Aber ich habe es zumindest mit ein paar kleinen Änderungen geschafft den Branch für „Arduino as IDF Component“ soweit zu bekommen, dass er bis auf den IRAM Speicherüberlauf baut. Allerdings ist der Überlauf jetzt plötzlich ~12 KiB. Das heißt da ist in der Konstellation jetzt irgendwas drin was davor nicht drin war.

@Joe91 Vielleicht bringt dich das irgendwie weiter!?

Vielen Dank dir. Ja an diesen Punkt bin ich auch schon etwas überrascht gekommen ^^.
Das mit dem Bluetooth ist ein guter Quickfix. Werde das wohl auch erstmal so machen…

Denke auch das zunächst das Linker-Problem mit zu wenig IRAM gelöst werden muss. Dazu sehe ich 2 Möglichkeiten:

  • Man kann ein angepasstes Arduino-Framework erzeugen und dann referenzieren. Dann wäre auch Feintuning möglich z.B. bei Speicherzuteilung, Wifi-Durchsatz oder auch Messung der Taskverteilung
    .
  • Man sucht sich die Teile aus unserem Code/Bibliotheken die viel IRAM verbrauchen und reduziert sie um >200 Bytes. Weil wenn das passt linkt der Code und läuft auch stabil.

Die 1.Möglichkeit ist schon einigermaßen kompliziert. Man muss das IDF-Framework mit einigen GB installieren und mittels Arduino Lib Builder neu erzeugen. Ich habe das noch nicht geschafft und möchte es auch keinem Einsteiger hier zumuten. Das müsste jemand hier transparent bereitstellen.

Bei der 2. Möglichkeit wissen wir ja genau was wie viel verbraucht:

C:\Users\Laszlo                                                            910    0.80
  Documents\PlatformIO\Projects\ESPuino                                    900    0.79
    .pio\libdeps\ttgo_t8                                                   882    0.77
      FastLED\src\platforms\esp\32\clockless_rmt_esp32.cpp                 863    0.76
        ESP32RMTController::doneOnChannel(rmt_channel_t, void*)            180    0.16
        ESP32RMTController::showPixels()                                   165    0.14
        ESP32RMTController::interruptHandler(void*)                        134    0.12
        ESP32RMTController::fillNext(bool)                                 129    0.11
        ESP32RMTController::tx_start()                                     122    0.11
        ESP32RMTController::startOnChannel(int)                             88    0.08
        ESP32RMTController::startNext(int)                                  45    0.04
      ESP32Encoder\src\ESP32Encoder.cpp                                     19    0.02
        ipc_install_isr_on_core(void*)                                      19    0.02
    src\Button.cpp                                                          18    0.02
      onTimer()                                                             18    0.02

Also FastLED ist hier der Kandidat. Habe dann versuchsweise anstelle des RMT- den I2S-Treiber eingebunden (Geht über ein #define). Danach kam Knacken aus dem Lautsprecher - Wir verwenden ja I2S für die Audio-Ausgabe. Kommt wohl nicht in Frage

Dann habe ich testweise dam IRAM Attribut für doneOnChannel und showPixels rausgenommen.
Es kompiliert, linkt und funktioniert Alles wie gewünscht. Ich kann bisher auch kein Flackern erkennen. Aber ob das die Lösung ist?

Mir ist klar das zeitkritische Routinen wie Interrupt-Handler das IRAM Attribut bekommen müssen. Und warscheinlich auch alle Methoden die aus einem solchen Handler aufgerufen werden. FastLED ist mit dem Treiber auf mehrere LED-Stripes Kanäle ausgelegt, wir verwenden ja nur einen mit <50 LEDs.

Evt. ist das ein einfacher & schneller Weg dort anzusetzen? Stabil muss es halt schon sein…

1 „Gefällt mir“

Das ist natürlich auch eine Möglichkeit & sehr einfach. Man gibt das dann als Systemvoraussetzung vor. Wer Bluetooth verwenden will muss an andere Stelle sparen…

Übrigens ich teste den DEV-Branch sehr oft ohne Bluetooth, weil das schneller kompiliert, linkt & hochlädt. Spart etwas Zeit!

2 „Gefällt mir“

Wie von @laszloh und mir oben schon vorgeschlagen und von @Joe91 und mir schon versucht kann man auch den Weg gehen Arduino als Komponente einzubinden. Dann kann man die ESP-IDF Optionen verändern und ESP-IDF wird automatisch neu gebaut. Das ist deutlich einfacher als das Arduino-Framework anzupassen.

Man müsste aber schon ein ganzes Stück mehr als 200 Bytes rausholen, dass man wenigstens einen Puffer hat. Sonst fliegt einem das bei jeder Änderung, die ein paar Byte mehr braucht wieder um die Ohren.

Ich würde vorschlagen langfristig an mehreren Stellen anzusetzen:

  • Bluetooth standardmäßig deaktivieren
  • Arduino als Komponente einbinden und IDF-Optionen für IRAM Optimierung setzen
  • Im eigenen Code (und wo möglich in Bibliotheken) IRAM sparen sofern möglich
1 „Gefällt mir“

OK, ich würde dann zunächst Bluetooth standardmässig deaktivieren damit DEV auch auf den verbreiteten Boards mit Port-Expander kompiliert & linkt. Damit niemand der den DEV-Branch ausprobieren möchte in einen Fehler hineinläuft.

Optimierung von FastLED wäre eine kleine schnelle Lösung. Klar, es kann bei der nächsten Erweiterung dann wieder knapp werden. Ich teste bereits Arduino 2.0.8, aber da gibt es keine Änderungen bzgl. Speichernutzung.

Für Arduino als Komponente freue ich mich auf ein Proof-of-concept!
Es sollte aber auch für Einsteiger machbar sein, also in Platform-IO „press play on tape“ drücken und los.

3 „Gefällt mir“

Man muss halt nur, wenn man das so macht, den Benutzern was an die Hand geben an Infos, was sie denn deaktivieren können, wenn sie BT brauchen. Also ich persönlich brauche es gar nicht und werde es auch nicht brauchen. Aber du hast, sicher nicht ohne Grund, ja viel Zeit in BT investiert und ganz grundsätzlich werden auf jeden Fall Fragen kommen, warum BT plötzlich nicht mehr geht :slight_smile:

Also ich hab’s eben mal getestet: Wenn man MDNS und FTP weglässt, dann kann man mit BT kompilieren.

2 „Gefällt mir“

Ja genau, wenn man eine Funktion deaktiviert dann schreien Alle die es jetzt verwenden.
Wenn ich jetzt MDNS deaktiviere funktioniert Bluetooth wieder (Weil MDNS verwendet auch ein wenig IRAM). Aber dann kann ich nicht mehr „espuino.local“ verwenden und andere schreien…

Es ist halt die Summe aller Funktionen die jetzt disen speziellen IRAM Speicher ans Limit bringen. Meine Lösung um alle Features weiterhin gleichzeitig nutzen zu können, in Platform.ini ändern

;	https://github.com/FastLED/FastLED.git@3.5.0
    https://github.com/tueddy/FastLED.git#IRAM

Kann da bisher keine Nebenwirkungen wie Flackern feststellen. Das klappt auch für das evt. kommende Arduino 2.0.8. Warum macht man es sich nicht einfach einfach? Ich würde jetzt nicht gleich das ganze Build-System umstellen. Wer kann das noch testen, mit allen Features aktiviert?

2 „Gefällt mir“

Ich habe jetzt nochmal einen Versuch gestartet und als Ausgangsbasis die sdkconfig aus arduino-esp32 genommen. Damit bekommen wir dann genau die gleichen ESP-IDF-Optionen wie bisher und damit auch den gleichen Memory-Footprint. Siehe Commits · fschrempf/ESPuino · GitHub.

Das funktioniert bei mir wunderbar. Zum Test habe ich dann mal CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH und CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH gesetzt und kann damit denn IRAM Footprint um ca. 7 KiB reduzieren. Das würde also z. B. schon ausreichen um BT an zu lassen und noch reichlich Reserve zu haben.

Wenn das keine Nebenwirkungen hat ist das natürlich eine mögliche Optimierung. Allerdings finde ich einen Fork der Bibliothek nur als temporäre Lösung sinnvoll. Wir wollen ja den ESPuino-Code pflegen und nicht noch zusätzlich mehrere Forks von irgendwelchen Libs. Ziel muss es also m. E. immer sein solche Optimierungen in die Upstream-Lib zu bekommen.

Es geht nicht darum das Build-System um zu stellen. Es wird alles nach wie vor mit PlatformIO und einem „einzigen Klick“ gebaut. Der Nutzer bekommt das eigentlich nicht mit ob arduino-esp32 verwendet wird oder esp-idf mit Arduino-Komponente. Es muss vielleicht initial bei einem Clean-Build mehr runtergeladen und gebaut werden, aber das sollte verschmerzbar sein.

Ich vermute stark, dass in der Zukunft wieder eine Situation kommen wird, wo man gerne etwas an den IDF-Optionen schrauben möchte und dann zahlt es sich aus nicht an die sdkconfig aus arduino-esp32 gebunden zu sein.

1 „Gefällt mir“

Von welchem zeitlichen Aufwand reden wir denn da, wenn Arduino auch kompiliert werden muss? Da Rechner logischerweise unterschiedlich schnell sind, vielleicht mal in Relation gesehen zur eigentlichen ESPuino-FW.

Hier mal ein Auszug von den CI-Builds, einmal vom aktuellen Dev-Branch:

Environment             Status    Duration
----------------------  --------  ------------
esp32-a1s               SUCCESS   00:01:53.505
lolin32                 SUCCESS   00:01:16.911
lolin_d32               SUCCESS   00:01:16.446
lolin_d32_pro           SUCCESS   00:01:16.596
lolin_d32_pro_sdmmc_pe  SUCCESS   00:01:14.768
nodemcu-32s             SUCCESS   00:01:14.999
az-delivery-devkit-v4   SUCCESS   00:01:14.522
ttgo_t8                 SUCCESS   00:01:18.041
complete                SUCCESS   00:01:17.119
========================= 9 succeeded in 00:12:02.908 =========================

Und von meinem Branch wo ESP-IDF mit kompliliert wird:

Environment             Status    Duration
----------------------  --------  ------------
esp32-a1s               FAILED    00:06:22.302
lolin32                 SUCCESS   00:04:46.292
lolin_d32               SUCCESS   00:04:44.760
lolin_d32_pro           SUCCESS   00:04:40.364
lolin_d32_pro_sdmmc_pe  SUCCESS   00:04:41.984
nodemcu-32s             SUCCESS   00:04:48.907
az-delivery-devkit-v4   SUCCESS   00:04:53.741
ttgo_t8                 SUCCESS   00:04:49.386
complete                SUCCESS   00:04:46.079
==================== 1 failed, 8 succeeded in 00:44:33.816 ====================

Wir reden also bei einem Clean-Build schon von einem Faktor größer drei. Allerdings macht man einen Clean-Build auch nicht allzu oft und in der CI könnte man auch mit Caching arbeiten.
Wenn man nur im ESPuino Code arbeitet und ESP-IDF schon übersetzt wurde gibt es keinen nennenswerten Overhead im Vergleich zu vorher.

2 „Gefällt mir“

Ich verstehe das so das zeitkritische Routinen im schnelleren IRAM abgelegt werden. Wenn jetzt diese Funktionen in den normalen Flash-Speicher verschoben werden hat das Nachteile? Warum haben die Arduino Leute das dann nicht gleich gemacht? Könnte mir vorstellen das es auch Nachteile hat, z.B. Wifi Durchsatz. Denke das Feintuning wäre schon wichtig.

@fschrempf kannst Du einmal die Web-Uploadrate vergleichen?

Hammer! Das habe ich einfachnicht hinbekommen. Vielen Dank dir!!
Jetzt können wir uns auch weitere Optionen anschauen. Sehe die längere Dauer eigentlich nicht wirklich kritisch und finde, dass die Vorteile überwiegen.

Z.B. kann man sich mal diesen Kandidaten hier anschauen, sofern hier keine anderen Versionen im Umlauf sind:

If the application uses PSRAM and is based on ESP32 rev. 3 (ECO3), setting CONFIG_ESP32_REV_MIN to 3 will disable PSRAM bug workarounds, saving ~10kB or more of IRAM.

Den PSRAM-Fix kann man doch jetzt auch schon deaktivieren, oder?

Also insgesamt begrüße ich den Vorstoß, aber ich habe so meine Bedenken, dass uns die ganzen Auswirkungen klar sind, die die ganzen Parameter haben. Insofern finde ich die Bedenken von @tueddy absolut angebracht.

Entsprechend müssen wir uns halt ein paar Testszenarien überlegen um die Stabiltät uns Aswirkung der einzelnen IRAM-Optionen zu testen. Völlig unabhängig der Nutzung der Optionen glaube ich, dass wir mit der Lösung von @fschrempf auf Lange sicht deutlich besser fahren als mit der fixen lib.

Nicht ganz. Wenn ich das richtig verstehe besteht der PSRAM Cache Workaround aus mehreren Teilen:

  1. Das Compiler-Flag -mfix-esp32-psram-cache-issue verhindert, dass der Compiler Instruktionen erzeugt, die den Silizium-Bug bei Revision 1 und 2 triggern.
  2. Zusätzlich werden Funktionen aus der Standard-Lib in die Firmware gebaut, die dann auch mit diesem Flag übersetzt wurden und somit „sicher“ sind. Diese Funktionen dienen als Ersatz für die bereits im ROM-Code vorhandenen Funktionen, die natürlich vermieden werden müssen, weil sie den Bug triggern können.

Punkt 1 können wir auch mit arduino-esp32 beeinflussen, aber Punkt 2 (was den IRAM mit ~10 kB belastet) soweit ich weiß nicht, weil hier eben in der sdkconfig bei arduino-esp32 folgendes enthalten ist, das wir nicht verändern können:

CONFIG_SPIRAM_CACHE_WORKAROUND=y

[...]
#
# SPIRAM workaround libraries placement
#
CONFIG_SPIRAM_CACHE_LIBJMP_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBMATH_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBNUMPARSER_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBIO_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBTIME_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBCHAR_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBMEM_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBSTR_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBRAND_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBENV_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBFILE_IN_IRAM=y
CONFIG_SPIRAM_CACHE_LIBMISC_IN_IRAM=y

Könnte sein, ja. Ich kann es zumindest nicht ausschließen. Es gibt ja auch einen Cache für den Flash (MMU Cache). Das heißt in den meisten Fällen sind die Zugriffe auf den Flash nicht langsamer als auf den IRAM, da sie über den Cache gehen. Nur wenn eine Funktion aktuell nicht im Cache liegt, und tatsächlich vom Flash geladen muss (cache miss) wird es langsam.

Meinem Verständnis nach wird das aber bei Dingen wie Webupload, etc. eher keine Rolle spielen. Da wird am Anfang des Uploads der Cache mit den nötigen Instruktionen befüllt und dann läuft der Upload aus dem Cache. Vor allem wenn andere Threads pausiert sind sollte das kein Thema sein.

Wo es eher ein Problem sein könnte ist wenn man irgendwelche Echtzeit-Anforderungen hat. Z. B. bei Schnittstellen wie SPI, etc. wo es zu hohen Latenzen kommen kann, wenn während der Übertragung ein Cache Miss auftritt und vom Flash geladen werden muss. Aber den Fall gibt es bei uns (außer vielleicht bei den LEDs) eher nicht.

Naja, ich würde das was die Entwickler dort machen auch nicht als „der Weisheit letzter Schluss“ sehen. Außerdem muss im arduino-esp32 ja eine Config enthalten sein, die möglichst alle Anwendungsfälle irgendwie abdeckt. Muss für uns also nicht unbedingt das Optimum, bzw. Maß der Dinge sein.

Hab ich eben gemacht und kann auf die Schnelle keine erkennbaren Unterschiede feststellen.

1 „Gefällt mir“

Ich verstehe die Reihenfolge hier als eine Empfehlung von „Kann ohne große Probleme geändert werden“ zu „Pass besser auf was du tust“ :slight_smile:
Durch die Option CONFIG_ESP32_REV_MIN_3=y sparen wir tatsächlich ~12K im iRam (Vergleich ohne BT Modul). Ich informiere mich mal noch bisschen welche Chips davon betroffen wären und ob das für uns eine Relevanz hätte…
Bei mir läuft es jedenfalls schonmal :smiley: