Forum: Compiler & IDEs Zeiger im FLASH Initialisieren


von anton (Gast)


Angehängte Dateien:

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?

von Chris (Gast)


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.

von anton (Gast)


Lesenswert?

danke für die schnelle Antwort.

Du meinst den Befehl "extern"?

aber ich find nichts über ihn...

von anton (Gast)


Lesenswert?

Ach sorry doch, ich hab es:

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


werde morgen ausprobieren

von Chris (Gast)


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.

von anton (Gast)


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.

von Chris (Gast)


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().

von anton (Gast)


Lesenswert?

hat jemand vielleicht ein kleines Beispiel zum  memcpy_P() ?

von Chris (Gast)


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));

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.