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
structrtconf_sEEMEMeeconf={
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?
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
structrtconf_s*eeconf=(structrtconf_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.
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
chareeDummy1[20];
2
structrtconf_sEEMEMeeconf={
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
chareeDummy2[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.
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!
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.
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.
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.
>> 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.
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 :-(
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
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