Versionshistorie

Version Anpassungen
1.0 (2023-10-29) Basis-Version

In­halts­ver­zeich­nis

Bibliothek UrsEsp

Restart

Heap

PSRAM

Flash

CPU

Sonstige

PSRAM (SPI-RAM)

Initialisierung

Reset-Blocker

Download

Bibliothek UrsEsp

Die Arduino-Bibliothek ESP (EspClass mit vordefinierter Instanz ESP in Esp.h) bietet bereits einige Methoden zur CPU-, Prozess- und Speicherkontrolle. Einige wichtige Funktionen fehlen jedoch. Die Klasse Bibliothek UrsEsp (UrsEspClass mit vordefinierter Instanz UrsESP in UrsEsp.h) ergänzt EspClass per Ableitung.

Die Arduino-Bibliothek ist außerdem schlecht dokumentiert. In der folgenden Funktionsbeschreibung sind ebenfalls die Funktionen aufgeführt, die in EspClass definiert sind. Diese stehen wegen der Ableitung natürlich auch über die Instanz UrsESP zur Verfügung.

Name Funktion Anmerkung Klasse
Restart
void restart () Führt einen Reset der CPU aus. Diese Funktion kann sowohl von PRO- als auch von APP-CPUs aufgerufen werden.
Nach einem erfolgreichen Neustart lautet der Grund für das Zurücksetzen der CPU SW_CPU_RESET (s. esp_err.h).
Peripheriegeräte(außer WiFi, BT, UART0, SPI1 und ältere Timer) werden nicht zurückgesetzt.
ESP
esp_err_t registerShutdownHandler ( void (*shutdownHandler)(void)) Registriert einen Shutdown-Handler. Mit dieser Funktion kann einen Handler registriert werden, der aufgerufen wird, bevor die Anwendung mit der Funktion restart neu gestartet wird.
Mögliche Fehler (s. esp_err.h)
- ESP_OK bei Erfolg.
- ESP_ERR_INVALID_STATE, wenn der Handler bereits registriert wurde.
- ESP_ERR_NO_MEM, wenn keine Shutdown-Handler-Slots mehr verfügbar sind.
UrsESP
esp_err_t unregisterShutdownHandler ( void (*shutdownHandler)(void)) Registrierung des Shutdown-Handlers aufheben Mögliche Fehler (s. esp_err.h)
- ESP_OK bei Erfolg.
- ESP_ERR_INVALID_STATE, wenn der angegebene Handler noch nicht registriert wurde.
UrsESP
int getResetReason ( int cpuNumber) Ruf den Grund für das Zurücksetzen der CPU ab. Die Enumeration RESET_REASON für die Gründe findet man in <cpu>rom/rtc.h. UrsESP
String getResetReasonName ( int reason) Liefert die Bezeichnung des Reset-Grundes. Z.B. POWERON_RESET. Die Enumeration RESET_REASON für die Gründe findet man in <cpu>rom/rtc.h. UrsESP
String getResetReasonDescription ( int reason) Liefert die Beschreibung des Reset-Grundes. Z.B. Vbat power on reset. Die Enumeration RESET_REASON für die Gründe findet man in <cpu>rom/rtc.h. UrsESP
Heap
uint32_t getHeapSize () Liefert die Größe des gesamten Heaps.   ESP
uint32_t getFreeHeap () Liefert die Größe des freien Heaps.   ESP
uint32_t getMinFreeHeap () Liefert den niedrigsten Stand des freien Heaps seit dem Booten.   ESP
uuint32_t getMaxAllocHeap () Ruft die Größe des größten freien Speicherblocks ab, der zugewiesen werden kann.   ESP
uint32_t getLargestFreeDmaHeapBlock () Ruft die Größe des größten freien Heap-Speicherblocks ab, der für DMA-Zugriff zugewiesen werden kann.   UrsESP
void* allocDmaHeapBlock ( size_t size) Allokiert size Bytes nicht initialisierten Speicher, auf den per DMA zugegriffen werden kann.
Liefert einen Zeiger auf den allokierten Bereich oder NULL (nullptr), wenn eine Zuweisung nicht möglich war.
Um ein Speicherleck zu vermeiden, muss der zurückgegebene Zeiger mit free oder dmaRealloc freigegeben werden. UrsESP
void* dmaMalloc ( size_t size) S.o., Alias von allocDmaHeapBlock S.o. UrsESP
void* reallocDmaHeapBlock ( void* ptr, size_t newSize) Allokiert den angegebenen Speicherbereich neu. Bereits vorhandene Zeiger in den Speicherbereich können dabei ungültig werden!  
void* dmaRealloc ( void* ptr, size_t newSize) S.o., Alias von reallocDmaHeapBlock S.o.  
PSRAM*)
uint32_t getPsramSize () Liefert die Größe des gesamten PSRAMs.    
uint32_t getFreePsram () Liefert die Größe des freien PSRAMs.    
uint32_t getMinFreePsram () Liefert den niedrigsten Stand des freien PSRAMs seit dem Booten.    
uint32_t getMaxAllocPsram () Ruft die Größe des größten freien PSRAM-Speicherblocks ab, der zugewiesen werden kann.    
bool psramFound () Liefert true, wenn PSRAM vorhanden ist.   UrsESP
void* psramMalloc ( size_t size) Allokiert size Bytes nicht initialisierten Speicher. Liefert einen Zeiger auf den allokierten Bereich oder NULL (nullptr), wenn eine Zuweisung nicht möglich war. Um ein Speicherleck zu vermeiden, muss der zurückgegebene Zeiger mit free oder psramRealloc freigegeben werden (s. cppreference.com:malloc). UrsESP
void* psramRealloc ( void *ptr, size_t newSize) Allokiert den angegebenen Speicherbereich neu.
Bereits vorhandene Zeiger in den Speicherbereich können dabei ungültig werden!
Die Neuzuweisung erfolgt entweder durch:
a) Erweiterung oder Verkleinerung des von ptr genannten bestehenden Bereichs, sofern möglich. Der Flächeninhalt bleibt bis zur kleineren der neuen und alten Größen unverändert. Wenn der Bereich erweitert wird, ist der Inhalt des neuen Teils des Arrays undefiniert.
b) Zuweisung eines neuen Speicherblocks mit der Größe newSize Bytes, Kopieren des Speicherbereichs mit einer Größe, die der kleineren der neuen und alten Größen entspricht, und Freigeben des alten Blocks. Wenn nicht genügend Speicher vorhanden ist, wird der alte Speicherblock nicht freigegeben und ein nullptr zurückgegeben.
Siehe cppreference.com:realloc
UrsESP
void* psramCalloc ( size_t num, size_t size) Allokiert Speicher für ein Array von num Objekten der Größe size und initialisiert alle Bytes im zugewiesenen Speicher auf 0. Wenn die Zuweisung erfolgreich ist, wird ein Zeiger auf das unterste (erste) Byte im zugewiesenen Speicherblock zurückgegeben, ansonsten nullptr (s. cppreference.com:calloc). UrsESP
Flash
uint32_t getFlashChipSize () Gibt die Größe des Flash-Speichers in Bytes zurück.   ESP
uint32_t getFlashChipSpeed () Gibt die Zugriffsgeschwindigkeit auf das Flash in Hz zurück. Dies ist i.d.R. die max. Mögliche SPI-Taktfrequenz von 80 MHz. ESP
FlashMode_t getFlashChipMode () Gibt die Art des Zugriffs auf das Flash zurück.  Die Enumeration FlashMode_t besitzt folgende Member:
FFM_QIO = 0x00, FM_QOUT = 0x01, FM_DIO = 0x02, FM_DOUT = 0x03, FM_FAST_READ = 0x04, FM_SLOW_READ = 0x05, FM_UNKNOWN = 0xff
ESP
uint32_t magicFlashChipSize ( uint8_t byte) Liefert eine Konstante zur Einstellung der Flash-Größe. Diese Erklärung der Funktion ist unsicher! ESP
uint32_t magicFlashChipSpeed ( uint8_t byte) Liefert eine Konstante zur Einstellung der Flash-Geschwindigkeit. Diese Erklärung der Funktion ist unsicher! ESP
FlashMode_t magicFlashChipMode ( uint8_t byte) Liefert eine Konstante zur Einstellung der Flash-Zugriffsart. Diese Erklärung der Funktion ist unsicher! ESP
bool flashEraseSector ( uint32_t sector) Löscht einen Flash-Sektor.
Sektor: Sektor-Nummer, die Zählung beginnt bei Sektor 0, 4KB pro Sektor.
Liefert true bei Erfolg.
  ESP
bool flashWrite ( uint32_t offset, uint32_t *data, size_t size) Daten ins Flash schreiben.
offset: Zieladresse im Flash.
data: Zeiger auf die Quelldaten.
size: Anzahl zu schreibender Bytes.
Liefert true bei Erfolg.
Die schnellste Schreibleistung erhält man, wenn die zu schreibende Menge ein Vielfaches von 4 Bytes ist (uint32_t, DWORD). Der Quellpuffer und der Flash-Offset sollte an einer 4-Byte-Grenze beginnen.
Das Variieren eines dieser Parameter funktioniert trotzdem, ist aber aufgrund der Pufferung langsamer.
Das Schreiben von mehr als 8 KB auf einmal wird in mehrere Schreibvorgänge aufgeteilt, um andere Aufgaben im System nicht zu stören.
ESP
bool flashRead ( uint32_t offset, uint32_t *data, size_t size) Daten aus dem Flash auslesen.
offset: Quelladresse im Flash.
data: Zeiger auf die Zieldaten.
size: Anzahl zu lesender Bytes.
Liefert true bei Erfolg.
Um die schnellste Leseleistung zu erzielen, sollten alle Parameter auf 4 Byte-Grenzen (uint32_t, DWORD) ausgerichtet sein. Wenn Quelladresse und Lesegröße nicht 4 Byte ausgerichtet sind, kann das Lesen in mehrere Flash-Operationen aufgeteilt werden. Wenn der Zielpuffer nicht auf 4 Byte ausgerichtet ist, wird ein temporärer Puffer auf dem Stack zugewiesen.
Das Lesen von mehr als 16 KB Daten auf einmal wird in mehrere Lesevorgänge aufgeteilt, um eine Unterbrechung anderer Aufgaben im System zu vermeiden.
ESP
bool partitionEraseRange ( const esp_partition_t *partition, uint32_t offset, size_t size) Zu Partitionen siehe Partition Table in der ESP32 Arduino Core’s documentation.   ESP
bool partitionWrite ( const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) Zu Partitionen siehe Partition Table in der ESP32 Arduino Core’s documentation.   ESP
bool partitionRead ( const esp_partition_t *partition, uint32_t offset, uint32_t *data, size_t size) Zu Partitionen siehe Partition Table in der ESP32 Arduino Core’s documentation.   ESP
CPU
uint8_t getChipRevision () Liefert die Revisionsnummer des Chips. Siehe Chip Revision ESP
const char* getChipModel () Liefert einen String mit der Modellbezeichnung. Z.B. "ESP32-S3" ESP
uint8_t getChipCores () Liefert die Anzahl der im Chip enthaltenen Kerne.   ESP
uint32_t getCpuFreqMHz () Liefert die CPU-Taktfrequenz in MHz.   ESP
uint32_t getCycleCount () Ermittelt den aktuellen Wert des internen Zählers, der bei jedem Prozessor-Taktzyklus erhöht wird. Liefert 0, wenn diese Funktion nicht unterstützt wird. ESP
const char* getSdkVersion () Rückgabe der vollständigen IDF-Versionszeichenkette.   ESP
Sonstige
void deepSleep ( uint32_t time_us) In den Deep-Sleep-Modus wechseln.
time_us: Anzahl μs für den Modus.
Das Gerät wacht nach der Tiefschlafzeit automatisch auf. Nach dem Aufwachen ruft das Gerät den Tiefschlaf-Wake-Stub (s. nächste Funktion) auf und fährt dann mit dem Laden der Anwendung fort.
deepSleep beendet WiFi-, BT- und höherwertige Protokollverbindungen nicht ordnungsgemäß. Es sollte sicher gestellt werden, dass die relevanten WiFi- und BT-Stack-Funktionen aufgerufen werden, um alle Verbindungen zu schließen und die Peripheriegeräte zu deinitialisieren. Dazu gehören: esp_bluedroid_disable, esp_bt_controller_disable, esp_wifi_stop
ESP
void esp_wake_deep_sleep(void) Standard-Stub für die Ausführung beim Aufwachen aus dem Deep-Sleep. Ermöglicht die Ausführung von Code unmittelbar nach dem Aufwachen aus dem Ruhezustand, bevor der Software-Bootloader oder die ESP-App gestartet wurde.
Diese Funktion ist schwach verlinkt (weak-linked), so dass eine eigene Version implementiert werden kann. Diese muss mit extern "C" umschrieben sein (Name Mangling bei C++).
 
uint64_t getEfuseMac() Liefert die MAC-Basisadresse, die werkseitig von Espressif über EFUSE programmiert wurde.   ESP

*) PSRAM oder SPI-RAM ist ein externes RAM, das per SPI mit der CPU verbunden ist. PSRAM muss aktiviert werden (s.u. PSRAM).

PSRAM (SPI-RAM)

PSRAM (Pseudo-RAM) oder SPI-RAM ist ein externes RAM, das per SPI mit der CPU verbunden ist. Beim ESP32-S3 ist die Größe in der Bezeichnung enthalten. Für den ESP32-S3 gilt die folgende Tabelle:

  Modul Flash PSRAM SPI Spannung  
ESP32-S3 Bezeichnung ESP32-S3-WROOM-1-N8 8 MB QD 3.3 V QD: Zugriff über Quad-SPI
OT: Zugriff über Octal-SPI
ESP32-S3-WROOM-1-N8R2 8 MB QD 2 MB QD 3.3 V
ESP32-S3-WROOM-1-N8R8 8 MB QD 8 MB OT 3.3 V
ESP32-S3-WROOM-2-N16R8V 16 MB OT 8 MB OT 1.8 V
ESP32-S3-WROOM-2-N32R8V 32 MB OT 8 MB OT 1.8 V
ESP32-S3-WROOM-1U-N8 8 MB QD 3.3 V
ESP32-S3-WROOM-1U-N8R2 8 MB QD 2 MB QD 3.3 V
ESP32-S3-WROOM-1U-N8R8 8 MB QD 8 MB OT 3.3 V

Initialisierung

PSRAM muss in den Sketch-Einstellungen aktiviert werden:

Ardiuino-IDE-Einstellungen für PSRAM   Visual-Micro-Einstellungen für PSRAM
Ardiuino-IDE-Einstellungen   Visual-Micro-Einstellungen

Alternativ kann esp_spiram_init (deklariert in spiram.h) aufgerufen werden. Dies ist die Beschreibung der Funktion: Initialize spiram interface/hardware. Normally called from cpu_start.c.

Reset-Blocker

Das Espressif-IDF, das Basis für das Arduino-Framework ist, sorgt dafür, dass nach einer Programm-Exception ein Reset ausgelöst wird. Da dadurch der Fehler nicht behoben wird, wird erneut ein Reset ausgelöst. So geht es dann endlos weiter. Wenn man dann noch Ausgaben über die serielle auf ein Terminal macht, gibt es dort schnell eine Pufferüberlauf.

Aus diesem Grund macht es Sinn, den Grund für den Reset abzufragen und bei einem nicht erwarteten Grund die Ausführung zu stoppen. Der folgende Code zeigt ein Beispiel:

...
#include <UrsEsp.h>

using namespace UrsCPU;

...

void setup() {
   Serial.begin(115200);

   Serial.println("\n" APP_NAME " gestartet. Version: " APP_VERSION "\n");

   auto resetReason = UrsESP.getResetReason(0);
   Serial.printf("CPU0 Reset Grund: %i (%s) %s\n", resetReason, UrsESP.getResetReasonName(resetReason).c_str(), UrsESP.getResetReasonDescription(resetReason).c_str());

   // Interne Fehler führen dauernd zu einem neuen Reset
   // Reason 1:  POWER_ON_RESET
   // Reason 12: SW_CPU_RESET (z.B. nach OTA)
   if (resetReason != 1 && resetReason != 12) 
      while (1);

Download

Das ZIP-Archiv für Bibliothek UrsEsp zum Download. Die entpackten Dateien ins Verzeichnis <user>\Documents\Arduino\libraries kopieren (siehe Installing Additional Arduino Libraries).