Forum: Compiler & IDEs AVR-GCC Verständnisfragen zur Speicherverwaltung


von AVR-GCC Verständnisfragen zur Speicherverwaltung (Gast)


Lesenswert?

Hi,

ich habe zwei Fragen zur AVR-GCC Speicherverwaltung (bezieht sich auf 
die Version im AtmelStudio 6).

Beispielcode:
1
static const __flash char t2[] = "Hallo Welt2";
2
3
int main(void)
4
{
5
    char *t1 = "Hallo Welt";
6
}
7
8
void anyStringFunction(const char* str);

1) Die Variable t2 wird im Programmspeicher angelegt, also dort, wo 
auch er "normale" Code liegt. t1 wird im RAM angelegt. Nun ist der RAM 
aber ein flüchtiger Speicher, kann also Inhalte nicht ohne 
Versorgungsspannung vorhalten. Außerdem können die Inhalte im RAM 
modifiziert werden (solange sie nicht als konstant deklariert sind). Bei 
einem Neustart soll jedoch wieder der Ursprungswert verwendet werden.
Theoretisch muss also der Inhalt bei jedem Programmstart erneut in den 
RAM kopiert werden. Und damit das möglich ist, muss der Inhalt auch 
irgendwo persistent abgelegt werden, was nur ebenfalls im 
Programmspeicher (Flash) oder im EEPROM möglich ist.

Werden die Inhalte wie von mir vermutet beim Start kopiert? Belegen 
somit alle RAM Variablen auch zusätzlich Platz im Flashspeicher?

2) Soweit ich es verstehe arbeitet der Compiler bei der Verwendung des 
__flash Attributs automatisch die entsprechenden Zugriffe ein, die 
auch in der pgmspace.h definiert sind. Dies kann er aber doch nur, 
solange er auch weiß, um was es sich handelt.

Habe ich nun eine Funktion wie anyStringFunction(char*), kann diese 
Funktion doch nicht "wissen", ob der Parameter ein Zeiger auf eine RAM- 
oder eine Programmspeicheradresse ist, oder? Was passiert in diesem 
Fall? Ist es möglich eine Funktion zu schreiben, die mit t1 und t2 
arbeiten könnte?

Danke im Voraus!


---

Threadtitel bereinigt.

-rufus

von Rene B. (themason) Benutzerseite


Lesenswert?

Ich glaub dir ist da beim Erstellen des Threads was durcheinenader 
gekommen :-))


zu 1)

Ja und ja :-)
Es gibt zusätzlich generierten Code der das RAM bevor main aufgerufen 
wird initialisiert.

zu 2)

Das ist in der tat ein großes Problem. Abhilfe gibts beim AVR nur über 
zusätzliche funktionen. printf und printf_P. Das _P behandelt dann die 
entsprechenden Zeiger anders das aus dem Flash gelesen wird. Weiterhin 
unterdrückt das attribut __flash bzw PROGMEM das auf dem RAM automatisch 
eine Variable erzeugt wird (ohne das Attribut geht der Compiler vom RAM 
aus).

Edit :

Wenn du selbst eine Funktion schreibst die wahlweise auf RAM oder Flash 
zugreifen sollen mußt du der Funktion einen Parameter mitgeben der sagt 
um welchen Speicher es sich handelt, und zusätzlich halt die 
Implementierung im wahlfreien Zugriff auf RAM oder Flash.
Ist leider Architekturbedingt ja nicht zu ändern (oder nur mit 
Klimmzügen)

von Peter Reither (Gast)


Lesenswert?

Rene B. schrieb:
> Ich glaub dir ist da beim Erstellen des Threads was durcheinenader
> gekommen :-))

ups...

Danke für deine Antworten, jetzt weiß ich Bescheid!

von MaWin (Gast)


Lesenswert?

1) Natürlich liegt der string von t1 nicht im RAM, sondern auch im 
flash.
Lediglich DER POINTER liegt im RAM und wird beim Start von main geladen. 
Übrigens ist t2 kein änderbarer pointer weil er kein l-Value ist, 
sondern ledigluch ein symbolischer Name für die Adresse vom string.

t1="Hilfe"

geht alo

t2 ="Hilfe"

geht nicht

2) Natürlich müssen Attribute wie_flash auch an den anderen Variablen 
stehen an die solche Werte übergeben werden, damit der Compiler an ihrer 
Verwendungsstelle den richtigen code erzeugen kann. Wenn er klug ist 
warnt er wenn die Typen nicht zusammenpassen, bei printf kann er es aber 
nicht erkennen.

von Simon K. (simon) Benutzerseite


Lesenswert?

MaWin schrieb:
> 1) Natürlich liegt der string von t1 nicht im RAM, sondern auch im
> flash.
Im Falle vom AVR-GCC liegt er allerdings auch im RAM.

> Lediglich DER POINTER liegt im RAM und wird beim Start von main geladen.
Schon, allerdings zeigt er ebenfalls auf eine RAM Adresse, wo der String 
liegt, der noch davor aus dem Flash in den RAM kopiert wird.

> 2) Natürlich müssen Attribute wie_flash auch an den anderen Variablen
> stehen an die solche Werte übergeben werden, damit der Compiler an ihrer
> Verwendungsstelle den richtigen code erzeugen kann. Wenn er klug ist
> warnt er wenn die Typen nicht zusammenpassen, bei printf kann er es aber
> nicht erkennen.

Wohl eher, wenn der Bediener klug ist und die entsprechenden Warnungen 
einschaltet.
Und es gibt auch Compiler, die printf-Format Strings überprüfen können.

Du widersprichst dir selber. Einerseits sagst du, dass bei 
Funktionsparameter ebenfalls wieder ein __flash dazu muss, damit der 
Compiler richtigen Code erzeugt. Andererseits sagst du, dass der char* 
(ohne __flash) auf den Flash zeigen kann.

von Wusel D. (stefanfrings_de)


Lesenswert?

char* können sowohl auf Flash Speicher als auch auf RAM zeigen. Es kommt 
drauf an, mit welchen Befehlen/Funktionen man die Pointer verwendet. Für 
Zugriffe auf Flash muss man die Funktionen nutzen, deren Namen mit _P 
enden.

von g457 (Gast)


Lesenswert?

> Belegen somit alle RAM Variablen auch zusätzlich Platz im Flashspeicher?

Nein, nicht alle. Man kann eine nicht-Initialisierung (und damit 
nicht-Flashspeicher-Nutzung) ausdrücklich erzwingen.

von Simon K. (simon) Benutzerseite


Lesenswert?

Stefan Frings schrieb:
> char* können sowohl auf Flash Speicher als auch auf RAM zeigen. Es kommt
> drauf an, mit welchen Befehlen/Funktionen man die Pointer verwendet. Für
> Zugriffe auf Flash muss man die Funktionen nutzen, deren Namen mit _P
> enden.

Der Witz von __flash (im Vergleich zum veralteten PROGMEM) ist, dass 
eben neue Datentypen (eigentlich ist es nur ein modifier, kein neuer 
Datentyp) eingeführt wurden, die zwischen FLASH und RAM unterscheiden 
und so nicht mehr explizit auf pgm_read_xyz Funktionen zurückgegriffen 
werden muss. Und jetzt willst du das wieder zusammenmixen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.