Forum: Compiler & IDEs Konfiguration in EEPROM speichern


von Tom M. (tomm) Benutzerseite


Lesenswert?

Hallo zusammen


Ich möchte gerne die Konfiguration meines Sensormoduls im EEPROM 
ablegen. Die SW drauf liest das EE blockweise aus und sucht nach einer 
Signatur. Findet es diese, wird ein struct verwendet, um die 
Konfiguration "reinzuziehen".

Nur - wie krieg ich sie ins EE an eine bestimmte Adresse? Ich will sie 
(übungshalber) nicht an den Start legen, sondern, sagen wir mal, ab 
0x0020 im EE haben.

Mein Code schaut wie folgt aus:
1
struct rtconf_s EEMEM eeconf = { 
2
   {'r','t'},
3
   198,
4
   #ifdef USE_MD5_HMAC
5
   SKEY,    // wird aufgefuellt
6
   #endif // USE_MD5_HMAC
7
   10000,
8
   2,  
9
   4,  
10
   NORMAL
11
};

Mein Makefile erzeugt daraus u.a. ein blah_eeprom.hex file mit dem 
gewünschten Inhalt, allerdings ist die Adresse immer 0x0000:
1
  1 :100000007274C64F74694162312D766A2000000017
2
  2 :0A00100000000010270204020000A7
3
  3 :00000001FF

Wie sag ich's dem Compiler/Linker?
Oder bin ich mit dem Ansatz auf dem Holzweg?

von André A. (nummer5) Benutzerseite


Lesenswert?

Eine Möglichkeit ist die Variable in eine eigene Sektion zu legen (GCC 
attribute section, weis grad die genaue Syntax nicht, EEMEM macht aber 
nichts anderes). Für diese Sektion kannst du dann im Linkerscript die 
Adresse angeben.

Im EEPROM nach der Variablen suchen finde ich sehr unglücklich, warum 
willst du das so implementieren?
Solange du nicht über verschiedene Firmwareversionen die Einstellungen 
auslesen möchtest, würde ich mich nicht weiter um die Adresse im EEPROM 
kümmern.

Eine andere Möglichkeit wäre du castest einfach eine Adresse:
1
struct rtconf_s* eeconf = (struct rtconf_s*)0x0020;

Dann darfst du aber kein EEMEM mehr im Code nutzen sondern musst alle 
Variablen fürs EEPROM so anlegen und darauf achten, dass sich die 
Speicherplätze nicht überschneiden. Hierbei kannst du nur keine 
Initialisierung angeben, bekommst also kein hex-File fürs EEPROM.

von Karl H. (kbuchegg)


Lesenswert?

Tom M. schrieb:

> Wie sag ich's dem Compiler/Linker?

André hat schon ein paar Dinge genannt.
Was du noch versuchen könntest.

Vor bzw. nach deine Strukturdaten einfach ein  Array von 20 Bytes 
anlegen
1
char eeDummy1[20];
2
struct rtconf_s EEMEM eeconf = { 
3
   {'r','t'},
4
   198,
5
   #ifdef USE_MD5_HMAC
6
   SKEY,    // wird aufgefuellt
7
   #endif // USE_MD5_HMAC
8
   10000,
9
   2,  
10
   4,  
11
   NORMAL
12
};
13
char eeDummy2[20];

Das sollte deine eigentlichen Daten auch im EEPROM verschieben.
Oder du machst dir ein spezielles Programm, welches du zuerst ins Flash 
schiebst und welches über die von André erwähnte Pointermethode die 
Daten gezielt an eine bestimmte Adresse schiebt.

> Oder bin ich mit dem Ansatz auf dem Holzweg?
Meiner Ansicht nach ja. Denn was du überhaupt nicht haben willst ist, 
dass du Daten erst mal im EEPROM suchen willst. Das ist aufwändig und 
birgt auch die Gefahr von Fehlern.
Die Daten können doch im EEPROM an immer der gleichen Stelle liegen. Und 
das ist auch gut so.

von Tom M. (tomm) Benutzerseite


Lesenswert?

André Althaus schrieb:
> Im EEPROM nach der Variablen suchen finde ich sehr unglücklich, warum
> willst du das so implementieren?
> Solange du nicht über verschiedene Firmwareversionen die Einstellungen
> auslesen möchtest, würde ich mich nicht weiter um die Adresse im EEPROM
> kümmern.

Ich bastle mehrere Sensor Module mit unterschiedlicher Ausstattung bzw. 
Konfiguration. Meine Idee ist es, die Konfiguration einmalig ins EEPROM 
(mit avrdude) zu schreiben und beim Reset einzulesen. DA sind Dinge drin 
wie ein Symmetric Key, Frequenz/Kanal und Sendeleistung für das RF 
Modul.

Karl Heinz Buchegger schrieb:
> Meiner Ansicht nach ja. Denn was du überhaupt nicht haben willst ist,
> dass du Daten erst mal im EEPROM suchen willst. Das ist aufwändig und
> birgt auch die Gefahr von Fehlern.

Wie gesagt ist es die Modulkonfiguration, die ich mit avrdude ins EE 
schreiben möchte, und das PRogramm sucht danach und verwendet sie, 
ansonsten fällt es auf die eincompilierten Werte zurück. Mein Programm 
liest das EE blockweise ein und sucht nach der Kennung "rt" an den 
Adressen 0x00, 0x20, 0x40 .. FLASH_END.


Danke für die Tipps, werd ich mal testen!

von Karl H. (kbuchegg)


Lesenswert?

Tom M. schrieb:

> Ich bastle mehrere Sensor Module mit unterschiedlicher Ausstattung bzw.
> Konfiguration. Meine Idee ist es, die Konfiguration einmalig ins EEPROM
> (mit avrdude) zu schreiben und beim Reset einzulesen. DA sind Dinge drin
> wie ein Symmetric Key, Frequenz/Kanal und Sendeleistung für das RF
> Modul.

Aber auch das macht man so, dass die Gesamtheit der Konfigurationen im 
EEPROM immer an der gleichen Stelle beginnt.
Dort beginnt man dann zu lesen. Das erste Byte welches gelesen wird, ist 
die Anzahl der Konfigurationen die folgen werden.
In einer Schleife geht man dann diese Anzahl durch und liest wieder nur 
das erste Byte des Kennungsdatensatzes. Dieses Byte ist eine Typkennung 
und verrät dir für welches Gerät/Modul/Sensor die Konfiguration gilt und 
damit auch implizit wieviele Bytes da noch zu dieser Konfiguration 
dazugehören.


Anstatt des ersten Anzahl-Bytes könnte man auch eine spezielle 
Gerätekennung benutzen, die einem verrät: Jetzt kommt nichts mehr.
Das würde sich sogar anbieten, da ein leeres EEPROM überall den Wert 
0xFF hat und wenn man dann das als diese Endekennung benutzt, dann läuft 
das Programm nicht Amok sondern erkennt ohne weiteres Zutun, dass keine 
Konfigurationen vorhanden sind.

Noch einfacher ist es allerdings alle überhaupt möglichen 
Konfigurationen in lediglich eine einzige Struktur zusammenzufassen.

Das allerwichtigste ist aber, dass dein Programm nicht den Speicher 
durchsucht wie ein Privatdetektiv und dann beliebige Bytesequenzen mit 
Konfigurationsdaten verwechselt. Da treibst du mehr Aufwand als das Wert 
ist. Zumal du dir ja höchst wahrscheinlich sowieso ein PC-Programm 
machen wirst, mit dem du die Konfigurationen (entweder direkt als 
HEX-File fertig zum Brennen, bzw. in dem das PC-Programm gleich direkt 
mit dem µC spricht) erstellst. D.h. du hast das unter Kontrolle, wo was 
im EEPROM Speicher steht. Und was du kontrollieren kannst, musst du 
nicht suchen.

von André A. (nummer5) Benutzerseite


Lesenswert?

Dann würd ich den Ansatz mit den Pointern von mir nehmen.

Schreib dir ein kleines Hilfsprogramm, dass eine Binärdatei mit einer 
Konfiguration erstellt. Die kannst du dann in eine Hex-Datei umwandeln 
und flashen.

Auf die Weise kannst du eine feste Adresse (z.B. 0x0000) nehmen ohne 
suchen zu müssen. Wenn die Konfigurationen unterschiedliche Daten 
enthalten musst du halt vor den eigentlichen Daten eine Magic-Number 
schreiben die angibt um welche Art von Konfiguration es sich handelt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
>
1
> char eeDummy1[20];
2
> ...
3
> char eeDummy2[20];
4
>

Fehlt da nicht das Schlüsselwort EEMEM?

Ist es sicher, dass der Compiler/Linker die 3 EEMEM-Objekte in genau der 
Reihenfolge im EEPROM anordnet? Ja, ich weiß, dass es so ist, aber ist 
das auch garantiert? Was ist, wenn später eine zusätzliche 
EEMEM-Variable in einer ganz anderen neuen .c-Datei zum Projekt 
hinzukommt?

Ich persönlich bin mit dem EEMEM-Konzept, so wie es realisiert ist, 
ziemlich unzufrieden. Damit garantiert ist, dass sämtliche 
EEMEM-Variablen immer gleich im EEPROM angeordnet werden, muss ich sie 
alle in ein- und derselben .c-Datei definieren und darf die Reihenfolge 
der Definition niemals ändern.

Aus diesem Dilemma hilft nur ein eigens geschriebenes eemem.c mit ein 
paar ReadWrite-Funktionen, denen man gezielt die EEPROM-Adressen 
übergibt. Damit verzichtet man aber auf den Komfort, die EEMEM-Adressen 
vom Compiler ausrechnen zu lassen. Das muss man dann mit sizeof() selber 
machen.

von Karl H. (kbuchegg)


Lesenswert?

Frank M. schrieb:
> Karl Heinz Buchegger schrieb:
>>
1
>> char eeDummy1[20];
2
>> ...
3
>> char eeDummy2[20];
4
>>
>
> Fehlt da nicht das Schlüsselwort EEMEM?

Mea culpa.
Ja darauf hab ich vergessen, war noch sehr früh :-)

> Ist es sicher, dass der Compiler/Linker die 3 EEMEM-Objekte in genau der
> Reihenfolge im EEPROM anordnet? Ja, ich weiß, dass es so ist, aber ist
> das auch garantiert?

Offiziell nicht.

Wenn du eine Garantie willst, dann musst du das Dummy Array, welches dir 
die Daten verschiebt mit in die Struktur aufnehmen.

> Was ist, wenn später eine zusätzliche
> EEMEM-Variable in einer ganz anderen neuen .c-Datei zum Projekt
> hinzukommt?

Du hast etwas wichtiges entdeckt:
Es ist unklug EEPROM Daten, bei denen es auf die tatsächliche Adresslage 
ankommt, auseinanderzureißen.

Aber du wirst ja nicht jedesmal, wenn du die Konfiguration änderst, das 
komplette Projekt neu kompilieren. Gerade bei Konfiguration geht es doch 
darum, eben keinen COmpiler/Linker zu benötigen.

> Aus diesem Dilemma ....
Im Prinzip ja.
Sobald du dich aber davon löst, dass du das EEPROM nur über ein vom 
Compiler generiertes Hex-File beschreiben kannst, macht es wieder Sinn. 
Sieht man das EEPROM als Speicher an, den der µC alleinig unter 
Kontrolle hat, macht es wieder Sinn. In deinem Fall würde man die 
Konfiguration dann eben nicht per Compiler generiertem Hex-File ins 
EEPROM schiessen, sondern man steckt den µC zb an eine serielle 
Schnittstelle, startet ein PC-Programm und wählt in einer Maske, schön 
mit Häkchen etc., die Konfiguration die man haben möchte. Vom PC gehen 
die Daten per serieller SChnittstelle wieder zum µC und der schreibt sie 
wieder zurück ins EEPROM. Das ist dann auch aussendienstmitarbeiter 
tauglich.
(ANstatt eines PC tuts auch ein LCD und ein paar Taster, die an einem 
Port angesteckt werden und ein Menüsystem im µC)

Das Compiler generierte Hex-File wird IMHO überbewertet.

von Uwe (de0508)


Lesenswert?

Hallo,

ich verwende gerne diese keinen Funktionen für den Zugriff, lesend und 
schreibend.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=91306

Hier kannst Du sehr einfach eine EEprom-Adresse angeben.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:

> Wenn du eine Garantie willst, dann musst du das Dummy Array, welches dir
> die Daten verschiebt mit in die Struktur aufnehmen.

Bei Strukturen ist die Reihenfolge garantiert?
Brauchst darauf nicht zu antworten, ich wollte nur provozieren ;-)

> Aber du wirst ja nicht jedesmal, wenn du die Konfiguration änderst, das
> komplette Projekt neu kompilieren.

.eep-Dateien interessieren mich überhaupt nicht. Ich lege aber in 
diversen Projekten Konfigurationswerte at runtime (nicht at compiletime) 
im EEPROM ab. Da die µCs allesamt Bootloader verwenden und sie deshalb 
auch regelmäßig Firmware-Updates genießen, muss gewährleistet werden, 
dass die EEPROM-Daten versionsübergreifend kompatibel bleiben.

Damit kann man das EEPROM nicht mehr als Black-Box ansehen, sondern muss 
penibel darauf achten, dass die Reihenfolge der EEMEM-Variablen dieselbe 
bleibt. Nun ist es aber so, dass ich gerne modular programmiere, d.h. 
die Variablen dorthin verpflanze, wo sie vom Code her auch hingehören.

Beispiel eines Projektes:

   ---------------------------------
   | regensensor.c                 |
   | uint8_t rain_threshold EEMEM; |
   ---------------------------------

   ---------------------------------
   | lcd.c                         |
   | uint8_t brightness EEMEM;     |
   ---------------------------------

Und damit geht das Theater schon los. Allein bei dieser Konstellation 
kannst Du Dich auf nichts mehr verlassen. Einmal die Link-Reihenfolge im 
Makefile oder AVR-Projekt geändert und nach einem Firmware-Update 
kalibriert die Helligkeit des Displays den Regensensor :-(

von Karl H. (kbuchegg)


Lesenswert?

Frank M. schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Wenn du eine Garantie willst, dann musst du das Dummy Array, welches dir
>> die Daten verschiebt mit in die Struktur aufnehmen.
>
> Bei Strukturen ist die Reihenfolge garantiert?
> Brauchst darauf nicht zu antworten, ich wollte nur provozieren ;-)

Ich tus trotzdem :-)
Die Reihenfolge ist garantiert, aber die Offsets nicht.
ok. beim AVR wird da nichts passieren. Aber im Allgmeinen gibt es keine 
Garantie, dass der COmpiler nicht zwischen Strukturmember ein paar 
Padding Bytes einfügt, um Alignment Restriktionen eines Prozessors zu 
erfüllen.
Wie gesagt - bei einem AVR ist das kein Thema.


> .eep-Dateien interessieren mich überhaupt nicht. Ich lege aber in
> diversen Projekten Konfigurationswerte at runtime (nicht at compiletime)
> im EEPROM ab. Da die µCs allesamt Bootloader verwenden und sie deshalb
> auch regelmäßig Firmware-Updates genießen, muss gewährleistet werden,
> dass die EEPROM-Daten versionsübergreifend kompatibel bleiben.

Oh ja.
Da wird es dann spannend :-)

> Damit kann man das EEPROM nicht mehr als Black-Box ansehen, sondern muss
> penibel darauf achten, dass die Reihenfolge der EEMEM-Variablen dieselbe
> bleibt. Nun ist es aber so, dass ich gerne modular programmiere, d.h.
> die Variablen dorthin verpflanze, wo sie vom Code her auch hingehören.

Bisher hatte ich dieses konkrete Problem noch nicht, weil es immer 
'wenig genug' Konfigurationswerte waren, so dass ich sie an einer Stelle 
zusammenfassen kann.

> Und damit geht das Theater schon los. Allein bei dieser Konstellation
> kannst Du Dich auf nichts mehr verlassen. Einmal die Link-Reihenfolge im
> Makefile oder AVR-Projekt geändert und nach einem Firmware-Update
> kalibriert die Helligkeit des Displays den Regensensor :-(

Jep. Das sehe ich ein.
Da muss man sich in der Tat mal über eine etwas intelligentere 
Verwaltung den Kopf zerbrechen. Mit einer Automatik ala EEMEM kommst du 
da nicht weiter.
Ich denke, ich würde mein Heil tatsächlich in so einer Art 'Taged 
Struktur' suchen, wo jedes Modul einen Nummernkreis für seine Tags hat, 
die es für seine Werte benutzen kann. Und dann eben eine Abfolge von 
Tags im EEPROM.

     Tag-1     Kennungsbyte
               Länge
               Daten
     Tag-2     Kennungsbyte
               Länge
               Daten
     ...
     Tag-n     Kennungsbyte
               Länge
               Daten
     Letztes
     Tag       Kennung - 0xFF

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:

> Da muss man sich in der Tat mal über eine etwas intelligentere
> Verwaltung den Kopf zerbrechen. Mit einer Automatik ala EEMEM kommst du
> da nicht weiter.

So ist es. Ich dachte da schon an eine Art assoziatives Array, wobei der 
Key ja nicht unbedingt ein String sein muss. Das kommt Deiner 
Tag-Struktur schon recht nahe. Muss mal drüber nachdenken. Erstmal Dank 
für dies:

>      Tag-1     Kennungsbyte
>                Länge
>                Daten
>      ...

Gruß,

Frank

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.