PROGMEM beim rp2040 oä. noch notwendig?

Hallo,

ich habe es nun geschafft, vom 8-Bit auf einen 32-Bit Controller, den rp2040 zu wechseln. Leider ist der Umstieg nicht ganz einfach für mich, da mir einiges noch nicht ganz klar ist.

Beim ATMEL Arduino habe ich, um Speicherplatz (RAM) zu sparen Arrays ab einer Größe gerne mit PROGMEM definiert und über einen Pointer wieder zurück ins RAM geladen. Beim rp2040 ist ja mit den 264kB über das 32-Fache des RAM Speichers vorhanden als beim Mega2560.

  1. Wie wird z.B. ein Array mit:
    uint8_t test[50];
    abgelegt? Werden hierfür 50 * 32-Bit = 200 Byte RAM benötigt, oder kann der Speicher trotz der 32 Bit Architektur in 1 Byte Schritten gelesen werden?

  2. In der Beschreibung des rp2040 steht: >> 2.6.2. SRAM ...There are no restrictions on what is stored in each bank: processor code, data buffers, or a mixture.<< Gilt das auch für den FLASH Speicher? Hier ist zu lesen, das sich das Externe FLASH über die Schnittstelle wie ein Interner Speicher verhält. Was macht der Compiler daraus?

  3. Ist es bei diesen Rechnern noch notwendig, den Umweg über PROGMEM zu gehen oder langt das, einfach ein
    const uint8_t test[50] = {1,2,3,4,...
    zu definieren. Durch das const liegt das Array halt im Flash, anstatt im SRAM und wird auch daraus gelesen.

  4. In diesem Zusammenhang ist wahrscheinlich auch das F Makro bei
    Serial.print(F("xxx");
    nicht mehr notwendig, oder?

  5. Sind alle die 32-Bit Controller alle ähnlich aufgebaut, oder muss ich hier z.b. bei einem weiteren Umstieg von rp2040 auf Arduino DUE oder die MKR Serie wieder alles überdenken???

Fragen über Fragen. Vielleicht kann mir jemand die eine oder andere beantworten.

Besten Dank im Voraus!

Grüße,
Horst

Du meinst bestimmt

uint16_t

Besten Dank für die Info - da hat sich der Fehler Teufel eingeschlichen... Habe es geändert

Gruß,
Horst

  1. Wofür wurde sizeof() erfunden?
  2. Was soll er denn tun?
  3. Die Definition von PROGMEM liegt auf deinem Rechner. Schau doch selber nach!
  4. .....
  5. Ja, und Ja!
uint8_t  test1[10];
uint16_t test2[10];
uint32_t test3[10];

Serial1.println(sizeof(test1));
Serial1.println(sizeof(test2));
Serial1.println(sizeof(test3));

Gibt 10,20,und 40 aus.
Das ist die Anzahl der belegten RAM Bytes. Es werden doch aber beim 32 Bit System auch immer 4 Byte gleichzeitig aus dem RAM/FLASH gelesen. Ich wollte wissen, ob da zwischen drin beim uint_8 immer 3 Füllbytes eingebaut werden müssen oder ob der ganze Speicher sich in 1 Byte Schritten auslesen lässt.

Ob er einen Unterschied macht, ob aus dem FLASH oder aus dem RAM gelesen werden muß. Beim AVR Arduino ist das lesen aus dem FLASH anders aufgebaut. Ist das bei den Systemen ähnlich?

In der Datei: pgmspace.h
steht nur:
#define PROGMEM

Ok, lässt sich nicht pauschal definieren.

Vielen Dank!

Gruß,
Horst

Genau!
Sehr gut erkannt!
Das muss jetzt nur noch in deine Hirnwindungen sickern.

Ein C++ Kompiler interessiert sich nicht für den Unterschied zwischen Flash und Ram.
Niemals.
Auch nicht bei AVRs

Genau!
Und, was bewirkt das?
(Das muss jetzt nur noch in deine Hirnwindungen sickern)

 PROGMEM  PROGMEM 
 PROGMEM  PROGMEM  PROGMEM 
 PROGMEM void  PROGMEM setup( PROGMEM )  PROGMEM 
{
  PROGMEM  Serial PROGMEM . PROGMEM begin(9600) PROGMEM ; PROGMEM 
  PROGMEM  Serial PROGMEM . PROGMEM  PROGMEM println PROGMEM ( PROGMEM "Hallo Welt!" PROGMEM ) PROGMEM ; PROGMEM 
}

void  PROGMEM  PROGMEM  PROGMEM  PROGMEM  loop() PROGMEM  PROGMEM  PROGMEM  PROGMEM  
{
 PROGMEM  PROGMEM  PROGMEM  PROGMEM  PROGMEM  PROGMEM 
} PROGMEM  PROGMEM  PROGMEM  PROGMEM  PROGMEM  PROGMEM  PROGMEM 

Besten Dank für die Erklärung - ich denke ich habe es verstanden. Das ganze mit dem PROGMEM ist wirklich nur bei den AVR's erforderlch, da bei diesen der FLASH in einem anderen Speicher Segment liegt.

In der rp2040 Definition ist das dann nur noch eine Definition, um ältere Programme nicht in einen Fehler laufen zu lassen. So weit habe ich dann auch nicht gedacht...

Ich gehe jetzt davon aus, das die Definition der Varialbe test

const uint8_t test = 5;

im Flash liegt und keinen weiteren RAM benötigt.

Gruß,
Horst

Tipp:
Bevor du deiner Fantasie freien Auslauf gewährst, lass dir doch mal die Adresse ausgeben. Die sagt dir ganz klar, in welchem Bereich die Variable wohnt.

Wenn ich nun in der Arduino Referenz bei Referenzoperator / Dereferenzoperator nachschlage und das Beispiel Programm nehme um mir die Adresse(anstatt dem Wert) einer Variablen anzeigen zu lassen, macht der Compiler mir einen Strich durch die Rechnung.

uint8_t test = 5;
 const uint8_t test1 = 7;
 uint32_t a, b;
 a = &test;
 b = &test1;
 Serial1.println (a,HEX);
 Serial1.println (b,HEX);
error: invalid conversion from 'uint8_t*' {aka 'unsigned char*'} to 'uint32_t' {aka 'long unsigned int'} [-fpermissive]
  154 |   a = &test;
      |       ^~~~~
      |       |
      |       uint8_t* {aka unsigned char*}

Leider habe ich bisher immer versucht, um Pointer und Referenzen einen großen Bogen zu machen...

uint8_t test = 5;
const uint8_t test1 = 7;


void setup() 
{
  Serial.begin(9600);
  Serial.println(unsigned(&test),HEX);
  Serial.println(unsigned(&test1),HEX);
}

Das änderst du!
Denn:
Warum was ausblenden, was man doch sowieso dauernd benutzt.

Ich rate zu einem schönen, dicken und modernem C++ Grundlagenbuch.

1 Like

Ergebnis ist:

Test:   0x20041FA3
Test1:  0x20041FA2

Da der RAM Bereich im rp2040 bei 0x20000000 anfängt und 2 weitere Blöcke bei 0x20040000 und 0x20041000 beginnen, ist somit bewiesen, das auch mit einer "const" Anweisung eine Variable im RAM Bereich angelegt wird - Ist hier nicht weiter tragisch, da ja genug RAM vorhanden ist. Es hat mich halt nur mal interessiert wie das denn wirklich läuft.

Auch ein weiterer Test mit der Definition der Variablen als uint16_t hat gezeigt, das wirklich nur so viele Bytes reserviert werden, wie notwendig sind.

Vielen Dank nochmals für die ganzen Hinweise. Das hat mir wirklich sehr geholfen und hat nebenbei noch sehr viel Spaß gemacht. Das letzte mal auf der Adress-Ebene war ich, als ich die AVR's noch in ASM programmiert habe.

Viele Grüße und noch ein schönes Wochenende,
Horst

Die Wirklichkeit, oder Realität, ist meistens viel komplexer, als man das als Einzelperson wissen und wahrnehmen kann.
Es macht auch übrigens keinen Sinn, auf Fragen, eine einfache Antwort zu erwarten, z.B. Ja/Nein Antworten, wenn sich dahinter ganze Universen befinden. Millionen von Details.

Mantra:

Einfache Antworten/Annahmen sind falsch.

Immer.(auch diese)

Siehe:

Keinesfalls ist das damit bewiesen.
Es zeigt nur, dass die readonly Variable im Ram angelegt wird, wenn man einen Pointer darauf nutzt, bzw. ihre Adresse herausfinden will.
Dann muss sie im Ram angelegt werden.

Ich behaupte:
Im Normalfall (wenn möglich) wird der Compiler sie so behandeln, wie er auch
constexpr byte test = 4;
behandelt.
Sie belegt dann weder Flash noch Ram.
Sondern wird als Literal in den generierten Code eingeflochten

Mit modernen Variablen, ist das schon etwas Quantenmechanisches....
Über das, wie die Variable wirklich behandelt wird, wie und wo sie steckt, darüber wird entschieden, wenn ein Beobachter das untersucht/verwendet.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.