mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ESP32 Wrover 4MB SPI-RAM mit Arduino nutzen


Autor: ESP-User (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo, ich versuche bei einem ESP32 Wrover Modul die externen 4MByte 
SPI-RAM zu nutzen. Dies gelingt mir leider nicht.

Gemäß Espressif Doku kann das RAM grundsätzlich in unterschiedlichen 
Betriebsarten genutzt werden, wenn man die Espressif Toolchain nutzt. 
Ich nutze aber die Arduino IDE. Da kann ich wohl nichts einstellen.

Die Programmzeile
Serial.printf("\n%d Bytes free.\n\n", ESP.getFreeHeap());
gibt folgendes aus:
291352 Bytes free.

Das ist nur das interne RAM. Ich nehme an, dass ich das SPI-RAM nur über 
direkten Adresszugriff ab Adresse 0x3F80000 nutzen kann.

Hier ein kleines Testprogramm:
#define SPIRAM ((byte*)0x3F800000)

void setup() {
  Serial.begin(115200);
  // Free Memory
  Serial.printf("\n%d Bytes free.\n\n", ESP.getFreeHeap());
  // test SPI RAM
  Serial.print("Test 128B:"); testram(128);
  Serial.print("Test 256B:"); testram(256);
  Serial.print("Test  1KB:"); testram(1024);
  Serial.print("Test 16KB:"); testram(16*1024);
  Serial.print("Test 64KB:"); testram(64*1024);
  Serial.print("Test  1MB:"); testram(1*1024*1024);
  Serial.print("Test  4MB:"); testram(4*1024*1024);
}

void loop() {
}

void testram(int ramSize) {
  // Test SPI-RAM: write
  for(int i=0; i<(ramSize); i++) {
    SPIRAM[i] = (0xA5-i) & 0xFF;
  }
  // Test SPI-RAM: verify
  int e = 0;
  for(int i=0; i<(ramSize); i++) {
    if(SPIRAM[i] != (0xA5-i) & 0xFF) e++;
  }
  Serial.printf(" %7d Bytes: %7d OK, %7d Errors.\n",ramSize,ramSize-e,e);
}


Wenn ich mehr als 128 Bytes nutze, geht es in die Hose.
//  291352 Bytes free.
//  
//  Test 128B:     128 Bytes:     128 OK,       0 Errors.
//  Test 256B:     256 Bytes:     166 OK,      90 Errors.
//  Test  1KB:    1024 Bytes:     166 OK,     858 Errors.
//  Test 16KB:   16384 Bytes:     166 OK,   16218 Errors.
//  Test 64KB:   65536 Bytes:       1 OK,   65535 Errors.
//  Test  1MB: 1048576 Bytes:       1 OK, 1048575 Errors.
//  Test  4MB: 4194304 Bytes:       1 OK, 4194303 Errors.


Frage:

Ist es jemand schon gelungen, den SPI-RAM mit der Arduino IDE zu nutzen?
Wo liegt mein Fehler?

Ich nutze einen Odroid Go, in dem das Wrover Modul sitzt.

Vielen Dank für Tipps.

Autor: K. S. (the_yrr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ESP-User schrieb:
> Das ist nur das interne RAM. Ich nehme an, dass ich das SPI-RAM nur über
> direkten Adresszugriff ab Adresse 0x3F80000 nutzen kann.
wieso sollte das so drekt gehen, muss da nichts initialisiert werden?

ESP-User schrieb:
> Gemäß Espressif Doku kann das RAM grundsätzlich in unterschiedlichen
> Betriebsarten genutzt werden, wenn man die Espressif Toolchain nutzt.
hast du mal Beispielcode dafür? ich denke da fehlt noch was damit das 
funktioniert, der Controller wüsste vllt. gerne dass du versuchst RAM zu 
mappen und nicht Flash oder vllt. irgendeinen Sensor.

in deinem Beispielcode schreibst du einfach an die Adresse
> #define SPIRAM ((byte*)0x3F800000)
ohne den SPI zu initialisieren? ich denke das solltest du tun. eventuell 
schreibst du zur Zeit nur in den Cache für den externen Ram, ohne dass 
dieser verwendet wird.

poste mal Beispielcode für Espressif.

Autor: K. S. (the_yrr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lies mal hier
https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/external-ram.html
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html#config-spiram-use

Du machst grade "ich hab nen Arduino auf nen Wecker geklebt, warum weiß 
der nicht wie spät es ist"

da muss alles konfiguriert werden und der RAM dann auch gemappt werden, 
dass musst du alles selber machen.

Datenblatt:
Accesses to the external flash and external SPI RAM are done through a 
cache and are also handled by an MMU. This Cache MMU can apply different 
mappings, depending on the PID of the process as well as the CPU the 
process is running on.
die MMU für den externen Speicher solltest du auch konfigurieren, 
entweder gibts da was fertiges oder es heißt Datenblatt lesen (nur die 
paar duzend interessanten Seiten, nicht alle <700) und alle register 
selber schreiben.

Autor: Weihnachtsmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ESP-User schrieb:
> Hallo, ich versuche bei einem ESP32 Wrover Modul die externen 4MByte
> SPI-RAM zu nutzen. Dies gelingt mir leider nicht.
>
> Gemäß Espressif Doku kann das RAM grundsätzlich in unterschiedlichen
> Betriebsarten genutzt werden, wenn man die Espressif Toolchain nutzt.
> Ich nutze aber die Arduino IDE. Da kann ich wohl nichts einstellen.
>
> Die Programmzeile
>
Serial.printf("\n%d Bytes free.\n\n", ESP.getFreeHeap());
> gibt folgendes aus:
>
291352 Bytes free.


Lass Dich vom Unsinn, den K.S. geschrieben hat, nicht verwirren. Ist 
vermutlich die zu hohe Dosis Weihnachtspunsch.

Du solltest die Arduino-Version prüfen. In den korrekten Versionen wird 
der PSRAM automatisch eingebunden, wenn er beim Booten erkannt wird.
ESP.getFreeHeap() sollte den gesamten RAM dann auch anzeigen.

Probier mal eine andere Arduino-Version aus.

Autor: Weihnachtsmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reservier zum Testen einfach mal 1MB RAM mit ps_malloc.

Autor: Weihnachtsmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, da hat sich in der Zwischenzeit was geändert. Das PSRAM wird 
nicht mehr zum Heap dazugenommen. Der Zugriff geht nur noch über 
ps_malloc:
https://github.com/espressif/arduino-esp32/issues/2226

Autor: ESP-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank schonmal an alle Helfer.

ps_malloc funktioniert leider nicht, oder vielleicht nutze ich es 
falsch.
const int N = 128*1024;
byte* buff;
  if (buff = (byte*)ps_malloc(sizeof(byte)*N)) 
    Serial.println("ps_malloc succeeded");
  else
    Serial.println("ps_malloc failed");
Ergibt
-> ps_malloc failed

Hier nochmal mein geändertes Testprogramm:

//  291352 Bytes free.
//  
//  Test 128B:     128 Bytes:     128 OK,       0 Errors.
//  Test 256B:     256 Bytes:     166 OK,      90 Errors.
//  Test  1KB:    1024 Bytes:     166 OK,     858 Errors.
//  Test 16KB:   16384 Bytes:     166 OK,   16218 Errors.
//  Test 64KB:   65536 Bytes:       1 OK,   65535 Errors.
//  Test  1MB: 1048576 Bytes:       1 OK, 1048575 Errors.
//  Test  4MB: 4194304 Bytes:       1 OK, 4194303 Errors.

#define SPIRAM ((byte*)0x3F800000)

const int N = 128*1024;
byte* buff;

void setup() {
  Serial.begin(115200);
  // Free Memory
  Serial.printf("\n%d Bytes free.\n\n", ESP.getFreeHeap());
  // ps_malloc
  if (buff = (byte*)ps_malloc(sizeof(byte)*N)) 
    Serial.println("ps_malloc succeeded");
  else
    Serial.println("ps_malloc failed");
  // heap_caps_malloc
  if (buff = (byte*)heap_caps_malloc(sizeof(byte)*N, MALLOC_CAP_8BIT))
    Serial.println("heap_caps_malloc succeeded");
  else
    Serial.println("heap_caps_malloc failed");
  // heap_info
  Serial.println("\nheap_info");
  heap_caps_print_heap_info(MALLOC_CAP_8BIT);
  Serial.println();
    
 
  // test SPI RAM
  Serial.print("Test 128B:"); testram(128);
//  Serial.print("Test 256B:"); testram(256);
//  Serial.print("Test  1KB:"); testram(1024);
//  Serial.print("Test 16KB:"); testram(16*1024);
//  Serial.print("Test 64KB:"); testram(64*1024);
  Serial.print("Test  1MB:"); testram(1*1024*1024);
  Serial.print("Test  4MB:"); testram(4*1024*1024);
}

void loop() {
}

void testram(int ramSize) {
  // Test SPI-RAM: write
  for(int i=0; i<(ramSize); i++) {
    SPIRAM[i] = (0xA5-i) & 0xFF;
  }
  // Test SPI-RAM: verify
  int e = 0;
  for(int i=0; i<(ramSize); i++) {
    if(SPIRAM[i] != (0xA5-i) & 0xFF) e++;
  }
  Serial.printf(" %7d Bytes: %7d OK, %7d Errors.\n",ramSize,ramSize-e,e);
}

Und hier die Ausgabe:

291344 Bytes free.

ps_malloc failed
heap_caps_malloc failed

heap_info
Heap summary for capabilities 0x00000004:
  At 0x3ffb0000 len 65536 free 56072 allocated 9272 min_free 56072
    largest_free_block 56072 alloc_blocks 9 free_blocks 1 total_blocks 10
  At 0x3ffae6e0 len 6192 free 6092 allocated 36 min_free 6092
    largest_free_block 6092 alloc_blocks 1 free_blocks 1 total_blocks 2
  At 0x3ffaff10 len 240 free 0 allocated 180 min_free 0
    largest_free_block 0 alloc_blocks 1 free_blocks 1 total_blocks 2
  At 0x3ffc3650 len 117168 free 99804 allocated 16312 min_free 93984
    largest_free_block 93932 alloc_blocks 62 free_blocks 4 total_blocks 66
  At 0x3ffe0440 len 15296 free 15248 allocated 0 min_free 15248
    largest_free_block 15248 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113792 allocated 0 min_free 113792
    largest_free_block 113792 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 291008 allocated 25800 min_free 285188 largest_free_block 113792

Test 128B:     128 Bytes:     128 OK,       0 Errors.
Test  1MB: 1048576 Bytes:       1 OK, 1048575 Errors.
Test  4MB: 4194304 Bytes:       1 OK, 4194303 Errors.

Autor: ESP-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weihnachtsmann schrieb:
> Du solltest die Arduino-Version prüfen.

Ich nutze derzeit Version 1.8.5. Werde mal nach einem Update suchen und 
dann nochmal probieren.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

beim Odroid Go nicht den Odroid als Board einstellen sondern entweder 
ESP32 Wrover oder ESP32 Devkit und dort PSRAM enable.
Warum die boards.txt beim OdriodGo bzw. auch beim M5Stack da falsch ist, 
wissen nur die Götter. Ich nutze auf dem Odroid Go den PSRAM als Buffer 
für MP3-Streamplay.
Initalisiert werden muß dann nichts, ps_malloc() geht dann problemlos.
Für die heap-Einbindung muß vermutlich noch was in der 
ArduinoIDE/boards.txt/Partitiontable beim ESP32 angepasst werden, habe 
ich aber bisher nicht weiter verfolgt.

IDE hier 1.8.7 / 1.8.8 und ESP32 Boardmanagerversion 1.0.0.

Gruß aus Berlin
Michael

Autor: ESP-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael U. schrieb:
> Hallo,
>
> beim Odroid Go nicht den Odroid als Board einstellen sondern entweder

Vielen Dank, Problem ist gelöst.
Update der IDE auf die neue 1.8.8 brachte keine Veränderung.
Nach Umstellung des Boards lief es.


Ursprünglich hatte ich ODROID ESP32 eingestellt, da ich den ODROID GO 
verwende.
Board: ODROID ESP32
291344 Bytes free.
ps_malloc failed
heap_caps_malloc failed


ESP32 Wrover Module geht.
Board: ESP32 Wrover Module
4480504 Bytes free.
ps_malloc succeeded
heap_caps_malloc succeeded


ESP32 Dev Module geht auch
Board: ESP32 Dev Module
PSRAM enabled
4480504 Bytes free.
ps_malloc succeeded
heap_caps_malloc succeeded

Autor: ESP-User (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag:

Ich verwende jetzt die Board-Einstellung "ESP32 Dev Module" mit PSRAM 
enabled (siehe Screenshot). Das läuft soweit.

Jedoch funktionierte der Zugriff auf die SD-Karte nicht mehr und ich 
konnte keine Grafiken mehr auf das Display laden.


Konnte das Porblem lösen indem ich im Sourcecode
  SD.begin()

durch
  SD.begin(22)

ersetzte.

Autor: ESP-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Nachtrag:

Die Konstante LED_BUILTIN ist beim Board ESP32 Dev Module nicht 
definiert.

Folgenden Zeilen beheben dies:
// ODROID GO LED_BUILTIN
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

SD.begin(22) ist richtig, CS_00 vom SPI liegt auf dem 
Erweiterungsstecker, CS_01 wird für die SD-Card benutzt.
Da ich das OdroidGo-Arduino-Paket ohnhin nur für wenihe Tests genutzt 
habe, mußte ich es ohnehin immer angeben. Die LIbs in dem Paket sind 
großtenteils Anleihen bzw. Anpassungen existierenden Libs, wo nur 
sozusagen ein Wrapper und ein paar Definitionen rübergelegt wurde. Sie 
sind auch nahezu identisch zum M5Stack-Paket.
Ich nutze, wie sonst auch, TFT_eSPI für das Display, ausgeliehen habe 
ich mir nur die Button-Lib, weil ich zu faul war, die Analogabfrage des 
Steuerkreuzes selber irgendwo einzubauen.
Der eingebaute Lautsprecher ist auch so eine Sache: der Verstärker hängt 
an Pin 25 und 26. Das sind auch die internen DAC des ESP32. Leider ist 
Pin 25 aber mit Shutdown des Verstärkers verbunden, will also Low um den 
Verstärker einzuschalten. Direkt Ausgabe an den DAC auf Pin 26 geht zwar 
und wird von Odroid Go genutzt, die Einbindung der ESP8266 Lib mit 
I2S-Ausgabe an den internen DAC ist mir aber noch nicht gelungen.

Ist nicht wirklich wichtig, ist ja sowieso keine HiFi-Box. ;-)

Pin 2 von der LED habe ich zusätzlich noch mit dem freien Pin 9 der 
Erweiterungsleiste verbunden, weil ich für Spielerein noch einen 
zusätzlichen IO haben wollte.

Gruß aus Berlin
Michael

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.