www.mikrocontroller.net

Forum: Compiler & IDEs AVR: prog_char* == char* ?


Autor: Sebastian Fahrner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mal eine Frage zu Pointern ins Flash beim AVR:
Gibt es überhaupt einen Unterschied zwischen Pointern, in ins RAM
zeigen und Pointer, die ins FLASH zeigen?

Es gibt zwar in AVRGCC die Pointer PGM_P und PGM_VOID_P, aber mir ist
aufgefallen, daß man statt diesen auch "normale" Pointer benutzen
kann. Der eigentliche Unterschied ob RAM oder FLASH liegt dann nur noch
in der Routine (z.B. ob memcpy() oder memcpy_P() ).

Grüße,

Sebastian

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim AVR ist Programmspeicher nicht das gleiche wie der Datenspeicher -
daher sind Pointer auf RAM in der Tat was anderes als Pointer auf
FLASH.

Das ist ziemlich heimtückisch.

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim aktuellen avr-gcc sind Pointer 'auf Flash' und Pointer 'auf
RAM' eben nicht wirklich "was anderes", denn dann gaebe es die ganze
"progmem"-Verwirrungen nicht, die hier und in anderen Foren immer
wieder auftreten, und man bzw. der Compiler und die
Laufzeitbibliotheksfunktionen koennten einem Pointer irgendwie
"ansehen" worauf er zeigt und ensprechenden Code generieren/nutzen.

Autor: Sebastian Fahrner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich erinnere mich dunkel, daß es beim Keil C51-Compiler einen "Generic
Pointer" gab, der 3 Bytes belegt. Dabei waren 2 Bytes für die Adresse
und das 3.Byte gab den Speicher-Typ an (IDATA, XDATA und CODE).

Aber wenn ich es richtig verstehe, gibt es beim AVR-GCC keinen
Unterschied zwischen RAM- und ROM-Pointern, da beide nur 2 Bytes für
die Adresse haben, oder?

Grüße,

Sebastian

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn RAM- und ROM-Pointer nur zwei Bytes belegen, muss man bei deren
Gebrauch aber höllisch aufpassen, daß man die nicht verwechselt - sonst
geht's in die Hose, da sie nicht auswechselbar verwendet werden
dürfen.

Damit sind die Pointer definitiv was unterschiedliches - auch wenn's
der Compiler nicht auseinanderhalten kann.
Die Unterscheidung muss also durch den Programmierer aufrechterhalten
werden; schafft der's nicht, geht so einiges in die Hose.

Also braucht man entweder von allen Funktionen, denen Pointer übergeben
werden können zwei Ausführungen (mit RAM- und mit ROM-Pointer) oder man
muss ineffiziente Umkopieraktionen durchführen.

Was für eine Grütze. Aber verständlich; das 3-Byte-Pointer-Konzept ist
in der Tat ineffizient, da ja bei Laufzeit bei jedem Pointerzugriff
erst einmal nachgesehen werden muss, worum es sich dabei handelt ...

Diese Architektur mit getrenntem Code/Datenspeicher ist vielleicht doch
nicht die allerpraktischste, oder?

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genauso ist es.

Es gibt wohl einen C-Standard-Vorschlag für distinct memory spaces,
und einen Willigen, der dies im längeren Zeitrahmen im GCC
implementieren möchte (Svein Seldal).  Damit sollte der Compiler dann
auch in der Lage sein, die Zeiger zumindest auseinanderzuhalten, d. h.
eine Warnung zu generieren, wenn man einen Zeiger in den falschen
memory space benutzt.

Bis dahin ist die Unterscheidung ausschließlich im Kopf des
Programmierers.  Manche Compiler (wie IAR) helfen dem Programmierer
mit einigen Automatismen mehr (z. B. beim Dereferenzieren), aber die
Auswahl der korrekten Routine obliegt dennoch dem Programmierer.

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Damit sind die Pointer definitiv was unterschiedliches - auch
wenn's der Compiler nicht auseinanderhalten kann."

"Genaus so ist es"

Hmm, was ist nach so definitiven Aussagen denn genau der Unterschied.
Ich frage nicht, wie mit den Addressangaben umzugehen ist oder was man
im Kopf haben muss, nur wo der definitive Unterschied ist, bezogen auf
die Pointer selbst.

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Pointer ist für den Compiler ein 16-Bit-Wert. Um diesen korrekt
nutzen zu können, muss der Compiler wissen, ob dieser Pointer auf RAM
oder ROM zeigt - die nämlich liegen nicht im gleichen Adressraum.

Damit ist ein ROM-Pointer mit dem Wert 0x1234 was anderes als ein
RAM-Pointer mit dem gleichen Wert.
Das heimtückische ist, daß man das dem Wert nicht ansehen kann.

Bevor man einen Pointer verwendet, muss man also sehr genau wissen,
worauf er zeigt bzw. worauf er zeigen soll.
Eine Funktion wie puts() erwartet als Argument einen Pointer - und zwar
aller Wahrscheinlichkeit nach einen RAM-Pointer.
Also muss man einen String aus dem ROM erstmal ins RAM kopieren, damit
man puts() aufrufen kann - oder man muss eine puts()-Variante
implementieren, die ROM-Pointer verarbeitet.

Würde der Compiler wenigstens zur Übersetzungszeit RAM- und ROM-Pointer
unterscheiden können, dann würden Aufrufe von Funktionen wie puts() mit
ROM-Pointern wenigstens mit entsprechenden Fehlermeldungen quittiert -
das aber ist, wenn ich J. Wunsch korrekt interpretiere, in GCC noch
lange nicht implementiert.

Damit wird den C-Anfängern hier im Forum noch ein ganz besonderer
Knüppel zwischen die Beine geworfen, vor allem, wenn C-Fragen von
Leuten beantwortet werden, die C zwar mit der Muttermilch aufgesogen
haben, aber eben "normale" Prozessoren damit programmieren ...

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin, es gibt derzeit nur einen Unterschied, der liegt in der
Definition dieser Objekte: all diese PGMSPACE usw. Makros expandieren
letztlich zu einem __attribute__((_progmem_)), was den Compiler
veranlasst, die derart definierten Objekte in eine separate section im
ELF-File einzusortieren.

Ich glaube, es gibt noch einen zweiten Unterschied, dass für deren zur
Compilezeit erfolgendes Dereferenzieren der pm-Operator im
Assemblercode benutzt wird.  Dadurch funktionieren eben solche Dinge
wie menu[2], obwohl menu[i] nicht mehr funktioniert (mit i != const).

Ansonsten sind damit definierte Zeiger aber in der Tat hernach für den
Compiler ,,ganz normale'' Zeiger.

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Merci fuer die Infromation Jörg

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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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