Dev-Branch

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:

Das geht vielleicht für Dein Board ist aber nicht für Alle:
Es gibt immer noch viele Boards mit älteren Chip-Revisionen V1, insbesondere diese billigen DevKit-Boards. Mein Sohn wird mich killen wenn ich sein Board mit dieser Option kaputt-flashe! Es ist ein TTGO-T18 Energy Board und zeigt beim Upload

Chip is ESP32-D0WD (revision v1.0)
1 „Gefällt mir“

Ja, zu dem Ergebnis bin ich auch schon gekommen, dass die noch verbreitet sind. Aber wir fangen ja auch gerade erst mit den Optionen an. Sollen natürlich Optionen sein, die allgemeingültig sind.
Hier mal ein paar erste Einsparungen der Optionen:

CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH ~6,3 KB
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH ~0,35 KB
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH ~1,1 KB --> noch nicht weiter getestet
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL (Disable) ~0,1 KB --> vermutlich das Risiko nicht Wert
CONFIG_ESP32_REV_MIN_3=y ~12,5 KB --> scheidet aus wegen Kompatibilitätsgründen

Zumindest bei mir konnte ich mit keiner der Optionen auf die schnelle irgendwas negatives feststellen.
Alles was mit ISR oder dem Ringbuffer zu tun hat will ich eigenltich erstmal ungern anfassen.
Mein Vorschlag wäre mal die CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH näher zu untersuchen. Das wäre sehr entspannt ziemlich viel IRAM mit vermutlich überschaubaren Einbusen. Bin nicht so glücklich jetzt Dinge wie BT einfach raus zu machen…
Ich teste gerne aber auch noch viel mehr Optionen :slight_smile:
Was denkt Ihr so über die verschiedenen Möglichkeiten?

Meine Meinung zu „Arduino as a component“:

@fschrempf Erstmal Vielen Dank für das Proof-of-Concept, Glückwunsch das Du es an den Start bekommen hast!

Ich werde das auf jeden Fall dieses lange Wochenende einmal ausprobieren, freue mich schon wenn der CPU-Lüfter den Raum heizt :wink:
Wenn das später auch für Anfänger leicht startbar ist, dann haben wir ganz neue Möglichkeiten.
Mich ärgert z.B. das Bluetooth nur ohne Wifi möglich ist, obwohl es wohl einen Koexistenz-Modus gibt. Wenn beides gleichzeitig möglich wäre - schon geil!
Oder wenn wir mittels vTaskGetRunTimeStats() die Lastverteilung der Tasks messen können ergeben sich hier auch Optimierungen, z.B. verbesserter Web-Upload.

Aber Leute: Ihr reißt hier ganz schön was auf!
Bis das vernünftig getestet & ausgereift ist, das wird noch ein Stück Arbeit. Sehe jetzt schon den Forum Hilferuf, der sich irgendwas in der SDKConfig verfummelt hat. Die vielen Optionen gehen ja jetzt schon drunter & drüber… Und hey, wir reden aktuell über 200 Bytes IRAM-Überlauf und auch nur wenn alle Features aktiviert sind!

Für den DEV-Branch sollte das schom ausgereift sein. Auch ein Einsteiger sollte leicht & problemlos auf DEV wechseln können um neue Funktionen & Verbesserungen zu bekommen.

Mein Vorschlag

„Go for (over-)engineering“ Ihr geht diesen Weg weiter und wir schauen wann das reif für den ESPuino ist.

Kurzfristig sparen wir uns die 200Bytes IRAM mit einem Fork von FastLED. Wenn das überflüssig wird nehmen wir den einfach wieder raus. Genauso wie das angepasste FS überflüssig wird wenn die nächste Arduino Version für PlatformIO kommt. Wir machen parallel ein Issue bei FastLED auf das wir ein wenig Speicher sparen möchten.

Ist das OK für Euch?

3 „Gefällt mir“

Finde das einen guten Vorschlag!
Zur Entwarnung: so schlimm ist es nicht seit es @fschrempf zum Laufen gebraucht hat :slight_smile: .
Wenn wir die sdkconfig.default einchecken und verwalten und bei z.B. einem Clean_All über eine weitere Aktion die Target-SdkConfigs löschen, kann eigentlich beim „dummen Anwender“ gar nichts schief gehen. Einfach auschecken/klonen, bauen und fertig.
Aktuell muss man halt noch aufpassen, die Target-Sdk-Files zu löschen wenn man Änderungen vornimmt, da sonst die geänderten Einstellungen nicht neu generiert werden.
Ich hätte tatsächlich keien Vorbehalte das auch relativ kurzfristig in den Dev-Branch zu bringen, da wir aber extrem viele Möglichkeiten haben hier die Sache zu verbessern lohnt es sich meiner Meinung nach diesen Weg weiter zu gehen.

Was wäre wenn wir den aktuellen Dev-Branch richtung master bringen (der Wunsch war ja weiter oben schon) und dann die nächste Runde DEV-BRANCH mit dieser Änderung starten?
Bin aber auch dabei erstmal noch einen weiteren Branch dafür anzulegen.
Eine gute Nacht und ein schönes langes Wochenende zusammen!

2 „Gefällt mir“