www.mikrocontroller.net

Forum: Compiler & IDEs Zeiger im FLASH Initialisieren


Autor: anton (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Abend zusammen,

Ich habe folgendes Problem.
Ich programmiere einen Menübaum für meinen Mega16. Dabei deklariere ich
eine Struktur des Typs „Knoten“ mit Zeigern auf  alle Nachbarknoten.
Die Initialisierung aller Datenfelder der Struktur muss nach der
Deklaration aller Knoten erfolgen, da sonst bei der Initialisierung
während der Deklaration die Adressen von Nachbarknoten noch nicht
bekannt sind.
Soweit funktioniert das Programm ohne Probleme (siehe Beispiel).
Nur, wenn ich jetzt das Programm für den Mega16 optimiere und dabei
alle Menüknoten als FLASH-Konstanten deklarieren möchte, tritt das
Problem auf, alle Zeiger zu initialisieren.

Da es sich um Konstanten handelt, müssen sie sofort (bei der
Deklaration) initialisiert werden. Aber wie kann ich sie initialisieren
wenn die Adressen noch nicht bekannt sind?

Ich hab versucht, Deklaration und Initialisierung zu trennen:

struct Knoten
{
  uint8_t     v1;
  uint16_t     v2;
  const char  *s;
  struct Knoten *vater;
};

const struct Knoten myknoten1 PROGMEM;
const struct Knoten myknoten2 PROGMEM;

const struct TableEntry myknoten1 PROGMEM = { 1,2,
STRING1,&myknoten2};
const struct TableEntry myknoten2 PROGMEM = { 3,4, STRING2,
&myknoten1};


Der Compiler mekerte aber:
main.c:33: warning: only initialized variables can be placed into
program memory area

Was meint Ihr, gibt es dafür eine intelligente Lösung?

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich hab versucht, Deklaration und Initialisierung zu trennen:

Deklaration und Definition sind die Stichworte, und das hast du nicht
getrennt. Ich weiß nicht, ob es so funktioniert, aber für eine reine
Deklaration (einer globalen Variable o. Konstante) musst du extern
davor schreiben.

Autor: anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die schnelle Antwort.

Du meinst den Befehl "extern"?

aber ich find nichts über ihn...

Autor: anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach sorry doch, ich hab es:

extern: lokale Deklaration von globalen Variablen, initialisiert mit
0.


werde morgen ausprobieren

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> extern: lokale Deklaration von globalen Variablen, initialisiert mit
> 0.

Das widerspricht sich ja selbst. Bei einer reinen Deklaration kann eine
Variable nicht initialisiert werden. Dann wäre würde die Deklaration
eine Definition beinhalten.

Mit:
extern const int i;
deklarierst du eine globale Variable namens i, definierst sie aber noch
nicht. Das heißt, der Compiler hat ihr noch keinen Speicher zugewiesen,
sondern weiß nur, dass es sie gibt (eine reine Deklaration).
Irgendwo später musst du die Variable noch definieren, indem du
schreibst:
const int i = 0;
Hier fehlt das extern, daher geht der Compiler von einer Definition aus
und reserviert Speicher für die Variable. Ohne diese Zeile würde sich
spätestens der Linker beschweren (der die ganzen Symbole
zusammenpfriemeln darf).

In C++ darf man übrigens "const int i = 0" in einen Header schreiben,
da so eine Konstante dort eine spezielle Art der Bindung hat ("internal
linkage"). In C darf man das meines Wissens nach aber nicht, da der
Linker sich dann über mehrfache Definitionen beschweren würde.

Autor: anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
scheint zu funktionieren, es kommt nur eine Warnung in der Zeile mit
Initiaklisierung:

main.c:119: warning: initialization discards qualifiers from pointer
target type

mir fehlt noch ein Befehl, der komplett eine Struktur aus dem Flash
liest und eine einfache Zuweisung macht:

akt_Knoten = Knoten23;

für EEPROM gibts einen, mit dem man blockweise lesen kann, aber nicht
für den Programmspeicher.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> main.c:119: warning: initialization discards qualifiers from
> pointer target type

qualifier sind in C "const" und "volatile". Vielleicht hast du
irgendwo eines der beiden vergessen.

> für EEPROM gibts einen, mit dem man blockweise lesen kann, aber
> nicht für den Programmspeicher.
Gibt es auch für Flash, die heißt nur anders: memcpy_P().

Autor: anton (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat jemand vielleicht ein kleines Beispiel zum  memcpy_P() ?

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert das nicht intuitiv? Habs nicht getestet, aber ich würde es
mal so probieren wie mit memcpy:

struct mystruct var;
memcpy_P(&var, pointer_to_flash_memory, sizeof(var));

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.