Hallo!
Wie kann man im C-Quellcode (AVR GCC) Variablen im EEPROM definieren so
dass diese an einer definierbaren Adresse liegen und einen
Initialisierungswert bekommen?
Die Standardwerte der Variablen (EEP Datei) möchte ich dann per avrdude
bei der ersten Programmierung des Controllers programmieren.
Beispiel:
Adresse 0x0000 bis 0x00FF : Frei
Adresse 0x0100 bis 0x0101 : uint8_t mit vordefiniertem Wert 0x10
Adresse 0x0102 bis 0x01FF : Frei
Adresse 0x0200 bis 0x0201 : uint8_t mit vordefiniertem Wert 0x11
Wenn ich die Variablen nun so definiere, dann bekomme ich eine EEP-Datei
mit den korrekten Initialisierungswerten, nur leider landen die
Variablen an Adresse 0x0000 und 0x0001
uint8_t var1 EEMEM = 0x10;
uint8_t var2 EEMEM = 0x11;
Alternativ kann ich per #define die Adressen der Werte festlegen und
dann an eeprom_read_byte übergeben.
Damit habe ich feste Adressen aber bekomme am Ende keine EEP-Datei mit
den Initialisierungswerten.
Ich suche nach einer Kombination der beiden Varianten. Geht das?
Grüße,
Bernhard
Hi
Geht perfekt über section und entsprechend angepasstes Linkerscript.
Dann hast du volle Kontrolle aber auch entsprechend Aufwand. Wenns
einfach sein soll erstellst du eine Struktur in der exakten Größe des
eeprom und platzierst darin deine variablen mit entsprechenden
Fullvariablen dazwischen.
Matthias
Kann man auch über gcc machen.
Beim Linken folgendes hinzufügen:
-Wl,-section-start=platz1=0x810100 <- Platz1 bei 0x0100 +0x810000 fürs
eeprom
-Wl,-section-start=platz2=0x810200 <- Platz2 bei 0x0200
Bei objcopy folgendes hinzufügen:
--change-section-lma platz1=0x100
--change-section-lma platz2=0x200
Und im Code dann bei den Variablen dann sections benutzen
uint8_t var1 EEMEM __attribute__((section("Platz1"))) = 0x10;
uint8_t var2 EEMEM __attribute__((section("Platz2"))) = 0x11;
Schließlich bekommt man ein kleines EEP-File mit nur den vordefinierten
Werten an der richtigen Adresse.
Das Auslesen der Werte ist auch einfach und der Compiler nutzt auch die
korrekten Adressen:
1
value=eeprom_read_byte(&val2);
- &val2 ist 0x100
- Nach dem Funktionsaufruf ist value dann 0x11
Im Prinzip hast du 3 Möglichkeiten:
1) EMEM verwenden.
Du bekommst eine .eep Datei, die zu deiner SW passt. Aber wenn du die SW
änderst kann es sein dass deine Variablen woanders liegen => der alte
EEPROM-Inhalt ist nutzlos
2) der obige Ansatz mit sections. Wär mir persönlich bisl zuviel Aufwand
:-)
3) Das EEPROM als Struktur abbilden. So mach ichs momentan. Du kriegst
leider erstmal kein .eep-File, aber das werd ich per sections noch
hinkriegen.
Nachteil: Wenn eine Softwarekomponente eine zusätzliche eep-Variable
braucht musst du sie ans Ende der Struktur pfriemeln. Kann also
irgendwann bisl durcheinander kommen. Ausser du hälst dir für jedes
Modul Reserveblöcke vor, für zukünftige Erweiterungen.
Das EEPROM zu spalten macht dann Sinn wenn man zwei quasi unabhängige
Applikations-Firmwares hat z.B. Bootloader und Hauptprogramm.
Jeder Teil soll was im EEPROM speichern können ohne den anderen zu
beeinträchtigen.
Ein automatisch generiertes EEP File mit Standardwerten macht Sinn bei
der Programmierung von > 1 Stück. Außerdem ist so in der Datei nur das
drin was ich brauche, keine unnötigen Füll-Arrays o.ä. die nur die
Programmierung verlangsamen.
Ich habe mir jetzt mit zwei Sections geholfen. Eine für den Bootloader
und eine für das Hauptprogramm.
Das schöne dabei: In dem Quellcode muss ich nur die Standardwerte
setzen.
Im Makefile setze ich nur die jeweiligen Startadressen der Sections.
Am Anfang des EEPROM lasse ich etwas Platz frei, dann der erste und
zweite Block.
In jeder Section ist dann wiederum ein struct mit den Variablen.
Der Zugriff erfolgt einfach per
1
eeprom_read_byte(&config_struct.variable)
Wenn ich in Zukunft noch mehr Variablen ablegen möchte, dann hab ich
innerhalb der Sections noch genug Platz. Die Section für den Bootloader
ist recht klein, z.B. 112 Bytes (128 Bytes - 16 Bytes vom Anfang),
Beginn der Section für das Hauptprogramm dann ab 0x80
Wenn man dann mal einen größeren Controller mit mehr EEPROM einsetzt
kann das dann auch genutzt werden (oder ist in gewissen Grenzen auch
abwärtskompatibel)